The Making of a CarPlay Audio Application | by Pierre-Yves Touzain | Apr, 2022

Photograph by Li Yan on Unsplash

Whereas working for Qobuz, a high-quality and high-fidelity music streaming service, I had the duty of remaking our CarPlay software who had some points right here and there. Qobuz, a french firm for context, is taking a share of the audiophile American market and we have been receiving unfavorable suggestions about our CarPlay software from US customers, who actually like to take heed to music of their vehicles.

As we’re concentrating on premium customers with premium sounds, we clearly wanted to ship a premium expertise, even of their vehicles. So we began to place work on fixing and enhancing our CarPlay software. Sadly, I had hassle discovering examples of an audio app on the web. Now that our new software is up and operating, I believed I might add myself some content material of my very own in regards to the making of a CarPlay audio software and embody some suggestions in regards to the growth course of. So let’s dive in!

Fortunate for me and to my nice shock, Apple introduced with iOS 14 again in 2020 a brand new framework, subtly named CarPlay, which launched a brand new and extra trendy strategy to develop CarPlay functions. Nice information! I can not say I am a giant fan of the previous approach, which used the MediaPlayer framework. It isn’t developer pleasant, has a bizarre implementation, and I discovered myself a number of occasions obligated to supply hacks to unravel my issues. 1/10, wouldn’t advocate.

However again in 2021, we have been supporting iOS 12.0 and additional, and because the new CarPlay equipment is simply obtainable beginning with iOS 14.0, I had no selection however to take care of each strategies with a purpose to give the CarPlay expertise to all our customers. Since I do not assume that, in 2022, it is related to speak in regards to the previous approach, I’ll largely cowl my work with CarPlay Package, and speak rapidly in regards to the one with MediaPlayer.

But when it’s a must to use this framework for older variations of iOS (robust luck) and have hassle, be at liberty to ship me a message right here on Medium, and I will see if I might help you :).

As I needed to start out on word, I made a decision to sort out the model utilizing the CarPlay framework, which is anyway the one aiming to characterize the long run and clearly crucial model of the 2. That is how issues labored:

Entitlement

To start with, the entitlement. You could head over here and supply details about your software. Apple will evaluate it and notify you again positively if it meets their standards.

As soon as it has been accepted, it’s a must to create a brand new provisioning profile that incorporates this new entitlement and add it to your mission.

Then, contained in the Entitlement.plist file (create one if it would not exist), wrap issues up by putting the next key:

<key>com.apple.developer.carplay-audio</key>
<true/>

Establishing the scenes

For the reason that introduction of iOS 13, Apple is pushing a brand new strategy to deal with the totally different screens of your app (which could possibly be your fundamental app, the CarPlay app, or your app duplicated in cut up view on iPad) and that is UIScene. And if like us at Qobuz you did not or do not help but this, properly, you could do a bit of labor earlier than shifting ahead in your fancy CarPlay software new technology.

In our case, now we have two totally different scenes: One named AppSceneDelegate and the opposite CarplaySceneDelegate. The names converse for themself right here. After creating these scenes, there’s a new key so as to add inside Data.plist: UIApplicationSceneManifest. It incorporates a dictionary describing the scenes inside your software.

That is the place you’re going to specify to begin with that your app will help a number of scenes, after which all types of properties, most notably the title of the category representing the entry level of your scene (So in our case, AppSceneDelegate and CarplaySceneDelegate). You may take a look beneath at how our scene manifest is represented, however in order for you extra data, verify the Apple documentation about it here:

However wait, what make these courses I instructed you about UIScene? As per Apple documentation, a UIScene is a category that implements the UISceneDelegate, offering strategies which are known as in the course of the software lifecycle. Appears acquainted? Certainly, it’s destined to switch the AppDelegate.

When filling the strategies in AppSceneDelegate, I really transferred code from our AppDelegate since I make the scene take over beginning iOS 13. Not rather more to say for this really, however for CarplaySceneDelegate, there’s one last item to do, and it’s to make it conform to CPTemplateApplicationSceneDelegate. Effectively, really there aren’t any required strategies so as to add, however nonetheless, two of them are utilized in our app right now:

templateApplicationScene(_ , didConnect:)
templateApplicationScene(_ , didDisconnectInterfaceController:)

It’s the entry and the exit level of our CarPlay software. Inside these strategies, a easy name is made:

//Entry level
carplayTemplateManager.join(interfaceController)
//Exit level
carplayTemplateManager.disconnect()

However what is that this carplayTemplateManager? Effectively, it is a property of CarplaySceneDelegate of kind CarplayTemplateManager. That is the category dealing with all of the code regarding our CarPlay software for the iOS variations 14 and above, and the following step of the event.

CarplayTemplateManager

It is time to construct our software for actual now! Because the title suggests, constructing a CarPlay software is predicated on templates. The bottom class is CPTemplate, and in our case, we use CPTabBarTemplate, which is giving the same expertise because the UITabBarController

Pardon my French, however you may clearly see the three tabs now we have on our CarPlay software

The fundamentals are that you just arrange a root template, which in that case is CPTabBarTemplate, after which create different templates and objects for each menu and sub-menus. Our base code for the basis template initialization appears to be like like this:

var tabTemplates = [CPTemplate]()
tabTemplates.append(myQobuzTemplate())
tabTemplates.append(localLibraryTemplate())
tabTemplates.append(discoverTemplate())
self.carplayInterfaceController!
.setRootTemplate(CPTabBarTemplate(templates: tabTemplates),
animated: true, completion: nil)

That is, for my part, developer-friendly code. Very simple to arrange, very simple to learn and perceive, and it produces a end result immediately. Adore it.

For every tab, a CPListTemplate is created. This template is populated with CPListItem. I took a little bit of our code creating the My Qobuz Template simply to indicate you the overall concept (bear in my thoughts that I, for readability functions, additionally modified a little bit of it too, the actual methodology being a bit longer)

The fascinating half is unquestionably the property handler in CPListItem. The block of code assigned to will probably be executed the second the consumer faucet on the record merchandise. If an asynchronous operation is made inside, CarPlay equipment will routinely put a wheel spinner on the merchandise, ready for the operation to finish.

Within the case above, there isn’t a asynchronous operation however the creation of one other template, which is pushed on the interface utilizing the strategy pushTemplate(:). It for certain reminds you of the way you work together with a UINavigationController. Which makes it much more pleasant.

Right here is considered one of our strategies that creates a CPListItem. On this one, there’s an asynchronous operation, loading albums from our net service. When the success block is hit, an array of CPListItem, every one representing an album, is created, assigned to a CPListTemplate after which pushed on carplayInterfaceController. The very last thing to notice is completion(). It is a parameter offered by the handler property. Calling it lets the handler know that you’re executed with the operation, and that it could transfer ahead in its execution.

One last item: on our monitor CPListItem handler, as an alternative of pushing a customized template, we do that:

self.pushNowPlayingTemplate()

NowPlayingTemplate is a default template offered by the CarPlay equipment and it is configurable with buttons (random play, repeat, and many others), the paintings of the monitor performed, a monitor queue, and all the things wanted to have a working participant. The template is commonplace, which implies that aside from possibly some buttons now we have roughly the identical participant look as Spotify or Apple Music.

And that is it. The remainder of the code is simply extra CPListTemplate and extra CPListItem creation put collectively and voila, you bought a CarPlay audio app with a clear UI and good UX.

As I mentioned, I cannot cowl the main points of my dev journey utilizing the MediaPlayer framework because the codebase of this model is destined to complete within the trash as quickly as potential. Nonetheless some small particulars to notice right here that may enable you to.

Limits

Remember to specify the boundaries of your CarPlay app. You must give a restrict for the variety of objects on a display (contentLimitItemCount) and the depth of the navigation tree (contentLimitTreeDepth). Apple advises not more than 5 in tree depth, however in addition they specify that vehicles producers have management of these numbers and might implement their very own algorithm relying on numerous parameters just like the velocity of the automotive, and many others.

About contentLimitItemCount, I set 200 as an arbitrary quantity after having performances points. That is the sort of hack I used to be speaking about.

var contentLimitItemCount: Int = 200
var contentLimitTreeDepth: Int = 5

Copying the New Means

Having began with CarPlay Package, I took inspiration from their API to assist me in the course of the growth of the previous model. So I ended up having my very own model of primary objects, as proven beneath:

class CarplayContentItem: MPContentItem 
var subItems: [CarplayContentItem] = []
var handler: (@escaping (Error?) -> Void)->() = _ in

It makes the implementation sort of related because of this piece of code. It is simply not working as easily. I had plenty of performances points, and I had to enhance issues right here and there, which makes me lose plenty of time for a minority of customers. A bit irritating, however in the long run, all of our customers are coated in order that was price it (I am nonetheless going to throw this code within the nearest trash as quickly as potential).

Growing this function was undoubtedly enjoyable for many of it. It was additionally extremely rewarding and even talked about in some information articles (like this one), so I undoubtedly take it. I’ve additionally been ready to make use of it myself whereas doing a highway journey within the USA (I don’t personal a automotive in France for context), which additionally provides some satisfaction to the combination :).

I hope you may discover some a part of this text helpful for the event of your CarPlay audio app (or some other sort of CarPlay app).

You may verify the event information from Apple here. It helps me, particularly in organising the fundamentals.

Completely happy coding, and protected driving, everybody!

More Posts