When we loose audio focus due to AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK we should reduce sound volume, untile audiofocus will be restored to AudioManager.AUDIOFOCUS_GAIN. However, it is fired if we registered listener before event.
How to check if audio focus is in state AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK if we registered after AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK event?
AudioManager.OnAudioFocusChangeListener audiofocusListener =
new AudioManager.OnAudioFocusChangeListener() {
#Override public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: {
}
break;
case AudioManager.AUDIOFOCUS_LOSS: {
}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: {
}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
}
break;
}
}
};
If I understand your question correctly, you want to know whether some other app is currently holding audio focus (and thus the audio output of your app should be ducked) before you actually have registered your audio focus listener.
If that's the case (some other app currently owns the audio focus), then your request for acquiring the audio focus will be denied, that is, your call to AudioManager.requestAudioFocus with audiofocusListener will return with AUDIOFOCUS_REQUEST_FAILED.
Related
I need to pause a player of a specific application - for example Spotify. But if some other player plays I would like to keep it playing and only pause the Spotify.
Is there any function how I can do it?
I ended up with possibility to pause all apps, but not the specific one.
Or other help would be if I could identify what app is currently playing a Media Player and if it is Spotify then I can pause all apps, but I will know that I stop only Spotify.
Cheers
There is no way to way extensively to stop particular app player audio
If they implement music api which is directly implemented with hardware
then if you play music in your app then its automatically stop
with AudioManager. You can also get callback if other application play audio.
private OnAudioFocusChangeListener focusChangeListener =
new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
AudioManager am =(AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (focusChange) {
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) :
// Lower the volume while ducking.
mediaPlayer.setVolume(0.2f, 0.2f);
break;
case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) :
pause();
break;
case (AudioManager.AUDIOFOCUS_LOSS) :
stop();
ComponentName component =new ComponentName(AudioPlayerActivity.this,MediaControlReceiver.class);
am.unregisterMediaButtonEventReceiver(component);
break;
case (AudioManager.AUDIOFOCUS_GAIN) :
// Return the volume to normal and resume if paused.
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.start();
break;
default: break;
}
}
};
I have created an application to play audio using media player but my player does not stops even if other app like youtube starts playing video.
How to stop audio if other app starts playing an audio.
I have used mediaPlayer.start(); to play an audio.
Any help would be appreciated.
You'll need to listen for Audio focus change.
Refer: https://developer.android.com/reference/android/media/AudioManager.OnAudioFocusChangeListener.html
OnAudioFocusChangeListener callback is called with a flag indicating audio focus status, which can be used to stop media player.
You can set a AudioFocusChangeListener to listen for Audio focus change.
private AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener;
audioFocusChangeListener =new AudioManager.OnAudioFocusChangeListener()
{
#Override
public void onAudioFocusChange ( int focusChange){
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
// Set volume level to desired levels
play();
break;
case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
// You have audio focus for a short time
play();
break;
case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
// Play over existing audio
play();
break;
case AudioManager.AUDIOFOCUS_LOSS:
stop();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// Temporary loss of audio focus expect to get it back you can keep your resources around
pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lower the volume
break;
}
}
}
;
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.
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.
I have a media application for the Amazon Fire tv and tv stick. I have successfully captured the buttons and have customized the events accordingly.
Issue arises in the case when some other media app such as pandora is running in the background. When I fastforward,rewind etc in my app , even pandora gets changed in the process.Amazon has declined the app for the same reason.How do I get to set the focus of the remote in the current app only.
The following is my code for remote
#Override
public boolean onKeyDown(int keyCode, KeyEvent event){
boolean handled = false;
switch (keyCode){
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_DPAD_LEFT:
mPlayerView.seek((int)mPlayerView.getPosition()-3000);
handled = true;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
Log.e("right","pressed");
mPlayerView.seek((int)mPlayerView.getPosition()+3000);
handled = true;
break;
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
mPlayerView.seek((int)mPlayerView.getPosition()+60000);
handled=true;
break;
case KeyEvent.KEYCODE_MEDIA_REWIND:
mPlayerView.seek((int)mPlayerView.getPosition()-60000);
handled=true;
break;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
mPlayerView.play();
handled=true;
break;
case KeyEvent.KEYCODE_MENU:
subtitle=!subtitle;
if(subsexists){
if(subtitle) {
mPlayerView.setCurrentCaptions(1);
Toast.makeText(this,"Subtitles ON",Toast.LENGTH_LONG).show();
}
else {
mPlayerView.setCurrentCaptions(0);
Toast.makeText(this,"Subtitles OFF",Toast.LENGTH_LONG).show();
}
}
handled=true;
break;
}
return handled || super.onKeyDown(keyCode, event);
}
See this section of the FireTV Developer FAQ. Specifically you need to implement code to:
When app starts playing, request audio focus with AudioManager.requestAudioFocus()
If audio focus was granted, register a media button receiver with AudioManager.registerMediaButtonEventReceiver()
you also need to make sure that you gracefully give up control as well if another media player app has the users attention
Listen for the loss of audio focus with AudioManager.onAudioFocusChangeListener()
If your app loses audio focus, stop playback and unregister the media buttons with AudioManager.unregisterMediaButtonEventReceiver()
I'm trying to setup my audio playing app to stop playback if there is an interruption. I followed directions in Android SDK Developer notes about setting up an AudioFocusHelper like so:
public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
AudioManager mAudioManager;
Media_Service mService;
Context mContext;
public AudioFocusHelper(Context ctx, Media_Service svc) {
mAudioManager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
mService = svc;
}
public boolean requestFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
}
public boolean abandonFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
mAudioManager.abandonAudioFocus(this);
}
#Override
public void onAudioFocusChange(int focusChange) {
// let your service know about the focus change
mService.AudioFocus(focusChange);
}
}
and I have my audio player running in a service as they suggest. I have this method in my audio service to respond to Audio Focus changes to pause the playback but its not working -- I don't know how to test this in the vm debugger so I can't really see what is happening on an incoming call. It doesn't appear to get called since I told it to popup toasts:
public void AudioFocus(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN: // resume playback
if (mMediaPlayer == null)
initMediaPlayer();
else if (!mMediaPlayer.isPlaying())
mMediaPlayer.start();
//mMediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS: // Lost focus for an unbounded amount of time: stop playback and release media player
if (mMediaPlayer.isPlaying()) {
Toast.makeText(this,
"Playback interrupted by focus loss", Toast.LENGTH_SHORT).show();
mMediaPlayer.stop();
}
mMediaPlayer.release();
mMediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: // Lost focus for a short time, but we have to stop
// playback. We don't release the media player because playback
// is likely to resume
if (mMediaPlayer.isPlaying()) {
Toast.makeText(this,
"Playback paused by focus loss (transient)", Toast.LENGTH_SHORT).show();
mMediaPlayer.pause();
}
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
if (mMediaPlayer.isPlaying()) {
Toast.makeText(this,
"Playback paused by focus loss (duck)", Toast.LENGTH_SHORT).show();
mMediaPlayer.pause();
//mMediaPlayer.setVolume(0.1f, 0.1f);
}
break;
}
}
I can post more of the code if necessary, it seems like I'm posting a lot of code already and I don't want to post an excessive amount. It looks to me like my onAudioFocusChange just isn't getting called. I am running this on Android 2.2 (minSDK 8) since these feature is not supported before 2.2. Searched hi and low for tips and I find very little about this topic at all so I'm hoping somebody out there can give me some clues.
I had this same issue, remember you need to call the requestFocus() method when you start playback and abandonFocus() when you are done.
I think this may help with generating incoming calls through DDMS: Fake Incoming Call Android
Hopefully, you can debug your application with this.