diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index b07b15a45..0fdcc972c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -641,6 +641,15 @@ public final class Player implements PlaybackListener, Listener { simpleExoPlayer.setWakeMode(C.WAKE_MODE_NETWORK); simpleExoPlayer.setHandleAudioBecomingNoisy(true); + // Enable automatic audio focus management - let Android handle ducking automatically + simpleExoPlayer.setAudioAttributes( + new com.google.android.exoplayer2.audio.AudioAttributes.Builder() + .setUsage(C.USAGE_MEDIA) + .setContentType(C.AUDIO_CONTENT_TYPE_MUSIC) + .build(), + true // handleAudioFocus = true for automatic management + ); + audioReactor = new AudioReactor(context, simpleExoPlayer); registerBroadcastReceiver(); @@ -1190,10 +1199,6 @@ public final class Player implements PlaybackListener, Listener { } UIs.call(PlayerUi::onPrepared); - - if (playWhenReady && !isMuted()) { - audioReactor.requestAudioFocus(); - } } private void onBlocked() { @@ -1341,11 +1346,6 @@ public final class Player implements PlaybackListener, Listener { public void toggleMute() { final boolean wasMuted = isMuted(); simpleExoPlayer.setVolume(wasMuted ? 1 : 0); - if (wasMuted) { - audioReactor.requestAudioFocus(); - } else { - audioReactor.abandonAudioFocus(); - } UIs.call(playerUi -> playerUi.onMuteUnmuteChanged(!wasMuted)); notifyPlaybackUpdateToListeners(); } @@ -1757,10 +1757,6 @@ public final class Player implements PlaybackListener, Listener { return; } - if (!isMuted()) { - audioReactor.requestAudioFocus(); - } - if (currentState == STATE_COMPLETED) { if (playQueue.getIndex() == 0) { seekToDefault(); @@ -1781,7 +1777,6 @@ public final class Player implements PlaybackListener, Listener { return; } - audioReactor.abandonAudioFocus(); simpleExoPlayer.pause(); saveStreamProgressState(); } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java index 084336d54..2ec33dc0f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java @@ -1,54 +1,36 @@ package org.schabi.newpipe.player.helper; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.media.audiofx.AudioEffect; -import android.util.Log; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; -import androidx.media.AudioFocusRequestCompat; import androidx.media.AudioManagerCompat; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.analytics.AnalyticsListener; -public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AnalyticsListener { +public class AudioReactor implements AnalyticsListener { private static final String TAG = "AudioFocusReactor"; - private static final int DUCK_DURATION = 1500; - private static final float DUCK_AUDIO_TO = .2f; - - private static final int FOCUS_GAIN_TYPE = AudioManagerCompat.AUDIOFOCUS_GAIN; private static final int STREAM_TYPE = AudioManager.STREAM_MUSIC; private final ExoPlayer player; private final Context context; private final AudioManager audioManager; - private final AudioFocusRequestCompat request; - public AudioReactor(@NonNull final Context context, @NonNull final ExoPlayer player) { this.player = player; this.context = context; this.audioManager = ContextCompat.getSystemService(context, AudioManager.class); player.addAnalyticsListener(this); - - request = new AudioFocusRequestCompat.Builder(FOCUS_GAIN_TYPE) - //.setAcceptsDelayedFocusGain(true) - .setWillPauseWhenDucked(true) - .setOnAudioFocusChangeListener(this) - .build(); } public void dispose() { - abandonAudioFocus(); player.removeAnalyticsListener(this); notifyAudioSessionUpdate(false, player.getAudioSessionId()); } @@ -57,14 +39,6 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An // Audio Manager //////////////////////////////////////////////////////////////////////////*/ - public void requestAudioFocus() { - AudioManagerCompat.requestAudioFocus(audioManager, request); - } - - public void abandonAudioFocus() { - AudioManagerCompat.abandonAudioFocusRequest(audioManager, request); - } - public int getVolume() { return audioManager.getStreamVolume(STREAM_TYPE); } @@ -77,73 +51,6 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An return AudioManagerCompat.getStreamMaxVolume(audioManager, STREAM_TYPE); } - /*////////////////////////////////////////////////////////////////////////// - // AudioFocus - //////////////////////////////////////////////////////////////////////////*/ - - @Override - public void onAudioFocusChange(final int focusChange) { - Log.d(TAG, "onAudioFocusChange() called with: focusChange = [" + focusChange + "]"); - switch (focusChange) { - case AudioManager.AUDIOFOCUS_GAIN: - onAudioFocusGain(); - break; - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: - onAudioFocusLossCanDuck(); - break; - case AudioManager.AUDIOFOCUS_LOSS: - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: - onAudioFocusLoss(); - break; - } - } - - private void onAudioFocusGain() { - Log.d(TAG, "onAudioFocusGain() called"); - player.setVolume(DUCK_AUDIO_TO); - animateAudio(DUCK_AUDIO_TO, 1.0f); - - if (PlayerHelper.isResumeAfterAudioFocusGain(context)) { - player.play(); - } - } - - private void onAudioFocusLoss() { - Log.d(TAG, "onAudioFocusLoss() called"); - player.pause(); - } - - private void onAudioFocusLossCanDuck() { - Log.d(TAG, "onAudioFocusLossCanDuck() called"); - // Set the volume to 1/10 on ducking - player.setVolume(DUCK_AUDIO_TO); - } - - private void animateAudio(final float from, final float to) { - final ValueAnimator valueAnimator = new ValueAnimator(); - valueAnimator.setFloatValues(from, to); - valueAnimator.setDuration(AudioReactor.DUCK_DURATION); - valueAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(final Animator animation) { - player.setVolume(from); - } - - @Override - public void onAnimationCancel(final Animator animation) { - player.setVolume(to); - } - - @Override - public void onAnimationEnd(final Animator animation) { - player.setVolume(to); - } - }); - valueAnimator.addUpdateListener(animation -> - player.setVolume(((float) animation.getAnimatedValue()))); - valueAnimator.start(); - } - /*////////////////////////////////////////////////////////////////////////// // Audio Processing //////////////////////////////////////////////////////////////////////////*/