前言:
昨天總結了視訊錄製,今天來學習一下視訊的播放,Android的視訊播放主要採用MediaPlayer類。
MediaPlayer介紹
MediaPlayer類可用於控制音訊/視訊檔案或流的播放。
MediaPlayer函式
1.)例項化方式
使用直接new的方式:
MediaPlayer mp = new MediaPlayer();
使用create的方式
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);
2.)設定播放源
setDataSource(String path)//指定裝載path路徑所代表的檔案。 setDataSource(Context context, Uri uri, Map<String, String headers)//指定裝載uri所代表的檔案。 setDataSource(Context context, Uri uri)//指定裝載uri所代表的檔案。 setDataSource(FileDescriptor fd, long offset, long length)//指定裝載fd所代表的檔案中從offset開始長度為length的檔案內容。 setDataSource(FileDescriptor fd)//指定裝載fd所代表的檔案。
3.)配置播放引數
setAudioStreamType(int streamtype)//設定音訊流的型別。 setDisplay(SurfaceHolder sh)//設定顯示方式。 setLooping(boolean looping)//設定是否迴圈播放。 setNextMediaPlayer(MediaPlayer next)//設定當前流媒體播放完畢,下一個播放的MediaPlayer。 setScreenOnWhilePlaying(boolean screenOn)//設定是否使用SurfaceHolder來顯示。 setSurface(Surface surface)//設定Surface。 setVideoScalingMode(int mode)//設定視訊縮放的模式。 setVolume(float leftVolume, float rightVolume)//設定播放器的音量。 setWakeMode(Context context, int mode)//為MediaPlayer設定低階電源管理行為。
4.)播放控制函式
start()//開始或恢復播放。 stop()//停止播放。 pause()//暫停播放。 prepare()//準備播放(裝載音訊),呼叫此方法會使MediaPlayer進入Prepared狀態。 prepareAsync()//準備播放非同步音訊。 release()//釋放媒體資源 reset()//重置MediaPlayer進入未初始化狀態。 seekTo(int msec)//指定的時間位置。
5.)監聽事件函式
setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)//註冊一個回撥函式,在網路視訊流緩衝變化時呼叫。 setOnCompletionListener(MediaPlayer.OnCompletionListener listener)//為Media Player的播放完成事件繫結事件監聽器。 setOnErrorListener(MediaPlayer.OnErrorListener listener)//為MediaPlayer的播放錯誤事件繫結事件監聽器。 setOnPreparedListener(MediaPlayer.OnPreparedListener listener)//當MediaPlayer呼叫prepare()方法時觸發該監聽器。 setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener)//當MediaPlayer呼叫seek()方法時觸發該監聽器。 setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)//註冊一個用於監聽視訊大小改變的監聽器。
6.)獲取引數函式
getCurrentPosition()//獲取當前播放的位置。 getDuration()//獲取音訊的時長。 getVideoHeight()//獲取視訊的高度。 getVideoWidth()//獲取視訊的寬度。 isLooping()//判斷MediaPlayer是否正在迴圈播放。 isPlaying()//判斷MediaPlayer是否正在播放。
MediaPlayer音視訊播放示例
1.)新增許可權
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2.)視訊播放簡單示例
public class MediaPlayerActivity extends Activity implements SurfaceHolder.Callback, View.OnClickListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener { private MediaPlayer player; private SurfaceView surface; private SurfaceHolder surfaceHolder; private Button play, pause, stop; private SeekBar seekBar; private String videoPath; private int seekProgress; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_media_player); initParams(); initViews(); } private void initParams() { videoPath = getIntent().getStringExtra("videoPath"); } private void initViews() { play = (Button) findViewById(R.id.btn_play); pause = (Button) findViewById(R.id.btn_pause); stop = (Button) findViewById(R.id.btn_stop); seekBar = (SeekBar) findViewById(R.id.skb_video); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { seekProgress = progress * player.getDuration() / seekBar.getMax(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { seekTo(seekProgress); } }); surface = (SurfaceView) findViewById(R.id.video_surface); surfaceHolder = surface.getHolder(); surfaceHolder.setFormat(PixelFormat.TRANSPARENT); surfaceHolder.setKeepScreenOn(true); surfaceHolder.addCallback(this); play.setOnClickListener(this); pause.setOnClickListener(this); stop.setOnClickListener(this); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } @Override public void surfaceCreated(SurfaceHolder arg0) { autoPlay(); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { stop(); release(); } @Override protected void onDestroy() { super.onDestroy(); stop(); release(); } /** * 自動播放 */ private void autoPlay() { //必須在surface建立後才能初始化MediaPlayer,否則不會顯示影像 player = new MediaPlayer(); player.setAudioStreamType(AudioManager.STREAM_MUSIC); //設定顯示視訊顯示在SurfaceView上 player.setDisplay(surfaceHolder); try { player.setDataSource(videoPath); player.setOnPreparedListener(this); player.setOnCompletionListener(this); player.setOnBufferingUpdateListener(this); player.prepare(); } catch (Exception e) { e.printStackTrace(); } } /** * 開始播放 */ private void start() { if (player == null || player.isPlaying()) { return; } player.start(); } /** * 暫停播放 */ private void pause() { if (player == null || player.isPlaying()) { return; } player.pause(); } /** * 停止播放 */ private void stop() { if (player == null || player.isPlaying()) { return; } player.stop(); } /** * 釋放資源 */ private void release() { if (player == null) { return; } player.release(); } /** * 重置播放器 */ private void reset() { if (player == null) { return; } player.reset(); } /** * 指定位置播放 * * @param pos */ private void seekTo(int pos) { if (player == null) { return; } player.seekTo(pos); start(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_play: start(); break; case R.id.btn_pause: pause(); break; case R.id.btn_stop: stop(); break; } } @Override public void onPrepared(MediaPlayer mp) { start(); } @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { seekBar.setSecondaryProgress(percent); int currentProgress = seekBar.getMax() * player.getCurrentPosition() / player.getDuration(); Log.e("currentProgress", "currentProgress----->" + currentProgress); } @Override public void onCompletion(MediaPlayer mp) { seekBar.setProgress(0); } }
3.)佈局檔案
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <SurfaceView android:id="@+id/video_surface" android:layout_width="match_parent" android:layout_height="0dp" android:layout_gravity="center" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:orientation="vertical"> <SeekBar android:id="@+id/skb_video" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_margin="10dp" android:max="100" android:focusable="true" android:maxHeight="4.0dip" android:minHeight="4.0dip" android:paddingLeft="16.0dip" android:paddingRight="16.0dip" android:thumb="@drawable/seekbar_thumb" android:progressDrawable="@drawable/po_seekbar" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:layout_margin="10dp" android:gravity="center" android:orientation="horizontal"> <Button android:id="@+id/btn_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="播放" /> <Button android:id="@+id/btn_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="暫停" /> <Button android:id="@+id/btn_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="停止" /> </LinearLayout> </LinearLayout> </LinearLayout>
4.)播放音訊簡單示例
if (player == null) { player = new MediaPlayer(); player.setDataSource(url); player.setVolume(0.7f, 0.7f); player.setAudioStreamType(AudioManager.STREAM_MUSIC); player.prepare(); player.start(); player.setOnCompletionListener(completionListener); player.setOnErrorListener(errorListener); return true; }
5.)知識擴充套件
用上面的示例只能播放部分片源,有些片源會播放不了,所以我公司專案後來未採用原生的MediaPlayer進行視訊播放。這裡推薦大家使用B站開源視訊播放解決方案ijkplayer。地址:https://github.com/Bilibili/