實測Android音頻的焦點獲取和歸還
前言
最近老板想在產品中的短視頻后者直播播放的時候對于手機中的音樂播放器進行暫停播放,并且退出視頻播放后手機的音樂播放器還能繼續播放之前的音樂。
先試試微信,emmm,確實可以。
官網管理音頻焦點準則:
- 在即將開始播放之前調用
requestAudioFocus()
,并驗證調用是否返回AUDIOFOCUS_REQUEST_GRANTED
。如果按照本指南中的說明設計應用,則應在媒體會話的onPlay()
回調中調用requestAudioFocus()
。 - 在其他應用獲得音頻焦點時,停止或暫停播放,或降低音量。
- 播放停止后,放棄音頻焦點。
不同版本音頻焦點的處理方式不太相同:
從 Android 2.2(API 級別 8)開始,應用通過調用
requestAudioFocus()
和abandonAudioFocus()
來管理音頻焦點。應用還必須為這兩個調用注冊AudioManager.OnAudioFocusChangeListener
,以便接收回調并管理自己的音量。對于以 Android 5.0(API 級別 21)及更高版本為目標平臺的應用,音頻應用應使用
AudioAttributes
來描述應用正在播放的音頻類型。例如,播放語音的應用應指定CONTENT_TYPE_SPEECH
。面向 Android 8.0(API 級別 26)或更高版本的應用應使用
requestAudioFocus()
方法,該方法會接受AudioFocusRequest
參數。AudioFocusRequest
包含有關應用的音頻上下文和功能的信息。系統使用這些信息來自動管理音頻焦點的得到和失去。
API介紹
處理音頻焦點都是通過AudioManager這個類,如下是獲得該類實例的方法:
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
requestAudioFocus()
//用于申請音頻焦點
abandonAudioFocus()
//用于釋放音頻焦點
AudioManager.OnAudioFocusChangeListener
接口,提供了onAudioFocusChange()
方法來監聽音頻焦點變化
-
requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)
參數:AudioManager.OnAudioFocusChangeListener l
:
用于監聽音頻焦點變化,從而可以進行適當的操作,例如暫停播放等。-
streamType
:
申請音頻焦點處理的音頻類型,例如,當播放音樂時,可以傳入STREAM_MUSIC
;當播放鈴聲時,可以傳入STREAM_RING
。表中列出了一些的可選值:類型 含義 值 STREAM_VOICE_CALL 通話 0 STREAM_SYSTEM 系統 1 STREAM_RING 鈴聲 2 STREAM_MUSIC 音樂 3 STREAM_ALARM 鬧鈴 4 STREAM_NOTIFICATION 系統通知 5 ... ... ... durationHint
(PS:重要參數):
可選值有以下五個:
(1)AUDIOFOCUS_GAIN
: 此參數表示希望申請一個永久的音頻焦點,并且希望上一個持有音頻焦點的App停止播放;例如在需要播放音樂時。
(2)AUDIOFOCUS_GAIN_TRANSIENT
:表示申請一個短暫的音頻焦點,并且馬上就會被釋放,此時希望上一個持有音頻焦點的App暫停播放。例如播放一個提醒聲音。
(3)AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
:效果同AUDIOFOCUS_GAIN_TRANSIENT
,只是希望上一個持有焦點的App減小其播放聲音(但仍可以播放),此時會混音播放。例如導航播報。
(4)AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
: 表示申請一個短暫的音頻焦點,并且會希望系統不要播放任何突然的聲音(例如通知,提醒等),例如用戶在錄音。返回值:
AUDIOFOCUS_REQUEST_GRANTED
或者AUDIOFOCUS_REQUEST_FAILED
。
abandonAudioFocus(OnAudioFocusChangeListener l)
參數通上AudioManager.OnAudioFocusChangeListener
.AudioManager.OnAudioFocusChangeListener
:當音頻焦點發生變化時進行onAudioFocusChange(int focusChange)
方法的回調;
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;
}
}
};
實測代碼:
核心是需要把 AudioManager.AUDIOFOCUS_GAIN
改為 AudioManager.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);
}
}
}
參考:
https://segmentfault.com/a/1190000022234509
http://www.lxweimin.com/p/26ea60c499a7
文章到這里就全部講述完啦,若有其他需要交流的可以留言哦~!~!