Search code examples
androidandroid-mediaplayerandroid-audiomanager

How to determine that other app lose the audio focus so that i can start my player


I have seen many Android Player online that as soon it start playing other app loses the focus and stop playing.

At other hand, as soon the gained focused app stop playing, focus Loosed app start playing again.

can any one suggest what am i missing here to achieve the same in my app? I want as soon other app stop playing my app should GAIN focus and start playing..

private void setupAudioManager() {
        audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        audioManager.requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        audioFocusListener = new OnAudioFocusChangeListener() {
            @Override
            public void onAudioFocusChange(int focusChange) {
                switch (focusChange) {
                    case AUDIOFOCUS_GAIN:
                        if (mediaPlayer == null) setupMediaPlayer();
                        else if (!mediaPlayer.isPlaying()) {
                            play();
                        }
                        mediaPlayer.setVolume(MEDIA_PLAYER_LEFT_VOLUME, MEDIA_PLAYER_RIGHT_VOLUME);
                        break;

                    case AUDIOFOCUS_LOSS:
                        if (isPlaying()) {
                            Intent intent = new Intent("HomeActivity");
                            intent.putExtra("playerState", "pause");
                            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
                        }

                        break;

                    case AUDIOFOCUS_LOSS_TRANSIENT:
                        if (isPlaying()) pause();
                        break;

                    case AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                        if (isPlaying()) mediaPlayer.setVolume(MEDIA_PLAYER_LEFT_VOLUME_LOW,
                                MEDIA_PLAYER_RIGHT_VOLUME_LOW);
                        break;

                }
            }
        };
    }

Looking for you suggestion.


Solution

  • Here are my findings

    In case of Permanent loss of focus

    If the audio focus loss is permanent (AUDIOFOCUS_LOSS), another application is playing audio. Your app should pause play immediately. At this point your app will never receive an AUDIOFOCUS_GAIN callback. To restart playback the user must take an explicit action, like pressing the play transport control in a notification or app UI.

    After pausing your app should wait a short interval and then stop its media session to release resources and abandon audio focus. Delaying the stop call gives the user the opportunity to restart your app's playback. This can be useful if your app goes silent because the user accidentally started a different app that requested the audio focus.

    The following code snippet demonstrates how to implement the OnAudioFocusChangeListener and its onAudioFocusChange() callback. Notice the use of a Handler to delay the stop callback on a permanent loss of audio focus.

    private Handler mHandler = new Handler();
    AudioManager.OnAudioFocusChangeListener afChangeListener =
      new AudioManager.OnAudioFocusChangeListener() {
        public void onAudioFocusChange(int focusChange) {
          if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
            // Permanent loss of audio focus
            // Pause playback immediately
            mediaController.getTransportControls().pause();
            // Wait 30 seconds before stopping playback
            mHandler.postDelayed(mDelayedStopRunnable,
              TimeUnit.SECONDS.toMillis(30));
          }
          else if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT) {
            // Pause playback
          } else if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
            // Lower the volume, keep playing
          } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Your app has been granted audio focus again
            // Raise volume to normal, restart playback if necessary
          }
        }
      };
    

    The handler uses a Runnable that looks like this:

    private Runnable mDelayedStopRunnable = new Runnable() {
        @Override
        public void run() {
            mediaController.getTransportControls().stop();
        }
    };
    

    To ensure the delayed stop does not kick in if the user restarts playback, call mHandler.removeCallbacks(mDelayedStopRunnable) in response to any state changes. For example, call removeCallbacks() in your Callback's onPlay(), onSkipToNext(), etc. You should also call this method in your service's onDestroy() callback when cleaning up the resources used by your service.