Apple CarPlay is a smart, intuitive way to interact with your iPhone while driving, enabling access to essential apps, music, messaging and more via the car's infotainment system. 

The application itself doesn't reside within the car's head unit. Instead, it relies on the iOS device to generate content, which is then streamed to the head unit. The head unit, in turn, communicates user input, both touch and non-touch, along with peripheral information such as screen size, GPS data and button presses, to the connected iOS device.

In 2020, Apple made CarPlay available to all developers. However, to integrate CarPlay support into our app and make it publicly available, we still require approval from Apple. The Team Agent is responsible for contacting Apple through http://developer.apple.com/carplay/ to request access. If our case is compelling enough and we receive approval, an option to provision the profile page on the developer's portal will be provided. Until we obtain approval, testing can only be done on the simulator.

The CarPlay Framework comprises templates that we define within our code and then transmit to the Interface Controller, which handles all the rendering tasks. Access to templates is determined by the category we specify in the entitlement and provisioning profile. It's crucial to choose the category carefully since an app can only access one category.

The categories include Audio, Communication, EV Charging, Navigation, Parking and Quick Food Ordering, each offering multiple templates for access.

Below are some key considerations and code examples for developing apps compatible with Apple CarPlay:

Step 1: Obtain CarPlay app entitlement

Every CarPlay application necessitates CarPlay app entitlements. To acquire an entitlement, visit http://developer.apple.com/carplay/, where we'll be prompted to furnish our app details, including the CarPlay app category. Additionally, we must consent to the CarPlay entitlement addendum. Apple will assess the request, and upon verifying that our app aligns with the CarPlay app criteria, Apple will generate a CarPlay app entitlement and notify us accordingly.

Step 2: Configure entitlements

Upon receiving the entitlement, log in to the developer site and generate a new provisioning profile that incorporates the entitlement. Once the profile is created, import it into Xcode for use in your project.

Step 3: Configuring entitlement keys

Within XCode, if not already present, generate an Entitlements.plist file in your project. Subsequently, insert your CarPlay app entitlement keys as boolean values within this file.

For instance, an app Entitlement key might be com.apple.developer.carplay-maps, which varies depending on the specific category of app for which you're requesting an entitlement.

Example:

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

Ensure to update your Project Build Settings by specifying the Code Signing Entitlements with this entitlements file.

Step 4: Updating application scene manifest

Open your Info.plist file and perform the following steps:

1. Set Enable Multiple Windows to YES with a Boolean value.

2. Under Scene Configuration, add External Display Session Role. Provide the following values:

   - Class Name: CPTemplateApplicationScene (name of the protocol implemented for CarPlay)

   - Delegate Class Name: $(PRODUCT_MODULE_NAME).CarPlaySceneDelegate (CarPlay's scene delegate)

   - Configuration Name: CarPlay (unique string to identify the configuration)

Step 5: Updating AppDelegate

Adjust the connectingSceneSession based on whether it's for the main application or CarPlay:

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    if (connectingSceneSession.role == UISceneSession.Role.carTemplateApplication) {
        let scene = UISceneConfiguration(name: "CarPlay", sessionRole: connectingSceneSession.role)
        scene.delegateClass = CarPlaySceneDelegate.self
        return scene
    } else {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
}

This function determines the appropriate scene configuration based on whether the connecting scene session is for the main application or CarPlay. Adjust the configuration accordingly to ensure seamless integration with CarPlay.

Step 6: Creating CarPlay scene

CarPlay apps are constructed using templates. Below are the types of templates that can be utilized in CarPlay apps: Tab bar Template, List Template, Map Template, Alert Template, Action Sheet Template, Contact Template, Search Template, Grid Template, Information Template, Now Playing Template, Point of Interest Template, Voice Control Template.

Below is the code to create a simple CarPlay app using Tab bar template and List Template:

import CarPlay
class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {
    var interfaceController: CPInterfaceController?
   
    func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, didConnect interfaceController: CPInterfaceController) {
        self.interfaceController = interfaceController
       
        let tab1 = CPListItem(text: "Home", detailText: "Subtitle for Home")
        let tab2 = CPListItem(text: "Recents", detailText: "Subtitle for Recents")
        let tab3 = CPListItem(text: "Search", detailText: "Subtitle for Search")
       
        let section1 = CPListSection(items: [tab1, tab2, tab3])
        let section2 = CPListSection(items: [tab1, tab3])
       
        let listTemplate1 = CPListTemplate(title: "", sections: [section1])
        let listTemplate2 = CPListTemplate(title: "", sections: [section2])
        let listTemplate3 = CPListTemplate(title: "", sections: [section1])
        let listTemplate4 = CPListTemplate(title: "", sections: [section2])
       
        let tabA: CPListTemplate = listTemplate1
        tabA.tabSystemItem = .favorites
        tabA.showsTabBadge = false
       
        let tabB: CPListTemplate = listTemplate2
        tabB.tabSystemItem = .mostViewed
        tabB.showsTabBadge = true
       
        let tabC: CPListTemplate = listTemplate3
        tabC.tabSystemItem = .search
        tabC.showsTabBadge = false
       
        let tabD: CPListTemplate = listTemplate4
        tabD.tabSystemItem = .contacts
        tabD.showsTabBadge = false
       
        let tabBarTemplate = CPTabBarTemplate(templates: [tabA, tabB, tabC, tabD])
       self.interfaceController?.setRootTemplate(tabBarTemplate, animated: true, completion: { _, _ in })
    }
   
    // CarPlay disconnected
    func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene, didDisconnect interfaceController: CPInterfaceController) {
        self.interfaceController = nil
    }
}

This code defines a CarPlaySceneDelegate class responsible for setting up the CarPlay interface. It creates a tab bar template with four tabs, each containing a list template with different sections. The tabs are configured with various system items and badge options. Finally, the root template is set to the tab bar template.

Step 7: Testing the application

CarPlay apps can be tested on the simulator during development, although some features may not be available. It's important not to solely rely on the simulator when developing CarPlay applications.

To run CarPlay on the simulator, navigate to I/O -> External Displays -> CarPlay.

However, it's highly recommended to develop and test CarPlay apps using a car or aftermarket systems that support CarPlay wirelessly. This allows for simultaneous connection of the device to XCode and the car, facilitating testing and debugging of the application in a real-world environment.

Conclusion

Apple CarPlay represents a powerful platform for extending the functionality of iOS apps into the automotive space. By leveraging CarPlay's capabilities, developers can create compelling in-car experiences that enhance safety, convenience and entertainment for users. With the right integration and design considerations, CarPlay apps can seamlessly integrate with the driving experience, providing users with access to essential features while on the road. Whether you're developing a navigation app, messaging platform, or music streaming service, Apple CarPlay opens up a world of possibilities for creating innovative and immersive in-car experiences.

For more detailed information

https://developer.apple.com/documentation/carplay/

https://developer.apple.com/carplay/documentation/CarPlay-App-Programming-Guide.pdf