Since requestAudioFocus(AudioManager.OnAudioFocusChangeListener l, int streamType, int durationHint)
is deprecated in API O , how do you set audio focus change list
Try to use setOnAudioFocusChangeListener()
What I have founded in official docs:
Explicit requests for audio focus: Your service can submit a more fine-grained request for receiving device-wide audio focus by using the requestAudioFocus() method. Pass in an AudioFocusRequest object, which you create using AudioFocusRequest.Builder. In this builder class, you can specify the following options:
The type of focus you wish to gain, such as AUDIOFOCUS_GAIN_TRANSIENT or AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK. Whether your service should continue more quietly or pause completely when another audio service takes over device focus. Whether your service can wait to gain focus until the device is ready.
Note: When building your instance of AudioFocusRequest, if you indicate that your service can wait to produce sound by calling setAcceptsDelayedFocusGain(), you must also call setOnAudioFocusChangeListener() so that your service knows when it can begin producing sound.
As @kelebro63 mentioned the following example shows how to use an AudioFocusRequest.Builder
to build an AudioFocusRequest
and request and abandon audio focus:
mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
mPlaybackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(mPlaybackAttributes)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(mMyFocusListener, mMyHandler)
.build();
mMediaPlayer = new MediaPlayer();
final Object mFocusLock = new Object();
boolean mPlaybackDelayed = false;
boolean mPlaybackNowAuthorized = false;
// ...
int res = mAudioManager.requestAudioFocus(mFocusRequest);
synchronized(mFocusLock) {
if (res == AUDIOFOCUS_REQUEST_FAILED) {
mPlaybackNowAuthorized = false;
} else if (res == AUDIOFOCUS_REQUEST_GRANTED) {
mPlaybackNowAuthorized = true;
playbackNow();
} else if (res == AUDIOFOCUS_REQUEST_DELAYED) {
mPlaybackDelayed = true;
mPlaybackNowAuthorized = false;
}
}
// ...
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mPlaybackDelayed || mResumeOnFocusGain) {
synchronized(mFocusLock) {
mPlaybackDelayed = false;
mResumeOnFocusGain = false;
}
playbackNow();
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
synchronized(mFocusLock) {
mResumeOnFocusGain = false;
mPlaybackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
synchronized(mFocusLock) {
mResumeOnFocusGain = true;
mPlaybackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// ... pausing or ducking depends on your application
break;
}
}
}
References:
Audio Focus Enhancements
Android O Features and APIs
To gain the focus use below (It will pause other player) :
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
mAudioManager.requestAudioFocus(null,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
To leave the focus use below (It will resume that player) :
mAudioManager.abandonAudioFocus(null);
Another option is to use AudiomanagerCompat together with AudioAttributesCompat and AudioRequestCompat, all part of Jetpack (androidx) compatibility libraries: https://developer.android.com/reference/androidx/media/AudioManagerCompat
In this way, you can use the same code for Android O+ and also for previous versions (without conditional checks on the API version. But one of the drawbacks of this approach is that you can't use: .setAcceptsDelayedFocusGain(true)
If you decide for this approach, then you have to use requestAudioFocus(mAudioManager, mFocusRequest) and abandonAudioFocusRequest(mAudioManager, mFocusRequest) to obtain and release audio focus.
Partial sample code (in Kotlin): (Note: if you do not use Timber for logging, replace it by the standard Log function)
class MyClass : AudioManager.OnAudioFocusChangeListener {
internal var audioManager: AudioManager? = null
private var focusRequest: AudioFocusRequestCompat? = null
private var playbackAttributes : AudioAttributesCompat? = null
// Create AudioManager and other audio related objects
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager?
playbackAttributes = AudioAttributesCompat.Builder()
.setUsage(AudioAttributesCompat.USAGE_MEDIA)
.setContentType(AudioAttributesCompat.CONTENT_TYPE_SPEECH)
.build()
focusRequest = AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN)
.setAudioAttributes(playbackAttributes ?: return)
.setWillPauseWhenDucked(false)
.setOnAudioFocusChangeListener(this)
.build()
// Request audio focus and check if it was granted to us
if (requestAudioFocus(audioManager!!, focusRequest!!) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// We obtained audio focus
}
else {
// We could not obtain audio focus
}
// And to remove audio focus
if (audioManager != null && focusRequest != null)
abandonAudioFocusRequest(audioManager!!, focusRequest!!)
// Implementation of OnAudioFocusChangeListener
override fun onAudioFocusChange(focusState: Int) {
// Invoked when the audio focus of the system is updated.
when (focusState) {
AudioManager.AUDIOFOCUS_GAIN -> {
// We recovered audio focus.
Timber.d("Audio Focus obtained")
}
AudioManager.AUDIOFOCUS_LOSS -> {
// Lost focus for an unbounded amount of time
Timber.d("Audio Focus lost")
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
// Lost focus for a short time, but it's ok to keep playing at an attenuated level
Timber.d("Audio Focus transient loss - can duck")
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
// Lost focus for a short time
Timber.d("Audio Focus transient loss - cannot duck")
}
}
}
}
https://developer.android.com/guide/topics/media-apps/audio-focusOfficial Link for the resource
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAudioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(
new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build()
)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
//Handle Focus Change
}
}).build()
);
} else {
mAudioManager.requestAudioFocus(focusChange -> {
//Handle Focus Change for earliest version of oreo
},
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
}