Serie de desarrollo de audio y video de Android: resumen de problemas de desarrollo de MediaPlayer

¡Acostúmbrate a escribir juntos! Este es el segundo día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .

prefacio

Después de la implementación del MediaPlayeruso simple, todavía hay muchos problemas en el desarrollo real. Aquí, los problemas se resumen para registrar las razones y soluciones. Es un resumen del desarrollo.

Resumen de problemas

Consulta de información de recursos de TrackInfo

prepareAsyncObtenga el recurso TrackInfo en el método de devolución de llamada después de cargar el recurso y ejecutar el método durante el desarrollo. Originalmente se esperaba obtener información de tamaño de video a través de este método, por ejemplo, para obtener información de recursos a MediaExtractortravés de un método . El objeto se puede obtener internamente , pero en el código fuente real, se encontrará que el retorno está vacío.getTrackFormatimagen.png TrackInfoMediaFormatMediaFormat

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

Por lo tanto, si MediaPlayerel archivo de recursos no se puede obtener directamente mediante estimación interna, solo se puede obtener MediaExtractorexternamente.

el inicio falla después de la pausa

imagen.pngEn el MediaPlayerdiagrama de secuencia se puede ver que se llama al método, si se llama no hay problema en pausevolver a llamarlo. startSi el tiempo está en stop, el método debe volver a ejecutarse preparepara esperar a que el recurso se vuelva a preparar antes de jugar.

  • Pregunta 1

El problema encontrado en el desarrollo real es que cuando el reproductor está Activityen segundo plano, Activityel método del ciclo de vida se llama onStop, porque MediaPlayerel ciclo de vida y la página están vinculados y también se llaman stop. Finalmente, sé dónde está el motivo . MediaPlayerActualmente se encuentra en el stopestado, por lo que tengo que reproducirlo para el método de MediaPlayerejecución .prepare

El problema 1 es resolver el problema de que el jugador puede reproducir el recurso después de regresar al fondo, pero el enlace SurfaceViewes una pantalla negra.

  • Pregunta 2

La situación de la pantalla negra vinculante SurfaceViewes esencialmente similar a la pregunta 1. Debido a que SurfaceViewtambién hay un ciclo de vida, cuando se Activityllama en segundo plano surfaceDestroyed, la SurfaceViewvinculación original con el reproductor Surfaceha caducado y debe volver a vincularse.

La lógica original es postinicializar y enlazar solo una vez en el método, por lo que parece postinapropiado enlazar solo en el método.

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();
    }
});
复制代码

El trabajo de enlace se realiza desde surfaceViewel método de devolución de llamada de , para garantizar que el enlace se pueda actualizar cada vez que se ingrese a la página desde el fondo.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");
    }
});
复制代码
  • Pregunta 3

MediaPlayerOtro problema es que no se proporciona una interfaz de devolución de llamada de progreso de reproducción. Aunque MediaPlayerexiste un getCurrentPositionmétodo para obtener el progreso de reproducción actual, no se puede encapsular para brindar la capacidad de obtener acceso en tiempo real, por lo que los desarrolladores deben implementar el método de acceso en tiempo real por sí mismos.

El valor de milisegundos de reproducción actual se puede obtener Threadllamando continuamente al getCurrentPositionmétodo del jugador en un bucle.Además, se puede agregar el procesamiento de demora de acuerdo con las necesidades comerciales reales.

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);
               }
            }
        }
    }
}
复制代码

Resumir

MediaPlayerAunque es simple de usar, aún se expondrán algunos detalles en el desarrollo de la implementación. Si realmente desea desarrollar e implementar la función completa del reproductor, aún necesita mejorar y considerar muchos escenarios funcionales, MediaPlayery todavía hay algunas capacidades subyacentes en las que puede profundizar.

Supongo que te gusta

Origin juejin.im/post/7084556894094196743
Recomendado
Clasificación