2

触发广播接收器时如何更改 ExoPlayer 的播放状态?

我有一个 BroadcastReceiver 在耳机断开连接时触发但是我不确定在调用 onReceive() 时处理音频暂停的正确方法。我需要在这里更改 Mediasession 的播放状态吗?

private static final int CORRECT_ANSWER_DELAY_MILLIS = 1000;
public static final String TAG = QuizActivity.class.getSimpleName();
private SimpleExoPlayer mExoPlayer;
private PlayerView mPlayerView;
private PlayerListener mPlayerListener;
private PlaybackStateCompat.Builder mPlaybackStateBuilder;
public static MediaSessionCompat mMediaSession;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_quiz);

    initializeMediaSession();

    mPlayerListener = new PlayerListener();

    // Initialize the player view.
    mPlayerView = (PlayerView) findViewById(R.id.playerView);


    // Initialize the player.
    initializePlayer(Uri.parse(answerSample.getUri()));

}

/**
 * Initialize ExoPlayer.
 *
 * @param mediaUri The URI of the sample to play.
 */
// done (2): Set the ExoPlayer.EventListener to this activity
private void initializePlayer(Uri mediaUri) {

    // 1. Create a default TrackSelector

    if (mExoPlayer == null) {
        Handler mainHandler = new Handler();
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory =
                new AdaptiveTrackSelection.Factory(bandwidthMeter);
        DefaultTrackSelector trackSelector =
                new DefaultTrackSelector(videoTrackSelectionFactory);

        // 2. Create the player
        mExoPlayer =
                ExoPlayerFactory.newSimpleInstance(this, trackSelector);

        mExoPlayer.addListener(mPlayerListener);
        mPlayerView.setPlayer(mExoPlayer);


        DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
        // Produces DataSource instances through which media data is loaded.
        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, "yourApplicationName"), defaultBandwidthMeter);
        // This is the MediaSource representing the media to be played.
        MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                .createMediaSource(mediaUri);
        // Prepare the player with the source.
        mExoPlayer.prepare(videoSource);
        mExoPlayer.setPlayWhenReady(true);
    }
}


/**
 * Release ExoPlayer.
 */
private void releasePlayer() {

    mExoPlayer.stop();
    mExoPlayer.release();
    mExoPlayer = null;
}


 * toggles the UI to show the correct answer.
 *
 * @param v The button that was clicked.
 */
@Override
public void onClick(View v) {


    // Wait some time so the user can see the correct answer, then go to the next question.
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mExoPlayer.stop();
            Intent nextQuestionIntent = new Intent(QuizActivity.this, QuizActivity.class);
            nextQuestionIntent.putExtra(REMAINING_SONGS_KEY, mRemainingSampleIDs);
            finish();
            startActivity(nextQuestionIntent);
        }
    }, CORRECT_ANSWER_DELAY_MILLIS);
}



/**
 * Release the player when the activity is destroyed.
 */
@Override
protected void onDestroy() {
    super.onDestroy();
    releasePlayer();
    mMediaSession.setActive(false);
}


private void initializeMediaSession() {

    mMediaSession = new MediaSessionCompat(this, TAG);

    mMediaSession.setFlags(
            MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                    MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

    // Do not let MediaButtons restart the player when the app is not visible.
       mMediaSession.setMediaButtonReceiver(null);


    mPlaybackStateBuilder = new PlaybackStateCompat.Builder()
            // Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player.
            .setActions(PlaybackStateCompat.ACTION_PLAY |
                    PlaybackStateCompat.ACTION_PAUSE |
                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
                    PlaybackStateCompat.ACTION_PLAY_PAUSE);

    mMediaSession.setPlaybackState(mPlaybackStateBuilder.build());

    mMediaSession.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public void onPlay() {

            mExoPlayer.setPlayWhenReady(true);
        }

        @Override
        public void onPause() {

            mExoPlayer.setPlayWhenReady(false);
        }

    });

    // Start the Media Session since the activity is active.
    mMediaSession.setActive(true);

}



public class PlayerListener extends Player.DefaultEventListener {
    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
        //super.onPlayerStateChanged(playWhenReady, playbackState);
        if (playbackState == Player.STATE_READY && playWhenReady) {
            mPlaybackStateBuilder.setState(STATE_PLAYING, mExoPlayer.getCurrentPosition(), 1f);
        } else if (playbackState == Player.STATE_READY) {
            mPlaybackStateBuilder.setState(STATE_PAUSED, mExoPlayer.getCurrentPosition(), 1f);
        }
            mMediaSession.setPlaybackState(mPlaybackStateBuilder.build());
            showMediaStyleNotification(mPlaybackStateBuilder.build());
    }
}

public static class MediaReceiver extends BroadcastReceiver {

    public MediaReceiver() { }

    @Override
    public void onReceive(final Context context, Intent intent) {
        if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {


            Toast.makeText(context, "Headset unplugged", Toast.LENGTH_SHORT).show();


        }
   }
}
4

2 回答 2

2

您应该首先在 Activity 中注册 Receiver,例如 -

MediaReceiver mr = new MediaReceiver(mPlayerView);
registerReceiver(mr);

然后,

private class MediaReceiver extends BroadcastReceiver {
        private PlayerView pv;

        public MediaReceiver(PlayerView playerView) {
            this.pv = playerView;
        } 

        @Override 
        public void onReceive(final Context context, Intent intent) {
            if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { 
                Toast.makeText(context, "Headset unplugged", Toast.LENGTH_SHORT).show(); 
                pv.pause();
            }
        }

另外,不要忘记在 onDestroy() 或 onPause() 中取消注册 Receiver

于 2018-09-02T04:07:10.640 回答
1

Exoplayer 2.11.0 支持 setHandleAudioBecomingNoisy:

SimpleExoPlayer.Builder(this).setHandleAudioBecomingNoisy(true).build()

于 2021-04-20T05:22:33.433 回答