Androidオーディオおよびビデオ開発シリーズ-MediaPlayer開発の問題の概要

一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して2日目です。クリックしてイベントの詳細をご覧ください

序文

簡単な使い方を実装した後もMediaPlayer、実際の開発にはまだまだ多くの問題がありますが、ここでは問題をまとめて理由と解決策を記録し、開発概要です。

問題の要約

TrackInfoリソース情報クエリ

リソースをロードし、開発中にメソッドを実行したprepareAsync後、コールバックメソッドでリソースTrackInfoを取得します。当初は、この方法でビデオサイズ情報を取得することが期待されていました。たとえば、メソッドMediaExtractorを介してgetTrackFormatリソース情報を取得する場合などです。image.png TrackInfoオブジェクトは内部で取得できますが、実際のソースコードでは、戻り値が空MediaFormatであることがわかります。MediaFormat

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

したがって、MediaPlayer内部推定を使用してリソースファイルを直接取得できない場合は、MediaExtractor外部でのみ取得できます。

一時停止後に開始が失敗する

image.pngMediaPlayerシーケンス図からメソッドが呼び出されていることがわかります。呼び出された場合は、pause再度呼び出してstartも問題ありません。タイミングが合っている場合はstop、メソッドを再実行prepareして、リソースが再準備されるのを待ってから再生する必要があります。

  • 質問1

実際の開発で遭遇する問題は、プレイヤーがActivityバックグラウンドにいるときに、ライフサイクルとページがバインドされ、また呼び出されるため、ライフサイクルActivityのメソッドが呼び出されることです。最後に、理由がわかりました。現在は状態なので、実行メソッドのために再生する必要があります。onStopMediaPlayerstopMediaPlayerstopMediaPlayerprepare

問題1は、プレーヤーがバックグラウンドに戻った後にリソースを再生できるが、バインディングSurfaceViewが黒い画面であるという問題を解決することです。

  • 質問2

拘束力のあるSurfaceView黒い画面の状況は、基本的に質問1と同様です。SurfaceViewライフサイクルもあるためActivity、バックグラウンドで呼び出されると、プレーヤーへsurfaceDestroyedの元のバインドが期限切れになり、再バインドする必要があります。SurfaceViewSurface

元のロジックは、メソッドで1回だけ初期化してバインドすることであるため、メソッドでのみバインドすることは不適切postと思われます。post

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

surfaceViewバインディング作業は、のコールバックメソッドから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");
    }
});
复制代码
  • 質問3

MediaPlayerもう1つの問題は、再生進行状況のコールバックインターフェイスが提供されていないことです。MediaPlayer現在の再生の進行状況を取得する方法はありますgetCurrentPositionが、リアルタイムアクセスを取得する機能を提供するためにカプセル化することはできないため、開発者は自分でリアルタイムアクセスの方法を実装する必要があります。

Thread現在の再生ミリ秒値は、プレーヤーメソッドをループで継続的に呼び出すことで取得できgetCurrentPositionます。また、実際のビジネスニーズに応じて遅延処理を追加することもできます。

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

要約する

MediaPlayer使い方は簡単ですが、実装開発ではまだいくつかの詳細が公開されます。完全なプレーヤー機能を本当に開発して実装したい場合でも、多くの機能シナリオを改善して検討する必要がありMediaPlayerます。さらに深く掘り下げることができるいくつかの基本的な機能があります。

おすすめ

転載: juejin.im/post/7084556894094196743