There's an app on my phone that keeps taking audio focus, even when no sound is playing. I'm wondering as an app developer if I'd be able to inform the user which app it is, or if I can tell if my app has audio focus?
I strongly doubt that there is any public APIs can tell you which app having the focus at the moment.
You can keep track if your app has the audio focus by requesting it, e.g.:
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
boolean requestGranted = AudioManager.AUDIOFOCUS_REQUEST_GRANTED == audioManager.requestAudioFocus(listener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if(requestGranted){
// you now has the audio focus
}
You should make sure to maintain a single instance of your listener when you request and abandon focus, see my answer here to troubleshoot common problems with audio focus
Here is an example of onAudioFocusChange():
#Override
public void onAudioFocusChange(int focus) {
switch (focus) {
case AudioManager.AUDIOFOCUS_LOSS:
Log.d(TAG,"AUDIOFOCUS_LOSS");
// stop and release your player
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
Log.d(TAG,"AUDIOFOCUS_LOSS_TRANSIENT");
// pause your player
break;
case AudioManager.AUDIOFOCUS_GAIN:
Log.d(TAG,"AUDIOFOCUS_GAIN");
// restore volume and resume player if needed
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
Log.d(TAG,"AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
// Lower volume
break;
}
}
Maybe this method does what you want:
AudioManager.isMusicActive()
http://developer.android.com/reference/android/media/AudioManager.html#isMusicActive%28%29
Related
I use audio focus in my app to play an audio file, but as I am testing the app against notifications it turns out that the audio focus for the app is not lost whenever a new message or a battery low notification pops up and the audio still plays with a reduced volume along with the notification sound even though I have not coded this behavior in the audio focus change listener rather I want the volume to be reduced to 0 for the Transient_May_Duck focus change which I think should be used by the notification sounds but it turns out that this is not the case for the notification sounds.
So is it so that the system itself reduces the volume while the notification sound starts (without requesting audio focus) even though this is not something coded by the developer for such audio focus change.
I am testing the app on a Virtual device running Android Oreo.
This is the code I wrote for the audio focus change,
AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
#Override
public void onAudioFocusChange(int i) {
switch (i) {
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
song.setVolume(0.0f, 0.0f);
Toast.makeText(MainActivity.this, "Can_Duck, reducing Vol to 0.0", Toast.LENGTH_SHORT).show();
break;
case AudioManager.AUDIOFOCUS_GAIN:
song.setVolume(1.0f, 1.0f);
song.start();
Toast.makeText(MainActivity.this, "Focus Gained, Ready Again", Toast.LENGTH_SHORT).show();
break;
case AudioManager.AUDIOFOCUS_LOSS:
releaseResources();
audioManager.abandonAudioFocus(audioFocusChangeListener);
Toast.makeText(MainActivity.this, "Loss, Releasing Res", Toast.LENGTH_SHORT).show();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
Toast.makeText(MainActivity.this, "Loss_Transient", Toast.LENGTH_SHORT).show();
song.pause();
break;
}
}
};
When the media is already playing in the background and you want to play the media in another app, I want to stop the media that was playing and stop the media that was playing after receiving the signal from the existing app. In other words, I want to detect the signal to stop the existing media playback signal if there is another media playback signal.
I think it might be related to android AUDIOFOCUS_REQUEST_GRANTED by calling android requestAudioFocus (), please help.
from the documentation
read the documentation. it explains everything.
in OnAudioFocusChangeListener you can listen when another app has audio focus and you can respond to the changes.
for example:
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
handler.postDelayed(delayedStopRunnable,
TimeUnit.SECONDS.toMillis(30));
}
else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
// Pause playback
} else if (focusChange == AudioManager.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
}
}
};
let me know if you need more clarification
I'm trying to modify my application to pause audio playback when Google maps is announcing a turn by turn direction.
I've added the following code (shown below) to my application. The audio focus listener is called when applications like Pandora Radio or Spotify request audio focus in order to play music but it's not called when Google maps announces a turn by turn direction. Is there another intent I should be listening for in order to detect this behavior?
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(
new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(new AudioManager.OnAudioFocusChangeListener() {
#Override
public void onAudioFocusChange(int focusChange) {
// This is called by Pandora Radio and Spotify
Log.d("Focus change:", " Event is: " + focusChange);
}
}).build());
You will need AudioManager's AudioPlaybackCallback updates.
This only works on Android O and above.
To do this you have to access the audio manager -
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
And then add the listener like this -
Handler handler = new Handler();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
audioManager.registerAudioPlaybackCallback(new AudioManager.AudioPlaybackCallback() {
#Override
public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
super.onPlaybackConfigChanged(configs);
// This will be called when navigation audio state on google maps changes
Log.d("audio active", String.valueOf(audioManager.isMusicActive()));
}
}, handler);
}
The List<AudioPlaybackConfiguration> configs returned in the callback has a AudioAttribute object which contains a string describing the audio playing. For Google maps navigation the String constant value is USAGE_ASSISTANCE_NAVIGATION_GUIDANCE which you can compare to be sure that it is Google Maps announcing the navigation direction.
Programatically you can get it like this
// Loop through the configs to see the media's usage data
configs.get(0).getAudioAttributes().getUsage();
For Android O, the missing navigation duck focus change notifications were only received after I explicitly set my player's AudioAttributes and content type to speech (as I am playing podcast mp3 files, didn't test with other content types):
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
AudioAttributes.Builder aab = new AudioAttributes.Builder();
aab.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH);
aab.setUsage(USAGE_MEDIA);
player.setAudioAttributes(aab.build());
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mPlayOnAudioFocus && !isPlaying()) {
play();
} else if (isPlaying()) {
setVolume(MEDIA_VOLUME_DEFAULT);
}
mPlayOnAudioFocus = false;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
setVolume(MEDIA_VOLUME_DUCK);
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (isPlaying()) {
mPlayOnAudioFocus = true;
pause();
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
mAudioManager.abandonAudioFocus(this);
mPlayOnAudioFocus = false;
stop();
break;
}
}
}
The following code snippet contains an implementation of this interface for an app that plays audio. And it handles ducking for transient audio focus loss. It also handles audio focus change due to the user pausing playback, vs another app (like the Google Assistant) causing transient audio focus loss
does your app temporarily need audio focus (with the option to duck), since it needs to play an audio notification, or a turn by turn spoken direction, or it needs to record audio from the user for a short period of time? This is
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.
Ducking vs pausing on transient audio focus loss
You can choose to pause playback or temporarily reduce the volume of your audio playback in the OnAudioFocusChangeListener, depending on what UX your app needs to deliver. Android O supports auto ducking, where the system will reduce the volume of your app automatically without you having to write any extra code. In your OnAudioFocusChangeListener, just ignore the AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK event.
In Android N and earlier, you have to implement ducking yourself (as shown in the code snippet above).
for Detail visit :https://medium.com/androiddevelopers/audio-focus-3-cdc09da9c122
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
added in API level 8
public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Used to indicate a temporary request of audio focus, anticipated to last a short amount of time, and where it is acceptable for other audio applications to keep playing after having lowered their output level (also referred to as "ducking"). Examples of temporary changes are the playback of driving directions where playback of music in the background is acceptable.
You should use "AudioManager.AUDIOFOCUS_GAIN_TRANSIENT", according to the documentation:
AUDIOFOCUS_GAIN_TRANSIENT
Used to indicate a temporary gain or request of audio focus, anticipated to last a short amount of time. Examples of temporary changes are the playback of driving directions, or an event notification.
I have tried finding an answer to this, but my searches kept returning irrelevant results...
So the problem is - I am writing a game that plays sound effects (no music just yet), and I set the stream type to Music. However, when I put my phone in silent mode (no vibration either, if that matters) the app still plays sounds. I can turn off the sound in the app using the volume keys, but what I expected (and what my future users would probably expect too) was that the app won't make a sound when the phone is in silent mode.
At this point, I am not sure if this should be automatically managed by the OS, or if I am expected to do something about it. I can surely detect the silent mode, set the volume to 0 in e.g onResume, but that will probably overwrite the setting the users set up by pressing the volume buttons - so when they unmute the phone, the app either has to set the volume programmatically to a predefined value, or ideally, to a saved one from sharedPrefs... which sounds relatively cumbersome. Is there a nicer solution?
This is how I initialize & then use sounds:
soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 100);
soundPoolMap = new SparseIntArray();
soundPoolMap.put(CLICK_1, soundPool.load(activity, R.raw.click1, 1));
soundPoolMap.put(CLICK_2, soundPool.load(activity, R.raw.click2, 2));
...
float volume = 1.0f;
soundPool.play(soundPoolMap.get(soundID), volume, volume, 1, 0, 1f);
What I understand from your question is you want to mute your app when device is on silent mode.
Try to check the the RingerMode every time before your app play sound/music and play sound only when the ringer RingerMode is normal.
Here is the sample code.
AudioManager audio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
switch (audio.getRingerMode())
{
case AudioManager.RINGER_MODE_NORMAL:
// Device is on Normal mode.
// you can play music.
break;
case AudioManager.RINGER_MODE_SILENT:
// Device is on Silent mode.
// you should not play sound now.
break;
case AudioManager.RINGER_MODE_VIBRATE:
// Device is on Vibrate/Meeting mode.
// you should not play sound but you can make vibrate device (if you want).
break;
}
Change Sound of media player in android
I am trying to change sound of media player. Default sound in beep now wants to change the beep sound. I have checked AudioManager property but not change.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
I think this is what you might be interested in:
1, increase/decrease the volume of the sound: Link Here
Basically Override the onKeyDown and then call mp.setVolumn(float leftVolume,float rightVolume);
2, mute the sound if the phone was set to silent mode
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_SILENT:
mp.setVolumn(0,0);
break;
}