Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onMetadataChanged MediaControllerCompat.Callback never called

I'm developing a simple Audio Player app for a radio station.
I have successfully made a MediaBrowser and registered a callback to listen for playBack- or metadata changes.

var mediaBrowser : MediaBrowserCompat by Delegates.notNull()
mediaBrowser = MediaBrowserCompat(
        activity,
        ComponentName(activity, MediaPlaybackService::class.java),
        object : MediaBrowserCompat.ConnectionCallback() {
            override fun onConnected() {
                val mediaController = MediaControllerCompat(activity, mediaBrowser.sessionToken)
                MediaControllerCompat.setMediaController(activity, mediaController)
                mediaController.registerCallback(ControllerCallback)
                mediaControllerFunc()
            }
        },
        null
)

object ControllerCallback : MediaControllerCompat.Callback() {
    override fun onMetadataChanged(metadata: MediaMetadataCompat) {
        //TODO: Never called
    }

    override fun onPlaybackStateChanged(state: PlaybackStateCompat) {
        //Called
    }
}

The playback changes are received when I call

mediaSession.setPlaybackState(
    PlaybackStateCompat.Builder()
            .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE)
            .setState(STATE_PLAYING, DEFAULT_PLAYBACK_POSITION, DEFAULT_PLAYBACK_SPEED)
            .build()
)

However metadata changes are not.
Even though I call

mediaSession.setMetadata(
    MediaMetadataCompat.Builder()
        .putLong(METADATA_KEY_DURATION, -1)
        .putString(METADATA_KEY_TITLE, title)
        .putString(METADATA_KEY_ARTIST, artist)
        .putBitmap(METADATA_KEY_ALBUM_ART, albumCover)
        .putString(METADATA_KEY_ALBUM_ART_URI, albumCoverUrl)
        .build()
)

What am I missing to receive metadata changes?
If it can help the complete repository is available on Github

Thanks in advance

like image 266
timr Avatar asked Nov 14 '17 18:11

timr


2 Answers

My solution for anybody experiencing the same problem.

It turned out I was mixing compat (service layer responsible for starting the audio service and connection to metadata) and non compat (UI layer) variants of the API.

In particular the activity.
Since I am targeting Lollipop and higher I decided to use Activity instead of the AppCompatActivity.

This apparently silently breaks the MediaControllerCompat.Callback for onMetadataChanged(), but not for onPlaybackStateChanged().
Can't seem to find why?!

In code it is as simple as changing:

class PlayableActivity : Activity() { ... }

to:

class PlayableActivity : AppCompatActivity() { ... }

like image 121
timr Avatar answered Sep 18 '22 10:09

timr


onPlaybackStateChanged properly works for support library before version 26 for me. Since then, I cannot make it trigger this specific callback at all. onMetadataChanged works properly after force update on onConnected(). Everything is of Comppat type. I looked into the source and in the case of onPlaybackStateChanged, it relies on some ExtraCallback which never gets triggered:

  @Override
        public void onPlaybackStateChanged(Object stateObj) {
            MediaControllerCompat.Callback callback = mCallback.get();
            if (callback != null) {
                if (callback.mHasExtraCallback) {
                    // Ignore. ExtraCallback will handle this.
                } else {
                    callback.onPlaybackStateChanged(
                            PlaybackStateCompat.fromPlaybackState(stateObj));
                }
            }
        }

I am not sure if it is related, but this ExtraCallback is weakly referenced so it might happen that it is being lost and collected.

like image 39
sh0m1 Avatar answered Sep 17 '22 10:09

sh0m1