2019年10月23日 星期三

[Android]Android SurfaceView + MediaPlayer實作 (Android studio + API28)

SurfaceView簡介
1.SurfaceView 就是自帶Surface 的 view,他是一個View的子類別,所以和其他 View一樣,可以在螢幕上展是東西接收用戶輸入資訊,具有 View 的生命周期call back function,如 onMeasure、onLayout、onDraw、onTouchEvent 等

2.SurfaceView在子線程(叫做渲染線程)中對Surface進行繪製,將繪製好的畫面呈現給View,不會影響主線程與用戶的交互操作

3.SurfaceView採用雙緩衝技術,繪製效率高

SurfaceView是在一個新起的单独线程中可以重新繪製畫面,而View必须在UI的主线程中更新画面。如果长时间在UI線程進行化畫面更新,可能会阻塞UI線程,導致UI的按键,触摸等不能得到及时响应,而如果在子线程中进行不断的画面更新操作则不会影响主线程。所以当涉及到UI的快速刷新时就需要用到SurfaceView(如游戏,视频等)
引用 : https://www.jianshu.com/p/f7c3299c3576

SurfaceHolder
SurfaceHolder是一个接口,是对 SurfaceView 的 Surface 的包装,不但在 SurfaceHolder.callback 接口中负责 Surface 创建和销毁的回调,而且还对 Surface 的关键方法 LockCanvas()、unLockCanvasAndPost() 方法进行了线程安全的包装,所以 SurfaceHolder 是 Surface 对象的持有者,负责 Surface 的生命周期中的对 Surface 操作的方法的调用

SurfaceView创建
新建一个类继承自SurfaceView并实现SurfaceHolder.Callback接口,然后重写以下方法:
(1)在surface创建时触发
public void surfaceCreated(SurfaceHolder holder) { }
(2)在surface大小发生改变时触发
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
(3)在surface销毁时触发
public void surfaceDestroyed(SurfaceHolder holder) { }

Surfaceview使用過程:繼承SurfaceView並實現SurfaceHolder.Callback的interface ----> SurfaceView.getHolder()獲得SurfaceHolder對象 ---->SurfaceHolder.addCallback(callback)添加回调函数---->SurfaceHolder.lockCanvas()獲得Canvas對像並鎖定畫布----> Canvas绘画 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束鎖定畫圖,並提交改變,將圖型顯示。


以上SurfaceView介紹後接著介紹SurfaceView新增的流程順序
1.find SurfaceView id
2.getHolder()
3.Holder add Callback


Layout xml

    android:id="@+id/outside_view"    android:layout_width="2560px"    android:layout_height="600px"    app:layout_constraintLeft_toLeftOf="@id/cluster_layout_background"    app:layout_constraintTop_toTopOf="@id/cluster_layout_background"    android:layout_marginTop="0px"    android:layout_marginLeft="0px"    />


import階段

import android.media.MediaPlayer;


程式宣告階段

public class MainActivity extends AppCompatActivity implements 
MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, 
MediaPlayer.OnErrorListener, SurfaceHolder.Callback {

變數宣告階段

private String mFilePath = "";private MediaPlayer mOutviewPlayer;private SurfaceView mSurfaceView_outside;private SurfaceHolder mSurfaceHolder_outside;

function宣告階段

@Overridepublic void surfaceCreated(SurfaceHolder holder) {
    if(DBG)
        Log.d(LOG_TAG, "surfaceCreated");    mOutviewPlayer = new MediaPlayer();    mOutviewPlayer.setDisplay(mSurfaceHolder_outside);    try {
        String file_common_dir  = Environment.getExternalStorageDirectory() + "/Download/";        mFilePath = file_common_dir + "outview.mp4";        mOutviewPlayer.setDataSource(mFilePath);        mOutviewPlayer.setLooping(true);        mOutviewPlayer.prepare();        mOutviewPlayer.start();        if(DBG)
            Log.d(LOG_TAG, "[KH]Video is playing.");    } catch (Exception e) {
        e.printStackTrace();    }
}

@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
   Log.e("video","surfaceChanged");}

@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {
    Log.e("video","surfaceDestroyed");    super.onDestroy();}

onCreate宣告階段

mSurfaceView_outside = (SurfaceView)findViewById(R.id.outside_view);mSurfaceHolder_outside = mSurfaceView_outside.getHolder(); // mSurfaceHolder_outside是mSurfaceView_outside的控制接口mSurfaceHolder_outside.addCallback(this);

onDestory宣告階段

@Overrideprotected void onDestroy() {
    super.onDestroy();    if (mOutviewPlayer.isPlaying()) {
        mOutviewPlayer.stop();    }
    mOutviewPlayer.release();}

打完收工

沒有留言:

張貼留言