diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/AudioFocusHandler.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/AudioFocusHandler.java new file mode 100644 index 00000000..282b1061 --- /dev/null +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/AudioFocusHandler.java @@ -0,0 +1,90 @@ +package org.moire.ultrasonic.service; + +import android.content.Context; +import android.content.SharedPreferences; +import android.media.AudioManager; +import android.util.Log; + +import org.moire.ultrasonic.domain.PlayerState; +import org.moire.ultrasonic.util.Constants; +import org.moire.ultrasonic.util.Util; + +import kotlin.Lazy; + +import static org.koin.java.standalone.KoinJavaComponent.inject; + +public class AudioFocusHandler +{ + private static final String TAG = AudioFocusHandler.class.getSimpleName(); + + private static boolean hasFocus; + private static boolean pauseFocus; + private static boolean lowerFocus; + + // TODO: This is a circular reference, try to remove it + private Lazy mediaPlayerControllerLazy = inject(MediaPlayerController.class); + private Context context; + + public AudioFocusHandler(Context context) + { + this.context = context; + } + + public void requestAudioFocus() + { + if (!hasFocus) + { + final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + hasFocus = true; + audioManager.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() + { + @Override + public void onAudioFocusChange(int focusChange) + { + MediaPlayerController mediaPlayerController = mediaPlayerControllerLazy.getValue(); + if ((focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) && !mediaPlayerController.isJukeboxEnabled()) + { + Log.v(TAG, "Lost Audio Focus"); + if (mediaPlayerController.getPlayerState() == PlayerState.STARTED) + { + SharedPreferences preferences = Util.getPreferences(context); + int lossPref = Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_TEMP_LOSS, "1")); + if (lossPref == 2 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) + { + lowerFocus = true; + mediaPlayerController.setVolume(0.1f); + } + else if (lossPref == 0 || (lossPref == 1)) + { + pauseFocus = true; + mediaPlayerController.pause(); + } + } + } + else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) + { + Log.v(TAG, "Regained Audio Focus"); + if (pauseFocus) + { + pauseFocus = false; + mediaPlayerController.start(); + } + else if (lowerFocus) + { + lowerFocus = false; + mediaPlayerController.setVolume(1.0f); + } + } + else if (focusChange == AudioManager.AUDIOFOCUS_LOSS && !mediaPlayerController.isJukeboxEnabled()) + { + hasFocus = false; + mediaPlayerController.pause(); + audioManager.abandonAudioFocus(this); + Log.v(TAG, "Abandoned Audio Focus"); + } + } + }, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + Log.v(TAG, "Got Audio Focus"); + } + } +} diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java index 3b3f8828..d10cf796 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java @@ -84,6 +84,7 @@ public class LocalMediaPlayer private PositionCache positionCache; private int secondaryProgress = -1; + private final AudioFocusHandler audioFocusHandler; private final Context context; static @@ -112,8 +113,9 @@ public class LocalMediaPlayer } } - public LocalMediaPlayer(Context context) + public LocalMediaPlayer(AudioFocusHandler audioFocusHandler, Context context) { + this.audioFocusHandler = audioFocusHandler; this.context = context; } @@ -240,9 +242,9 @@ public class LocalMediaPlayer Util.unregisterMediaButtonEventReceiver(context, true); wakeLock.release(); } - catch (Throwable ignored) + catch (Throwable exception) { - Log.w(TAG, "LocalMediaPlayer onDestroy exception: ", ignored); + Log.w(TAG, "LocalMediaPlayer onDestroy exception: ", exception); } Log.i(TAG, "LocalMediaPlayer destroyed"); @@ -286,7 +288,7 @@ public class LocalMediaPlayer if (playerState == PlayerState.STARTED) { - Util.requestAudioFocus(context); + audioFocusHandler.requestAudioFocus(); } if (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED) diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java index 4de5fa45..8b4108f2 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java @@ -92,10 +92,6 @@ public class Util extends DownloadActivity public static final String CM_AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged"; public static final String CM_AVRCP_METADATA_CHANGED = "com.android.music.metachanged"; - private static boolean hasFocus; - private static boolean pauseFocus; - private static boolean lowerFocus; - private static boolean mediaButtonsRegisteredForUI; private static boolean mediaButtonsRegisteredForService; @@ -1181,60 +1177,6 @@ public class Util extends DownloadActivity return size; } - public static void requestAudioFocus(final Context context) - { - if (!hasFocus) - { - final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - hasFocus = true; - audioManager.requestAudioFocus(new OnAudioFocusChangeListener() - { - @Override - public void onAudioFocusChange(int focusChange) - { - MediaPlayerController mediaPlayerController = (MediaPlayerController) context; - if ((focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) && !mediaPlayerController.isJukeboxEnabled()) - { - if (mediaPlayerController.getPlayerState() == PlayerState.STARTED) - { - SharedPreferences preferences = getPreferences(context); - int lossPref = Integer.parseInt(preferences.getString(Constants.PREFERENCES_KEY_TEMP_LOSS, "1")); - if (lossPref == 2 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) - { - lowerFocus = true; - mediaPlayerController.setVolume(0.1f); - } - else if (lossPref == 0 || (lossPref == 1)) - { - pauseFocus = true; - mediaPlayerController.pause(); - } - } - } - else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) - { - if (pauseFocus) - { - pauseFocus = false; - mediaPlayerController.start(); - } - else if (lowerFocus) - { - lowerFocus = false; - mediaPlayerController.setVolume(1.0f); - } - } - else if (focusChange == AudioManager.AUDIOFOCUS_LOSS && !mediaPlayerController.isJukeboxEnabled()) - { - hasFocus = false; - mediaPlayerController.pause(); - audioManager.abandonAudioFocus(this); - } - } - }, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); - } - } - public static int getMinDisplayMetric(Context context) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MediaPlayerModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MediaPlayerModule.kt index c740f0b4..96489a63 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MediaPlayerModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MediaPlayerModule.kt @@ -10,6 +10,7 @@ import org.moire.ultrasonic.service.LocalMediaPlayer import org.moire.ultrasonic.service.MediaPlayerController import org.moire.ultrasonic.service.MediaPlayerControllerImpl import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport +import org.moire.ultrasonic.service.AudioFocusHandler import org.moire.ultrasonic.util.ShufflePlayBuffer val mediaPlayerModule = module { @@ -23,7 +24,8 @@ val mediaPlayerModule = module { single { ExternalStorageMonitor(androidContext()) } single { ShufflePlayBuffer(androidContext()) } single { Downloader(androidContext(), get(), get(), get()) } - single { LocalMediaPlayer(androidContext()) } + single { LocalMediaPlayer(get(), androidContext()) } + single { AudioFocusHandler(get()) } // TODO Ideally this can be cleaned up when all circular references are removed. single { MediaPlayerControllerImpl(androidContext(), get(), get(), get(), get(), get()) }