Android - How to determine which music app is currently playing?

630 Views Asked by At

I want to know what song is currently played on my Android phone. In the past, the solution would be to add an IntentFilter but now the solution should be based on MediaSession. Each media app posts its MediaSession. I have a the following listener:

private val mSessionsChangedListener =
    MediaSessionManager.OnActiveSessionsChangedListener { list: List<MediaController>? ->
        //...here
    }

This listener fires every time a change in the active sessions occur. Then I can utilise MediaMetadata in order to grab the info about the currently playing song. In case there is only 1 active MediaSession, that works. However in case there are multiple apps with active sessions, I'm not sure how to determine which one of the List<MediaController> is actually playing.

I tried checking the playbackState like this:

    list.forEach {
        if (it.playbackState?.state == PlaybackState.STATE_PLAYING) {
            currentMediaController = it
        }
    } 

But when switching between 2 media apps, the playbackState is not updated yet when this listener is triggered.

What is the correct way of determining which MediaController is actually playing?

Thanks!

2

There are 2 best solutions below

1
Patrick Nomad On

I think maybe something like the following might work:

private var currentMediaController: MediaController? = null

private val mSessionsChangedListener =
    MediaSessionManager.OnActiveSessionsChangedListener { list: List<MediaController>? ->
        var latestPlaybackState: PlaybackState? = null
        var latestMediaController: MediaController? = null

        list?.forEach { mediaController ->
            val playbackState = mediaController.playbackState
            if (playbackState != null) {
                if (latestPlaybackState == null || playbackState.lastPositionUpdateTime > latestPlaybackState.lastPositionUpdateTime) {
                    if (playbackState.state == PlaybackState.STATE_PLAYING) {
                        latestPlaybackState = playbackState
                        latestMediaController = mediaController
                    }
                }
            }
        }

        currentMediaController = latestMediaController
        // Now you have the MediaController that is currently playing.
        // You can get the playback state using currentMediaController?.playbackState.
    }

This code iterates over all the MediaControllers in the list and checks their PlaybackState. If a MediaController has a PlaybackState that is newer than the previous PlaybackState seen, it becomes the new "latest" PlaybackState, and the corresponding MediaController becomes the new latestMediaController. If the PlaybackState indicates that the media is playing, latestMediaController is updated accordingly.

Note that this code assumes that each MediaController has a unique PlaybackState object. If two MediaControllers have the same PlaybackState object (i.e., they are both playing the same media), this code may not work correctly. In that case, you could use other criteria (such as the package name of the MediaController) to determine which one is actually playing. cg

1
Daniel Ngandu On

To determine which MediaController is currently playing when there are multiple active sessions, you can use the MediaController.getPlaybackState() method to get the current playback state of each MediaController. Here's an example code snippet that demonstrates how to do this:

private val mSessionsChangedListener =
    MediaSessionManager.OnActiveSessionsChangedListener { list: List<MediaController>? ->
        list?.forEach { mediaController ->
            val playbackState = mediaController.playbackState
            if (playbackState?.state == PlaybackState.STATE_PLAYING || 
                playbackState?.state == PlaybackState.STATE_BUFFERING) {
                val mediaMetadata = mediaController.metadata
                // Use the metadata to get information about the currently playing song
                //
            }
        }
    }