Android使用MediaPlayer和TextureView实现视频无缝切换
需求描述
比如广告播放,每个视频15秒,视频之间切换的时候,性能不太好的机器可能会黑屏一段时间,体验不太好,接下来我们就是要解决这个黑屏问题。
解决方案
使用两个surfaceView方式,经过测试不行
使用一个MediaPlayer,在MediaPlayer上面加一层ImageView,每次播放完成后,获取视频的最后一帧的图像给ImageView,视频切换完成,ImageView隐藏,如此往复循环,可行
实践
1.获取视频流图片方式,通过MediaMetadataRetriever,测试发现,部分机器获取的Bitmap可能为空,无法解决,放弃
2.使用TextureView方式,可以获取当前帧的Bitmap,可行,下面贴代码
packagecom.winson.blog.video;
importandroid.graphics.Bitmap;
importandroid.graphics.SurfaceTexture;
importandroid.media.MediaPlayer;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.os.Environment;
importandroid.os.Handler;
importandroid.support.annotation.Nullable;
importandroid.support.v4.app.Fragment;
importandroid.util.Log;
importandroid.view.Gravity;
importandroid.view.LayoutInflater;
importandroid.view.Surface;
importandroid.view.TextureView;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.FrameLayout;
importandroid.widget.ImageView;
importjava.io.IOException;
publicclassVideoFragmentextendsFragment{
publicstaticfinalStringTAG=VideoFragment.class.getSimpleName();
StringTEST_PATH=Environment.getExternalStorageDirectory().getAbsolutePath()+"/testmp4.mp4";
intmIndex=0;
Stringpath1=TEST_PATH;
String[]paths=newString[]{TEST_PATH,TEST_PATH,TEST_PATH,TEST_PATH,TEST_PATH,TEST_PATH};
booleandestory;
HandlermHandler;
RunnablemPlayRun;
FrameLayoutcontent;
TextureViewtextureView;
ImageViewframeImage;
MediaPlayermediaPlayer;
BitmaplastFrameBitmap;
publicvoidupdateResources(String[]paths){
this.paths=paths;
if(mHandler!=null&&mPlayRun!=null){
mHandler.post(mPlayRun);
}
}
@Override
publicvoidonCreate(@NullableBundlesavedInstanceState){
super.onCreate(savedInstanceState);
mHandler=newHandler();
mediaPlayer=newMediaPlayer();
mPlayRun=newRunnable(){
@Override
publicvoidrun(){
if(mediaPlayer==null||destory){
return;
}
mediaPlayer.pause();
mediaPlayer.reset();
try{
Stringpath=paths[mIndex%paths.length];
mIndex++;
mediaPlayer.setDataSource(getActivity(),Uri.parse(path));
mediaPlayer.setOnPreparedListener(newMediaPlayer.OnPreparedListener(){
@Override
publicvoidonPrepared(MediaPlayerarg0){
mediaPlayer.start();
frameImage.setVisibility(View.GONE);
}
});
mediaPlayer.setOnCompletionListener(newMediaPlayer.OnCompletionListener(){
@Override
publicvoidonCompletion(MediaPlayermp){
frameImage.setVisibility(View.VISIBLE);
BitmapcurrentFrameBitmap=textureView.getBitmap();
frameImage.setImageBitmap(currentFrameBitmap);
if(lastFrameBitmap!=null){
lastFrameBitmap.recycle();
}
lastFrameBitmap=currentFrameBitmap;
mHandler.post(mPlayRun);
}
});
mediaPlayer.prepareAsync();
}catch(Exceptione){
e.printStackTrace();
}
}
};
}
publicvoidrelease(){
mHandler.removeCallbacks(mPlayRun);
if(mediaPlayer!=null){
mediaPlayer.pause();
mediaPlayer.release();
}
}
publicBitmapgetBitmap(){
returntextureView==null?null:textureView.getBitmap();
}
@Override
publicvoidonDestroy(){
super.onDestroy();
release();
}
@Nullable
@Override
publicViewonCreateView(LayoutInflaterinflater,@NullableViewGroupcontainer,@NullableBundlesavedInstanceState){
content=newFrameLayout(getActivity());
FrameLayout.LayoutParamslp=newFrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT);
lp.gravity=Gravity.LEFT|Gravity.TOP;
textureView=newTextureView(getActivity());
textureView.setLayoutParams(lp);
content.addView(textureView);
frameImage=newImageView(getActivity());
frameImage.setScaleType(ImageView.ScaleType.FIT_XY);
frameImage.setLayoutParams(lp);
content.addView(frameImage);
textureView.setSurfaceTextureListener(newTextureView.SurfaceTextureListener(){
@Override
publicvoidonSurfaceTextureAvailable(SurfaceTexturesurface,intwidth,intheight){
Surfaces=newSurface(surface);
mediaPlayer.setSurface(s);
}
@Override
publicvoidonSurfaceTextureSizeChanged(SurfaceTexturesurface,intwidth,intheight){
}
@Override
publicbooleanonSurfaceTextureDestroyed(SurfaceTexturesurface){
returnfalse;
}
@Override
publicvoidonSurfaceTextureUpdated(SurfaceTexturesurface){
}
});
returncontent;
}
@Override
publicvoidonActivityCreated(@NullableBundlesavedInstanceState){
super.onActivityCreated(savedInstanceState);
testPlay();
}
publicvoidtestPlay(){
//mediaPlayer.pause();
//mediaPlayer.reset();
//
//try{
//mediaPlayer.setDataSource(getActivity(),Uri.parse(TEST_PATH));
//mediaPlayer.prepare();
//mediaPlayer.start();
//}catch(IOExceptione){
//e.printStackTrace();
//}
mHandler.post(mPlayRun);
}
}
相关链接,github地址
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。