使用SurfaceView&MediaPlayer播放視訊
阿新 • • 發佈:2019-01-08
SurfaceView
個人理解:SurfaceView跟普通的如TextView、Button等不一樣,它跟它的檢視容器並不是在同一個檢視層上,它的 UI 顯示也可以不在一個獨立的執行緒中完成,所以對 SurfaceView 的繪製並不會影響到主執行緒的執行。如果需要在另外的執行緒繪製介面或者渲染UI介面需要較長時間則可以選擇使用SurfaceView。
使用SurfaceView常與SurfaceHolder 及surfaceHolder.callback一塊使用 還可以例項化一個Runnable 在run方法中繪製View在繪畫開始需要
Canvas mCanvas = mHolder.lockCanvas(); // 獲得畫布物件 。在繪畫結束 時需要
mHolder.unlockCanvasAndPost(mCanvas); // 完成畫畫,把畫布顯示在螢幕。
private SurfaceHolder mSurfaceHolder;
private SurfaceView mSurfaceView;
mSurfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new HoldCallback());
private class HoldCallback implements SurfaceHolder .Callback {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//當Surface尺寸等引數改變時觸發
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//此處耗時操作的開始
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
//耗時操作結束釋放資源等
}
}
MediaPlayer
MediaPlayer的API
談起MediaPlayer不看安卓關於播放的圖就說不過去
MediaPlayer關於播放器所有的操作按照這張圖。能用程式碼解決的不廢話。
說明:
- 每一個方法的呼叫必須在MediaPlayer特定的狀態中prepareAsync()在{Idle, Prepared, Started, Paused, PlaybackCompleted, Error}就會出錯;
- MediaPlayer在執行播放動作前必須指定載入視訊的SurfaceHolder mMediaPlayer.setDisplay(mSurfaceHolder);否者就會只有聲音而沒有影象,同時也需要設定這個媒體播放器的音訊流型別mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);且這個方法必須在prepareAsync(),或者prepare();方法前。
- 可能用到的方法getDuration();//獲取視訊時長、getCurrentPosition();//當前播放的時間seekTo(int msec) //選擇時段播放
- 載入字幕mMediaPlayer.addTimedTextSource(path, MediaPlayer.MEDIA_MIMETYPE_TEXT_SUBRIP);
- 獲取視訊的縮圖Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Video.Thumbnails.MINI_KIND); - 從ContentResolver 中獲取視訊列表傳入合適的URI即可,如:Media.EXTERNAL_CONTENT_URI 、Media.INTERNAL_CONTENT_URI
public final Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
return query(uri, projection, selection, selectionArgs, sortOrder, null);
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/ll_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#33000000"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingTop="10dp" >
<LinearLayout
android:id="@+id/img_play"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:gravity="center"
android:visibility="gone" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:src="@mipmap/vedio_play" />
</LinearLayout>
<LinearLayout
android:id="@+id/img_pause"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="30dp"
android:layout_marginStart="30dp"
android:gravity="center"
android:visibility="visible" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:src="@mipmap/zanting" />
</LinearLayout>
<TextView
android:id="@+id/tv_current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:text="00:00"
android:textColor="#ffffff"
android:textSize="14sp" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" >
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
<LinearLayout
android:id="@+id/iv_resize"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingRight="5dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="bottom"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_duration_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:text="00:00"
android:textColor="#acacac"
android:textSize="14sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:layout_marginRight="10dp"
android:clickable="false"
android:src="@mipmap/quanp" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
package me.itangqi.waveloadingview.view;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
import me.itangqi.waveloadingview.R;
public class MediaPlayerActivity extends AppCompatActivity {
private String TAG = MediaPlayerActivity.class.getSimpleName();
private SurfaceHolder mSurfaceHolder;
private SurfaceView mSurfaceView;
private MediaPlayer mMediaPlayer;
private SeekBar mSeekBar;
private static final int MESSAGE_UPDATE_TIME = 0x01;
private TextView mDurationTime ;
private TextView mCurrentTime ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_media_player);
initView();
}
private void initView() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // 螢幕常亮
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new HoldCallback());
mSeekBar = (SeekBar) findViewById(R.id.seekbar);
mDurationTime = (TextView) findViewById(R.id.tv_duration_time);
mCurrentTime= (TextView) findViewById(R.id.tv_current_time);
seekBarListener();
}
private class HoldCallback implements SurfaceHolder.Callback {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i(TAG, "--surfaceChanged");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "--surfaceCreated");
String path = Environment.getExternalStorageDirectory().getPath()+"/yimaoshow/media/local/yimaosl.mp4";
initMedia();
if (mSurfaceHolder.getSurface().isValid()) {
mMediaPlayer.reset();
try {
// 設定音樂流
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 設定播入檔案地址
mMediaPlayer.setDataSource(path);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.prepareAsync();
} catch (IOException e) {
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "--surfaceDestroyed");
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.release();
Log.d("VideoSurfaceView", "mMediaPlayer release");
}
mMediaPlayer = null;
}
}
}
private void initMedia() {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
});
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.i(TAG, "視訊播放中發生錯誤" + "what:"+what +"extra"+extra);
return false;
}
});
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.i(TAG, "視訊裝載完畢");
if (mMediaPlayer != null) {
mMediaPlayer.start();
mSeekBar.setMax(mMediaPlayer.getDuration());
mDurationTime.setText(mMediaPlayer.getDuration()/1000+"");
updateTime();
}
}
});
}
}
private void updateTime() {
if (mMediaPlayer != null) {
mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());
mHandler.sendEmptyMessageDelayed(MESSAGE_UPDATE_TIME, 1000);
mCurrentTime.setText(mMediaPlayer.getCurrentPosition()/1000 +"");
}
}
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MESSAGE_UPDATE_TIME:
updateTime();
break;
}
}
};
private void seekBarListener() {
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mMediaPlayer.seekTo(seekBar.getProgress());
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
});
}
}