一景用、控制app的音量與播放
使用硬件音量鍵來(lái)控制音量
需要在Activity或者Fragment創(chuàng)建的時(shí)候就設(shè)置音量控制,這樣確保不管App是否可見(jiàn)览徒,音頻控制功能都正常工作突诬。
setVolumeControlStream(AudioManager.STREAM_MUSIC);
使用硬件的播放控制按鍵來(lái)控制App的音頻播放
無(wú)論用戶通過(guò)手機(jī)或者線控耳機(jī)等按下哪些控制按鈕,比如播放睦袖、暫停珊肃,系統(tǒng)都會(huì)廣播一個(gè)帶有ACTION_MEDIA_BUTTON的Intent。
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Receiver需要判斷廣播來(lái)自哪個(gè)按鈕
public class RemoteControlReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
// Handle key press.
}
}
}
}
如何注冊(cè)監(jiān)聽(tīng)和取消監(jiān)聽(tīng)
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
...
// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
二馅笙、管理音頻焦點(diǎn)
請(qǐng)求獲取音頻焦點(diǎn)
requestAudioFocus() 來(lái)獲取到音頻流焦點(diǎn)伦乔。
- 短暫的焦點(diǎn)鎖定:當(dāng)期待播放一個(gè)短暫的音頻時(shí)候(比如推送聲音)
- 永久的焦點(diǎn)鎖定:當(dāng)計(jì)劃播放可預(yù)期到的較長(zhǎng)的音頻時(shí)候(比如播放音樂(lè))
我們必須在開(kāi)始播放前請(qǐng)求音頻焦點(diǎn),比如用戶此時(shí)點(diǎn)擊了播放按鈕
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
// Start playback.
}
一旦結(jié)束播放董习,需要調(diào)用abandonAudioFocus()方法烈和,通知系統(tǒng)說(shuō)不再需要獲取焦點(diǎn)并且取消注冊(cè)AudioManager.OnAudioFocusChangeListener的焦點(diǎn)。
// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener);
當(dāng)請(qǐng)求短暫音頻焦點(diǎn)皿淋,我們可以選擇是否開(kāi)啟"ducking"招刹,Ducking機(jī)制可以允許音頻間歇性短暫播放∥讶ぃ可以讓其他App繼續(xù)播放疯暑,僅在短暫的時(shí)間內(nèi)降低自己的音量。
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// Start playback.
}
處理失去音頻焦點(diǎn)
- 失去短暫焦點(diǎn):在這種情況下哑舒,暫停當(dāng)前音頻的播放或者降低音量妇拯,需要準(zhǔn)備恢復(fù)播放在重新獲取到焦點(diǎn)之后。
- 失去永久焦點(diǎn):假設(shè)另一個(gè)程序開(kāi)始播放音樂(lè)洗鸵,此時(shí)我們的程序就應(yīng)該徹底結(jié)束越锈。停止播放,放棄自己的音頻焦點(diǎn)膘滨。
- Ducking:降低音量甘凭,讓其余短暫聲音突出,之后恢復(fù)原音量吏祸。
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
// Pause playback
//失去短暫焦點(diǎn)
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
//恢復(fù)焦點(diǎn)
} else if (focusChange==AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
// Lower the volume
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
// 失去永久焦點(diǎn)
}
}
};
三对蒲、音頻設(shè)備的相關(guān)問(wèn)題
檢測(cè)目前正在使用的硬件設(shè)備
可以使用AudioManager來(lái)查詢某個(gè)音頻是否輸出到揚(yáng)聲器钩蚊,有線耳機(jī)還是藍(lán)牙上。
if (isBluetoothA2dpOn()) {
// Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
// Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
// Adjust output for headsets
} else {
// If audio plays and noone can hear it, is it still playing?
}
處理音頻輸出設(shè)備的改變
當(dāng)耳機(jī)線被拔出蹈矮,或者藍(lán)牙耳機(jī)連接斷開(kāi)時(shí)砰逻,如果在播放音樂(lè)/視頻,為了用戶體驗(yàn)泛鸟,避免突如其來(lái)的揚(yáng)聲器播放蝠咆,我們通常做法是暫停此時(shí)正在播放的音樂(lè)/視頻。
在這種情況下北滥,系統(tǒng)會(huì)廣播帶有ACTION_AUDIO_BECOMING_NOISY的intent刚操。我們只需要接受這種廣播,對(duì)其進(jìn)行處理即可再芋。
private class NoisyAudioStreamReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
// Pause the playback
}
}
}
private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private void startPlayback() {
registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
}
private void stopPlayback() {
unregisterReceiver(myNoisyAudioStreamReceiver);
}