最近打算做一個日語學習的應用,用來輔助我學習日語,主要是播放前文、單詞什么的,最好lrc能配合滾動,因此學習一下MediaPlayer。
一、Controlling Your App’s Volume and Playback
setVolumeControlStream() 音量控制
setVolumeControlStream(AudioManager.STREAM_MUSIC);
在初始化的onCreate()中調(diào)用,只需調(diào)用一次
Use Hardware Playback Control Keys to Control Your App’s Audio Playback
二、Managing Audio Focus
-
Request the Audio Focus
在你的app開始播放任何audio前,應該獲取當前正在使用的流的音頻焦點[requestAudioFocus](https://developer.android.com/reference/android/media/AudioManager.html?hl=zh-cn#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int)),返回AUDIOFOCUS_REQUEST_GRANTED
RequestAudioFocus
翻譯好難還是直接看原文吧。。
You must specify which stream you're using and whether you expect to require transient(短暫) or permanent(常駐) audio focus. Request transient focus when you expect to play audio for only a short time (for example when playing navigation(導航) instructions(說明). Request permanent audio focus when you plan to play audio for the foreseeable(可預見的) future (for example, when playing music).
The following snippet(片段) requests permanent audio focus on the music audio stream. You should request the audio focus immediately before you begin playback, such as when the user presses play or the background music for the next game level begins.
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.registerMediaButtonEventReceiver(RemoteControlReceiver);
// Start playback.
}
Once you've finished playback be sure to call abandonAudioFocus(). This notifies the system that you no longer require focus and unregisters the associated AudioManager.OnAudioFocusChangeListener. In the case of abandoning transient focus, this allows any interupted app to continue playback.(為了防止放棄短暫焦點,它允許任何中斷的app能夠繼續(xù)回放)
// Abandon audio focus when playback complete
am.abandonAudioFocus(afChangeListener);
When requesting transient audio focus you have an additional option: whether or not you want to enable "ducking(低頭,閃避)." Normally, when a well-behaved audio app loses audio focus it immediately silences its playback. By requesting a transient audio focus that allows ducking you tell other audio apps that it’s acceptable for them to keep playing, provided they lower their volume until the focus returns to them.
// 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.
}
Ducking is particularly suitable for apps that use the audio stream intermittently(間歇的), such as for audible(能聽到的) driving directions.
Whenever another app requests audio focus as described(描述) above, its choice between permanent and transient (with or without support for ducking) audio focus is received by the listener you registered when requesting focus.
- Handle the Loss(損失) of Audio Focus
If your app can request audio focus, it follows that it will in turn lose that focus when another app requests it. How your app responds to a loss of audio focus depends on the manner of that loss.
The onAudioFocusChange() callback method of the audio focus change listener you registered when requesting audio focus receives a parameter that describes the focus change event(收到一個描述焦點改變事件的參數(shù)). Specifically, the possible focus loss events mirror(反映) the focus request types from the previous section—permanent loss, transient loss, and transient with ducking permitted.(特別地,那個可能的焦點事件跟前面的請求類型有關,短暫、常駐還是常駐躲避)
Generally speaking, a transient (temporary) loss of audio focus should result in your app silencing it’s audio stream, but otherwise maintaining the same state. You should continue to monitor changes in audio focus and be prepared to resume playback where it was paused once you’ve regained the focus.
(通常來說,audio focus的transient loss會導致播放暫停,但是除此以外維持同樣的狀態(tài)。你應該繼續(xù)監(jiān)視audio focus變化,在你暫停的地方準備恢復播放 當你重新獲取到焦點時。)
If the audio focus loss is permanent, it’s assumed that another application is now being used to listen to audio and your app should effectively end itself. In practical terms, that means stopping playback, removing media button listeners—allowing the new audio player to exclusively(獨占,只,僅僅) handle those events—and abandoning your audio focus. At that point, you would expect a user action (pressing play in your app) to be required before you resume playing audio.
(如果是permanent loss,它被假定為另一個應用現(xiàn)在正在聽音頻,你的app應該有效的結束它自己。在實際項目中,這意味著停止播放,移除media button監(jiān)聽器——允許新的音頻播放器獨占處理這些事件——放棄你的音頻焦點。在那時候,你應該期望用戶行為(在你app里點擊播放)在你重新播放之前。)
In the following code snippet, we pause the playback or our media player object if the audio loss is transient and resume it when we have regained the focus. If the loss is permanent, it unregisters our media button event receiver and stops monitoring audio focus changes.
AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT) {
// Pause playback
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
}
}
};
In the case of a transient loss of audio focus where ducking is permitted, rather than pausing playback, you can "duck" instead.
- Duck!
Ducking is the process of lowering your audio stream output volume to make transient audio from another app easier to hear without totally disrupting the audio from your own application.
(Ducking 是降低你的音頻音量,使其它app的短暫音頻更容易被聽到,而不完全被你的音頻干擾。)
In the following code snippet lowers the volume on our media player object when we temporarily lose focus, then returns it to its previous level when we regain focus.
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
// Lower the volume
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Raise it back to normal
}
}
};
A loss of audio focus is the most important broadcast to react to, but not the only one. The system broadcasts a number of intents to alert you to changes in user’s audio experience. The next lesson demonstrates(演示) how to monitor them to improve the user’s overall experience.
三、Dealing with Audio Output Hardware
- Check What Hardware is Being Used
How your app behaves might be affected by which hardware its output is being routed to.
You can query the AudioManager to determine if the audio is currently being routed to the device speaker, wired headset(有線耳機), or attached Bluetooth device as shown in the following snippet(代碼段):
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?
}
- Handle Changes in the Audio Output Hardware
When a headset is unplugged(拔出), or a Bluetooth device disconnected, the audio stream automatically reroutes to the built in speaker. If you listen to your music at as high a volume as I do, that can be a noisy surprise.
Luckily the system broadcasts an ACTION_AUDIO_BECOMING_NOISY intent when this happens. It’s good practice to register a BroadcastReceiver that listens for this intent whenever you’re playing audio. In the case of music players, users typically expect the playback to be paused—while for games you may choose to significantly(顯著地) lower the volume.
(當你的耳機被拔出,斷開藍牙時,暫停播放)
