Android Registered Media Keyboard Monitor (MediaSession Compatible with Android 5.0+)

Keywords: Session Mobile Android

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.

Posted by cruz610 on Sun, 02 Jun 2019 12:49:38 -0700