Abandon audio focus when a phone call comes in

Otherwise playback continues directly after the end of the call
This commit is contained in:
daniel oeh 2014-08-01 13:17:02 +02:00
parent 876b69d21c
commit 18372a4d9b
1 changed files with 53 additions and 48 deletions

View File

@ -4,12 +4,21 @@ import android.content.ComponentName;
import android.content.Context;
import android.media.AudioManager;
import android.media.RemoteControlClient;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Pair;
import android.view.SurfaceHolder;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.feed.Chapter;
import de.danoeh.antennapod.feed.MediaType;
@ -20,14 +29,6 @@ import de.danoeh.antennapod.util.playback.IPlayer;
import de.danoeh.antennapod.util.playback.Playable;
import de.danoeh.antennapod.util.playback.VideoPlayer;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the MediaPlayer object of the PlaybackService.
*/
@ -380,7 +381,8 @@ public class PlaybackServiceMediaPlayer {
} else if (mediaPlayer != null) {
mediaPlayer.reset();
} else {
if (BuildConfig.DEBUG) Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null");
if (BuildConfig.DEBUG)
Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null");
}
playerLock.unlock();
}
@ -694,54 +696,56 @@ public class PlaybackServiceMediaPlayer {
public void run() {
playerLock.lock();
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS:
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus");
pause(true, false);
callback.shouldStop();
break;
case AudioManager.AUDIOFOCUS_GAIN:
if (BuildConfig.DEBUG)
Log.d(TAG, "Gained audio focus");
if (pausedBecauseOfTransientAudiofocusLoss) // we paused => play now
resume();
else // we ducked => raise audio level back
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE, 0);
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (playerStatus == PlayerStatus.PLAYING) {
if (!UserPreferences.shouldPauseForFocusLoss()) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus temporarily. Ducking...");
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER, 0);
pausedBecauseOfTransientAudiofocusLoss = false;
} else {
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
pause(false, false);
pausedBecauseOfTransientAudiofocusLoss = true;
}
}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (playerStatus == PlayerStatus.PLAYING) {
// If there is an incoming call, playback should be paused permanently
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final int callState = (tm != null) ? tm.getCallState() : 0;
if (BuildConfig.DEBUG) Log.d(TAG, "Call state: " + callState);
Log.i(TAG, "Call state:" + callState);
if (focusChange == AudioManager.AUDIOFOCUS_LOSS || callState != TelephonyManager.CALL_STATE_IDLE) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus");
pause(true, false);
callback.shouldStop();
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Gained audio focus");
if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now
resume();
} else { // we ducked => raise audio level back
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE, 0);
}
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
if (playerStatus == PlayerStatus.PLAYING) {
if (!UserPreferences.shouldPauseForFocusLoss()) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus temporarily. Pausing...");
Log.d(TAG, "Lost audio focus temporarily. Ducking...");
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER, 0);
pausedBecauseOfTransientAudiofocusLoss = false;
} else {
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
pause(false, false);
pausedBecauseOfTransientAudiofocusLoss = true;
}
}
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
if (playerStatus == PlayerStatus.PLAYING) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Lost audio focus temporarily. Pausing...");
pause(false, false);
pausedBecauseOfTransientAudiofocusLoss = true;
}
playerLock.unlock();
}
playerLock.unlock();
}
});
}
};
public void endPlayback() {
executor.submit(new Runnable() {
@Override
@ -778,7 +782,8 @@ public class PlaybackServiceMediaPlayer {
if (playerStatus == PlayerStatus.INDETERMINATE) {
setPlayerStatus(PlayerStatus.STOPPED, null);
} else {
if (BuildConfig.DEBUG) Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
if (BuildConfig.DEBUG)
Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
}
playerLock.unlock();