publicfinalclassMyServiceextendsService{privatestaticMediaSession s_mediaSession;@OverridepublicvoidonCreate(){// Instantiate new MediaSession object.configureMediaSession();}@OverridepublicvoidonDestroy(){if(s_mediaSession !=null)
s_mediaSession.release();}}
The following method instantiates and configures the MediaSession button callbacks:
privatevoid configureMediaSession {
s_mediaSession =newMediaSession(this,"MyMediaSession");// Overridden methods in the MediaSession.Callback class.
s_mediaSession.setCallback(newMediaSession.Callback(){@OverridepublicbooleanonMediaButtonEvent(Intent mediaButtonIntent){Log.d(TAG,"onMediaButtonEvent called: "+ mediaButtonIntent);KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);if(ke !=null&& ke.getAction()==KeyEvent.ACTION_DOWN){int keyCode = ke.getKeyCode();Log.d(TAG,"onMediaButtonEvent Received command: "+ ke);}returnsuper.onMediaButtonEvent(mediaButtonIntent);}@OverridepublicvoidonSkipToNext(){Log.d(TAG,"onSkipToNext called (media button pressed)");Toast.makeText(getApplicationContext(),"onSkipToNext called",Toast.LENGTH_SHORT).show();skipToNextPlaylistItem();// Handle this button press.super.onSkipToNext();}@OverridepublicvoidonSkipToPrevious(){Log.d(TAG,"onSkipToPrevious called (media button pressed)");Toast.makeText(getApplicationContext(),"onSkipToPrevious called",Toast.LENGTH_SHORT).show();skipToPreviousPlaylistItem();// Handle this button press.super.onSkipToPrevious();}@OverridepublicvoidonPause(){Log.d(TAG,"onPause called (media button pressed)");Toast.makeText(getApplicationContext(),"onPause called",Toast.LENGTH_SHORT).show();mpPause();// Pause the player.super.onPause();}@OverridepublicvoidonPlay(){Log.d(TAG,"onPlay called (media button pressed)");mpStart();// Start player/playback.super.onPlay();}@OverridepublicvoidonStop(){Log.d(TAG,"onStop called (media button pressed)");mpReset();// Stop and/or reset the player.super.onStop();}});
s_mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
s_mediaSession.setActive(true);}
The following method sends meta data (stored in a HashMap(opens new window)) to the device using A2DP:
voidsendMetaData(@NonNullfinalHashMap<String,String> hm){// Return if Bluetooth A2DP is not in use.if(!((AudioManager)getSystemService(Context.AUDIO_SERVICE)).isBluetoothA2dpOn())return;MediaMetadata metadata =newMediaMetadata.Builder().putString(MediaMetadata.METADATA_KEY_TITLE, hm.get("Title")).putString(MediaMetadata.METADATA_KEY_ALBUM, hm.get("Album")).putString(MediaMetadata.METADATA_KEY_ARTIST, hm.get("Artist")).putString(MediaMetadata.METADATA_KEY_AUTHOR, hm.get("Author")).putString(MediaMetadata.METADATA_KEY_COMPOSER, hm.get("Composer")).putString(MediaMetadata.METADATA_KEY_WRITER, hm.get("Writer")).putString(MediaMetadata.METADATA_KEY_DATE, hm.get("Date")).putString(MediaMetadata.METADATA_KEY_GENRE, hm.get("Genre")).putLong(MediaMetadata.METADATA_KEY_YEAR,tryParse(hm.get("Year"))).putLong(MediaMetadata.METADATA_KEY_DURATION,tryParse(hm.get("Raw Duration"))).putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER,tryParse(hm.get("Track Number"))).build();
s_mediaSession.setMetadata(metadata);}
The following method sets the PlaybackState(opens new window). It also sets which button actions the MediaSession will respond to:
privatevoidsetPlaybackState(@NonNullfinalint stateValue){PlaybackState state =newPlaybackState.Builder().setActions(PlaybackState.ACTION_PLAY |PlaybackState.ACTION_SKIP_TO_NEXT
|PlaybackState.ACTION_PAUSE |PlaybackState.ACTION_SKIP_TO_PREVIOUS
|PlaybackState.ACTION_STOP |PlaybackState.ACTION_PLAY_PAUSE).setState(stateValue,PlaybackState.PLAYBACK_POSITION_UNKNOWN,0).build();
s_mediaSession.setPlaybackState(state);}
For best practice, use the media-compat library. The library takes care of backward compatibility by translating media session methods to the equivalent methods on older platform versions when available.