Apple CarPlay

CarPlay with React Native

Welcome to CarPlay Development!

Begin your journey with the App Programming Guidelines for CarPlay (opens in a new tab), a comprehensive 50-page manual by Apple detailing the essentials for CarPlay apps.

For additional details while developing or contributing, refer to the CarPlay Documentation (opens in a new tab).

🚀 Quickstart: Utilize the simulator to test CarPlay capabilities without waiting for Apple's entitlement approval.

🔑 Entitlements: To deploy on a device or distribute via App Store Connect or TestFlight, obtain a CarPlay entitlement here (opens in a new tab). The approval duration varies, and participation in the MFi program may expedite the process. Incorporate the entitlement into your app's provisioning profile in Xcode.

🖥 Simulator: In Xcode, navigate to the Simulator window, choose IO > External Displays > CarPlay to launch the CarPlay simulator.

Important:

Ensure your Entitlements.plist within the iOS/ directory contains the correct entitlement key, whether for simulation or actual deployment.

Installing

You need to convert your project to using Scenes (opens in a new tab), as this is the standard when managing multiple windows in iOS 13+. This is a requirement for CarPlay apps.

1. Add your PhoneScene

This is where your app will run on the phone.

PhoneSceneDelegate.h

#import <UIKit/UIKit.h>
 
@interface PhoneSceneDelegate : UIResponder <UIWindowSceneDelegate>
 
@property (strong, nonatomic) UIWindow *window;
 
@end

PhoneSceneDelegate.m

#import "PhoneSceneDelegate.h"
 
@implementation PhoneSceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
  AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
  UIWindowScene *windowScene = (UIWindowScene *)scene;
  UIViewController *rootViewController = [[UIViewController alloc] init];
  rootViewController.view = appDelegate.rootView;
  UIWindow *window = [[UIWindow alloc] initWithWindowScene:windowScene];
  window.rootViewController = rootViewController;
  self.window = window;
  [window makeKeyAndVisible];
}
 
@end

2. Add your CarScene

This is where your app will run on CarPlay.

CarSceneDelegate.h

#import <Foundation/Foundation.h>
#import <CarPlay/CarPlay.h>
 
@interface CarSceneDelegate : UIResponder <CPTemplateApplicationSceneDelegate>
@end

CarSceneDelegate.m

#import "CarSceneDelegate.h"
#import "CarSceneDelegate.h"
#import "RNCarPlay.h"
 
@implementation CarSceneDelegate
 
- (void)templateApplicationScene:(CPTemplateApplicationScene *)templateApplicationScene
      didConnectInterfaceController:(CPInterfaceController *)interfaceController {
    // Dispatch connect to RNCarPlay
    [RNCarPlay connectWithInterfaceController:interfaceController window:templateApplicationScene.carWindow];
}
 
- (void)templateApplicationScene:(CPTemplateApplicationScene *)templateApplicationScene
      didDisconnectInterfaceController:(CPInterfaceController *)interfaceController {
    // Dispatch disconnect to RNCarPlay
 in   [RNCarPlay disconnect];
}
 
@end

3. Add Scene Manifest to Info.plist

ios/App/Info.plist

<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
    <key>CPTemplateApplicationSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneClassName</key>
        <string>CPTemplateApplicationScene</string>
        <key>UISceneConfigurationName</key>
        <string>CarPlay</string>
        <key>UISceneDelegateClassName</key>
        <string>$(PRODUCT_MODULE_NAME).CarSceneDelegate</string>
      </dict>
    </array>
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneClassName</key>
        <string>UIWindowScene</string>
        <key>UISceneConfigurationName</key>
        <string>Phone</string>
        <key>UISceneDelegateClassName</key>
        <string>$(PRODUCT_MODULE_NAME).PhoneSceneDelegate</string>
      </dict>
    </array>
  </dict>
</dict>

Entitlement matrix

ListGridT BAlertA S🎤▶️Map🔎POIInfo📇
com.apple.developer.carplay-audio
com.apple.developer.carplay-communication
com.apple.developer.carplay-charging
com.apple.developer.carplay-maps
com.apple.developer.carplay-parking
com.apple.developer.carplay-quick-ordering

Connect / Disconnect

Efficiently manage CarPlay connections by utilizing the connected status and on-connect/disconnect events. Ensure to check the connection state before invoking CarPlay APIs, ideally within a useEffect hook or by using a non-React function.

// react
useEffect(() => {
  CarPlay.registerOnConnect(onConnect);
  return () => {
    CarPlay.unregisterOnConnect(onConnect);
  };
});
 
// imperative
CarPlay.registerOnConnect(() => {
  CarPlay.setRootTemplate(/* template */);
});

Templates

Templates are used to render contents on the CarPlay screen from your app. Details of the templates supported by apple can be found in the developer guide (opens in a new tab)

MapTemplate

A template that displays a navigation overlay that your app draws on the map.

Visual Previews

Map Template Map Template

Example Usage

new MapTemplate({
  component: /* react native view */ MapView,
  guidanceBackgroundColor: '#eeff00',
  onAlertActionPressed() {},
  onStartedTrip() {},
});

See more configuration options in the TypeScript Docs

Relevant Links

ListTemplate

A template that displays and manages a list of items.

Visual Previews

List Template

Example Usage

new ListTemplate({
  sections: [
    {
      header: 'Header A',
      items: [
        {
          text: 'Item 1',
        },
      ],
    },
  ],
  title: 'List Template',
  async onItemSelect() {},
});

See more configuration options in the TypeScript Docs

Relevant Links

InformationTemplate

A template that provides information for a point of interest, food order, parking location, or charging location.

Visual Previews

Information Template

Example Usage

new InformationTemplate({
  title: 'Information',
  items: [{ title: 'foo', detail: 'bar' }],
  actions: [{ id: 'demo', title: 'Demo' }],
  onActionButtonPressed() {},
});

See more configuration options in the TypeScript Docs

Relevant Links

GridTemplate

A template that displays and manages a grid of items.

Visual Previews

Grid Template

Example Usage

new GridTemplate({
  trailingNavigationBarButtons: [
    {
      id: 'a',
      type: 'image',
      image: require('star.jpg'),
    },
  ],
  buttons: [
    {
      id: '0',
      titleVariants: ['Item 0'],
      image: require('click.jpg'),
    },
  ],
  title: 'Grid Template',
  onButtonPressed() {},
  onBarButtonPressed() {},
});

See more configuration options in the TypeScript Docs

Relevant Links

SearchTemplate

A template that provides the ability to search for a destination and see a list of search results.

Visual Previews

Search Template

Example Usage

new SearchTemplate({
  async onSearch(query) {},
  async onItemSelect({ index }) {},
  onSearchButtonPressed() {},
});

See more configuration options in the TypeScript Docs

Relevant Links

VoiceTemplate

A template that displays a voice control indicator during audio input.

This template is presented via CarPlay.presentTemplate. In order to implement voice recognition, take a look at the @react-native-voice/voice (opens in a new tab) package.

Visual Previews

Voice Template

Example Usage

new VoiceControlTemplate({
  voiceControlStates: [
    {
      identifier: 'a',
      image: require('cat.jpg'),
      repeats: true,
      titleVariants: ['Searching...'],
    },
  ],
});

See more configuration options in the TypeScript Docs

Relevant Links

AlertTemplate

A template that displays a modal alert and should be presented via CarPlay.presentTemplate.

Visual Previews

Alert Template

Example Usage

new AlertTemplate({
  titleVariants: ['Hello world'],
  actions: [
    {
      id: 'ok',
      title: 'Ok',
    },
    {
      id: 'ok',
      title: 'Cancel',
    },
    {
      id: 'remove',
      title: 'Remove',
      style: 'destructive',
    },
  ],
  onActionButtonPressed() {},
});

Relevant Links

ActionSheetTemplate

A template that displays a modal action sheet and should be presented via CarPlay.presentTemplate.

Visual Previews

ActionSheet Template

Example Usage

new ActionSheetTemplate({
  title: 'Example',
  message: 'This is an message for you',
  actions: [
    {
      id: 'ok',
      title: 'Ok',
    },
    {
      id: 'remove',
      title: 'Remove',
      style: 'destructive',
    },
  ],
  onActionButtonPressed() {},
});

Relevant Links

TabBarTemplate

A container template that displays and manages other templates, presenting them as tabs.

Note: This template must be set as the root template and cannot be pushed on top of other templates.

Visual Previews

TabBar Template

Example Usage

// Define tab templates
const tpl1 = new ListTemplate(/* ... */);
const tpl2 = new ListTemplate(/* ... */);
 
// Setup the tab container template
new TabBarTemplate({
  templates: [tpl1, tpl2],
  onTemplateSelect() {},
});

Relevant Links

Troubleshooting

Image Size and Resolution

Quirks observed where PNG image resolutions should be specfied with scale factor of 3.0 (i.e. append with @3x) with ListTemplate image sizing suggested around 80 x 80 px per Issue #6 (opens in a new tab)