use of android.support.v4.media.session.MediaSessionCompat in project kdeconnect-android by KDE.
the class MprisMediaSession method updateMediaNotification.
/**
* Update the media control notification
*/
private void updateMediaNotification() {
BackgroundService.RunCommand(context, service -> {
// If the user disabled the media notification, do not show it
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (!prefs.getBoolean(context.getString(R.string.mpris_notification_key), true)) {
closeMediaNotification();
return;
}
// Make sure our information is up-to-date
updateCurrentPlayer(service);
// If the player disappeared (and no other playing one found), just remove the notification
if (notificationPlayer == null) {
closeMediaNotification();
return;
}
// Update the metadata and playback status
if (mediaSession == null) {
mediaSession = new MediaSessionCompat(context, MPRIS_MEDIA_SESSION_TAG);
mediaSession.setCallback(mediaSessionCallback);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
MediaMetadataCompat.Builder metadata = new MediaMetadataCompat.Builder();
// Fallback because older KDE connect versions do not support getTitle()
if (!notificationPlayer.getTitle().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, notificationPlayer.getTitle());
} else {
metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, notificationPlayer.getCurrentSong());
}
if (!notificationPlayer.getArtist().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, notificationPlayer.getArtist());
metadata.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, notificationPlayer.getArtist());
}
if (!notificationPlayer.getAlbum().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, notificationPlayer.getAlbum());
}
if (notificationPlayer.getLength() > 0) {
metadata.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, notificationPlayer.getLength());
}
Bitmap albumArt = notificationPlayer.getAlbumArt();
if (albumArt != null) {
metadata.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt);
}
mediaSession.setMetadata(metadata.build());
PlaybackStateCompat.Builder playbackState = new PlaybackStateCompat.Builder();
if (notificationPlayer.isPlaying()) {
playbackState.setState(PlaybackStateCompat.STATE_PLAYING, notificationPlayer.getPosition(), 1.0f);
} else {
playbackState.setState(PlaybackStateCompat.STATE_PAUSED, notificationPlayer.getPosition(), 0.0f);
}
// Create all actions (previous/play/pause/next)
Intent iPlay = new Intent(service, MprisMediaNotificationReceiver.class);
iPlay.setAction(MprisMediaNotificationReceiver.ACTION_PLAY);
iPlay.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPlay.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPlay = PendingIntent.getBroadcast(service, 0, iPlay, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPlay = new NotificationCompat.Action.Builder(R.drawable.ic_play_white, service.getString(R.string.mpris_play), piPlay);
Intent iPause = new Intent(service, MprisMediaNotificationReceiver.class);
iPause.setAction(MprisMediaNotificationReceiver.ACTION_PAUSE);
iPause.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPause.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPause = PendingIntent.getBroadcast(service, 0, iPause, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPause = new NotificationCompat.Action.Builder(R.drawable.ic_pause_white, service.getString(R.string.mpris_pause), piPause);
Intent iPrevious = new Intent(service, MprisMediaNotificationReceiver.class);
iPrevious.setAction(MprisMediaNotificationReceiver.ACTION_PREVIOUS);
iPrevious.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPrevious.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPrevious = PendingIntent.getBroadcast(service, 0, iPrevious, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPrevious = new NotificationCompat.Action.Builder(R.drawable.ic_previous_white, service.getString(R.string.mpris_previous), piPrevious);
Intent iNext = new Intent(service, MprisMediaNotificationReceiver.class);
iNext.setAction(MprisMediaNotificationReceiver.ACTION_NEXT);
iNext.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iNext.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piNext = PendingIntent.getBroadcast(service, 0, iNext, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aNext = new NotificationCompat.Action.Builder(R.drawable.ic_next_white, service.getString(R.string.mpris_next), piNext);
Intent iOpenActivity = new Intent(service, MprisActivity.class);
iOpenActivity.putExtra("deviceId", notificationDevice);
iOpenActivity.putExtra("player", notificationPlayer.getPlayer());
/*
TODO: Remove when Min SDK >= 16
The only way the intent extra's are delivered on API 14 and 15 is by either using a different requestCode every time
or using PendingIntent.FLAG_CANCEL_CURRENT instead of PendingIntent.FLAG_UPDATE_CURRENT
*/
PendingIntent piOpenActivity = TaskStackBuilder.create(context).addNextIntentWithParentStack(iOpenActivity).getPendingIntent(Build.VERSION.SDK_INT > 15 ? 0 : (int) System.currentTimeMillis(), PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NotificationHelper.Channels.MEDIA_CONTROL);
notification.setAutoCancel(false).setContentIntent(piOpenActivity).setSmallIcon(R.drawable.ic_play_white).setShowWhen(false).setColor(ContextCompat.getColor(service, R.color.primary)).setVisibility(androidx.core.app.NotificationCompat.VISIBILITY_PUBLIC).setSubText(service.getDevice(notificationDevice).getName());
if (!notificationPlayer.getTitle().isEmpty()) {
notification.setContentTitle(notificationPlayer.getTitle());
} else {
notification.setContentTitle(notificationPlayer.getCurrentSong());
}
// Only set the notification body text if we have an author and/or album
if (!notificationPlayer.getArtist().isEmpty() && !notificationPlayer.getAlbum().isEmpty()) {
notification.setContentText(notificationPlayer.getArtist() + " - " + notificationPlayer.getAlbum() + " (" + notificationPlayer.getPlayer() + ")");
} else if (!notificationPlayer.getArtist().isEmpty()) {
notification.setContentText(notificationPlayer.getArtist() + " (" + notificationPlayer.getPlayer() + ")");
} else if (!notificationPlayer.getAlbum().isEmpty()) {
notification.setContentText(notificationPlayer.getAlbum() + " (" + notificationPlayer.getPlayer() + ")");
} else {
notification.setContentText(notificationPlayer.getPlayer());
}
if (albumArt != null) {
notification.setLargeIcon(albumArt);
}
if (!notificationPlayer.isPlaying()) {
Intent iCloseNotification = new Intent(service, MprisMediaNotificationReceiver.class);
iCloseNotification.setAction(MprisMediaNotificationReceiver.ACTION_CLOSE_NOTIFICATION);
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piCloseNotification = PendingIntent.getBroadcast(service, 0, iCloseNotification, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setDeleteIntent(piCloseNotification);
}
// Add media control actions
int numActions = 0;
long playbackActions = 0;
if (notificationPlayer.isGoPreviousAllowed()) {
notification.addAction(aPrevious.build());
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
++numActions;
}
if (notificationPlayer.isPlaying() && notificationPlayer.isPauseAllowed()) {
notification.addAction(aPause.build());
playbackActions |= PlaybackStateCompat.ACTION_PAUSE;
++numActions;
}
if (!notificationPlayer.isPlaying() && notificationPlayer.isPlayAllowed()) {
notification.addAction(aPlay.build());
playbackActions |= PlaybackStateCompat.ACTION_PLAY;
++numActions;
}
if (notificationPlayer.isGoNextAllowed()) {
notification.addAction(aNext.build());
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
++numActions;
}
// Documentation says that this was added in Lollipop (21) but it seems to cause crashes on < Pie (28)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (notificationPlayer.isSeekAllowed()) {
playbackActions |= PlaybackStateCompat.ACTION_SEEK_TO;
}
}
playbackState.setActions(playbackActions);
mediaSession.setPlaybackState(playbackState.build());
// Only allow deletion if no music is notificationPlayer
notification.setOngoing(notificationPlayer.isPlaying());
// Use the MediaStyle notification, so it feels like other media players. That also allows adding actions
MediaStyle mediaStyle = new MediaStyle();
if (numActions == 1) {
mediaStyle.setShowActionsInCompactView(0);
} else if (numActions == 2) {
mediaStyle.setShowActionsInCompactView(0, 1);
} else if (numActions >= 3) {
mediaStyle.setShowActionsInCompactView(0, 1, 2);
}
mediaStyle.setMediaSession(mediaSession.getSessionToken());
notification.setStyle(mediaStyle);
notification.setGroup("MprisMediaSession");
// Display the notification
mediaSession.setActive(true);
final NotificationManager nm = ContextCompat.getSystemService(context, NotificationManager.class);
nm.notify(MPRIS_MEDIA_NOTIFICATION_ID, notification.build());
});
}
use of android.support.v4.media.session.MediaSessionCompat in project kdeconnect-android by KDE.
the class MprisMediaNotificationReceiver method onReceive.
@Override
public void onReceive(Context context, Intent intent) {
// First case: buttons send by other applications via the media session APIs
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
// Route these buttons to the media session, which will handle them
MediaSessionCompat mediaSession = MprisMediaSession.getMediaSession();
if (mediaSession == null)
return;
mediaSession.getController().dispatchMediaButtonEvent(intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT));
} else {
// Second case: buttons on the notification, which we created ourselves
// Get the correct device, the mpris plugin and the mpris player
BackgroundService service = BackgroundService.getInstance();
if (service == null)
return;
Device device = service.getDevice(intent.getStringExtra(EXTRA_DEVICE_ID));
if (device == null)
return;
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null)
return;
MprisPlugin.MprisPlayer player = mpris.getPlayerStatus(intent.getStringExtra(EXTRA_MPRIS_PLAYER));
if (player == null)
return;
// Forward the action to the player
switch(intent.getAction()) {
case ACTION_PLAY:
player.play();
break;
case ACTION_PAUSE:
player.pause();
break;
case ACTION_PREVIOUS:
player.previous();
break;
case ACTION_NEXT:
player.next();
break;
case ACTION_CLOSE_NOTIFICATION:
// The user dismissed the notification: actually handle its removal correctly
MprisMediaSession.getInstance().closeMediaNotification();
}
}
}
use of android.support.v4.media.session.MediaSessionCompat in project cordova-plugin-local-notifications by katzer.
the class Options method getMediaSessionToken.
/**
* Gets the token for the specified media session.
*
* @return null if there no session.
*/
MediaSessionCompat.Token getMediaSessionToken() {
String tag = options.optString("mediaSession", null);
if (tag == null)
return null;
MediaSessionCompat session = new MediaSessionCompat(context, tag);
return session.getSessionToken();
}
use of android.support.v4.media.session.MediaSessionCompat in project Signal-Android by WhisperSystems.
the class VoiceNotePlaybackService method onCreate.
@Override
public void onCreate() {
super.onCreate();
mediaSession = new MediaSessionCompat(this, TAG);
voiceNotePlaybackParameters = new VoiceNotePlaybackParameters(mediaSession);
mediaSessionConnector = new MediaSessionConnector(mediaSession);
becomingNoisyReceiver = new BecomingNoisyReceiver(this, mediaSession.getSessionToken());
keyClearedReceiver = new KeyClearedReceiver(this, mediaSession.getSessionToken());
player = new VoiceNotePlayer(this);
voiceNoteNotificationManager = new VoiceNoteNotificationManager(this, mediaSession.getSessionToken(), new VoiceNoteNotificationManagerListener());
voiceNotePlaybackPreparer = new VoiceNotePlaybackPreparer(this, player, voiceNotePlaybackParameters);
player.addListener(new VoiceNotePlayerEventListener());
mediaSessionConnector.setPlayer(player);
mediaSessionConnector.setEnabledPlaybackActions(SUPPORTED_ACTIONS);
mediaSessionConnector.setPlaybackPreparer(voiceNotePlaybackPreparer);
mediaSessionConnector.setQueueNavigator(new VoiceNoteQueueNavigator(mediaSession));
VoiceNotePlaybackController voiceNotePlaybackController = new VoiceNotePlaybackController(player.getInternalPlayer(), voiceNotePlaybackParameters);
mediaSessionConnector.registerCustomCommandReceiver(voiceNotePlaybackController);
setSessionToken(mediaSession.getSessionToken());
mediaSession.setActive(true);
keyClearedReceiver.register();
}
use of android.support.v4.media.session.MediaSessionCompat in project zype-android by zype.
the class PlayerFragment method initMediaSession.
private void initMediaSession() {
// ComponentName mediaButtonReceiver = new ComponentName(getContext().getApplicationContext(),
// MediaButtonReceiver.class);
ComponentName mediaButtonReceiver = new ComponentName(getContext().getApplicationContext(), RemoteControlReceiver.class);
mediaSession = new MediaSessionCompat(getContext().getApplicationContext(), "TAG_MEDIA_SESSION", mediaButtonReceiver, null);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setClass(getActivity(), RemoteControlReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 0, mediaButtonIntent, 0);
mediaSession.setMediaButtonReceiver(pendingIntent);
PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PLAY_PAUSE);
mediaSession.setPlaybackState(stateBuilder.build());
mediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
super.onPlay();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
super.onPlayFromMediaId(mediaId, extras);
}
@Override
public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
return super.onMediaButtonEvent(mediaButtonEvent);
}
});
MediaControllerCompat mediaController = new MediaControllerCompat(getActivity(), mediaSession);
MediaControllerCompat.setMediaController(getActivity(), mediaController);
}
Aggregations