Setting up your first CarPlay

Intro

Allthough apps on CarPlay are commonly refered to as “Open the CarPlay app”, it is actually not an app by itself.
CarPlay is merely a seperate screen to your iPhone, much like a projector is to a laptop. The content that is shown on the car’s headunit is generated by the iOS device and streamed to the headunit. The only thing the headunit does is it tells the iOS devices connected (either via bluetooth & Wifi or via USB cable) the input from the user (which can both be touch and non-touch) and some pheripheral information such as screen size, GPS, button press ect.

So, a “CarPlay-app” shares the resources with the main app on the iOS device; thus if you would launch your app from CarPlay and then open it on the iOS device; the app should already be loaded into memory… and vice-versa.

The evolution of CarPlay

A few years ago, before the launch of Xcode 12 and iOS 14, the CarPlay documentation was a bit hush-hush… only a selected few such as Waze, Spotify and BookBeat ect were allowed to build a CarPlay integration.
This, however, all changed in 2020 when Apple released CarPlay to all developers to play around with. That being said, in order to add support for CarPlay in your app and release it to the world you still need Apple’s approval. You (or better yet, your team agent) need to contact apple via http://developer.apple.com/carplay/ and request access. If you have made a strong enough case and get approved, an option to your provisioning profiles page on Apple’s developer portal will be added. It is at this point that you can build your app to a device and test it in an actual car as well as releaae it on the AppStore. Until that point you can only test it locally using the simulator.

The essentials of CarPlay

The CarPlay Framework consists of templates which you set in your code and send to the Interface Controller, whom in turn will take care of all the rendering. Which templates you’ll have access to depends on the category you are using in your entitlement and provisioning profile. Be careful when you make your choice, since your app can only have access to 1 category.

These are the templates which are availble to you: CarPlay Categories Source: CarPlay App Programming Guide

Getting started

Lets start off with a basic app. I assume that you already have an app in place, if not then there are multiple good guides out there on how to get started with your first project.

Now that we have our app, we need to add an entitlement to it. The easiest way to have Xcode add an entitlement is by opening the project and add a capability to it. Add something like Associated domain or so, and it’ll add the entitlement file.

Now with the entitlement file created, you can open it in Xcode and add the category. In this tutorial, we’re going to use the com.apple.developer.carplay-parking category, since that is the one I am most familiar with. Add a new line and add the category name as key and 1 as value, like so: Entitlement Now you can also select the Associated domain line and remove it.

With this added, you also need to make a change to your Info.plist file. Open your project, select the Info tab. Copy the XML below, and paste this into your Info.plist. If you are adding CarPlay to an app which uses Scene Delegates than locate the row called Application Scene Manifest and paste the contents of UISceneConfigurations, otherwise paste the whole thing.

<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
    <key>CPTemplateApplicationSceneSessionRoleApplication</key>
    <array>
        <dict>
            <key>UISceneClassName</key>
            <string>CPTemplateApplicationScene</string>
            <key>UISceneDelegateClassName</key>
            <string>$(PRODUCT_MODULE_NAME).CarPlaySceneDelegate</string>
            <key>UISceneConfigurationName</key>
            <string>ParkingPlay-Car</string>
        </dict>
    </array>
</dict>

The endresult should look like this: Info.plist

What this last part does is it tells the system where to send the scene lifecycle event when your app is launched. So when the app is launched via CarPlay, the file CarPlaySceneDelegate will be called, which will have to conform to CPTemplateApplicationSceneDelegate.

SceneDelegate

Now that those are in place, lets start with some code.

Create a new folder called “CarPlay” under your main project folder and add a file called CarPlaySceneDelegate.swift. Open this file and lets start adding some code:

import CarPlay

class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {
    private var interfaceController: CPInterfaceController?

    /// 1. CarPlay connected
    func templateApplicationScene(
        _ templateApplicationScene: CPTemplateApplicationScene,
        didConnect interfaceController: CPInterfaceController
    ) {
        // 2
        self.interfaceController = interfaceController

        // 3
        setInformationTemplate()
    }

    /// 4. Information template
    private func setInformationTemplate() {
        // 5 - Setting the content for the template
        let items: [CPInformationItem] = [
            CPInformationItem(
                title: "Template type",
                detail: "Information Template (CPInformationTemplate)"
            )
        ]

        // 6 - Selecting the template
        let infoTemplate = CPInformationTemplate(title: "My first template",
                                                 layout: .leading,
                                                 items: items,
                                                 actions: [])

        // 7 - Setting the information template as the root template
        interfaceController?.setRootTemplate(infoTemplate,
                                             animated: true,
                                             completion: { success, error in
            debugPrint("Success: \(success)")

            if let error = error {
                debugPrint("Error: \(error)")
            }
        })
    }
}

The following things happen in the code above:

1

This is called by the CarPlay Framework when CarPlay is launched.

2

We store the interface controller to our class. The Interface Controller is what we use to set which template should be shown, animations and transitions.

3

We call our method setInformationTemplate(), which will show us an information template.

4

The information template method.

5

For the information template, we need an array of items to show. Here we’re just going to show one item on our template with a title and a subtitle.

6

Now we setup our CPInformationTemplate, giving it a title and a list if items to display in the template. It can also take actions and have a different layout.

7

Now we are telling the Interface Controller, which we stored in step 2, that we want to display an template. When it is done, it will show the template we’ve send in.

Launch

Now lets launch the app on the CarPlay simulator and see how it looks. If you have done the above right, the result should look like this: CarPlay

End

Now you have successfully built your first CarPlay app and launched in the simulator. Before I continue and write a Part 2 to this article, going into depth about the other templates in the sample project, send me a comment below if this is of interest to you!

Happy coding!