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 MediaPlayer
simple 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
prepareAsync
Get 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 MediaExtractor
through a method . The object can be obtained internally , but in the actual source code, it will be found that the return is empty.getTrackFormat
TrackInfo
MediaFormat
MediaFormat
public MediaFormat getFormat() {
if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
|| mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
return mFormat;
}
return null;
}
复制代码
Therefore, if MediaPlayer
the resource file cannot be directly obtained using internal estimation, it can only be obtained MediaExtractor
externally.
start fails after pause
It can be seen from the MediaPlayer
sequence diagram that the method is called. If it is called , there is no problem in calling pause
it again . start
If the timing is in stop
, the method must be re-executed prepare
to wait for the resource to be re-prepared before playing.
- Question 1
The problem encountered in actual development is that when the player is Activity
in the background, Activity
the method of the life cycle will be called onStop
, because MediaPlayer
the life cycle and the page are bound and also called stop
. Finally, I know where the reason is. MediaPlayer
It is currently in the stop
state, so I have to replay it for the MediaPlayer
execution prepare
method.
Problem 1 is to solve the problem that the player can replay the resource after returning to the background, but the binding SurfaceView
is a black screen.
- Question 2
The binding SurfaceView
black screen situation is essentially similar to question 1. Because there SurfaceView
is also a life cycle, when it is Activity
called in the background surfaceDestroyed
, the original SurfaceView
binding to the player Surface
has expired and needs to be re-bound.
The original logic is post
to initialize and bind only once in the method, so it seems post
inappropriate 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 surfaceView
the callback method of , so as to ensure that the binding can be refreshed every time the page is entered from the background.surfaceCreated
Surface
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
MediaPlayer
Another problem is that there is no playback progress callback interface provided. Although MediaPlayer
there is a getCurrentPosition
method 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 Thread
continuously calling the player getCurrentPosition
method 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
MediaPlayer
Although 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, MediaPlayer
and there are still some underlying capabilities that you can dig deeper into.