surfaceviewholderholder怎么实例化

Android多媒体学习十二:Android中Video的三种播放方式的实现
Android多媒体学习十二:Android中Video的三种播放方式的实现
1432人阅读
在Android中,我们有三种方式来实现视频的播放。
1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。
2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。
3、使用MediaPlayer类和SurfaceView来实现。这种方式最灵活,也最复杂。
下面给出这三种方式,
1、调用其自带的播放器:
[java] Uri&uri&=&Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v");&&&&&&&&&Intent&intent&=&new&Intent(Intent.ACTION_VIEW);&&&&&&Log.v("URI:::::::::",&uri.toString());&&&&&&intent.setDataAndType(uri,&"video/mp4");&&&&&&startActivity(intent);&&
2、使用VideoView来实现:
[java] Uri&uri&=&Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v");&&VideoView&videoView&=&(VideoView)this.findViewById(R.id.video_view);&&videoView.setMediaController(new&MediaController(this));&&videoView.setVideoURI(uri);&&&&videoView.requestFocus();&&
3、使用MediaPlayer:
[java] package&demo.&&import&java.io.IOE&&import&android.app.A&&import&android.media.MediaP&&import&android.media.MediaPlayer.OnCompletionL&&import&android.media.MediaPlayer.OnErrorL&&import&android.media.MediaPlayer.OnInfoL&&import&android.media.MediaPlayer.OnPreparedL&&import&android.media.MediaPlayer.OnSeekCompleteL&&import&android.media.MediaPlayer.OnVideoSizeChangedL&&import&android.os.B&&import&android.os.E&&import&android.util.L&&import&android.view.D&&import&android.view.SurfaceH&&import&android.view.SurfaceV&&import&android.widget.LinearL&&&&&&&&&&&&&&&public&class&VideoSurfaceDemo&extends&Activity&implements&OnCompletionListener,OnErrorListener,OnInfoListener,&&&&&&OnPreparedListener,&OnSeekCompleteListener,OnVideoSizeChangedListener,SurfaceHolder.Callback{&&&&&&private&Display&currD&&&&&&private&SurfaceView&surfaceV&&&&&&private&SurfaceHolder&&&&&&&private&MediaPlayer&&&&&&&private&int&vWidth,vH&&&&&&&&&&&&&&&&&&&&&&&&public&void&onCreate(Bundle&savedInstanceState){&&&&&&&&&&super.onCreate(savedInstanceState);&&&&&&&&&&this.setContentView(R.layout.video_surface);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&surfaceView&=&(SurfaceView)this.findViewById(R.id.video_surface);&&&&&&&&&&&&&&&&&&&&holder&=&surfaceView.getHolder();&&&&&&&&&&holder.addCallback(this);&&&&&&&&&&&&&&&&&&&&holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&player&=&new&MediaPlayer();&&&&&&&&&&player.setOnCompletionListener(this);&&&&&&&&&&player.setOnErrorListener(this);&&&&&&&&&&player.setOnInfoListener(this);&&&&&&&&&&player.setOnPreparedListener(this);&&&&&&&&&&player.setOnSeekCompleteListener(this);&&&&&&&&&&player.setOnVideoSizeChangedListener(this);&&&&&&&&&&Log.v("Begin:::",&"surfaceDestroyed&called");&&&&&&&&&&&&&&&&&&&&String&dataPath&=&Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v";&&&&&&&&&&try&{&&&&&&&&&&&&&&player.setDataSource(dataPath);&&&&&&&&&&&&&&Log.v("Next:::",&"surfaceDestroyed&called");&&&&&&&&&&}&catch&(IllegalArgumentException&e)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&e.printStackTrace();&&&&&&&&&&}&catch&(IllegalStateException&e)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&e.printStackTrace();&&&&&&&&&&}&catch&(IOException&e)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&e.printStackTrace();&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&currDisplay&=&this.getWindowManager().getDefaultDisplay();&&&&&&}&&&&&&&&&&&&@Override&&&&&&public&void&surfaceChanged(SurfaceHolder&arg0,&int&arg1,&int&arg2,&int&arg3)&{&&&&&&&&&&&&&&&&&&&&Log.v("Surface&Change:::",&"surfaceChanged&called");&&&&&&}&&&&&&@Override&&&&&&public&void&surfaceCreated(SurfaceHolder&holder)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&player.setDisplay(holder);&&&&&&&&&&&&&&&&&&&&player.prepareAsync();&&&&&&&&&&&&&&&&}&&&&&&@Override&&&&&&public&void&surfaceDestroyed(SurfaceHolder&holder)&{&&&&&&&&&&&&&&&&&&&&Log.v("Surface&Destory:::",&"surfaceDestroyed&called");&&&&&&}&&&&&&@Override&&&&&&public&void&onVideoSizeChanged(MediaPlayer&arg0,&int&arg1,&int&arg2)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Log.v("Video&Size&Change",&"onVideoSizeChanged&called");&&&&&&&&&&&&&&&&}&&&&&&@Override&&&&&&public&void&onSeekComplete(MediaPlayer&arg0)&{&&&&&&&&&&&&&&&&&&&&Log.v("Seek&Completion",&"onSeekComplete&called");&&&&&&&&&&&&&&&&}&&&&&&@Override&&&&&&public&void&onPrepared(MediaPlayer&player)&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&vWidth&=&player.getVideoWidth();&&&&&&&&&&vHeight&=&player.getVideoHeight();&&&&&&&&&&&&&&&&&&&&if(vWidth&&&currDisplay.getWidth()&||&vHeight&&&currDisplay.getHeight()){&&&&&&&&&&&&&&&&&&&&&&&&&&&&float&wRatio&=&(float)vWidth/(float)currDisplay.getWidth();&&&&&&&&&&&&&&float&hRatio&=&(float)vHeight/(float)currDisplay.getHeight();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&float&ratio&=&Math.max(wRatio,&hRatio);&&&&&&&&&&&&&&&&&&&&&&&&&&&&vWidth&=&(int)Math.ceil((float)vWidth/ratio);&&&&&&&&&&&&&&vHeight&=&(int)Math.ceil((float)vHeight/ratio);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&surfaceView.setLayoutParams(new&LinearLayout.LayoutParams(vWidth,&vHeight));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&player.start();&&&&&&&&&&}&&&&&&}&&&&&&@Override&&&&&&public&boolean&onInfo(MediaPlayer&player,&int&whatInfo,&int&extra)&{&&&&&&&&&&&&&&&&&&&&switch(whatInfo){&&&&&&&&&&case&MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:&&&&&&&&&&&&&&break;&&&&&&&&&&case&MediaPlayer.MEDIA_INFO_METADATA_UPDATE:&&&&&&&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&case&MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:&&&&&&&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&case&MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:&&&&&&&&&&&&&&&&&&&&&&&&&&&&break;&&&&&&&&&&}&&&&&&&&&&return&false;&&&&&&}&&&&&&@Override&&&&&&public&boolean&onError(MediaPlayer&player,&int&whatError,&int&extra)&{&&&&&&&&&&Log.v("Play&Error:::",&"onError&called");&&&&&&&&&&switch&(whatError)&{&&&&&&&&&&case&MediaPlayer.MEDIA_ERROR_SERVER_DIED:&&&&&&&&&&&&&&Log.v("Play&Error:::",&"MEDIA_ERROR_SERVER_DIED");&&&&&&&&&&&&&&break;&&&&&&&&&&case&MediaPlayer.MEDIA_ERROR_UNKNOWN:&&&&&&&&&&&&&&Log.v("Play&Error:::",&"MEDIA_ERROR_UNKNOWN");&&&&&&&&&&&&&&break;&&&&&&&&&&default:&&&&&&&&&&&&&&break;&&&&&&&&&&}&&&&&&&&&&return&false;&&&&&&}&&&&&&@Override&&&&&&public&void&onCompletion(MediaPlayer&player)&{&&&&&&&&&&&&&&&&&&&&Log.v("Play&Over:::",&"onComletion&called");&&&&&&&&&&this.finish();&&&&&&}&&}&&
使用的布局文件都很简单,就不贴了。实际测试时,发现在模拟器中会出现卡在第一帧的现象,具网上牛人们说,这是模拟器自身的问题。
在真机上测试就可以。
发表评论:
TA的最新馆藏[转]&[转]&[转]&下次自动登录
现在的位置:
& 综合 & 正文
surfaceview 和surfaceholder
SurfaceView介绍
通常情况的View和用户响应都是在同一个线程中处理的,这也是为什么处理长时间事件(例如访问网络)需要放到另外的线程中去(防止阻塞当前线程的操作和绘制)。但是在其他线程中却不能修改UI元素,例如用后台线程更新自定义View(调用View的在自定义View中的onDraw函数)是不允许的。
如果需要在另外的线程绘制界面、需要迅速的更新界面或则渲染UI界面需要较长的时间,这种情况就要使用SurfaceView了。SurfaceView中包含一个Surface对象,而Surface是可以在后台线程中绘制的。Surface属于
OPhone底层显示系统,关于这方面的介绍请参考附录中的资料[1]。SurfaceView的性质决定了其比较适合一些场景:需要界面迅速更新、对帧率要求较高的情况。使用SurfaceView需要注意以下几点情况:
SurfaceView和SurfaceHolder.Callback函数都从当前SurfaceView窗口线程中调用(一般而言就是程序的主线程)。有关资源状态要注意和绘制线程之间的同步。
在绘制线程中必须先合法的获取Surface才能开始绘制内容,在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之间的状态为合法的,另外在Surface类型为SURFACE_TYPE_PUSH_BUFFERS时候是不合法的。
额外的绘制线程会消耗系统的资源,在使用SurfaceView的时候要注意这点。
使用SurfaceView
只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:
surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。
surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。
surfaceDestroyed(SurfaceHolder holder):当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface了,一般在该函数中来清理使用的资源。
通过SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas(Rect dirty)函数来获取Canvas对象,通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或则尚未创建调用该函数会返回null,在
unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的,所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分则可以调用lockCanvas(Rect dirty)函数来指定一个dirty区域,这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、修改)。
当在Canvas中绘制完成后,调用函数unlockCanvasAndPost(Canvas canvas)来通知系统Surface已经绘制完成,这样系统会把绘制完的内容显示出来。为了充分利用不同平台的资源,发挥平台的最优效果可以通过SurfaceHolder的setType函数来设置绘制的类型,目前接收如下的参数:
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface
SURFACE_TYPE_GPU:适用于GPU加速的Surface
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。
目前OPhone还不支持GIF动画图片的显示,这里就通过一个SurfaceView来展示如何定制一个支持GIF动画的View,同时从该示例(注释)中也可以看出如何使用SurfaceView。
首先创建一个GifView继承在SurfaceView,如下:
class GifView extends SurfaceView implements Callback { //GifThread是用来绘制的后台线程,一般使用SurfaceView都会使用一个 //后台线程来做绘制的工作 private GifThread mGifT //GifDecoder是一个Gif图片格式的解析器,用来解析Gif图片的每帧数据和显示时间。 private GifDecoder mGifD public GifView(Context context,int
gifId) { super(context); //获取Gif图片数据 InputStream is = context.getResources().openRawResource(gifId); //解析Gif图片数据 mGifDecoder = new GifDecoder(); mGifDecoder.read(is); try { is.close(); } catch (IOException e) { e.printStackTrace(); } is = //获取SurfaceHolder
SurfaceHolder holder = getHolder(); //如果有必要可以设置合适的SurfaceType //holder.setType(SurfaceHolder.SURFACE_TYPE_HARDWARE); //设置回调函数 holder.addCallback(this); //创建Gif绘制线程 mGifThread = new GifThread(holder,this); } public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) { //Do nothing } public void surfaceCreated(SurfaceHolder holder) { //当Surface创建成功后,启动绘制线程 mGifThread.setRunning(true); mGifThread.start(); } public void surfaceDestroyed(SurfaceHolder holder) { //当Surface即将摧毁的时候,停止绘制线程 boolean
retry = mGifThread.setRunning(false); while (retry) { try { mGifThread.join(); retry = } catch (InterruptedException e) { // we will try it again and again... } } } } 在代码中都有详细的注释,这里就不再解释,下面是GifThread代码: class GifThread extends Thread { private
SurfaceHolder mSurfaceH private boolean mR private int mCurrentF//当前绘制的帧数 private long mLastT//上一帧绘制的时间 private int mFrameC//总帧数 private Bitmap[] mB//每帧的图片数据 private int[] mD//每帧的显示时间 public GifThread(SurfaceHolder surfaceHolder,
GifView gifView) { mSurfaceHolder = surfaceH GifDecoder mGifDecoder = gifView.mGifD mLastTime = System.currentTimeMillis(); mFrameCount = mGifDecoder.getFrameCount(); mBitmap = new Bitmap[mFrameCount]; mDelay = new int[mFrameCount]; for (int i
= 0; i & mFrameC i++) { mBitmap[i] = mGifDecoder.getFrame(i); mDelay[i] = mGifDecoder.getDelay(i); } mGifDecoder = } public void setRunning(boolean running) { mRunning = } private void doDraw(Canvas canvas) { mLastTime = System.currentTimeMillis();;
canvas.drawBitmap(mBitmap[mCurrentFrame], new Matrix(), null); mCurrentFrame ++; } @Override public void run() { C int delay = 0; while (mRunning) { c = if(mCurrentFrame != 0) { delay = mDelay[mCurrentFrame-1]; } if(mCurrentFrame == mFrameCount)
{ mCurrentFrame = 0; } long currentTime = System.currentTimeMillis(); long t = currentTime - mLastT //如果到下一帧绘制时间开始绘制下一帧 if(t &= delay) { try { //获取Canvas来绘制界面 c = mSurfaceHolder.lockCanvas(null); //通过mSurfaceHolder来同步绘制操作 synchronized (mSurfaceHolder)
{ doDraw(c); } } finally { // 在finally中执行该操作,这样当上面的代码抛出异常的时候 //不会导致Surface出去不一致的状态。 if (c != null) { mSurfaceHolder.unlockCanvasAndPost(c); } } } } } }
最后创建一个Activity来测试下GifView:
public class SurfaceActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new GifView(this,R.raw.pic)); } }
&&&&推荐文章:
【上篇】【下篇】为什么我下面的代码不能实现播放,求大神指导,或者可以的话给我一个关于视频播放的demo,谢谢大家!MainActivity.javapublic class MainActivity extends Activity{private final String TAG="tag";@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);//和页面关联setContentView(R.layout.main_view);//按钮初始化Button btn = (Button)findViewById(R.id.main_btn1);//点击事件,实现页面跳转btn.setOnClickListener(new OnClickListener(){//点击事件@Overridepublic void onClick(View v){//初始化Intent ,用于Android的各种交互信息//第一个参数是上下文参数,第二个参数是目标文件new Thread(){public void run(){Intent intent = new Intent(MainActivity.this,VideoSurfaceActivity.class);//startActivity(intent);MainActivity.this.startActivity(intent);}}.start();}});}}VideoSurfaceActivity.java/** *该实例中使用MediaPlayer完成播放,同时界面使用SurfaceView来实现 *这里我们实现MediaPlayer中很多状态变化时的监听器 *使用Mediaplayer时,也可以使用MediaController类,但是需要实现MediaController.mediaController接口 *实现一些控制方法。 *然后,设置controller.setMediaPlayer(),setAnchorView(),setEnabled(),show()就可以了,这里不再实现 *@author Administrator */ public class VideoSurfaceActivity extends Activity implements OnCompletionListener,OnErrorListener,OnInfoListener, OnPreparedListener, OnSeekCompleteListener,OnVideoSizeChangedListener,SurfaceHolder.Callback{private Display currDprivate SurfaceView surfaceVprivate SurfaceHprivate MediaPprivate int vWidth,vHpublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.video_surface_view);surfaceView = (SurfaceView)this.findViewById(R.id.video_surfaceView1);//给SurfaceView添加CallBack监听 holder = surfaceView.getHolder();holder.addCallback(this);//为了可以播放视频或者使用Camera预览,我们需要指定其Buffer类型 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//下面开始实例化MediaPlayer对象 player = new MediaPlayer();player.setOnCompletionListener(this);player.setOnErrorListener(this);player.setOnInfoListener(this);player.setOnPreparedListener(this);player.setOnSeekCompleteListener(this);player.setOnVideoSizeChangedListener(this);Log.v("Begin:::", "surfaceDestroyed called");//然后指定需要播放文件的路径,初始化MediaPlayerString dataPath = "/29c35d-be3e-64c819e5c177/L.mp4";try{player.setDataSource(dataPath);Log.v("Next:::", "surfaceDestroyed called");}catch (Exception e){e.printStackTrace();}//然后,我们取得当前Display对象 currDisplay = this.getWindowManager().getDefaultDisplay();}@Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3){// 当Surface尺寸等参数改变时触发 Log.v("Surface Change:::", "surfaceChanged called");}@Override public void surfaceCreated(SurfaceHolder holder){// 当SurfaceView中的Surface被创建的时候被调用 ,在这里我们指定MediaPlayer在当前的Surface中进行播放 player.setDisplay(holder);//在指定了MediaPlayer播放的容器后,我们就可以使用prepare或者prepareAsync来准备播放了 player.prepareAsync();}@Override public void surfaceDestroyed(SurfaceHolder holder){}@Override public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2){// 当video大小改变时触发 //这个方法在设置player的source后至少触发一次 Log.v("Video Size Change", "onVideoSizeChanged called");}@Override public void onSeekComplete(MediaPlayer arg0){// seek操作完成时触发 Log.v("Seek Completion", "onSeekComplete called");}@Override public void onPrepared(MediaPlayer player){// 当prepare完成后,该方法触发,在这里我们播放视频 //首先取得video的宽和高 vWidth = player.getVideoWidth();vHeight = player.getVideoHeight();if(vWidth & currDisplay.getWidth() || vHeight & currDisplay.getHeight()){//如果video的宽或者高超出了当前屏幕的大小,则要进行缩放 float wRatio = (float)vWidth/(float)currDisplay.getWidth();float hRatio = (float)vHeight/(float)currDisplay.getHeight();//选择大的一个进行缩放 float ratio = Math.max(wRatio, hRatio);vWidth = (int)Math.ceil((float)vWidth/ratio);vHeight = (int)Math.ceil((float)vHeight/ratio);//设置surfaceView的布局参数 surfaceView.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight));//然后开始播放视频 player.start();}}@Override public boolean onInfo(MediaPlayer player, int whatInfo, int extra){// 当一些特定信息出现或者警告时触发 switch(whatInfo){case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING: case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING: case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
}}@Override public boolean onError(MediaPlayer player, int whatError, int extra){Log.v("Play Error:::", "onError called");switch (whatError){case MediaPlayer.MEDIA_ERROR_SERVER_DIED: Log.v("Play Error:::", "MEDIA_ERROR_SERVER_DIED");case MediaPlayer.MEDIA_ERROR_UNKNOWN: Log.v("Play Error:::", "MEDIA_ERROR_UNKNOWN");default: }}@Override public void onCompletion(MediaPlayer player){// 当MediaPlayer播放完成后触发 Log.v("Play Over:::", "onComletion called");this.finish();}}Player.javapackage com.ltm.main.import java.util.Timport java.util.TimerTimport android.media.AudioMimport android.media.MediaPimport android.media.MediaPlayer.OnBufferingUpdateLimport android.media.MediaPlayer.OnCompletionLimport android.os.Himport android.os.Mimport android.util.Limport android.view.SurfaceHimport android.view.SurfaceVimport android.widget.SeekBpublic class Player implements OnBufferingUpdateListener,
OnCompletionListener, MediaPlayer.OnPreparedListener,
SurfaceHolder.Callback{private int videoWprivate int videoHpublic MediaPlayer mediaPprivate SurfaceHolder surfaceHprivate SeekBar skbPprivate Timer mTimer=new Timer();public Player(SurfaceView surfaceView,SeekBar skbProgress)
{this.skbProgress=skbPsurfaceHolder=surfaceView.getHolder();surfaceHolder.addCallback(this);surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);mTimer.schedule(mTimerTask, 0, 1000);}/******************************************************* *通过定时器和Handler来更新进度条
******************************************************/
TimerTask mTimerTask = new TimerTask(){@Overridepublic void run(){if(mediaPlayer==null)
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 /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 (Exception e){e.printStackTrace();}}public void pause(){ mediaPlayer.pause();}public void stop(){ if (mediaPlayer != null){
mediaPlayer.stop();mediaPlayer.release();mediaPlayer =}}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3){Log.e("mediaPlayer", "surface changed");}@Overridepublic 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");}@Overridepublic 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");}@Overridepublic void onCompletion(MediaPlayer arg0){}@Overridepublic void onBufferingUpdate(MediaPlayer arg0, int bufferingProgress){skbProgress.setSecondaryProgress(bufferingProgress);int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();Log.e(currentProgress+"% play", bufferingProgress + "% buffer");}}Videoplayer.javapublic class Videoplayer extends Activity{private SurfaceView surfaceVprivate Button btnPause, btnPlayUrl, btnSprivate SeekBar skbPprivate P/**Called when the activity is first created. */
@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent intent=getIntent();Bundle bundle=intent.getExtras();String vioUrl=bundle.getString("vioUrl");Log.i("============", vioUrl);}class ClickEvent implements OnClickListener{@Overridepublic void onClick(View arg0){if (arg0 == btnPause){player.pause();
}else if (arg0 == btnPlayUrl){String url="/cdbd2cd7--d0a249/L.mp4";player.playUrl(url);
}else if (arg0 == btnStop){player.stop();
}}}class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener{@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser){// 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()
this.progress = progress *player.mediaPlayer.getDuration()
/ seekBar.getMax();}@Overridepublic void onStartTrackingTouch(SeekBar seekBar){}@Overridepublic void onStopTrackingTouch(SeekBar seekBar){// seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字
player.mediaPlayer.seekTo(progress);}}}main_view.xml&ScrollView xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="wrap_content"&&RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/bkcolor"tools:context="${relativePackage}.${activityClass}" &&Buttonandroid:id="@+id/main_btn1"android:layout_width="match_parent"android:layout_height="50dp"android:text="播放" /&&/RelativeLayout&&/ScrollView&main.xml&?xml version="1.0" encoding="utf-8"?&
&FrameLayout xmlns:android="/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&
未来,加油!
一共有4个java文件,2个XML文件!希望知道如何播放视频的指导一下!网上找的资料都不能用!要求是播放网络视频!
你还没有登录,请先登录或注册慕课网帐号
34255人关注
Copyright (C)
All Rights Reserved | 京ICP备 号-2

我要回帖

更多关于 surface holder 的文章

 

随机推荐