MediaSession

Android newbie here. Pretty much a Juce newbie as well.
Using Juce 7.0.9, creating a music player app running on Android.

I want to receive transport control events via AVRCP so that my music player can be controlled from a car’s music system, etc. I have created MediaSession and BroadcastReceiver classes attempting to obtain these events. I didn’t see anything in Juce to help with this, although I likely have missed something.

My app (via its MediaSession and BroadcastReceiver objects) is never receiving these transport control events, even though I have verified from the logs that Bluetooth is sending them to my app. Of course something must be blocking them, or hogging them, or I’ve messed up the code and/or initialization of this.

I see that there is another receiver in place, apparently one created/used by Juce itself : receiver android:name=“com.rmsl.juce.Receiver” android:exported=“false”

Not sure if this could conflict with my receiver object.

Please advise me the best way to do all of this, and to debug what is going on. Obviously if Juce provides support for all of this, that is preferable.

My music player currently is using the most simple manner of sound output, with my MainComponent deriving from juce::AudioAppComponent. The audio “just runs” without me having to select sample rate, buffer size, etc. Not sure if that makes a difference related to this issue.

Figured it out.
I didn’t have a PlaybackState object in my MediaSession.

tl;dr version…

As mentioned, I am a total Android newbie (first timer), java newbie (first timer), and nearly a Juce newbie as well (used Juce 15 years ago, but didn’t go very deep into it). Because of my total inexperience in the tech involved, I asked a friend if he could suggest where to start on this task. He suggested ChatGPT. I can see some of you rolling your eyes already…

ChatGPT suggested the direction to take, and gave example code for the MediaSession. I used this code, without understanding it obviously, and without consulting any Android documentation, expecting that it would work as is.

When I asked ChatGPT why I was not receiving any transport control events in my MediaSession, the subject of a PlaybackState never came up, nor was one part of the original MediaSession example code.

I asked ChatGPT how to debug this, and was not given any really useful options. Some Android objects could possibly be used to interrogate MediaSession state, etc., but nothing worked. My assumption was that there was another MediaSession that had taken control, possibly being part of Juce itself. I was looking for a way to trace the path of these transport control events though the code of my app, regardless of whether that code was my own or that of Juce. Again, no useful suggestions came from this inquiry.

Somehow I stumbled upon the now obvious fact that Android sources were present on my system (based on Linux, open source, duh !). I then was able to locate a place in Android to put breakpoints to watch the transport event flow. I then noticed that the Android code was discarding these events because my PlaybackState was null.

Of course once I asked ChatGPT about this, I was then given correct information about how to setup this playback state, and of course transport control events then began reaching my code.

So, in summary - ChatGPT did give me some very good info, and likely saved me a bunch of time that it would have otherwise taken me to figure all of this out by myself from reading Android reference material. However, some of this info was incomplete (the PlaybackState object should have been part of the MediaSession example, because it could never work without it). And only when I finally stumbled into the missing pieces did ChatGPT finally explain them to me (when it surely should have been obvious that this missing PlaybackState could have been a potential cause of the trouble that I kept asking it how to debug).

Of course after all of this, I have now scanned this forum for the ChatGPT adventures of others, and had my own eye roll reaction to what I found here. I also enjoyed the naming of the concept of “hallucination”, which I of course also did experience with ChatGPT. It invented a number of things that didn’t exist. It also takes a lot of thought in the user to focus ChatGPT on the smallest subset of possibility that you are interested in, because it will otherwise tell you all sorts of things that simply won’t work, usually due to being unavailable in the version of Juce, Android, or whatever you’re using.

So, one step forward…

My next adventure is related to these transport control events. Namely, there is something amiss with play/pause (and/or stop).

I am receiving pause and play events, but it’s not working as I expect.
I have tested this in three scenarios :

  1. Tesla Model 3
  2. JBL Clip 4 bluetooth speaker
  3. JBL Go 4 bluetooth speaker

The two speakers have a single “>” button, which looks to be multi-functional.
The Tesla has a scroll wheel, where a push toggles play/pause in some way, and left/right pushes to the side provide prev/next.

On the Tesla, left/right pushes give the expected prev/next. Pushes of the wheel will stop or pause (not sure which) my player if it’s running, but will never start it again with subsequent pushes.

The Go 4 is nearly the same. Double pushes of the “>” provide a next event. Pushes of the “>” stop or pause my player but never start it again.

The Clip 4 is different. Double pushes also give the expected next event. But single pushes of “>” rotate through three states - stop/pause/and pause again. In pause state, a pause event is rejected because it makes no sense, and I have disallowed that in my PlaybackState. But only on the Clip 4 can I actually start my player again, which suggests that my events handlers seem to be OK.

Of course I suspect that I have not done something I need to, to inform Android about the playing state of my audio engine. So I’m off to go read some Android docs now, and also ChatGPT for the fun of it.

Any other advice from the forum here is of course most welcome and appreciated.