Android使用MediaPlayer和TextureView實現(xiàn)視頻無縫切換
需求描述
比如廣告播放,每個視頻15秒,視頻之間切換的時候,性能不太好的機器可能會黑屏一段時間,體驗不太好,接下來我們就是要解決這個黑屏問題。
解決方案
使用兩個surfaceView方式,經(jīng)過測試不行
使用一個MediaPlayer,在MediaPlayer上面加一層ImageView,每次播放完成后,獲取視頻的最后一幀的圖像給ImageView,視頻切換完成,ImageView隱藏,如此往復循環(huán),可行
實踐
1.獲取視頻流圖片方式,通過MediaMetadataRetriever,測試發(fā)現(xiàn),部分機器獲取的Bitmap可能為空,無法解決,放棄
2.使用TextureView方式,可以獲取當前幀的Bitmap,可行,下面貼代碼
package com.winson.blog.video;
import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.io.IOException;
public class VideoFragment extends Fragment {
public static final String TAG = VideoFragment.class.getSimpleName();
String TEST_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/testmp4.mp4";
int mIndex = 0;
String path1 = TEST_PATH;
String[] paths = new String[]{TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH};
boolean destory;
Handler mHandler;
Runnable mPlayRun;
FrameLayout content;
TextureView textureView;
ImageView frameImage;
MediaPlayer mediaPlayer;
Bitmap lastFrameBitmap;
public void updateResources(String[] paths) {
this.paths = paths;
if(mHandler != null && mPlayRun!= null){
mHandler.post(mPlayRun);
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
mediaPlayer = new MediaPlayer();
mPlayRun = new Runnable() {
@Override
public void run() {
if (mediaPlayer == null || destory) {
return;
}
mediaPlayer.pause();
mediaPlayer.reset();
try {
String path = paths[mIndex % paths.length];
mIndex++;
mediaPlayer.setDataSource(getActivity(), Uri.parse(path));
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer arg0) {
mediaPlayer.start();
frameImage.setVisibility(View.GONE);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
frameImage.setVisibility(View.VISIBLE);
Bitmap currentFrameBitmap = textureView.getBitmap();
frameImage.setImageBitmap(currentFrameBitmap);
if (lastFrameBitmap != null) {
lastFrameBitmap.recycle();
}
lastFrameBitmap = currentFrameBitmap;
mHandler.post(mPlayRun);
}
});
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
public void release() {
mHandler.removeCallbacks(mPlayRun);
if (mediaPlayer != null) {
mediaPlayer.pause();
mediaPlayer.release();
}
}
public Bitmap getBitmap() {
return textureView == null ? null : textureView.getBitmap();
}
@Override
public void onDestroy() {
super.onDestroy();
release();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
content = new FrameLayout(getActivity());
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
lp.gravity = Gravity.LEFT | Gravity.TOP;
textureView = new TextureView(getActivity());
textureView.setLayoutParams(lp);
content.addView(textureView);
frameImage = new ImageView(getActivity());
frameImage.setScaleType(ImageView.ScaleType.FIT_XY);
frameImage.setLayoutParams(lp);
content.addView(frameImage);
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Surface s = new Surface(surface);
mediaPlayer.setSurface(s);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
return content;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
testPlay();
}
public void testPlay() {
// mediaPlayer.pause();
// mediaPlayer.reset();
//
// try {
// mediaPlayer.setDataSource(getActivity(), Uri.parse(TEST_PATH));
// mediaPlayer.prepare();
// mediaPlayer.start();
// } catch (IOException e) {
// e.printStackTrace();
// }
mHandler.post(mPlayRun);
}
}
相關(guān)鏈接,github地址
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持我們。
上一篇:Android MediaPlayer 音頻倍速播放 調(diào)整播放速度問題
欄 目:Android
下一篇:Android MediaPlayer 播放音頻的方式
本文標題:Android使用MediaPlayer和TextureView實現(xiàn)視頻無縫切換
本文地址:http://www.jygsgssxh.com/a1/Android/9170.html
您可能感興趣的文章
- 01-10Android自定義View之繪制圓形頭像功能
- 01-10Android實現(xiàn)雙擊返回鍵退出應用實現(xiàn)方法詳解
- 01-10android實現(xiàn)記住用戶名和密碼以及自動登錄
- 01-10android實現(xiàn)簡單計算器功能
- 01-10Android 友盟第三方登錄與分享的實現(xiàn)代碼
- 01-10android實現(xiàn)指紋識別功能
- 01-10Emoji表情在Android JNI中的兼容性問題詳解
- 01-10Android實現(xiàn)圓形漸變加載進度條
- 01-10android開發(fā)環(huán)境中SDK文件夾下的所需內(nèi)容詳解
- 01-10android異步消息機制 源碼層面徹底解析(1)


閱讀排行
本欄相關(guān)
- 01-10Android自定義View之繪制圓形頭像功能
- 01-10Android實現(xiàn)雙擊返回鍵退出應用實現(xiàn)方
- 01-10android實現(xiàn)簡單計算器功能
- 01-10android實現(xiàn)記住用戶名和密碼以及自動
- 01-10C++自定義API函數(shù)實現(xiàn)大數(shù)相乘算法
- 01-10Android 友盟第三方登錄與分享的實現(xiàn)代
- 01-10android實現(xiàn)指紋識別功能
- 01-10如何給Flutter界面切換實現(xiàn)點特效
- 01-10Android實現(xiàn)圓形漸變加載進度條
- 01-10Emoji表情在Android JNI中的兼容性問題詳
隨機閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10C#中split用法實例總結(jié)
- 01-10使用C語言求解撲克牌的順子及n個骰子


