Car Play: the bumps in the road

Daniela P. Riesgo
Mac O’Clock
Published in
10 min readJan 17, 2020

Hi everyone! After many reviews from users requesting the CarPlay feature in The Podcast App, we finally got time to do it. So the only question was: how to do it? I couldn't find too much centralized and complete information and when I did find something, it didn't talk about the various development issues you could encounter. Just typical: you copy the tutorial exactly and it still doesn't work.

So here is my attempt at giving you the sort-of guide, for Audio Apps, I didn't have. Please leave any comment if you found new issues or solutions and I can update this guide so it keeps being complete and useful. Sorry for the huge wall of text, but not so sorry at the same time if it becomes useful.

Available material

First of all, here is the existing official material on CarPlay:

  • WWDC talk for Navigation Apps (audio apps useful portion: 04:06–15:11)
  • WWDC talk on CarPlay (audio apps useful portion: 04:50–11:00)
  • Design guidelines for CarPlay

All the usual steps or utilities everyone says you should use for CarPlay development:

1

Add entitlements file with com.apple.developer.playable-content as a Boolean in YES.

[You can do this for development, but for it to work in "production", you need Apple's entitlement granting.]

2

Enroll here for Apple's permission to deploy a CarPlay app.

They give you special entitlements you should add to certificates and provisioning profiles in order to deploy a CarPlay app.
They also send a nice, but somewhat plain, guide for CarPlay development.

I've read many people have had difficulty with getting this approved by Apple, so apply as early as possible. Luckily, I can't give any insight on this because we had it easy, but I can say that we explained our app and the user experience and so how it could be improved with CarPlay. Of course, we also sent data on how this feature was requested on many App Store reviews and our stats in the Store.

3

CarPlay Simulator

You can use CarPlay with the Xcode simulator. You turn it on in Hardware → External Displays → CarPlay. But, just a heads up, it's broken in Xcode 11 for now.

Right now I can't remember exactly, but I think you need Apple's approval before being able to try it on a real car. [Let me know if this is not true!]

4

Ways to get support on this new technology

Luckily, from some conference, we got in touch with some Apple employees and had their contact information, so we ask for help. Apple is really eager for people to adopt new technologies and will happily help you develop them. I'll leave you my highlights of these communications below, but remember that ultimately you always have Feedback Assistant or even Developer Technical Services. People tend to ignore the fact that you have 2 free TSIs each time you renew your membership, or you can pay for more and they'll credit back if they can't solve your problem.

Getting more technical

You will be working with MediaPlayer framework.

  • You will use MPRemoteCommandCenter and MPNowPlayingInfoCenter that you are likely to have because it's used in the lock screen.
  • The new part will be using the MPPlayableContentManager and setting its MPPlayableContentDataSource and MPPlayableContentDelegate properties to give playable content for the user to browse and react to user choices.
  • Each "playable content" is represented by a MPContentItem which is flexible enough to represent a section or a "leaf", that is to say, a group of playable items or a concrete playable item. Each item is something shown in the UI and is unequivocally recognized by its id.
  • You can use UIBrowsableContentSupportsSectionedBrowsing key in true in the Info.plist to have the root interface look like tabs instead of a list.
  • Use the beginUpdates() and endUpdates()methods found in MPPlayableContentManager to update several MPContentItem objects at once.
  • Change the MPContentItem properties or create a new item with the same id and set its properties to update the information on the screen.
  • You can make the item that is playing have a special icon by setting its id in the manager's nowPlayingIdentifiers property.
  • You should also pay attention to other properties in the MPContentItem like isStreaming and isExplicitContent that add icons to give the user more information and a better UX.

Issues and Considerations I learned on the way

Bear in mind, this was my experience.

1

Because of the Entitlements:
bye bye Automatic Code Signing, hello Apple Code Signing Hell. So, you may want to start looking at Fastlane or developing your own team process for this.

2

I can't say I know how CarPlay simulator works, but I can say there is some sort of caching.
So if you changed something in the Info.plist (for example, for adding UIBrowsableContentSupportsSectionedBrowsing), in Assets or even in the source code, the good old restart strategy may make it work. Many times I had to make a clean and/or delete the Derived Data, close the CarPlay external display and restart the Simulator.

3

Sometimes the iPhone simulator stops responding although the CarPlay external display seems to work well.
If you just need CarPlay, ignore it. If you need both, you may need to change simulator because resetting it doesn't always work. Sometimes it's good to unlock the iPhone simulator as soon as you open the app, and leave it unlocked for it to continue to work.

4

CarPlay Simulator is not like testing in a real car
Like always, it's difficult to reproduce the same use cases with all their variables, but apart from this, you will find the Simulator won't show any indicator for the NowPlaying screen or icon on item, and the streaming icon doesn't always work well.

5

CarPlay is still a relatively new technology not so widely used and developed for, so there might be a lot of issues and improvements. The ball is in our court to submit these issues and requests. As far as my experience, these are the limitations I found:
1. No "diffable" handling of content. No insert or remove item at, no reload section, just reload the whole data.
2. No paging. You have no callback for when the user reaches the end of the list to load more content.
3. No filtering or reordening interface available. All actions like this should be done in the phone and then you can have CarPlay reflect it, but you can't have the user do these things by interacting with CarPlay.

6

However, these limitations don't become so serious when you think that the user will only see 5–15 elements per section and Apple allows only 5 levels of hierarchy.
Let's remember that CarPlay is not only a cool new technology but a safer way to use your apps while driving. So Apple took safety into account for this and established content and interaction limitations. The quantity of elements shown to the user varies continuously, for example, based on the current speed of the car.

7

On one of our calls with Apple employees, we got a good advice as far as UI is concerned.
All Audio Apps have the exact same interface in CarPlay, so try to give it your app's personality through the few icons or images you can use.

Getting more technical

  • When setting CarPlay up, the interaction with MPPlayableContentDataSource may not work correctly.
    Sometimes it works, sometimes not. I recommend to always do these things just in case: on app launch, start responding to MPRemoteCommandCenter events and set the MPNowPlayingInfoCenter dictionary at app launch (even if it's an empty command or dictionary).
  • In theory, you can update an MPContentItem object by changing its properties during runtime or by creating a new MPContentItem object with new property values but the same identifier as the previous MPContentItem object.
    My advice: don’t create a new MPContentItem with same id, sometimes it doesn’t update things correctly, like isStreaming for example.
  • Also in relation to the MPContentItem , since they are identified by a String id, we tried to "optimize" things (especially because of lack of diffing capability) by making that id refer not to the content itself, but to the UI item it represents. For example, we have a Continue Listening playlist, so the child item ids of that section were "continue-listening.1", "continue-listening.2", etc. In this way, if things change order or the first element disappears, it's just un update and not a deletion and insertion. However, we can't ensure that this is, in fact, more optimal than not using this. [Let me know if you do the benchmark!]
  • Because of those safety content changes, the callback func playableContentManager(_:didUpdate context:) is called many many times, so don't reload your data on each change! But the official advice is to check the enforcedContentItemsCount property to see which information to show and react upon it.
    For us, we just focused on showing the most important things on top and let the content server truncate delegate content when it decides to.
  • playableContentManager(_:didUpdate context:) callback is a great place for reliable information on whether the app is connected to CarPlay or not: just check the property endpointAvailable on the MPPlayableContentManagerContext object.
  • We had a really hard time making image updates work, and sadly we never achieved it.
    We had a Podcast item which when tapped opened the episodes on that podcast. The list had many Podcast, each with its own image, so there where many images to load. Sometimes you would see them perfectly. Sometimes it wouldn't load, and when you entered the episodes (which all had the Podcast image) you would see none with an image or even weirder the first without image and all the other with it.
    I guess maybe using batch updates after all images downloaded would make it work better, but we couldn't get around to do it.

And that's all for now!

That my experience all wrapped up. Hope this helps.
I leave you one last highlight of the whole CarPlay experience.

Fun story bonus: My first Car Office day

Testing CarPlay feature is clearly not easy. The Simulator doesn't work so well. You could also buy <one of those devices link?>, but I've never tried it, I don't know if it's similar to the car real experience. So, you really need a car with CarPlay. Let me tell you I'm in Argentina, so it's not that common. Some coworkers tried to book cars in apps like Uber, but few times they came with CarPlay. I knew nobody who had a car with CarPlay [all useful car models listed here], but a coworker, who is in the USA, did know somebody in Argentina who had a car with CarPlay. And so it began…

It’s a warm summer evening, circa 600 BC. Well, no, but it was, in fact, a really hot summer morning. I was entering the Starbucks in which I was going to meet this guy which I had never seen in my life. Messaging I was able to find him and here I was in a situation where I needed to say "Hello! Nice to meet you. Can I have your car keys?". Luckily, Gero was really cool. I even arrived at a moment he was trying to deal with a problem because he needed to deploy and I couldn't help him even a bit.

With the car keys in hand and a few directions, I got to the car after a few open-close tries. So I got in. The car had been under the sun for some time. I started connecting everything. Some minutes later, out of nowhere the car alarm starts going off. Let me tell you another thing, I don't know how to drive, so my experience with cars is minimum. Without knowing why it fired and how to stop it I open-close again. Some minutes later, the same and the same and the same. So I message Gero for advice, he tried to help to say to put the key in the ignition. In Spanish, "in ignition" is said with the same words you would say "in contact", so I understood "just put them in contact". I put the key in the hole and a few minutes later, the same happens. So I message Gero again, he must have guessed that I was completely ignorant of cars because he came over, even while he was trying to get in touch with Apple since he continued with his problem, and explained I had to turn the key after getting it in the hole. And with that turn, I got air conditioning !! (I'd been under the sun some hours now)

At the same time, I tried testing my app, but I had several problems getting the Car Play screen to appear in the car. I tried Bluetooth and didn't work, I tried to give up the debugger and connect the phone by USB and it didn't work. Turns out you need to enable Siri as well as Bluetooth for it to work, and you need a good USB cable. When Gero came around we switch USB cables and everything started working.

So I kept doing my tests, but the car was always parked. As noon came nearer, Gero asked a friend to meet him at the car and then go to lunch. That was my chance. So I asked for permission to test while he was driving (just a few blocks away). So I got Gero's friend to travel on the back seats while I was connected and debugging everything. Finally, when we reached the destination, they got free of me.

Thank you very much Gero for all your help!

--

--