Android提高之MediaPlayer播放网络视频的实现方法
前面讲解了mediaplayer播放网络音频,主要介绍了mediaplayer关于网络音频的缓冲和进度条控制的方法,本文再来讲解一下mediaplayer播放网络视频的方法。播放网络视频比播放网络音频需要多一个surfaceview而已,在已经熟悉了mediaplayer播放网络音频之后,相信大家对本文所述的播放网络视频也能很快地掌握。
先来看看本文程序运行截图,如下所示:
本文程序的视频来自http://daily3gp.com,大家可以替换程序中的视频链接,试试其他影片。
main.xml的源码如下:
<?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="fill_parent" android:layout_width="fill_parent"> <surfaceview android:id="@+id/surfaceview1" android:layout_height="fill_parent" android:layout_width="fill_parent"></surfaceview> <linearlayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_gravity="bottom" android:orientation="vertical"> <linearlayout android:orientation="horizontal" android:layout_gravity="center_horizontal" android:layout_margintop="4.0dip" android:layout_height="wrap_content" android:layout_width="wrap_content"> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnplayurl" android:text="播放网络视频"></button> <button android:layout_height="wrap_content" android:id="@+id/btnpause" android:text="暂停" android:layout_width="80dip"></button> <button android:layout_height="wrap_content" android:layout_width="80dip" android:text="停止" android:id="@+id/btnstop"></button> </linearlayout> <linearlayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginbottom="20dip"> <seekbar android:paddingright="10dip" android:layout_gravity="center_vertical" android:paddingleft="10dip" android:layout_weight="1.0" android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/skbprogress" android:max="100"></seekbar> </linearlayout> </linearlayout> </framelayout>
player.java是本文的核心,player.java实现了“进度条更新”、“数据缓冲”、“surfaceholder生命周期”等功能,其中“surfaceholder生命周期”是视频与音频播放的最大区别,通过surfacecreated()、surfacedestroyed()、surfacechanged()可以创建/释放某些资源。下面这个地方需要注意一下:
videowidth = mediaplayer.getvideowidth(); videoheight = mediaplayer.getvideoheight(); if (videoheight != 0 && videowidth != 0) { arg0.start(); }
有些视频是android播放器不能播放的,不能播放时videoheight=0,videowidth=0,以此来判断是否播放视频。
player.java源码如下:
package com.videoplayer; import java.io.ioexception; import java.util.timer; import java.util.timertask; import android.media.audiomanager; import android.media.mediaplayer; import android.media.mediaplayer.onbufferingupdatelistener; import android.media.mediaplayer.oncompletionlistener; import android.os.handler; import android.os.message; import android.util.log; import android.view.surfaceholder; import android.view.surfaceview; import android.widget.seekbar; public class player implements onbufferingupdatelistener, oncompletionlistener, mediaplayer.onpreparedlistener, surfaceholder.callback { private int videowidth; private int videoheight; public mediaplayer mediaplayer; private surfaceholder surfaceholder; private seekbar skbprogress; private timer mtimer=new timer(); public player(surfaceview surfaceview,seekbar skbprogress) { this.skbprogress=skbprogress; surfaceholder=surfaceview.getholder(); surfaceholder.addcallback(this); surfaceholder.settype(surfaceholder.surface_type_push_buffers); mtimer.schedule(mtimertask, 0, 1000); } /******************************************************* * 通过定时器和handler来更新进度条 ******************************************************/ timertask mtimertask = new timertask() { @override public void run() { if(mediaplayer==null) return; if (mediaplayer.isplaying() && skbprogress.ispressed() == false) { handleprogress.sendemptymessage(0); } } }; handler handleprogress = new handler() { public void handlemessage(message msg) { int position = mediaplayer.getcurrentposition(); int duration = mediaplayer.getduration(); if (duration > 0) { long pos = skbprogress.getmax() * position / duration; skbprogress.setprogress((int) pos); } }; }; //***************************************************** public void play() { mediaplayer.start(); } public void playurl(string videourl) { try { mediaplayer.reset(); mediaplayer.setdatasource(videourl); mediaplayer.prepare();//prepare之后自动播放 //mediaplayer.start(); } catch (illegalargumentexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (illegalstateexception e) { // todo auto-generated catch block e.printstacktrace(); } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); } } public void pause() { mediaplayer.pause(); } public void stop() { if (mediaplayer != null) { mediaplayer.stop(); mediaplayer.release(); mediaplayer = null; } } @override public void surfacechanged(surfaceholder arg0, int arg1, int arg2, int arg3) { log.e("mediaplayer", "surface changed"); } @override public void surfacecreated(surfaceholder arg0) { try { mediaplayer = new mediaplayer(); mediaplayer.setdisplay(surfaceholder); mediaplayer.setaudiostreamtype(audiomanager.stream_music); mediaplayer.setonbufferingupdatelistener(this); mediaplayer.setonpreparedlistener(this); } catch (exception e) { log.e("mediaplayer", "error", e); } log.e("mediaplayer", "surface created"); } @override public void surfacedestroyed(surfaceholder arg0) { log.e("mediaplayer", "surface destroyed"); } @override /** * 通过onprepared播放 */ public void onprepared(mediaplayer arg0) { videowidth = mediaplayer.getvideowidth(); videoheight = mediaplayer.getvideoheight(); if (videoheight != 0 && videowidth != 0) { arg0.start(); } log.e("mediaplayer", "onprepared"); } @override public void oncompletion(mediaplayer arg0) { // todo auto-generated method stub } @override public void onbufferingupdate(mediaplayer arg0, int bufferingprogress) { skbprogress.setsecondaryprogress(bufferingprogress); int currentprogress=skbprogress.getmax()*mediaplayer.getcurrentposition()/mediaplayer.getduration(); log.e(currentprogress+"% play", bufferingprogress + "% buffer"); } }
test_videoplayer.java是主程序,负责调用player类,其中关键部分是seekbarchangeevent这个seekbar拖动的事件:seekbar的progress是0~seekbar.getmax()之内的数,而mediaplayer.seekto()的参数是0~mediaplayer.getduration()之内数,所以mediaplayer.seekto()的参数是(progress/seekbar.getmax())*mediaplayer.getduration()。
test_videoplayer.java源码如下:
package com.videoplayer; import android.app.activity; import android.content.pm.activityinfo; import android.net.uri; import android.os.bundle; import android.util.log; import android.view.surfaceview; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; import android.widget.seekbar; public class test_videoplayer extends activity { private surfaceview surfaceview; private button btnpause, btnplayurl, btnstop; private seekbar skbprogress; private player player; /** called when the activity is first created. */ @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); setrequestedorientation(activityinfo.screen_orientation_landscape); surfaceview = (surfaceview) this.findviewbyid(r.id.surfaceview1); btnplayurl = (button) this.findviewbyid(r.id.btnplayurl); btnplayurl.setonclicklistener(new clickevent()); btnpause = (button) this.findviewbyid(r.id.btnpause); btnpause.setonclicklistener(new clickevent()); btnstop = (button) this.findviewbyid(r.id.btnstop); btnstop.setonclicklistener(new clickevent()); skbprogress = (seekbar) this.findviewbyid(r.id.skbprogress); skbprogress.setonseekbarchangelistener(new seekbarchangeevent()); player = new player(surfaceview, skbprogress); } class clickevent implements onclicklistener { @override public void onclick(view arg0) { if (arg0 == btnpause) { player.pause(); } else if (arg0 == btnplayurl) { string url="http://daily3gp.com/vids/family_guy_penis_car.3gp"; player.playurl(url); } else if (arg0 == btnstop) { player.stop(); } } } class seekbarchangeevent implements seekbar.onseekbarchangelistener { int progress; @override public void onprogresschanged(seekbar seekbar, int progress, boolean fromuser) { // 原本是(progress/seekbar.getmax())*player.mediaplayer.getduration() this.progress = progress * player.mediaplayer.getduration() / seekbar.getmax(); } @override public void onstarttrackingtouch(seekbar seekbar) { } @override public void onstoptrackingtouch(seekbar seekbar) { // seekto()的参数是相对与影片时间的数字,而不是与seekbar.getmax()相对的数字 player.mediaplayer.seekto(progress); } } }
感兴趣的读者可以自己动手测试一下本文实例代码,相信对大家进行android程序开发有一定的借鉴作用。
下一篇: 象棋中的楚河汉界到底在哪个地方呢?
推荐阅读
-
Android编程实现播放视频的方法示例
-
Android提高之MediaPlayer音视频播放
-
Android提高之MediaPlayer播放网络音频的实现方法
-
Android提高之AudioRecord实现助听器的方法
-
Android提高之ListView实现自适应表格的方法
-
Android提高之MediaPlayer播放网络视频的实现方法
-
解决Android使用MediaPlayer只播放视频不播放音频的方法
-
Android MediaPlayer 在API 28的手机上播放本地视频正常,播放网络视频,报错:what=1, extra=-2147483648
-
Android提高之MediaPlayer音视频播放
-
Android提高之AudioRecord实现助听器的方法