J'utilise MediaSessionCompat
de AppCompat Support Library Revision 22. Et sur Lollipop, je reçois une notification et l'arrière-plan de lockscreen est la pochette de l'album. Et tout fonctionne bien.
Sur les appareils Pre-Lollipop, les commandes de musique sur l'écran de verrouillage ne sont pas du tout affichées. C'est bizarre et j'ai tout essayé mais ça n'apparaît pas, pas même le fond change.
J'espère que quelqu'un a une solution à ce problème.
Remarque: RemoteControlClient
utilisé pour travailler sur Lollipop & KitKat
/**
* Initializes the remote control client
*/
private void setupMediaSession() {
/* Activate Audio Manager */
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
ComponentName mRemoteControlResponder = new ComponentName(getPackageName(),
MediaButtonReceiver.class.getName());
final Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(mRemoteControlResponder);
mMediaSessionCompat = new MediaSessionCompat(getApplication(), "JairSession", mRemoteControlResponder, null);
mMediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
PlaybackStateCompat playbackStateCompat = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_SEEK_TO |
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_STOP
)
.setState(
isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
getCurrentPosition(),
1.0f)
.build();
mMediaSessionCompat.setPlaybackState(playbackStateCompat);
mMediaSessionCompat.setCallback(mMediaSessionCallback);
mMediaSessionCompat.setSessionActivity(retrievePlaybackActions(5));
mMediaSessionCompat.setActive(true);
updateMediaSessionMetaData();
mTransportController = mMediaSessionCompat.getController().getTransportControls();
Voici la updateMediaSessionMetaData()
:
/**
* Updates the lockscreen controls, if enabled.
*/
private void updateMediaSessionMetaData() {
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, getArtistName());
builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, getAlbumName());
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, getTrackName());
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, getDuration());
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, MusicUtils.getArtwork(this, getAlbumID(), true));
mMediaSessionCompat.setMetadata(builder.build());
}
Les méthodes de rappel de session multimédia
private final MediaSessionCompat.Callback mMediaSessionCallback = new MediaSessionCompat.Callback() {
@Override
public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
final String intentAction = mediaButtonEvent.getAction();
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {
if (PrefUtils.isHeadsetPause(getBaseContext())) {
Log.d(LOG_TAG, "Headset disconnected");
pause();
}
} else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
final KeyEvent event = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) return super.onMediaButtonEvent(mediaButtonEvent);
final int keycode = event.getKeyCode();
final int action = event.getAction();
final long eventTime = event.getEventTime();
if (event.getRepeatCount() == 0 && action == KeyEvent.ACTION_DOWN) {
switch (keycode) {
case KeyEvent.KEYCODE_HEADSETHOOK:
if (eventTime - mLastClickTime < DOUBLE_CLICK) {
playNext(mSongNumber);
mLastClickTime = 0;
} else {
if (isPlaying())
pause();
else resume();
mLastClickTime = eventTime;
}
break;
case KeyEvent.KEYCODE_MEDIA_STOP:
mTransportController.stop();
break;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
if (isMediaPlayerActive()) {
if (isPlaying()) mTransportController.pause();
else mTransportController.play();
}
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
mTransportController.skipToNext();
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
mTransportController.skipToPrevious();
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
mTransportController.pause();
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
mTransportController.play();
break;
}
}
}
return super.onMediaButtonEvent(mediaButtonEvent);
}
@Override
public void onPlay() {
super.onPlay();
resume();
}
@Override
public void onPause() {
super.onPause();
pause();
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
playNext(mSongNumber);
}
@Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
playPrevious(mSongNumber);
}
@Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
seekTo(pos);
}
@Override
public void onStop() {
super.onStop();
pause();
commitMusicData();
updatePlayingUI(STOP_ACTION);
stopSelf();
}
};
Entrée du manifeste du récepteur du bouton multimédia
<!-- Media button receiver -->
<receiver Android:name=".receiver.MediaButtonReceiver" >
<intent-filter>
<action Android:name="Android.intent.action.MEDIA_BUTTON" />
<action Android:name="Android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
J'essaie depuis quelques semaines de résoudre ce problème sans succès et dans un besoin désespéré d'aide.
Modifier: un tutoriel ou un exemple de MediaSessionCompat serait également bien
Enfin, j'ai trouvé une solution pour cela. Merci à @ ianhanniballake & @ user1549672
BroadcastReceiver
peut être trouvé si vous effectuez une recherche sur Google et également sur les documents officiels Android DocssetupMediaSession()
donnée dans ma question ci-dessusFlags
MediaSessionCallbacks
également disponible ci-dessusMediaSession
sur MediaPlayer#onPause()
, MediaPlayer#onStart()
et enfin quand un nouveau morceau est joué (comprend également le jeu suivant et précédent) mentionné par @ user1549672MediaSession
dans onDestory()
Eh bien c'est tout, la plupart du matériel (code) est disponible ci-dessus. Cette question a pris quelques mois à résoudre, enfin c'est fait.
Bien que n'étant pas strictement requis pour MediaSession
, RemoteControlClient
utilisé sur les appareils API14-19, nécessite focus audio et il est fortement recommandé à 100% pour toutes les lectures de médias.
Ajout de lignes telles que:
AudioManager audioManager = (AudioManager)
getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this,
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_GAIN) {
return; //Failed to gain audio focus
}
Avant de jouer, n'importe quel média doit gagner la focalisation audio et afficher les commandes.
Enfin, j'ai obtenu une réponse à la vôtre et à mon problème. Vous devez spécifier des actions (mMediaSessionCompat.setActions (PlaybackStateCompat.ACTION_PLAY_PAUSE) même lors de la mise à jour de la médiasession. Par conséquent, votre code devrait maintenant ressembler à
private void updateMediaSessionMetaData() {
int playState = mPlaying
? PlaybackStateCompat.STATE_PLAYING
: PlaybackStateCompat.STATE_PAUSED;
mMediaSessionCompat.setMetadata(new MediaMetadataCompat.Builder()
.putString(MediaMetadata.METADATA_KEY_ARTIST, getArtist())
.putString(MediaMetadata.METADATA_KEY_ALBUM, getAlbum())
.putString(MediaMetadata.METADATA_KEY_TITLE, getSongTitle())
.putLong(MediaMetadata.METADATA_KEY_DURATION, duration())
.putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, mSongPosn)
.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, songs.size())
.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, albumArt)
.build());
mMediaSessionCompat.setPlaybackState(new PlaybackStateCompat.Builder()
.setState(playState, position(), 1.0f)
.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE| PlaybackStateCompat.ACTION_SKIP_TO_NEXT|PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS).build());
MISE À JOUR: Ajout du code pour MediaCallback & Receiver
private final class MediaSessionCallback extends MediaSessionCompat.Callback {
@Override
public void onPlay() {
pausePlayer();
}
@Override
public void onPause() {
pausePlayer();
}
public void onSeekTo(long pos) {
seek(pos);
}
@Override
public void onSkipToNext() {
playNext();
}
@Override
public void onSkipToPrevious() {
playPrev();
}
}
Destinataire :
public class MusicIntentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
Android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
Intent intent1 = new Intent(MusicService.ACTION_PAUSE);
intent1.setClass(context,
com.xyz.service.MusicService.class);
// send an intent to our MusicService to telling it to pause the
// audio
context.startService(intent1);
} else if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) {
KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(
Intent.EXTRA_KEY_EVENT);
if (keyEvent.getAction() != KeyEvent.ACTION_DOWN)
return;
switch (keyEvent.getKeyCode()) {
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
Intent intentToggle = new Intent(
MusicService.ACTION_TOGGLE_PLAYBACK);
intentToggle.setClass(context,
com.xyz.service.MusicService.class);
context.startService(intentToggle);
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
Intent intentPlay = new Intent(MusicService.ACTION_PLAY);
intentPlay.setClass(context,
com.xyz.service.MusicService.class);
context.startService(intentPlay);
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
Intent intentPause = new Intent(MusicService.ACTION_PAUSE);
intentPause.setClass(context,
com.xyz.service.MusicService.class);
context.startService(intentPause);
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
Intent intentNext = new Intent(MusicService.ACTION_NEXT);
intentNext.setClass(context,
com.xyz.service.MusicService.class);
context.startService(intentNext);
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
Intent intentPrev = new Intent(MusicService.ACTION_PREV);
intentPrev.setClass(context,
com.xyz.service.MusicService.class);
context.startService(intentPrev);
break;
default:
break;
}
}
}
}