Replay: The growing struggle of playback controls via Bluetooth
Music is the most important function of my phone. No, I am not kidding.
It is what I use at work, home, in bed, in the shower and everywhere in between to keep me sane and happy. Music makes me better, and since music is such a large part of my Android experience, there's been a slow decline that I've been painfully aware of over the last few years, and especially the last few months.
Sometimes I turn on my Bluetooth headphones, hit play, and nothing happens. And nothing happens a lot more than it used to.
In my early Android days, with Soarin in my pocket (yes, I named my Samsung Captivate Glide) and my first pair of Kinivo Bluetooth headphones around my neck, I didn't have to have Google Play Music open, I just needed to hit play on my headphones. In fact, I took a Samsung Galaxy SII out of a drawer, booted it up for the first time in months, paired Bluetooth headphones with it, and hit the play button. And the music played.
Not so much on the current devices in my stable.
The HTC 10 just does not to obey Bluetooth controls sometimes, persistent notification for the music app or not. It would rather I hit play on my Moto 360, or on the phone itself. The HTC A9 is just as finicky. The Nexus 5X sometimes won't start music back up with the persistent notification up, but will sometimes do it without one. The Samsung S6 edge will play, but sometimes instead of playing the music app most recently active, it will default back to the pre-loaded Music app.
There's a word that keeps repeating here: sometimes. That's because this is a problem that has a lot of variables: what Android device you're using, what Bluetooth device you're using, what version of Android and Bluetooth your devices have, what music app you're trying to play through, what environment you're in, etc. That's a lot of things to contribute to a seemingly simple problem of buttons not working every time you press them.
So what's actually happening here? Well, the answer gets a little — ok, a lot — technical.
When you press the button, it is interpreted by Android and broadcasted across the system through KeyEvents. The next button on your headset is interpreted and delivered as KEYCODE_MEDIA_NEXT through a KeyEvent. There are a large variety of values that can be pulled up for different buttons, or even for the same button. The play button on most headsets is also the pause button, so the key could return KEYCODE_MEDIA_PAUSE, KEYCODE_MEDIA_PLAY, or the much more likely KEYCODE_MEDIA_PLAY_PAUSE depending on the device and its current state. By the way, if you've ever hit pause and music started somewhere else while what you were watching/listening paused, this is the KeyEvent to blame, because it was received and acted on by two apps.
Once the KeyEvents are interpreted, they still have to be heard by a music app that's listening for media buttons through a BroadcastReceiver intent. After all, an app can't act on a KeyEvent if it can't see it. If something is preventing the receiver in an app from receiving button presses, it can mess up the playback controls in several ways, including the intermittent issue I described above. If an app unregisters its BroadcastReceiver too quickly when it loses Audio Focus (the method through which Android determines which apps can play audio at a given time), then when you pause your music, it may lose stop listening and not hear the button press telling it to start playing again. That's why it's important for media apps to handle both Audio Focus and their BroadcastReceiver properly so that even when a device has lost the former, it doesn't lose the latter.
A lot of this comes down to how well your music app is programmed and which media buttons are being broadcast by your device when you press a button on your headset. This also means that even if playback controls are consistent when you buy a device, they can be broken by app updates or system updates that change how quickly it stops listening.
In the case of apps like Google Play Music, updates breaking things seem to be getting more and more frequent. While most breaks are fixed quickly, others can take months to be fixed. Intermittent issues, such as your music not starting up properly on Bluetooth, can be difficult to log and properly identify, further slowing a possible fix.
If music apps don't have audio focus and aren't running as foreground services (if the persistent notification for the media player isn't there), there's a chance that the Android system (more specifically Doze) or so-called "resource-saving" apps could kill the app to free up memory for other activities. When that happens, hitting play might not do anything because there aren't any receivers open and listening for commands.
Now, just as there are several things that could break your playback controls, there's also options for trying to fix it.
The first solution is a bit extreme, but one of the few that users could implement on their current phones today without any root alterations to the software. Using apps like Tasker and AutoInput, we can detect the button-press, suppress the original KeyEvent action, then carry out a more specialized (and more consistent) command aimed directly at one app. For instance, rather than the play button being a generic play media command that could be picked up or ignored by dozens of media services, we could remap it as a play/pause toggle command specific to Google Play Music so that other apps don't start up instead.
This can be tedious to program, and by suppressing the original action and replacing it, we break the native pause button that we may want to use in other apps like YouTube or Netflix. In short, it's not much of a solution for non-technical users or users who use a variety of media apps.
Many phones include a bevy of gesture and button actions that you can turn on or off in Settings, like double-tap to wake or double-press Home/power for the camera. While adding Bluetooth controls to this list may lengthen and complicate it, if the Android system were to acknowledge and direct the KeyEvent to a specific app rather than broadcasting a generic signal to whatever receivers are (or are not) listening, we could ensure consistency. We've seen this done on devices before, for example opening Moto Assist turning on a designated music app when it connected to your car's Bluetooth.
Changing the way Android handles media buttons — and deals with button inputs overall, as Bluetooth controllers and keyboards run into problems of their own — could create as many new problems as it solves, but considering the number of places things can — and do — go wrong in the current system, it might be worth breaking the eggs to make a new omelet.
At the end of the day, everyday users don't want to dig into key commands, receivers, and which app has audio focus right now. We want our focus to be on the music itself and where it takes us. And if I can't turn on the music that keeps me sane in loud, crowded places on the first try, I'm not a happy girl. And I'll bet I'm not the only one.