Use scenario description:
When music needs to be played in applications, there is usually an urgent problem: media focus; if you play music with your own application at the same time with QQ music, who can respond to the media button? It depends on who finally applied for the focus.
First let's see how to request focus, register media keys to listen (when your player plays, call the following code to register to grab the media focus);
audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); mComponentName = new ComponentName(mContext.getPackageName(),MediaButtonIntentReceiver.class.getName()); int result = audioManager .requestAudioFocus(new MyOnAudioFocusChangeListener(), AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); if (AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result) {//At this point, the focus request has been successful if (android.os.Build.VERSION.SDK_INT >= 21) { //Register Media Key API 21+ (Android 5.0) setMediaButtonEvent(); } else { //Register media keys below API 21, usual practice audioManager.registerMediaButtonEventReceiver(mComponentName); } }
Media Focus Change Monitor (see the above code first requests focus, then registers monitor according to API level, so Focus Change Monitor is common here)
class MyOnAudioFocusChangeListener implements AudioManager.OnAudioFocusChangeListener { @Override public void onAudioFocusChange(int focusChange) { switch(focusChange) { case AudioManager.AUDIOFOCUS_GAIN: // Re-focus, restore playback, restore background volume operation break; case AudioManager.AUDIOFOCUS_LOSS: // Permanent loss of focus unless actively retrieved, this situation is grabbed by other players, in order to avoid mixing with other players, music can be paused. break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: // Temporarily losing focus, which is a case where other applications have applied for a brief focus that can lower the background volume break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // Short-term loss of focus, in which other applications apply for short-term focus in the hope that other voices can lower the volume (or turn off the voice) to highlight the voice (such as text message prompts). break; } } }
Prior to API 21, keypress notifications were obtained by broadcasting registration:
public class MediaButtonIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String intentAction = intent.getAction(); if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) { KeyEvent event = (KeyEvent) intent .getParcelableExtra(Intent.EXTRA_KEY_EVENT); if (event == null)return; int keycode = event.getKeyCode(); switch (keycode) { case KeyEvent.KEYCODE_MEDIA_STOP: //CMD STOP break; case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: //CMD TOGGLE PAUSE break; case KeyEvent.KEYCODE_MEDIA_NEXT: //CMD NEXT Here Processing Player Logic Next Song break; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: //CMD PREVIOUS Processing Logic of Player break; case KeyEvent.KEYCODE_MEDIA_PAUSE: //CMD PAUSE Handles Player Logical pause here break; case KeyEvent.KEYCODE_MEDIA_PLAY: //CMD PLAY Processing Player Logic Playback here break; } } }
Next, let's look at API 21 registered media keys listening
If API 21 + uses the above broadcasting registration method, it can also be monitored. The difference is that if other players grab the focus, you won't be able to grab it back.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)//Attention should be paid to affirming API 21 private void setMediaButtonEvent() { session = new MediaSession(mContext, "Write a random string tag Just go"); session.setCallback(new MediaSession.Callback() { @Override public void onPlay() { super.onPlay(); //Processing player logic playback here updatePlaybackState(true);//Play pause update control center playback status } @Override public void onPause() { super.onPause(); //Processing Player Logical pause here updatePlaybackState(false);//Play pause update control center playback status } @Override public void onSkipToNext() { super.onSkipToNext(); //CMD NEXT Here Processing Player Logic Next Song } @Override public void onSkipToPrevious() { super.onSkipToPrevious(); //Here's how to deal with the logic of the player } }); }
Play the playback status logic of the pause update control center (the playback status of the song will be displayed behind the lock screen of the mobile phone):
/* * update mediaCenter state */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void updatePlaybackState(boolean isPlaying) { PlaybackState.Builder stateBuilder = new PlaybackState.Builder() .setActions(PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS | PlaybackState.CONTENTS_FILE_DESCRIPTOR); if (isPlaying) { stateBuilder.setState(PlaybackState.STATE_PLAYING, PlaybackState.PLAYBACK_POSITION_UNKNOWN, SystemClock.elapsedRealtime()); } else { stateBuilder.setState(PlaybackState.STATE_PAUSED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, SystemClock.elapsedRealtime()); } session.setPlaybackState(stateBuilder.build()); }
Switch the song update control center to play the song information (will display the song name, singer and other information behind the mobile phone lock screen)
//Call this method after clicking Play Register Monitor to grab the media focus @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void updateMediaCenterInfo(String title, String artist) { if (session == null) return; MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder(); metadataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE, title);//Song name metadataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST, artist);//singer session.setMetadata(metadataBuilder.build()); updatePlaybackState(true); }
Finally, you don't need to use media focus to remember to cancel:
@TargetApi(Build.VERSION_CODES.LOLLIPOP) private void unRegisterMediaButton(){ if(audioManager==null|mComponentName==null)return; audioManager.abandonAudioFocus(onAudioFocusChangeListener); audioManager.unregisterMediaButtonEventReceiver(mComponentName); if (session != null) { session.setCallback(null); session.setActive(false); session.release(); } }
MediaSession:
Register the monitor in the way of MediaSession, display the play interface after some mobile phone lock screen without processing, and control the download and pause/play.
Description of official documents:
It allows interaction with media controllers, volume keys, media buttons and transmission controls.
MediaSession should be created when an application wants to publish media playback information or process media keys. Generally speaking, an application only needs one session for all playback, although multiple sessions can be created to provide more sophisticated media control.
Once a session is created, the session owner can pass its session token to other processes to allow them to create a Media Controller to interact with the session.
To receive commands, media keys, and other events, you must set MediaSession.Callback using setCallback and setActive (true).
When the application finishes playing, release () must be called to clear the session and notify any controller.
MediaSession objects are thread-safe.
Author: jarylan
Link: http://www.jianshu.com/p/b52754 c50f89
Source: Brief Book
Copyright belongs to the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.