• Stars
    star
    657
  • Rank 68,589 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

CarPlay with React Native

CarPlay with React Native

What if you could create CarPlay with React Native. Well, now you can.

Animated Demo

Discord Channel

Come join us on our discord channel: https://discord.gg/b235pv6QHM

Support

This version of react-native-carplay supports iOS 14. If you need support for versions before this please refer to version 1.3.1 of this package.

CarPlay Entitlement and XCode Project Setup

Entitlement matrix

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

Read this section if you are new to CarPlay!

One of the most useful resources for undertanding the requirements, constraints and capabilities of CarPlay apps is the official App Programming Guidelines from Apple. It's a 50-page document that clearly lays out steps required and you are strongly encouraged to read it if you are new to CarPlay. Further to the above guide, when developing a CarPlay app or if contributing to this package; you'll find the CarPlay Documentation invaluable.

You can develop CarPlay capabilities with this project without waiting for Apple to send you back an entitlement, through the simulator.

If you want to build and run your app on an iPhone or share it with others through the App Store Connect or TestFlight, you will need to request a CarPlay entitlement from Apple first. The process will take anywhere from a few days to weeks - your mileage will vary. This depends on the type of Entitlement you are requesting. If you are part of the MFi program, this may help speed things up too. You then need to add the entitlement to your provisioning profile or signing certificate that you use for signing your app in XCode.

You can go to this Apple CarPlay entitlement request page to request a CarPlay Entitlement. You need to be logged in with an Apple Developer account.

To start a CarPlay simulator in XCode, within the Simulator window, go to the menu option IO, click on External Displays, then select CarPlay.

NB:

Whether you are running through a simulator or building the app for distribution, you need to ensure that the correct entitlement key is added in your Entitlements.plist file. If you don't have an Entitlements.plist file, create one in your iOS/ directory.

Installing

  1. Install the library
yarn add react-native-carplay --save
  1. Link using normal or cocoapods method
react-native link react-native-carplay
# in ios/Podfile:

pod 'react-native-carplay', path: '../node_modules/react-native-carplay'
  1. Edit your AppDelegate
// AppDelegate.h

// [step 1] add this line to the top
#import <CarPlay/CarPlay.h>

// [step 2] add the "CPApplicationDelegate" to the end, before ">":
@interface AppDelegate : UIResponder <UIApplicationDelegate, CPApplicationDelegate>
// AppDelegate.m

// [step 1] add this line to the top
#import <RNCarPlay.h>

// ...

// [step 2] add the following two methods before @end

- (void)application:(UIApplication *)application didConnectCarInterfaceController:(CPInterfaceController *)interfaceController toWindow:(CPWindow *)window {
  [RNCarPlay connectWithInterfaceController:interfaceController window:window];
}

- (void)application:(nonnull UIApplication *)application didDisconnectCarInterfaceController:(nonnull CPInterfaceController *)interfaceController fromWindow:(nonnull CPWindow *)window {
  [RNCarPlay disconnect];
}

@end

Basic Usage

See full example

The exported CarPlay class gives you the API needed to add / remove templates from the CarPlay view hierarchy.

import { CarPlay, GridTemplate } from 'react-native-carplay';

const template = new GridTemplate({
  title: 'Hello, World',
  buttons: [],
});

CarPlay.setRootTemplate(template);

Connect / Disconnect

When working with CarPlay it is important to detect and respond to the connect / disconnect events. The CarPlay class provides both a connected boolean and an on connect / disconnect event you can register a callback to.

When you are creating and displaying a template within your existing app screens you may want to ensure CarPlay is connected before calling any carplay apis. This can be done within a useEffect.

useEffect(() => {
  function onConnect() {
    // Do things now that carplay is connected
  }

  function onDisconnect() {
    // Do things now that carplay is disconnected
  }

  CarPlay.registerOnConnect(onConnect);
  CarPlay.registerOnDisconnect(onDisconnect);

  return () => {
    CarPlay.unregisterOnConnect(onConnect);
    CarPlay.unregisterOnDisconnect(onDisconnect);
  };
});

CarPlay API

CarPlay.setRootTemplate

Sets the root template of CarPlay. This must be called before running any other CarPlay commands. Can be called multiple times.

CarPlay.setRootTemplate(template, /* animated */ false);

CarPlay.pushTemplate

Pushes a new template to the navigation stack. Note you cannot push the same template twice.

CarPlay.pushTemplate(template, /* animated */ true);

CarPlay.popTemplate

Pop currently presented template from the stack.

CarPlay.popTemplate(/* animated */ false);

CarPlay.popToTemplate

Pop currently presented template from the stack to a specific template. The template must be in the stack.

CarPlay.popToTemplate(template, /* animated */ false);

CarPlay.popToRoot

Pop the stack to root template.

CarPlay.popToRoot(/* animated */ false);

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

MapTemplate

Map Template Map Template

import { CarPlay } from 'react-native-carplay';

const mapTemplate = new MapTemplate({
  component: /* react native view */ MapView,
  onAlertActionPressed(e) {
    console.log(e);
  },
  onStartedTrip({ tripId, routeIndex }) {
    // start your navigation code
    onStartNavigation(routeIndex);
  },
});

CarPlay.setRootTemplate(mapTemplate);

ListTemplate

List Template

import { CarPlay } from 'react-native-carplay';

const listTemplate = new ListTemplate({
  sections: [],
  title: 'List Template',
  async onItemSelect({ index }) {
    // use the selected index
    setSelected(index);
  },
});

CarPlay.pushTemplate(listTemplate, true);

InformationTemplate

Information Template

import { CarPlay } from 'react-native-carplay';

const template = new InformationTemplate({
  title: 'Information',
  items: Array.from({ length: 30 }).fill({ title: 'foo', detail: 'bar' }),
  actions: [
    { id: 'u', title: 'Update List' },
    { id: 'r', title: 'Random #:' },
  ],
  onActionButtonPressed(action) {
    console.log('pressed', action);
    if (action.id == 'u') {
      const numOfItems = Math.floor(Math.random() * 6);
      template.updateInformationTemplateItems(
        Array.from({ length: numOfItems }).fill({ title: 'foo', detail: 'bar' }),
      );
    } else if (action.id == 'r') {
      template.updateInformationTemplateActions([
        { id: 'u', title: 'Update List' },
        { id: 'r', title: 'Random #:' + Math.floor(Math.random() * 100) },
      ]);
    }
  },
});

CarPlay.pushTemplate(informationTemplate);

GridTemplate

Grid Template

import { CarPlay } from 'react-native-carplay';

const gridTemplate = new GridTemplate({
  trailingNavigationBarButtons: [],
  buttons: [
    {
      id: 'List',
      titleVariants: ['List'],
      image: listImage,
    },
    {
      id: 'Grid',
      titleVariants: ['Grid'],
      image: gridImage,
    },
  ],
  title: 'Grid Template',
  onButtonPressed({ id }) {
    // id of button pressed
    setSelected(id);
  },
  onBarButtonPressed({ id }) {
    // id of bar button pressed
    setSelected(id);
  },
});

CarPlay.pushTemplate(gridTemplate, true);

SearchTemplate

Search Template

const searchTemplate = new SearchTemplate({
  async onSearch(query) {
    // use the query to search
    // and return item array
    return performSearch(query);
  },
  async onItemSelect({ index }) {
    // index of the selected item
    setSelected(index);
  },
  onSearchButtonPressed() {
    // on search button pressed, should display
    // list template with results
    navigation.navigate('List');
  },
});

CarPlay.pushTemplate(searchTemplate, true);

VoiceTemplate

Voice Template

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

const voiceControlTemplate = new VoiceControlTemplate({
  // pass the control states
  voiceControlStates: [
    {
      identifier: 'TEST',
      image: require('../images/cat.jpg'),
      repeats: true,
      titleVariants: ['Searching...'],
    },
  ],
});

CarPlay.presentTemplate(voiceControlTemplate, true);

AlertTemplate

Alert Template

This template is presented via CarPlay.presentTemplate.

const alertTemplate = new AlertTemplate({
  titleVariants: ['Hello world'],
  actions: [
    {
      id: 'ok',
      title: 'Ok',
    },
    {
      id: 'remove',
      title: 'Remove',
      style: 'destructive',
    },
  ],
  onActionButtonPressed({ id }) {
    // id of the pressed button
    if (id === 'remove') {
      // presentable templates can be
      // dismissed
      CarPlay.dismissTemplate();
    }
  },
});

CarPlay.presentTemplate(alertTemplate);

ActionSheetTemplate

ActionSheet Template

This template is presented via CarPlay.presentTemplate.

const actionSheetTemplate = new ActionSheetTemplate({
  title: 'Example',
  message: 'This is an message for you',
  actions: [
    {
      id: 'ok',
      title: 'Ok',
    },
    {
      id: 'remove',
      title: 'Remove',
      style: 'destructive',
    },
  ],
  onActionButtonPressed({ id }) {
    // the id of the button pressed
  },
});

CarPlay.presentTemplate(actionSheetTemplate);

TabTemplate

Tab Template

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

const template1 = new ListTemplate({
  sections: [
    {
      header: 'Test 1',
      items: [{ text: 'Hello world 1' }],
    },
  ],
  title: 'AA',
});
const template2 = new ListTemplate({
  sections: [
    {
      header: 'Test 2',
      items: [{ text: 'Hello world 3' }],
    },
  ],
  title: 'BB',
});

const tabBarTemplate = new TabBarTemplate({
  templates: [template1, template2],
  onTemplateSelect(e: any) {
    console.log('selected', e);
  },
});

CarPlay.setRootTemplate(tabBarTemplate);

Example App

A working example app can be found here.

To run it you must first install dependencies and pods.

  1. install dependencies and build react-native-carplay
yarn install
  1. move to example dir and install dependencies
cd example
yarn install
  1. run build dev in root dir, this will copy the output to the examples node modules.
cd ..
yarn build:dev
  1. install pods in example app and start the metro bundler
cd example/ios
pod install
yarn start
  1. start xcode and run the project on your simulator or device

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

Not working / In progress

UI Elements

  • Contact Template
  • Now Playing Template
  • Point of Interest Template

Getters

  • topTemplate
  • rootTemplate

More Repositories

1

prime

✨Open Source GraphQL CMS
TypeScript
1,718
star
2

react-three-gui

GUI tools for react-three-fiber and react-spring
TypeScript
528
star
3

hekla

Hekla for Hacker News (open source React Native app)
TypeScript
363
star
4

gatsby-source-prismic-graphql

Gatsby source plugin for Prismic GraphQL
TypeScript
137
star
5

react-native-sfsymbols

SF Symbols in your iOS app
Objective-C
126
star
6

react-native-appstore

App Store clone in React Native
JavaScript
109
star
7

homebridge-plugin-eufy-security

Eufy security homebridge plugin
TypeScript
84
star
8

kvikmyndr-app

Whats in the movies tonight?
TypeScript
50
star
9

graphql-gatsby

Direct access to Gatsby's GraphQL schema and resolvers without the ecosystem
JavaScript
49
star
10

react-three-fiber-examples

react-three-fiber examples in react native
JavaScript
36
star
11

react-native-webgl-arkit

THREE.js ARKit extension for react-native-webgl
Objective-C
32
star
12

kohana-gitweb

GitHub 'like Repository Browser for Kohana 3.3
JavaScript
29
star
13

gatsby-plugin-prismic-preview

Preview plugin for gatsby-source-prismic
CSS
25
star
14

graphql-mst

Convert GraphQL to mobx-state-tree models
TypeScript
23
star
15

react-typescript-iso-kit

Another starter kit with typescript, jest, isomorphic, webpack etc.
JavaScript
22
star
16

gatsby-source-graphql-universal

Plugin for connecting arbitrary GraphQL APIs to Gatsby GraphQL with client side execution
JavaScript
20
star
17

react-suspense-demo

React Suspense Demo inspired by Dan's future api
JavaScript
20
star
18

obdii

OBD2 in TypeScript
JavaScript
19
star
19

react-native-youtubetv-demo

Re-creating YouTube TV's animated list in React Native
JavaScript
12
star
20

arduino-wiegand

Wiegand-26 library for communicating with 2-wire wiegand protocol.
C++
10
star
21

next-meets-gatsby

NextJS meets Gatsby source plugins as a graphql server
JavaScript
10
star
22

kohana-schema

Kohana 3.3 database schema and migration.
PHP
8
star
23

evrange

Estimate kW consumption routes for electric vehicles
TypeScript
8
star
24

react-starter-kit-rdb

React Starter Kit - Rethinkdb Universal Edition
JavaScript
7
star
25

react-children-addons

React Children Addons
TypeScript
7
star
26

bootstrap-tableselect

Table row selection for twitter bootstrap
7
star
27

kohana-media

Kohana 3.3 media module
PHP
6
star
28

react-native-three-renderer

Experimental react-native three.js renderer
JavaScript
6
star
29

kohana-app-places

The mobile and desktop website to find something to eat.
PHP
5
star
30

matr-app

JavaScript
5
star
31

plugin.video.oztv

XBMC Port of the popular OZ app for Android and iOS devices
Python
3
star
32

kohana-api-bokun

Kohana REST client for Bokun API.
PHP
3
star
33

universal-redux-demo

Universal redux demo
JavaScript
3
star
34

support-tickets

Support Ticket system written for Kohana 3.3
PHP
2
star
35

codingame

CodinGame solutions
JavaScript
2
star
36

kohana-app-drag

Drag times application
JavaScript
2
star
37

gatsby-plugin-config

Config plugin for gatsby
JavaScript
2
star
38

ovms-client

OVMS client written in TypeScript
TypeScript
2
star
39

react-native-css-modules-theme

Theme support for CSS Modules in React Native
TypeScript
2
star
40

material-components-react-native

React Native wrapper for material-components-ios
Objective-C
2
star
41

sensornodes

A RF node network providing sensing devices to my home
C++
2
star
42

arduino-ledtable

led-table matrix effect generator
C++
2
star
43

OZ.bundle

OZ TV bundle for Plex Media Server
Python
1
star
44

sass-flexbox-grid

Sass flexbox grid
CSS
1
star
45

kohana-hhvm

HHVM module for the Kohana Framework
PHP
1
star
46

cra-pipeline

create-react-app pipeline experiments
JavaScript
1
star
47

prime-bokun

Bokun module for Prime 3.3
PHP
1
star
48

app-postbox

React Native Postbox Client
JavaScript
1
star
49

cheffy

Recipes in React, Redux and Firebase
JavaScript
1
star
50

react-native-app-center-ndk

Example repo to reproduce NDK build failure in AppCenter
Objective-C
1
star