Begin your journey with the App Programming Guidelines for CarPlay, 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.
🚀 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. 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.
Ensure your Entitlements.plist
within the iOS/
directory contains the correct entitlement key, whether for simulation or actual deployment.
You need to convert your project to using Scenes, as this is the standard when managing multiple windows in iOS 13+. This is a requirement for CarPlay apps.
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
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
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>
List | Grid | T B | Alert | A S | 🎤 | Map | 🔎 | POI | Info | 📇 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|
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 | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
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 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
A template that displays a navigation overlay that your app draws on the map.
new MapTemplate({
component: /* react native view */ MapView,
guidanceBackgroundColor: '#eeff00',
onAlertActionPressed() {},
onStartedTrip() {},
});
See more configuration options in the TypeScript Docs
- CPMapTemplate: Learn more about the capabilities and limitations of the MapTemplate in CarPlay.
- CPMapTemplateDelegate: Understand the delegate callbacks that can be used to manage user interactions with the MapTemplate.
A template that displays and manages a list of items.
new ListTemplate({
sections: [
{
header: 'Header A',
items: [
{
text: 'Item 1',
},
],
},
],
title: 'List Template',
async onItemSelect() {},
});
See more configuration options in the TypeScript Docs
- CPListTemplate: Learn more about the capabilities and limitations of the ListTemplate in CarPlay.
- CPListTemplateDelegate: Understand the delegate callbacks that can be used to manage user interactions with the ListTemplate.
A template that provides information for a point of interest, food order, parking location, or charging location.
new InformationTemplate({
title: 'Information',
items: [{ title: 'foo', detail: 'bar' }],
actions: [{ id: 'demo', title: 'Demo' }],
onActionButtonPressed() {},
});
See more configuration options in the TypeScript Docs
- CPInformationTemplate: Learn more about the capabilities and limitations of the InformationTemplate in CarPlay.
- CPInformationTemplateDelegate: Understand the delegate callbacks that can be used to manage user interactions with the InformationTemplate.
A template that displays and manages a grid of items.
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
- CPGridTemplate: Discover the capabilities and constraints of the CPGridTemplate in CarPlay.
- CPGridTemplateDelegate: Delve into the delegate callbacks available for handling user interactions within the CPGridTemplate.
A template that provides the ability to search for a destination and see a list of search results.
new SearchTemplate({
async onSearch(query) {},
async onItemSelect({ index }) {},
onSearchButtonPressed() {},
});
See more configuration options in the TypeScript Docs
- CPSearchTemplate: Explore the features and limitations of the CPSearchTemplate in CarPlay.
- CPSearchTemplateDelegate: Learn about the delegate callbacks for managing interactions within the CPSearchTemplate.
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
package.
new VoiceControlTemplate({
voiceControlStates: [
{
identifier: 'a',
image: require('cat.jpg'),
repeats: true,
titleVariants: ['Searching...'],
},
],
});
See more configuration options in the TypeScript Docs
- CPVoiceControlTemplate: Investigate the functionalities and boundaries of the CPVoiceControlTemplate in CarPlay.
- CPVoiceControlTemplateDelegate: Gain insights into the delegate methods designed to handle user voice commands in the CPVoiceControlTemplate.
- SFSpeechRecognizer: Learn about speech recognition tasks and integrations with CarPlay applications.
A template that displays a modal alert and should be presented via CarPlay.presentTemplate
.
new AlertTemplate({
titleVariants: ['Hello world'],
actions: [
{
id: 'ok',
title: 'Ok',
},
{
id: 'ok',
title: 'Cancel',
},
{
id: 'remove',
title: 'Remove',
style: 'destructive',
},
],
onActionButtonPressed() {},
});
- CPAlertTemplate: Explore the functionality of CPAlertTemplate for displaying alerts in CarPlay.
- CPAlertTemplateDelegate: Learn about delegate methods for managing user interactions with CarPlay alerts.
A template that displays a modal action sheet and should be presented via CarPlay.presentTemplate
.
new ActionSheetTemplate({
title: 'Example',
message: 'This is an message for you',
actions: [
{
id: 'ok',
title: 'Ok',
},
{
id: 'remove',
title: 'Remove',
style: 'destructive',
},
],
onActionButtonPressed() {},
});
- CPActionSheetTemplate: Discover how to present an action sheet in CarPlay using the CPActionSheetTemplate.
- CPActionSheetTemplateDelegate: Delve into the delegate methods to manage selections and handle user actions within a CPActionSheetTemplate.
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.
// Define tab templates
const tpl1 = new ListTemplate(/* ... */);
const tpl2 = new ListTemplate(/* ... */);
// Setup the tab container template
new TabBarTemplate({
templates: [tpl1, tpl2],
onTemplateSelect() {},
});
- CPTabBarTemplate: Investigate the features and usage of CPTabBarTemplate to create a tab bar interface in CarPlay.
- CPTabBarTemplateDelegate: Explore the delegate methods for responding to tab selection events in the CPTabBarTemplate. ``
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