Android オーディオ開発 (3): ExoPlayer を使用してオーディオを再生する

1. Android オーディオ開発 (1): オーディオの基本
2. Android オーディオ開発 (2): オーディオの録音 (WAV および MP3 形式)
3. Android オーディオ開発 (3): ExoPlayer を使用したオーディオの再生
4. Android オーディオ開発 (4) :オーディオ再生モード
5.Androidオーディオ開発(5):誘導(画面オフ/明るい画面)管理

添付の GitHub ソース コード: MultimediaExplore


備考: ExoPlayer のデコードは、ビデオおよびオーディオのデコード用に Android システムが提供するネイティブのデコード モジュールMediaCodecに依存しています。ExoPlayer の詳細については、ExoPlayerを参照してください。

 1. オーディオ再生の許可と依存関係:

オーディオの再生に関連する可能性のあるアクセス許可:

    <uses-permission android:name="android.permission.INTERNET" />
    <!--音频模式切换权限-->
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

    <!--唤屏/息屏权限-->
    <uses-permission android:name="android.Manifest.permission.DEVICE_POWER"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

オーディオ プレーヤーは、以下に依存する必要があります。 

    // 多媒体播放器
    implementation 'com.google.android.exoplayer:exoplayer-core:2.15.0'
    implementation 'com.google.android.exoplayer:exoplayer-ui:2.15.0'
    implementation 'com.google.android.exoplayer:exoplayer-hls:2.15.0'
    implementation 'com.google.android.exoplayer:exoplayer-dash:2.15.0'
    implementation 'com.google.android.exoplayer:exoplayer-transformer:2.15.0'
    implementation 'com.google.android.exoplayer:exoplayer-rtsp:2.15.0'
    implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.15.0'

2. ExoPlayer インスタンスの生成: 

SimpleExoPlayer インスタンスを生成し、ビルドされたオーディオ リソースを再生するオーディオ プレーヤーに設定します。ここで注意すべきことは、オーディオの再生進行状況を取得する場合は、下の図に示すようにhandlerInner Handler インスタンスを生成し、それを addEventListener に追加する必要があることです。そうでない場合、外部から渡されたハンドラを直接使用すると、取得したオーディオ再生の進行状況は常に 0 になります。

    public void prepareAudioPlayer(Context context, Handler handler, Uri uri) {
        if (player == null) {
            player = new SimpleExoPlayer.Builder(context).build();
        }
        mediaSource = AudioMediaSourceManager.getInstance().buildMediaSource(uri, isLocalResource);
        if (mediaSource == null || player == null) {
            return;
        }

        if (handlerInner == null) {
            handlerInner = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Message msgOuter = new Message();
                    if (msg.what == WHAT_POSITION) {
                        currentPosition = player.getCurrentPosition() / 1000;
                        contentPosition = player.getContentPosition() / 1000;
                        contentBufferedPosition = player.getContentBufferedPosition() / 1000;
                        Log.d(TAG, "-----> currentPosition:" + currentPosition + " contentPosition:" + contentPosition + " contentBufferedPosition:" + contentBufferedPosition);
                        HashMap<String, Long> hashMap = new HashMap<>();
                        hashMap.put("currentPosition", currentPosition);
                        hashMap.put("contentPosition", contentPosition);
                        hashMap.put("contentBufferedPosition", contentBufferedPosition);
                        msgOuter.what = WHAT_POSITION;
                        msgOuter.obj = hashMap;
                        handler.sendMessage(msgOuter);
                        if (currentPosition < duration) {
                            sendEmptyMessageDelayed(WHAT_POSITION, 300);
                        }
                    } else if (msg.what == WHAT_DURATION) {
                        msgOuter.obj = msg.obj;
                        handler.sendMessage(msgOuter);
                    }
                }
            };
        }

        mediaSource.addEventListener(handlerInner, new MediaSourceEventListener() {

            @Override
            public void onLoadStarted(int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) {
                Log.d(TAG, "onLoadStarted ---> duration:" + duration);
            }

            @Override
            public void onLoadCompleted(int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) {
                mediaSource.removeEventListener(this);

                //发送时长消息
                duration = player.getDuration() / 1000;
                Message msg = new Message();
                msg.what = WHAT_DURATION;
                msg.obj = duration;
                handlerInner.sendMessage(msg);

                //发送position消息
                Message msgPos = new Message();
                msgPos.what = WHAT_POSITION;
                handlerInner.sendMessage(msgPos);

                Log.d(TAG, "onLoadCompleted ---> duration:" + duration);
            }
        });
        player.setMediaSource(mediaSource);
        player.addListener(new Player.Listener() {

            @Override
            public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
                Log.d(TAG, "onPlayWhenReadyChanged---> playWhenReady:" + playWhenReady);
                AudioPlayer.this.playWhenReady = playWhenReady;
            }

            @Override
            public void onPlaybackStateChanged(int playbackState) {
                Log.d(TAG, "onPlaybackStateChanged---> playbackState:" + playbackState);
                switch (playbackState) {
                    case Player.STATE_READY:
                        Log.d(TAG, "STATE_READY");
                        break;
                    case Player.STATE_BUFFERING:
                        Log.d(TAG, "STATE_BUFFERING");
                        break;
                    case Player.STATE_ENDED:
                        Log.d(TAG, "STATE_ENDED");
                        audioStatus = AudioPlayStatus.AUDIO_STOP;
                        AudioModeManager.getInstance().abandonAudioFocus();
                        break;
                    case Player.STATE_IDLE:
                        Log.d(TAG, "STATE_IDLE");
                        audioStatus = AudioPlayStatus.AUDIO_IDLE;
                        AudioModeManager.getInstance().abandonAudioFocus();
                        break;
                }
            }

            @Override
            public void onIsPlayingChanged(boolean isPlaying) {
                Log.d(TAG, "onIsPlayingChanged---> isPlaying:" + isPlaying);
                if (isPlaying) {
                    audioStatus = AudioPlayStatus.AUDIO_START;
                } else {

                }
            }
        });

        player.prepare();
    }

3. オーディオ再生ライフサイクル メソッド:

    public void play() {
        Log.d(TAG, "play");
        if (player == null) {
            return;
        }
        AudioModeManager.getInstance().requestAudioFocus();
        if (playWhenReady) {
            if (!player.isPlaying()) {
                player.setPlayWhenReady(true);
            }
        } else {
            player.prepare();
            player.setPlayWhenReady(true);
        }
        audioStatus = AudioPlayStatus.AUDIO_START;
    }

    public void pause() {
        Log.d(TAG, "pause");
        if (player == null) {
            return;
        }
        AudioModeManager.getInstance().abandonAudioFocus();
        if (player.isPlaying()) {
            player.pause();
        }
        audioStatus = AudioPlayStatus.AUDIO_PAUSE;
    }

    public void stop() {
        Log.d(TAG, "stop");
        if (player == null) {
            return;
        }
        AudioModeManager.getInstance().abandonAudioFocus();
        player.stop();
        audioStatus = AudioPlayStatus.AUDIO_STOP;
    }

    public void cancel() {
        Log.d(TAG, "cancel");
    }

    public void release() {
        Log.d(TAG, "release");
        if (player == null) {
            return;
        }
        AudioModeManager.getInstance().abandonAudioFocus();
        player.release();
        if (handlerInner != null) {
            handlerInner.removeCallbacksAndMessages(null);
        }
        audioStatus = AudioPlayStatus.AUDIO_RELEASE;
    }

4. オーディオ再生管理AudioPlayManager :

AudioRecordManager の役割と同様に、オーディオ プレーヤーはグローバル シングルトンであり、コードは省略されています。

おすすめ

転載: blog.csdn.net/u012440207/article/details/121722809