Commit 9f005b50 authored by Nicolas Fella's avatar Nicolas Fella

Hide our own media notification for Spotify when Spotify is running on the phone

parent 470eab52
......@@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
package org.kde.kdeconnect.Plugins.MprisPlugin;
......@@ -31,17 +31,21 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.service.notification.StatusBarNotification;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Pair;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationReceiver;
import org.kde.kdeconnect_tp.R;
import java.util.HashSet;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.TaskStackBuilder;
import androidx.media.app.NotificationCompat.MediaStyle;
......@@ -54,12 +58,14 @@ import androidx.media.app.NotificationCompat.MediaStyle;
* - The media session (via MediaSessionCompat; for lock screen control on
* older Android version. And in the future for lock screen album covers)
*/
public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceChangeListener {
public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceChangeListener, NotificationReceiver.NotificationListener {
private final static int MPRIS_MEDIA_NOTIFICATION_ID = 0x91b70463; // echo MprisNotification | md5sum | head -c 8
private final static String MPRIS_MEDIA_SESSION_TAG = "org.kde.kdeconnect_tp.media_session";
private static final MprisMediaSession instance = new MprisMediaSession();
private boolean spotifyRunning;
public static MprisMediaSession getInstance() {
return instance;
}
......@@ -132,6 +138,19 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
mpris.setPlayerListUpdatedHandler("media_notification", mediaNotificationHandler);
mpris.setPlayerStatusUpdatedHandler("media_notification", mediaNotificationHandler);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
NotificationReceiver.RunCommand(context, service -> {
service.addListener(MprisMediaSession.this);
boolean serviceReady = service.isConnected();
if (serviceReady) {
onListenerConnected(service);
}
});
}
updateMediaNotification();
}
......@@ -164,52 +183,62 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
* @param service The background service
*/
private void updateCurrentPlayer(BackgroundService service) {
Device device = null;
MprisPlugin.MprisPlayer playing = null;
Pair<Device, MprisPlugin.MprisPlayer> player = findPlayer(service);
//Update the last-displayed device and player
notificationDevice = player.first == null ? null : player.first.getDeviceId();
notificationPlayer = player.second;
}
private Pair<Device, MprisPlugin.MprisPlayer> findPlayer(BackgroundService service) {
//First try the previously displayed player
if (notificationDevice != null && mprisDevices.contains(notificationDevice) && notificationPlayer != null) {
device = service.getDevice(notificationDevice);
}
MprisPlugin mpris = null;
if (device != null) {
mpris = device.getPlugin(MprisPlugin.class);
}
if (mpris != null) {
playing = mpris.getPlayerStatus(notificationPlayer.getPlayer());
}
if (notificationDevice != null && mprisDevices.contains(notificationDevice)) {
Device device = service.getDevice(notificationDevice);
//If nonexistant or not playing, try a different player for the same device
if ((playing == null || !playing.isPlaying()) && mpris != null) {
MprisPlugin.MprisPlayer playingPlayer = mpris.getPlayingPlayer();
if (device != null && device.isPluginEnabled("MprisPlugin")) {
if (shouldShowPlayer(notificationPlayer) && notificationPlayer.isPlaying()){
return new Pair<>(device, notificationPlayer);
}
//Only replace the previously found player if we really found one
if (playingPlayer != null) {
playing = playingPlayer;
// Try a different player for the same device
MprisPlugin.MprisPlayer player = getPlayerFromDevice(device);
if (player != null) {
return new Pair<>(device, player);
}
}
}
//If nonexistant or not playing, try a different player for another device
if (playing == null || !playing.isPlaying()) {
for (Device otherDevice : service.getDevices().values()) {
//First, check if we actually display notification for this device
if (!mprisDevices.contains(otherDevice.getDeviceId())) continue;
mpris = otherDevice.getPlugin(MprisPlugin.class);
if (mpris == null) continue;
MprisPlugin.MprisPlayer playingPlayer = mpris.getPlayingPlayer();
//Only replace the previously found player if we really found one
if (playingPlayer != null) {
playing = playingPlayer;
device = otherDevice;
break;
}
// Try a different player from another device
for (Device otherDevice : service.getDevices().values()) {
MprisPlugin.MprisPlayer player = getPlayerFromDevice(otherDevice);
if (player != null) {
return new Pair<>(otherDevice, player);
}
}
return new Pair<>(null, null);
}
//Update the last-displayed device and player
notificationDevice = device == null ? null : device.getDeviceId();
notificationPlayer = playing;
private MprisPlugin.MprisPlayer getPlayerFromDevice(Device device) {
if (!mprisDevices.contains(device.getDeviceId()))
return null;
MprisPlugin plugin = device.getPlugin(MprisPlugin.class);
if (plugin == null) {
return null;
}
MprisPlugin.MprisPlayer player = plugin.getPlayingPlayer();
if (shouldShowPlayer(player)) {
return player;
}
return null;
}
private boolean shouldShowPlayer(MprisPlugin.MprisPlayer player) {
return player != null && !(player.isSpotify() && spotifyRunning);
}
/**
......@@ -316,7 +345,7 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
*/
PendingIntent piOpenActivity = TaskStackBuilder.create(context)
.addNextIntentWithParentStack(iOpenActivity)
.getPendingIntent(Build.VERSION.SDK_INT > 15 ? 0 : (int)System.currentTimeMillis(), PendingIntent.FLAG_UPDATE_CURRENT);
.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);
......@@ -433,4 +462,33 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
notificationPlayer = player;
updateMediaNotification();
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onNotificationPosted(StatusBarNotification n) {
if (n.getPackageName().equals("com.spotify.music")) {
spotifyRunning = true;
updateMediaNotification();
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onNotificationRemoved(StatusBarNotification n) {
if (n.getPackageName().equals("com.spotify.music")) {
spotifyRunning = false;
updateMediaNotification();
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onListenerConnected(NotificationReceiver service) {
for (StatusBarNotification n : service.getActiveNotifications()) {
if (n.getPackageName().equals("com.spotify.music")) {
  • Maybe "com.spotify.music" should be a named variable so it can be changed if the package name changes in the future? (Or better, a one-element list so we can add special-cases for other apps we want to hide from)

  • This was merged a while back, but feel free to refractor this name out into a constant.

  • It's only in this single place, so I'd say we fix it when (if ever) we need to.

Please register or sign in to reply
spotifyRunning = true;
updateMediaNotification();
}
}
}
}
......@@ -87,7 +87,7 @@ public class MprisPlugin extends Plugin {
return player;
}
private boolean isSpotify() {
boolean isSpotify() {
return getPlayer().toLowerCase().equals("spotify");
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment