From 3a0888ac31341e5786ab7eb2ecb068b62863c9a1 Mon Sep 17 00:00:00 2001 From: CappielloAntonio Date: Sat, 17 Jul 2021 18:52:12 +0200 Subject: [PATCH] refactor: let exoplayer handle audio focus commit fcf2c62d9a1d997be64c268c7689b4ca59fef1d4 by jakobkukla --- .../play/service/MultiPlayer.java | 8 ++ .../play/service/MusicService.java | 121 ++---------------- 2 files changed, 18 insertions(+), 111 deletions(-) diff --git a/app/src/main/java/com/cappielloantonio/play/service/MultiPlayer.java b/app/src/main/java/com/cappielloantonio/play/service/MultiPlayer.java index 2377efc2..500afe76 100644 --- a/app/src/main/java/com/cappielloantonio/play/service/MultiPlayer.java +++ b/app/src/main/java/com/cappielloantonio/play/service/MultiPlayer.java @@ -11,6 +11,8 @@ import com.cappielloantonio.play.model.Song; import com.cappielloantonio.play.util.DownloadUtil; import com.cappielloantonio.play.util.MusicUtil; import com.cappielloantonio.play.util.PreferenceUtil; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.audio.AudioAttributes; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; @@ -88,8 +90,14 @@ public class MultiPlayer implements Playback { .setUpstreamDataSourceFactory(DownloadUtil.getHttpDataSourceFactory(context)) .setCacheWriteDataSinkFactory(null); // Disable writing. + AudioAttributes audioAttributes = new AudioAttributes.Builder() + .setUsage(C.USAGE_MEDIA) + .setContentType(C.CONTENT_TYPE_MUSIC) + .build(); + exoPlayer = new SimpleExoPlayer.Builder(context) .setMediaSourceFactory(new DefaultMediaSourceFactory(cacheDataSourceFactory)) + .setAudioAttributes(audioAttributes, true) .build(); // TODO: “Player is accessed on the wrong thread” suppressed diff --git a/app/src/main/java/com/cappielloantonio/play/service/MusicService.java b/app/src/main/java/com/cappielloantonio/play/service/MusicService.java index 0e68d242..9baa6974 100644 --- a/app/src/main/java/com/cappielloantonio/play/service/MusicService.java +++ b/app/src/main/java/com/cappielloantonio/play/service/MusicService.java @@ -56,6 +56,7 @@ import static com.google.android.exoplayer2.Player.MEDIA_ITEM_TRANSITION_REASON_ import static com.google.android.exoplayer2.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM; public class MusicService extends Service implements Playback.PlaybackCallbacks { + private static final String TAG = "MusicService"; public static final String PACKAGE_NAME = "com.antoniocappiello.play"; public static final String ACTION_TOGGLE = PACKAGE_NAME + ".toggle"; public static final String ACTION_PLAY = PACKAGE_NAME + ".play"; @@ -77,11 +78,7 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks public static final int PLAY_SONG = 3; public static final int PREPARE_NEXT = 4; public static final int SET_POSITION = 5; - public static final int FOCUS_CHANGE = 6; - public static final int DUCK = 7; - public static final int UNDUCK = 8; public static final int LOAD_QUEUE = 9; - private static final String TAG = "MusicService"; private static final long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE @@ -97,7 +94,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks private int nextPosition = -1; private boolean notHandledMetaChangedForCurrentTrack; private boolean queuesRestored; - private boolean pausedByTransientLossOfFocus; private PlayingNotification playingNotification; private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() { @Override @@ -107,16 +103,9 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks } } }; - private AudioManager audioManager; private MediaSessionCompat mediaSession; private PowerManager.WakeLock wakeLock; private PlaybackHandler playerHandler; - private final AudioManager.OnAudioFocusChangeListener audioFocusListener = new AudioManager.OnAudioFocusChangeListener() { - @Override - public void onAudioFocusChange(final int focusChange) { - playerHandler.obtainMessage(FOCUS_CHANGE, focusChange, 0).sendToTarget(); - } - }; private Handler uiThreadHandler; private ThrottledSeekHandler throttledSeekHandler; private QueueHandler queueHandler; @@ -160,14 +149,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks mediaSession.setActive(true); } - private AudioManager getAudioManager() { - if (audioManager == null) { - audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - } - - return audioManager; - } - private void initMediaSession() { ComponentName mediaButtonReceiverComponentName = new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class); @@ -332,8 +313,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks private void quit() { pause(); playingNotification.stop(); - - getAudioManager().abandonAudioFocus(audioFocusListener); stopSelf(); } @@ -412,10 +391,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks increaseSongCount(); } - private boolean requestFocus() { - return getAudioManager().requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED; - } - public void initNotification() { playingNotification = new PlayingNotification(); playingNotification.init(this); @@ -582,7 +557,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks } public void pause() { - pausedByTransientLossOfFocus = false; if (playback.isPlaying()) { playback.pause(); notifyChange(STATE_CHANGED); @@ -591,27 +565,17 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks public void play() { synchronized (this) { - if (requestFocus()) { - if (!playback.isPlaying()) { - if (!playback.isReady()) { - playSongAt(getPosition()); - } else { - playback.start(); - if (notHandledMetaChangedForCurrentTrack) { - handleChangeInternal(META_CHANGED); - notHandledMetaChangedForCurrentTrack = false; - } - - notifyChange(STATE_CHANGED); - - // fixes a bug where the volume would stay ducked - // happens when audio focus GAIN event not sent - playerHandler.removeMessages(DUCK); - playerHandler.sendEmptyMessage(UNDUCK); + if (!playback.isPlaying()) { + if (!playback.isReady()) { + playSongAt(getPosition()); + } else { + playback.start(); + if (notHandledMetaChangedForCurrentTrack) { + handleChangeInternal(META_CHANGED); + notHandledMetaChangedForCurrentTrack = false; } + notifyChange(STATE_CHANGED); } - } else { - Toast.makeText(this, getResources().getString(R.string.audio_focus_denied), Toast.LENGTH_SHORT).show(); } } } @@ -758,7 +722,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks private static final class PlaybackHandler extends Handler { private final WeakReference mService; - private int currentDuckVolume = 100; public PlaybackHandler(final MusicService service, @NonNull final Looper looper) { super(looper); @@ -773,36 +736,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks } switch (msg.what) { - case DUCK: - if (PreferenceUtil.getInstance(service).getAudioDucking()) { - currentDuckVolume -= 5; - if (currentDuckVolume > 20) { - sendEmptyMessageDelayed(DUCK, 10); - } else { - currentDuckVolume = 20; - } - } else { - currentDuckVolume = 100; - } - - service.playback.setVolume(currentDuckVolume); - break; - - case UNDUCK: - if (PreferenceUtil.getInstance(service).getAudioDucking()) { - currentDuckVolume += 3; - if (currentDuckVolume < 100) { - sendEmptyMessageDelayed(UNDUCK, 10); - } else { - currentDuckVolume = 100; - } - } else { - currentDuckVolume = 100; - } - - service.playback.setVolume(currentDuckVolume); - break; - case TRACK_CHANGED: if (service.isLastTrack()) { service.pause(); @@ -851,40 +784,6 @@ public class MusicService extends Service implements Playback.PlaybackCallbacks case PREPARE_NEXT: service.prepareNextImpl(); break; - - case FOCUS_CHANGE: - switch (msg.arg1) { - case AudioManager.AUDIOFOCUS_GAIN: - if (!service.isPlaying() && service.pausedByTransientLossOfFocus) { - service.play(); - service.pausedByTransientLossOfFocus = false; - } - removeMessages(DUCK); - sendEmptyMessage(UNDUCK); - break; - - case AudioManager.AUDIOFOCUS_LOSS: - // Lost focus for an unbounded amount of time: stop playback and release media playback - service.pause(); - break; - - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: - // Lost focus for a short time, but we have to stop - // playback. We don't release the media playback because playback - // is likely to resume - boolean wasPlaying = service.isPlaying(); - service.pause(); - service.pausedByTransientLossOfFocus = wasPlaying; - break; - - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: - // Lost focus for a short time, but it's ok to keep playing - // at an attenuated level - removeMessages(UNDUCK); - sendEmptyMessage(DUCK); - break; - } - break; } } }