Nothing is more magical than having your favorite music streaming app switch to car mode automatically as soon as you start playing music via your car’s bluetooth stereo. By the end of this article you will discover how we detect when an app is connected to the car stereo via bluetooth or not.
Car mode detection allows us to implement our Car Mode feature seamlessly by replacing the conventional music player with a minimalistic and very functional one suitable for usage in cars.
Before we dive into the details, a little about me (because I’m sure ur wondering if you can truly trust what I’m saying or not hehehe). My name is Amer and I’m the iOS lead at Anghami.
Anghami is a music streaming platform based out of Beirut, Lebanon – and we are just really really really really really (almost enough reallys) really passionate about music.
The purpose of this article is to go over (technically) how we detect when our users are listening to Anghami via their car’s bluetooth and the steps we took that led us to our preferred solution.
Attempt 1 — Core Motion 🏃♂️
Core Motion is an Apple framework that allows the developer to detect whether a person is in a car/running/walking/cycling using the phone’s accelerometers, gyroscopes, pedometer, and others sensors.
We had several problems with this solution:
- We needed to ask the user for permission to use this framework which would remove the Magic away from automatic car detection.
- This solution might also trigger false positives— if you’re a passenger on the bus, if you’e in an Uber, etc.
Attempt 2 — ExternalAccessory
External Accessory is an Apple framework that connects with accessories connected wirelessly through Bluetooth.
This solution doesn’t ask the user for permission but was useless due to car bluetooth stereos not being detected as External Accessories. So on to the next attempt.
Attempt 3 — Core Bluetooth
Core Bluetooth is another Apple framework that “communicates with Bluetooth low energy and BR/EDR (“Classic”) Devices”.
This solution does ask for the user’s permission but does not detect bluetooth stereos as anything other than regular bluetooth devices.
Attempt 4 — AVAudioSession.Port
Since we are a music app, we were able to use AVAudioSession.sharedInstance().currentRoute to get info on the port. This info told us whether the current route used A2DP, HFP, carAudio, etc (Full list of ports https://developer.apple.com/documentation/avfoundation/avaudiosession/port).
This seemed like a wonderful solution because it doesn’t ask for user’s permission and can tell us if bluetooth device’s port type is car audio or hands free or anything that is car related.
Problem with this attempt is that all car stereos we tested on always returned port type as A2DP, therefore this solution was unsuitable.
Solution of our choice
We noticed most of the car manufacturers had default bluetooth device names for their stereos. We utilized this and compared the bluetooth name to a list of common car manufacturer’s stereo default names.
This solution did not ask the user for bluetooth permission and this code could be triggered whenever AVAudioSession.sharedInstance().currentRoute changes (e.g when user disconnects from a bluetooth device, etc).
The most apparent problem with this solution is that if you change your device’s name to a car related name, it’ll think it’s a car stereo. An example of that is if you change your Bose speaker’s device name to “Kia”, Anghami will think it’s a car.
The Key is MAC Addresses
Bluetooth Device Address is a unique 48-bit identifier assigned to each Bluetooth device by the manufacturer. The first 6 letters of the address represents the device manufacturer’s. This helped us pinpoint car bluetooth devices more accurately without relying on the device name.
Mining all the bluetooth device names and their MAC addresses allows for a more accurate crosscheck on what bluetooth devices are car stereos and which aren’t.
Example: Some BMWs use Harman Kardon stereos in their cars. Their manufacturer’s mac address is 9C:DF:03.
This helps us pinpoint that even if Harman Kardon’s device name changes to anything, we can still detect that it’s a car just by relying on the MAC address.
One last problem
There is one last problem which we have yet to solve. What if the bluetooth manufacturer makes household speakers as well as car speakers.
An example of that is Alfa Romeos. Some Alfa Romeos have Bose stereos in their cars. The problem here is that we cannot rely on the MAC address of Bose immediately or else it will assume every Bose device (Headphones, home speakers, etc) connected to their phones are cars.
In this case, the only solution is to fall back on the device name. Unfortunately this can fail if bluetooth name is deceiving (e.g . Bose speaker’s device name is “BMW” — This causes the app to think it’s in the car).
Final Product
We were able to finally find the best solution possible to automatically switch to car mode. Car mode has already been added to Anghami (turned on by entering audio settings in the music player) but we are currently in the process of implementing this following solution to make car mode, just a tad bit better than before. Coming to an App store near you 😅.
Conclusion
I hope this medium article gives future developers some insight into how we detect playing audio via car bluetooth stereos, and hopefully it would save them the trouble of googling all this (and going crazy at the same time).
This couldn’t have been possible without the entire Anghami team.