Automaker CarPlay apps without Apple’s or automakers’ blessings

Foti Dim
Foti Dim’s
Published in
9 min readJun 12, 2022

--

A touch-enabled CarPlay app running on a VW Touareg

Disclaimer: For writing this article, there was no “insider information” from an automaker or Apple. It was the result of multiple hours of reverse engineering, trial n error, and connecting the dots between the scarce crumbles that I have managed to find on the wild internet.

CarPlay supports multiple types of apps. Music apps and messaging apps are among the most common. Navigation apps are a bit less common but also supported. It is essentially a not-so-long list with all those app types having something in common.

CarPlay app types

The list of app types from Apple’s entitlements page as of iOS 16 is:

  • Audio (com.apple.developer.carplay-audio)
  • Communication (com.apple.developer.carplay-communication)
  • EV Charging (com.apple.developer.carplay-charging)
  • Fueling (com.apple.developer.carplay-fueling)
  • Navigation (com.apple.developer.carplay-maps)
  • Parking (com.apple.developer.carplay-parking)
  • Quick Food Ordering (com.apple.developer.carplay-quick-ordering)
  • Driving Task (com.apple.developer.carplay-driving-task)

App restrictions

All the above app types have one common denominator. Neither of them supports touch control on views provided by the app. Instead, what Apple has opted for, is standardized templates with predefined UI controls.

Map Template with navigation bar and map buttons

For example, navigation apps are not allowed to use pinch gestures to zoom the map but instead the user has to use the predefined plus/minus overlay buttons. You can see that in any navigation app in CarPlay.

You have to use + / - to zoom in / out

This leads to awkward situations like In Google Maps where there are UI icons that while they are tappable and functional on the phone, on CarPlay they are not.

The button on the right is not tappable

Allegedly, the reason for such restrictions is driving safety concerns that called for the use of consistent single-tap interactions which allowed more precise control in a moving and bouncing-around vehicle. On the other hand, it could be that the underlying cause was not so noble. Some vehicles do not support multi-touch and it can be that Apple did not want to fragment the user experience and wanted to provide a consistent product across different car brands. It is far from ideal but it is what it is.

It is worth mentioning though that CarPlay’s rival, Android Auto, does support multi-touch thus it is possible to pinch-zoom the map.

A 3rd party app can do nothing but to make use of those “restricted” templates and of course, it has to adhere to the nature of one of the supported app types.

Even in the recently announced iOS 16 as part of WWDC 22 while there was a new CarPlay app category called driving task apps, those are still limited to the predefined CarPlay templates that exist today.

The Automaker app type

However, there is one more app type that is not exactly advertised by Apple. It is the Automaker app type…

Automaker apps are the only category of apps that can display a custom user interface in CarPlay. That is with full-touch support. In this example, the Automaker app provides controls for adjusting the climate settings, selecting radio stations, and summoning roadside assistance.

A sample Automaker app

Automaker apps were first mentioned in WWDC 2016 and then again in WWDC 2017. They are available since iOS 10, yet, there is no mention of them in the CarPlay API documentation. There is only a brief reference to tham in the CarPlay App Programming Guide only noting that “This guide does not cover CarPlay Automaker apps (published by car manufacturers)”. In the WWDC 2016 slides, it states that “Automakers should contact Apple for more details” clearly indicating that this is a “private” feature that is only meant to be used by a few privileged companies.

Developing an “Automaker” app

Automaker apps are completely unrestricted in terms of what they can do with UI. Could we make use of the Automaker app type to free our CarPlay app from Apple’s template restrictions?

To whitelist an app for the full CarPlay experience, you need to know the protocol string of your car. Every car acts as an MFI accessory and because of that, it bears a vendor-generated protocol string.

Getting the Protocol String

The is no standard way to get the protocol string of a certain MFI accessory so you need to get creative. Some products have been open-sourced, so manufacturers were kind enough to publicly document their protocol strings. As far as I could find there is no way to get this string from iOS itself. It is not printed in the system logs nor is there an API call to get it. I could also not find any jailbreak tweak that would be able to display the protocol string of a connected accessory.

If the accessory vendor has a published iOS app that makes use of the Automaker app type then you could get your hands on the .ipa and inspect the info.plist file. This will include all the necessary protocol strings. This applies to any iOS app that makes use of external accessories not just Automaker apps.

Seeing what a pain it is to get access to protocol strings I started an initiative to publicly document protocol strings that are discovered. In cases like Romo where the vendor went out of business and the app got pulled from the App Store, not knowing the protocol string casts the device useless since it does not allow other apps to be written for it. This generates e-waste since all those devices sold, will eventually need to be recycled or at worst thrown away. It is our duty to persevere the longevity of those devices. I have created the protocol-strings GitHub repo as an initiative to crowdsource all known protocol strings. This will enable developers to breathe new life into old and deprecated accessories. I would love to see contributions and watch this list grow in the future.

Prepare your CarPlay project

We now have all the missing puzzle pieces to create our Automaker app. Let’s go for a sample app with a counter and a button to make sure that touch controls work.

A sample app with a counter and a button

I won’t go into details about the code that was specifically added to implement CarPlay functionality, as this is out of scope for this article. You can find other guides that can help you with this. In this article, we will only focus on the parts that would be different from your standard CarPlay guide. In case you do not want to start from scratch you can always use the code in my AutomakerCarPlayUnleashed GitHub repo.

Set your entitlements

You need to open your entitlements file and enter com.apple.developer.carplay-protocols and set the value of Item 0 to the protocol string of choice. For my simulator tests I used com.brand.carplay.feature.

If you want to test on a real car you need to add your car’s protocol string there. Otherwise, the app won’t show up on the car’s screen. This is how Apple makes sure that only the apps of the same vendor show up. Having said that I don’t see anything stopping you from adding all known protocol strings to your app and making it universally compatible with every car in the world!

Display your custom View

You need to do 3 things:

  • Make your AppDelegate conform to the deprecated CPApplicationDelegate. Despite being deprecated it works fine using the iOS 16 SDK under Xcode 14. Apple has provided a replacement called CPTemplateApplicationSceneDelegate since iOS 13 but this does not support Automaker apps as of iOS 16. The reason is there is that the API to set a custom window is strictly limited to navigation apps.
  • Set CPMapTemplate() as root template otherwise we get a black screen.
  • Finally set the rootViewController to any UIViewController you want. You can instantiate it in code, use Storyboards, anything goes!

Your application(didConnectCarInterfaceController:to) delegate method will look like this:

func application(_ application: UIApplication,      didConnectCarInterfaceController interfaceController: CPInterfaceController, to window: CPWindow) {  self.interfaceController = interfaceController  self.carPlayWindow = window  interfaceController.setRootTemplate(CPMapTemplate(), animated: true)  let carPlayStoryBoard = UIStoryboard(name: "CarPlay", bundle:nil)  window.rootViewController =     carPlayStoryBoard.instantiateInitialViewController()}

Testing on Simulator

Automaker app shows up on the simulator

We can start with testing on the iOS simulator. In my tests, the iOS 12.4 simulator was the version that did the trick. I didn’t have any success on iOS 13, 14, 15, or 16 simulators each of them failing in different ways. However, I have reasons to believe that the app will run just fine on real devices with the newest iOS versions. I wasn’t able to verify this yet as this requires a jailbroken device running on those iOS versions.

Enable hidden simulator features

You will need to enable some hidden simulator features to get the full CarPlay experience. Run those commands in your terminal:

defaults write com.apple.iphonesimulator CarPlay -bool YES

defaults write com.apple.iphonesimulator CarPlayExtraOptions -bool YES

defaults write com.apple.iphonesimulator CarPlayProtocols -array-add com.brand.carplay.feature

Not that com.brand.carplay.feature needs to match the value you used in your entitlements.

We got touch 💪

Testing on a real car

Since we have the app running on the simulator, now it is time to test it on the car. Normally you need Apple’s special entitlements to be able to do so. Fear not though, since in my previous article I outlined all the necessary steps needed to run a CarPlay app on a car without Apple’s entitlements.

Depending on the car you will need to add a different protocol string to your app’s entitlements. As described above this can be anything from easy to impossible. Of course, keep in mind that such an app will never be approved on the App Store. Let’s hope that sideloading iOS apps will soon be a reality.

Once the correct protocol string is in place we have to put the app on a jailbroken device. As explained in my last article this is required since it is not possible to officially sign the app while injecting the CarPlay entitlement.

Moment of truth

Here comes testing on a real car… Since we configured things right our app pops up on the car’s infotainment screen. Not only that but we also have a fully custom UI and full touch support! I was able to have the app running successfully on a Ford Mondeo and a VW Touareg. Add the right protocol strings and you can have it running on other brands too!

Custom CarPlay UI on a Ford Mondeo / Fusion
Custom CarPlay UI on a VW Touareg

In both cases, we have a full custom CarPlay UI with touch controls enabled!

Touch-enabled CarPlay UI on a VW Touareg

Conclusion

We have proven that custom CarPlay UIs are totally feasible even though not really advertised by Apple. It is also noteworthy that the feature has been heavily underused by automakers themselves. I had quite a hard time finding an app that was making use of this functionality.

That was a long journey and I wish Apple made our lives a little bit easier with it. I hope you find it useful and start building cool stuff with it. If you know the protocol string of an accessory (any device, not only cars) go to the protocol-strings GitHub repo and make a pull request to add it.

Hopefully, Apple will open up custom CarPlay UIs for more app categories in the future. Until then we have to resort to bypassing their restrictions!

--

--

Software craftsman — iOS📱 MachineLearning🤖 AutonomousDriving🚙 AR👓 Bass🎸 Nintendo🎮