Measured focus acquisition and return of Android audio
foreword
Recently, the boss wants to pause the music player in the mobile phone when the short video in the product is played live, and the music player in the mobile phone can continue to play the previous music after exiting the video playback.
Try WeChat first, emmm, it does work.
Android official website: manage audio focus
Official site management audio focus guidelines:
- Called just before playback starts
requestAudioFocus()
, and verifies that the call returnsAUDIOFOCUS_REQUEST_GRANTED
. If you design your app as described in this guide, it should be called in the media session'sonPlay()
callbackrequestAudioFocus()
. - Stop or pause playback, or lower the volume while another app has audio focus.
- After playback stops, relinquishes audio focus.
Different versions of audio focus are handled differently:
-
Beginning with Android 2.2 (API level 8),
requestAudioFocus()
appsabandonAudioFocus()
manage audio focus by calling and . Apps must also register for these two callsAudioManager.OnAudioFocusChangeListener
in order to receive callbacks and manage their own volume. -
For apps targeting Android 5.0 (API level 21) and higher, audio apps should use
AudioAttributes
to describe the type of audio the app is playing. For example, an application that plays speech should specifyCONTENT_TYPE_SPEECH
. -
Apps targeting Android 8.0 (API level 26) or higher should use
requestAudioFocus()
the method , which acceptsAudioFocusRequest
a parameter.AudioFocusRequest
Contains information about the app's audio context and capabilities. The system uses this information to automatically manage the gaining and losing of audio focus.
API introduction
Audio focus is handled through the AudioManager class, as follows to obtain an instance of this class:
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
requestAudioFocus()
//Used to apply for audio focus
abandonAudioFocus()
//Used to release the audio focus
AudioManager.OnAudioFocusChangeListener
interface, which providesonAudioFocusChange()
methods to monitor audio focus changes
-
requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
parameter:-
AudioManager.OnAudioFocusChangeListener l
:
Used to monitor audio focus changes, so that appropriate operations can be performed, such as pausing playback, etc. -
streamType
:
The type of audio that applies for audio focus processing, for example, it can be passed in when playing musicSTREAM_MUSIC
; it can be passed in when playing a ringtoneSTREAM_RING
. Some optional values are listed in the table:type meaning value STREAM_VOICE_CALL call 0 STREAM_SYSTEM system 1 STREAM_RING ring 2 STREAM_MUSIC music 3 STREAM_ALARM alarm clock 4 STREAM_NOTIFICATION system notification 5 … … … -
durationHint
(PS: important parameters):
There are five optional values:
(1)AUDIOFOCUS_GAIN
: This parameter indicates that you want to apply for a permanent audio focus, and you want the last app that holds the audio focus to stop playing; for example, when you need to play music.
(2)AUDIOFOCUS_GAIN_TRANSIENT
: It means to apply for a short-term audio focus, and it will be released immediately. At this time, it is hoped that the previous app that holds the audio focus will pause playback. For example, play an alert sound.
(3)AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
: The effect is the sameAUDIOFOCUS_GAIN_TRANSIENT
, except that the last App that holds the focus reduces its playing sound (but it can still be played), and it will play with mixed audio at this time. For example, navigation broadcast.
(4)AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
: Indicates that a short audio focus is applied, and the system will not play any sudden sounds (such as notifications, reminders, etc.), such as the user is recording. -
Return value:
AUDIOFOCUS_REQUEST_GRANTED
orAUDIOFOCUS_REQUEST_FAILED
.
-
-
abandonAudioFocus(OnAudioFocusChangeListener l)
Parameters pass onAudioManager.OnAudioFocusChangeListener
. -
AudioManager.OnAudioFocusChangeListener
: Callback ofonAudioFocusChange(int focusChange)
the method ;
new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
// TBD 继续播放
break;
case AudioManager.AUDIOFOCUS_LOSS:
// TBD 停止播放
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// TBD 暂停播放
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// TBD 混音播放
break;
default:
break;
}
}
};
Tested code:
The core is to AudioManager.AUDIOFOCUS_GAIN
changeAudioManager.AUDIOFOCUS_GAIN_TRANSIENT
public class MainActivity extends Activity {
private AudioManager mAudioManager;
private AudioFocusRequest mFocusRequest;
private AudioManager.OnAudioFocusChangeListener mListener;
private AudioAttributes mAttribute;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mListener = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
// TBD 继续播放
break;
case AudioManager.AUDIOFOCUS_LOSS:
// TBD 停止播放
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// TBD 暂停播放
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// TBD 混音播放
break;
default:
break;
}
}
};
//android 版本 5.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mAttribute = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
}
//android 版本 8.0
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
.setWillPauseWhenDucked(true)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(mListener, mHandler)
.setAudioAttributes(mAttribute)
.build();
}
}
private void requestAudioFocus() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAudioManager.requestAudioFocus(mFocusRequest);
} else {
mAudioManager.requestAudioFocus(mListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
}
}
private void abandonAudioFocus() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mAudioManager.abandonAudioFocusRequest(mFocusRequest);
} else {
mAudioManager.abandonAudioFocus(mListener);
}
}
}
reference:
https://segmentfault.com/a/1190000022234509
https://www.jianshu.com/p/26ea60c499a7
The article is all told here, if you have other needs to communicate, you can leave a message~! ~!
If you want to read more articles by the author, you can check out my personal blog and public account: