Guo Xiaoxing
Weibo: Guo Xiaoxing's Sina Weibo
Email:[email protected]
Blog: http://blog.csdn.net/allenwells
Github:https://github.com/allenwells
Android has maintained an isolated audio stream for playing music, alarms, notification bells, incoming calls, system sounds, call sounds, and DTMF channels, which is the premise that we can control different audio, most of which are system-limited and cannot be used indiscriminately.
One audio control
By default, pressing the volume Control key adjusts the currently activated audio stream, and if our app does not play any sound, it will adjust the sound of the alarm. If it is a game or music program, you will need to adjust the volume keys of your hardware, regardless of whether you are playing a song or whether the game is currently making a sound.
Android provides the Setvolumecontrolstream () method to directly control the specified audio stream, and we need to set the volume control when the activity or fragment is created, after identifying which audio stream the app is using. This ensures that the app is visible and the audio function works as follows:
setVolumeControlStream(AudioManager.STREAM_MUSIC);
The common media playback controls are as follows:
- Play
- Pause
- Stop
- Skip
- Previous
When we do this in software or hardware (headset line control, etc.), the system broadcasts a Action_media_button intent, in response to those operations, You need to register a broadcastreceiver in the Androidmanifest.xml file as follows:
<receiver android:name=".RemoteControlReceiver"> <intent-filter> <action android:name="android.intent.action.MEDIA_BUTTON" /> </intent-filter></receiver>
Receiver needs to determine which button the broadcast is from, intent contains KEY information in Extra_key_event, and the KeyEvent class contains a column of Keycode_media_ static variables to represent different media buttons. As shown below:
public class remotecontrolreceiver extends broadcastreceiver { @Override public void onreceive (context context, Intent Intent) {if (Intent.ACTION_MEDIA_BUTTON.equals (Intent.getaction ())) {KeyEvent event = (keyevent) in Tent.getparcelableextra (intent.extra_key_event); if (Keyevent.keycode_media_play = = Event.getkeycode ()) {//Handle Key Press. } } }}
Because there may be multiple programs that are also listening to which control buttons, it is necessary to deliberately control which receiver in the code is currently responding, that is, the need for timely registration monitoring and cancellation of listening, as follows:
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);...for button pressesam.registerMediaButtonEventReceiver(RemoteControlReceiver);...for button pressesam.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
Two audio focus
When multiple audio plays audio, their interactions are important to the user experience, and to prevent multiple apps from playing audio at the same time, Android uses focus audio to control audio playback, and only apps that have audio focus can play The process for playing audio is as follows:
- Make a request
- Accept Request
- Audio Focus Lock
2.1 Request for Audio focus
Before the app plays audio. We need to get the audio focus of the audio stream it will use. By using the Requsetaudiofocus () method to get the desired audio focus, the method returns audiofocus_request_granted if the request succeeds.
When requesting the focus, we need to determine which focus type is requested, as follows:
- Short Focus Lock: When you expect to play a short audio, for example, play a navigation prompt.
- Open ducking short focus Lock: When requesting a short audio focus, we can choose whether to turn on ducking.
Ducking is a special mechanism that allows for transient playback of audio intermittently. Normally, a good app will be quiet as soon as it loses its audio focus. If we choose to turn on ducking when we request a short audio focus, it means that the other app can continue to play, just to lower its volume at this moment and return to normal volume after a brief re-acquisition of the audio focus.
That is, ignore the request for a short focus, this does not lead to the current playback of the audio is pinned, such as when playing music suddenly appear a short text message prompt sound, this time just to play the volume of the song temporarily lowered, so that the text message can be heard by the user, then immediately resume normal playback.
- Permanent focus Lock: When you plan to play long audio that you anticipate, such as playing music.
Example 1
When playing music, request a permanent audio focus, as shown below:
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);...for playbackint 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 the playback is over, we need to make sure to call the Abandonaudiofocus () method. This notifies the system that you no longer need to get the focus and unregister audiomanager.onaudiofocuschangelistener for monitoring. This allows any interrupted app to continue playing, in the event of releasing a short audio focus.
Abandonwhen playback completeam.abandonAudioFocus(afChangeListener);
Example 2
Turn on the short focus lock for ducking as follows:
// Request audio focus for playbackint 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.}
2.2 Handling lost audio focus
In the listener for the audio focus, the Onaudiofocuschange () callback method is triggered when the event that describes the focus change is received, and there are three types of lost focus, as follows:
- Momentary loss of focus: Usually we pause the playback of the current audio or lower the volume when the focus is lost, and we need to be ready to resume playback after the focus is regained.
- The momentary loss of focus on ducking: ducking is a special mechanism that allows intermittent playback of audio. In the case of ducking, the normally played song will lower the volume to highlight the short audio sound, so that this short-term sound is more prominent, without interrupting the normal sound.
- Permanent loss of Focus: Suppose another program starts playing music, then our program should effectively end itself. It is common practice to remove the button listener, allowing the new audio player to listen exclusively to those buttons for the time, and discard its own audio focus, in this case, before re-playing your audio. We need to make sure that the user clicks the app's play button again.
Example 1
Momentary loss of focus, as follows:
Onaudiofocuschangelistener Afchangelistener =NewOnaudiofocuschangelistener () { Public void Onaudiofocuschange(intFocuschange) {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} }};
Example 2
The player lowers the volume while temporarily losing focus and restores the original volume after the audio focus is regained, as shown below:
new OnAudioFocusChangeListener() { publicvoidonAudioFocusChange(int focusChange) { if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK // Lower the volume elseif (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Raise it back to normal } }};
Three Audio Devices
Users have multiple choices when playing music and can use built-in speakers, wired headphones or A2DP Bluetooth headphones.
A2DP (Advanced Audio distribution Profile) is a Bluetooth audio transmission model Agreement, A2DP is able to use the chip inside the headset to stack data to achieve high-definition sound. The headset with A2DP is a Bluetooth stereo headset. Sound can reach 44.1kHz, the average headset can only reach 8kHz. If your phone supports Bluetooth, you can use the A2DP headset as long as the A2DP protocol is loaded.
3.1 Detecting audio output device
Selecting an audio output device affects the behavior of the app, and you can use Audiomanager to query whether an audio is output to a speaker, a wired headset, or a Bluetooth, as follows:
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?}
2.2 Handling changes to audio devices
When the wired headset is unplugged or the Bluetooth device is disconnected, the audio stream is automatically output to the built-in speakers. Assuming that the sound is very loud before, this time suddenly turn to the speaker playback will appear very noisy. The Android system broadcasts a intent with Action_audio_becoming_noisy when that event occurs. It is a good practice to listen to the intent whenever you play the audio to register a broadcastreceiver.
Under music player, users usually want to be able to pause the playback of the current song when something like that happens. In the game, you usually choose to reduce the amount of bass.
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} }}PrivateIntentfilter Intentfilter =NewIntentfilter (Audiomanager.action_audio_becoming_noisy);Private void Startplayback() {Registerreceiver (Mynoisyaudiostreamreceiver (), intentfilter);}Private void Stopplayback() {unregisterreceiver (mynoisyaudiostreamreceiver);}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
"Android App Development technology: Media Development" audio