最近打算做一个日语学习的应用,用来辅助我学习日语,主要是播放前文、单词什么的,最好lrc能配合滚动,因此学习一下MediaPlayer。
一、Controlling Your App’s Volume and Playback
setVolumeControlStream() 音量控制
setVolumeControlStream(AudioManager.STREAM_MUSIC);
在初始化的onCreate()中调用,只需调用一次
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
翻译好难还是直接看原文吧。。
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能够继续回放)
// 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(收到一个描述焦点改变事件的参数). 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会导致播放暂停,但是除此以外维持同样的状态。你应该继续监视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,它被假定为另一个应用现在正在听音频,你的app应该有效的结束它自己。在实际项目中,这意味着停止播放,移除media button监听器——允许新的音频播放器独占处理这些事件——放弃你的音频焦点。在那时候,你应该期望用户行为(在你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.
(当你的耳机被拔出,断开蓝牙时,暂停播放)