Android Audio and Video Development Series - Summary of MediaPlayer Development Issues

Get into the habit of writing together! This is the second day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

foreword

After the implementation of MediaPlayersimple use, there are still many problems in actual development. Here, the problems are summarized to record the reasons and solutions. It is a development summary.

Summary of problems

TrackInfo resource information query

prepareAsyncGet the resource TrackInfo in the callback method after loading the resource and executing the method during development. It was originally expected to obtain video size information through this method, for example, to obtain resource information MediaExtractorthrough a method . The object can be obtained internally , but in the actual source code, it will be found that the return is empty.getTrackFormatimage.png TrackInfoMediaFormatMediaFormat

public MediaFormat getFormat() {
    if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
            || mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
        return mFormat;
    }
    return null;
}
复制代码

Therefore, if MediaPlayerthe resource file cannot be directly obtained using internal estimation, it can only be obtained MediaExtractorexternally.

start fails after pause

image.pngIt can be seen from the MediaPlayersequence diagram that the method is called. If it is called , there is no problem in calling pauseit again . startIf the timing is in stop, the method must be re-executed prepareto wait for the resource to be re-prepared before playing.

  • Question 1

The problem encountered in actual development is that when the player is Activityin the background, Activitythe method of the life cycle will be called onStop, because MediaPlayerthe life cycle and the page are bound and also called stop. Finally, I know where the reason is. MediaPlayerIt is currently in the stopstate, so I have to replay it for the MediaPlayerexecution preparemethod.

Problem 1 is to solve the problem that the player can replay the resource after returning to the background, but the binding SurfaceViewis a black screen.

  • Question 2

The binding SurfaceViewblack screen situation is essentially similar to question 1. Because there SurfaceViewis also a life cycle, when it is Activitycalled in the background surfaceDestroyed, the original SurfaceViewbinding to the player Surfacehas expired and needs to be re-bound.

The original logic is postto initialize and bind only once in the method, so it seems postinappropriate to bind only in the method.

surfaceView.post(new Runnable() {
    @Override
    public void run() {
        AndroidMediaPlayer.Builder builder = new AndroidMediaPlayer.Builder(TestSimpleMediaPlayerActivity.this,uri,listener);
        builder.withSurface(surfaceView.getHolder().getSurface());
        androidMediaPlayer = builder.createPlayer();
        androidMediaPlayer.prepareAsync();
    }
});
复制代码

Binding work is performed from surfaceViewthe callback method of , so as to ensure that the binding can be refreshed every time the page is entered from the background.surfaceCreatedSurface

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        if(androidMediaPlayer != null)
        androidMediaPlayer.setSurface(surfaceView.getHolder().getSurface());
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
        Log.d("<> surfaceView","surfaceChanged");

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
        Log.d("<> surfaceView","surfaceDestroyed");
    }
});
复制代码
  • Question 3

MediaPlayerAnother problem is that there is no playback progress callback interface provided. Although MediaPlayerthere is a getCurrentPositionmethod to obtain the current playback progress, it cannot be encapsulated to provide the ability to achieve real-time acquisition, so developers need to implement the method of real-time acquisition by themselves.

The current playback millisecond value can be obtained by Threadcontinuously calling the player getCurrentPositionmethod in a loop, and delay processing can also be added according to actual business needs.

private class PlayerThread extends Thread{
    private boolean toGet = false;
    public void startGet(){
        toGet = true;
    }
    public void stopGet(){
        toGet = true;
    }
    @Override
    public void run() {
        super.run();
        while (toGet){
            if(mMediaPlayer != null){
               int position =  mMediaPlayer.getCurrentPosition();
               if(mListener != null){
                   playerInfo.playerProgress = position;
                   mListener.onPlayerInfoCallBack(playerInfo);
               }
            }
        }
    }
}
复制代码

Summarize

MediaPlayerAlthough it is simple to use, some details will still be exposed in the implementation development. If you really want to develop and implement the complete player function, you still need to improve and consider many functional scenarios, MediaPlayerand there are still some underlying capabilities that you can dig deeper into.

Guess you like

Origin juejin.im/post/7084556894094196743