2

Background

I want to see if I can get information about the currently playing song, to be able to show more information about it, or just the information I get instead.

I've wanted to check it out because I've noticed there is a setting (here) on a popular music player app called "Musicolet", of "Broadcast album art". Sure it says just "album art", but it also says it's for "3rd party". So I wanted to investigate if it's possible.

The problem

Not sure if it's possible or not. I see conflicting answers about it.

What I've found

I've found some interesting links about it:

  1. I've also found a question on StackOverflow (here) about getting it, but it is missing some crucial code.
  2. On the other hand, I've found another post saying that it's not official and that you probably can't do it, here.
  3. I've noticed that Spotify had (or still have?) something like that (here, except I can't see album art there), but it's a bit old.
  4. I've also found an interesting interface RemoteControlClient.OnMetadataUpdateListener (from here), but couldn't find any sample or tutorial about it, except perhaps this one one from XDA.

Of course, I tried using the tips I've found from those links, but failed to get anything to really work.

So maybe it was not possible in the past, and then it was possible. But then for some reason I don't see a sample/tutorial of how to use it, including on the docs.

I think that it if's possible, it requires notification access, because it's about the same as reading the currently playing music from the notification of the music player.

The questions

  1. Is it possible to register to a callback (and also query whenever you wish) of when a song plays, and get information about it ?

    Meaning song-title, album-name, file-path/uri, album-art...

  2. If it's possible, how? What does it require?

  3. If it's not possible, is there any workaround? Anything that works for some apps? Maybe something that exists in the notifications, more officially, that I can detect that it's of this kind, and fetch this information?

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • You can try to [`MediaSessionManager.getActiveSessions`](https://developer.android.com/reference/android/media/session/MediaSessionManager#getActiveSessions(android.content.ComponentName)), determine which session is currently playing then read its metadata. This of course assumes developer of media player correctly constructed media session object and its metadata. – Pawel Sep 07 '20 at 21:38
  • It causes an exception of needing a permission. Can you please try it out? – android developer Sep 07 '20 at 21:45

1 Answers1

5

You need to have notification listener service, third party apps cannot access media sessions otherwise.

Declare service somewhere:

import android.service.notification.NotificationListenerService

class NotiService : NotificationListenerService()

Add it to manifest:

<service android:name=".service.NotiService"
    android:label="Enable media controls"
    android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>

Then you can pass it as an argument to getActiveMediaSessions inside Activity:

val m = getSystemService<MediaSessionManager>()!!
val component = ComponentName(this, NotiService::class.java)
val sessions = m.getActiveSessions(component)
Log.d("Sessions", "count: ${sessions.size}")
sessions.forEach {
    Log.d("Sessions", "$it -- " + (it?.metadata?.keySet()?.joinToString()))
    Log.d("Sessions", "$it -- " + (it?.metadata?.getString(MediaMetadata.METADATA_KEY_TITLE)))
}

Now navigate to System Settings -> Notification Access and enable it for NotiService and it should run without issues.

Pawel
  • 15,548
  • 3
  • 36
  • 36
  • But how can I get a callback for the case of start/stop playback? And how can I get the various information? – android developer Sep 07 '20 at 23:00
  • You get "various information" by accessing metadata field. If you want live updates look through `MediaSessionManager`/`MediaController` documentation, they have methods to register listeners. – Pawel Sep 07 '20 at 23:04
  • You mean addOnActiveSessionsChangedListener ? If so, it causes an exception: `java.lang.SecurityException: Missing permission to control media.` . Can you please show any of these, to show how to make them work too? – android developer Sep 07 '20 at 23:40
  • 1
    As stated in documentation you have to pass component name of your notification listener service as an argument. Null is reserved for system apps. – Pawel Sep 08 '20 at 00:02
  • Why does it need it? It already has a listener, and it could use a package name to see if the app has the required permission. No? Anyway, I will check it later. Seems promising. Have +1 for now. – android developer Sep 08 '20 at 05:21
  • Seems to work as I get various things, but for some reason I don't see how I can get the file information of the played music file. The only similar thing is MEDIA_ID, but I don't think it's possible to get where the file is from this information. And not sure if the album art we get from it can be high quality. Not only that, but I think the callback sometimes gets called multiple times, and sometimes not get called at all when starting to play. – android developer Sep 09 '20 at 16:15
  • Is it possible to get the file path/Uri? Or it depends on the app, and not all do this? And do you also have the issue of having the callback called multiple times, and sometimes being missed when starting to play? – android developer Sep 11 '20 at 15:28
  • Available metadata and callbacks are set and controlled by media app. You can't guarantee anything in there aside from bare minimum that's used by media notification/lock screens. – Pawel Sep 11 '20 at 16:41
  • What is the bare minimum, then? Also, why the callbacks occur as I wrote? – android developer Sep 11 '20 at 20:05
  • 1
    Minimum is track title, album title and cover art (thumb). Callbacks are controlled by media apps so I can't vouch for any inconsistencies. – Pawel Sep 11 '20 at 20:47
  • So it's so unreliable :( I thought it got better over the years... Can you please publish a sample of how it's best to get this information, including the callback, as you see it? – android developer Sep 11 '20 at 23:21
  • If callbacks are unreliable perhaps it's better to run periodic action that checks the current `MediaController` state. I think that's what I did when I was dealing with it. – Pawel Sep 12 '20 at 00:24
  • I was told by Google, that in addition to getting active sessions, I could get the metadata, but I don't understand how to do it. Can you please check it out? Here: https://issuetracker.google.com/issues/163066429#comment11 – android developer Sep 18 '20 at 11:13
  • You already are getting metadata object. Issue is media apps choose not to include [`METADATA_KEY_ALBUM_ART_URI`](https://developer.android.com/reference/android/media/MediaMetadata#METADATA_KEY_ALBUM_ART_URI) which is out of your control. – Pawel Sep 18 '20 at 12:14
  • @Pawel thank you so much -- but how did you know this? "You need to have notification listener service, third party apps cannot access media sessions otherwise." I did not find that anywhere in the documentation until I found your answer. I still don't understand why this works. Is there someplace else I should be looking for find documentation about things like this? – davidgyoung Dec 10 '21 at 16:21