mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-25 18:15:49 +01:00
Add handling for media session notifications
Since Android 5.0, media players can have interactive notifications that reside in the notification area, and offer up to 5 control buttons (play/pause, next, previous, etc), and information about the currentlu playing media file. We use these notifications to get information about the currently playing media file such as: - artist - track (title) - album - duration (length of the media file) - play state (playing, paused, stopped) - position - play rate (how fast is the media file being played) We then send this information up to the device. On Pebble, the music app will display the title and the artist, as well as a progress bar showing the current position. The progress bar is animated when the media file is being played, and if it is being paused, it displays a pause symbol. This code will be skipped when GadgetBridge is run on a device with Android version older than 5.0 (lollipop).
This commit is contained in:
parent
73fbaf0a54
commit
fb71cdf55b
@ -11,8 +11,14 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.MediaMetadata;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSession;
|
||||
import android.media.session.PlaybackState;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.MediaStore;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
@ -26,6 +32,7 @@ import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
|
||||
@ -183,10 +190,8 @@ public class NotificationListener extends NotificationListenerService {
|
||||
String source = sbn.getPackageName();
|
||||
Notification notification = sbn.getNotification();
|
||||
|
||||
if (source.equals("au.com.shiftyjelly.pocketcasts")) {
|
||||
if (handlePocketCastNotification(notification))
|
||||
if (handleMediaSessionNotification(notification))
|
||||
return;
|
||||
}
|
||||
|
||||
if ((notification.flags & Notification.FLAG_ONGOING_EVENT) == Notification.FLAG_ONGOING_EVENT) {
|
||||
return;
|
||||
@ -318,32 +323,69 @@ public class NotificationListener extends NotificationListenerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to handle pocket cast notifications that tell info about the current play state.
|
||||
* Try to handle media session notifications that tell info about the current play state.
|
||||
*
|
||||
* @param notification The notification to handle.
|
||||
* @return true if notification was handled, false otherwise
|
||||
*/
|
||||
public boolean handlePocketCastNotification(Notification notification) {
|
||||
public boolean handleMediaSessionNotification(Notification notification) {
|
||||
|
||||
// this code requires Android 5.0 or newer
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MusicSpec musicSpec = new MusicSpec();
|
||||
MusicStateSpec stateSpec = new MusicStateSpec();
|
||||
|
||||
Bundle extras = notification.extras;
|
||||
if (extras == null)
|
||||
return false;
|
||||
|
||||
CharSequence title = extras.getCharSequence(Notification.EXTRA_TITLE);
|
||||
if (title != null)
|
||||
musicSpec.artist = title.toString();
|
||||
if (extras.containsKey(Notification.EXTRA_TEXT)) {
|
||||
CharSequence contentCS = extras.getCharSequence(Notification.EXTRA_TEXT);
|
||||
if (contentCS != null)
|
||||
musicSpec.track = contentCS.toString();
|
||||
if (extras.get(Notification.EXTRA_MEDIA_SESSION) == null)
|
||||
return false;
|
||||
|
||||
MediaController c;
|
||||
try {
|
||||
c = new MediaController(getApplicationContext(), (MediaSession.Token) extras.get(Notification.EXTRA_MEDIA_SESSION));
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
musicSpec.album = "unknown";
|
||||
PlaybackState s = c.getPlaybackState();
|
||||
stateSpec.position = (int)s.getPosition();
|
||||
stateSpec.playRate = Math.round(100 * s.getPlaybackSpeed());
|
||||
stateSpec.repeat = 1;
|
||||
stateSpec.shuffle = 1;
|
||||
switch (s.getState()) {
|
||||
case PlaybackState.STATE_PLAYING:
|
||||
stateSpec.state = 0x01;
|
||||
break;
|
||||
case PlaybackState.STATE_STOPPED:
|
||||
case PlaybackState.STATE_PAUSED:
|
||||
stateSpec.state = 0x00;
|
||||
break;
|
||||
default:
|
||||
stateSpec.state = 0x04;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG.info("handlePocketCastsNotification: artist " + musicSpec.artist + ", track " + musicSpec.track);
|
||||
MediaMetadata d = c.getMetadata();
|
||||
if (d == null)
|
||||
return false;
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_ARTIST))
|
||||
musicSpec.artist = d.getString(MediaMetadata.METADATA_KEY_ARTIST);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_ALBUM))
|
||||
musicSpec.album = d.getString(MediaMetadata.METADATA_KEY_ALBUM);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_TITLE))
|
||||
musicSpec.track = d.getString(MediaMetadata.METADATA_KEY_TITLE);
|
||||
if (d.containsKey(MediaMetadata.METADATA_KEY_DURATION))
|
||||
musicSpec.duration = (int)d.getLong(MediaMetadata.METADATA_KEY_DURATION) / 1000;
|
||||
|
||||
// finally, tell the device about it
|
||||
GBApplication.deviceService().onSetMusicInfo(musicSpec);
|
||||
GBApplication.deviceService().onSetMusicState(stateSpec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user