Skip to content

Commit 933209a

Browse files
feat: add carplay and android auto support (#255)
Adds support for Apple CarPlay and Android Auto. Added BaseAutoSceneDelegate for iOS and AndroidAutoBaseScreen for Android on a plugin level to manage setting up the base functionality for each platform. Added example of setting up each platform in the SampleApp. iOS SampleApp has a new separate target for CarPlay support SampleAppCarPlay. Added separate native module NavAutoModule to manage communication between RN code and the map instance. Added a generic event channel so that user actions can be sent from native code to RN. e.g. user presses a button in CarPlay window and this event is sent to RN code. Added a function to NavAutoModule to check whether CarPlay or Android Auto screen has been initialized and is available. Co-authored-by: Joonas Kerttula <[email protected]>
1 parent 13d6fa8 commit 933209a

File tree

69 files changed

+4679
-1275
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+4679
-1275
lines changed

ANDROIDAUTO.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Navigation for Android Auto
2+
3+
This guide explains how to enable and integrate Android Auto with the React Native Navigation SDK.
4+
5+
## Requirements
6+
7+
- Android device
8+
- Android Auto test device or Android Automotive OS emulator
9+
10+
## Setup
11+
12+
Refer to the [Android for Cars developer documentation](https://developer.android.com/training/cars) to understand how the Android Auto works and to complete the initial setup. Key steps include:
13+
14+
- Installing Android for Cars App Library.
15+
- Configuring your app's manifest file to include Android Auto.
16+
- Declaring a minimum car-app level in your manifest.
17+
- Creating 'CarAppService' and session
18+
19+
For all the steps above, you can refer to the Android example application for guidance.
20+
21+
### Screen for Android Auto
22+
23+
Once your project is configured accordingly, and you are ready to build the screen for Android Auto, you can leverage the `AndroidAutoBaseScreen` provided by the SDK. This base class simplifies the setup by handling initialization, teardown, and rendering the map on the Android Auto display.
24+
25+
Please refer to the `SampleAndroidAutoScreen.java` file in the Android example app for guidance.
26+
27+
To customize the Android Auto experience, override the `onGetTemplate` method in your custom AndroidAutoScreen class, providing your own `Template`:
28+
29+
```java
30+
@NonNull
31+
@Override
32+
public Template onGetTemplate() {
33+
/** ... */
34+
@SuppressLint("MissingPermission")
35+
NavigationTemplate.Builder navigationTemplateBuilder =
36+
new NavigationTemplate.Builder()
37+
.setActionStrip(
38+
new ActionStrip.Builder()
39+
.addAction(
40+
new Action.Builder()
41+
.setTitle("Re-center")
42+
.setOnClickListener(
43+
() -> {
44+
if (mGoogleMap == null) return;
45+
mGoogleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED);
46+
})
47+
.build())
48+
.addAction(
49+
new Action.Builder()
50+
.setTitle("Custom event")
51+
.setOnClickListener(
52+
() -> {
53+
WritableMap map = Arguments.createMap();
54+
map.putString("sampleKey", "sampleValue");
55+
sendCustomEvent("sampleEvent", map);
56+
})
57+
.build())
58+
.build())
59+
.setMapActionStrip(new ActionStrip.Builder().addAction(Action.PAN).build());
60+
/** ... */
61+
}
62+
```
63+
64+
For advanced customization, you can bypass the base class and implement your own screen by inheriting `Screen`. You can use the provided `AndroidAutoBaseScreen` base class as a reference on how to do that.
65+
66+
### React Native specific setup
67+
68+
On the React Native side, you can use the `useNavigationAuto` hook to interface with the Android Auto instance. The `mapViewAutoController` allows you to call map functions on the Android Auto map, and you can manage listeners using the provided functions.
69+
70+
```tsx
71+
const {
72+
mapViewAutoController,
73+
addListeners: addAutoListener,
74+
removeListeners: removeAutoListeners,
75+
} = useNavigationAuto();
76+
77+
const navigationAutoCallbacks: NavigationAutoCallbacks = useMemo(
78+
() => ({
79+
onCustomNavigationAutoEvent: (event: CustomNavigationAutoEvent) => {
80+
console.log('onCustomNavigationAutoEvent:', event);
81+
},
82+
onAutoScreenAvailabilityChanged: (available: boolean) => {
83+
console.log('onAutoScreenAvailabilityChanged:', available);
84+
setMapViewAutoAvailable(available);
85+
},
86+
}),
87+
[]
88+
);
89+
90+
const setMapType = (mapType: MapType) => {
91+
console.log('setMapType', mapType);
92+
mapViewAutoController.setMapType(mapType);
93+
};
94+
```
95+
96+
For a more detailed example, refer to the `NavigationScreen.tsx` in the React Native example application.
97+
98+
## Example Project
99+
100+
For a fully functional Android Auto implementation, check out the [SampleApp](./example/android/) Android Studio project.

CARPLAY.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Navigation for Apple CarPlay
2+
3+
This guide explains how to enable and integrate Apple CarPlay with the React Native Navigation SDK.
4+
5+
## Requirements
6+
7+
- iOS device or iOS simulator (iOS 14.0+)
8+
- CarPlay Simulator
9+
- CarPlay entitlement for your application (provided by Apple)
10+
11+
## Setup
12+
13+
Refer to the [Apple CarPlay Developer Guide](https://developer.apple.com/carplay/) to understand how CarPlay works and to complete the initial setup. Key steps include:
14+
15+
- Adding the CarPlay entitlement to your Xcode project.
16+
- Creating a separate scene for the CarPlay map and enabling support for multiple scenes.
17+
18+
### SceneDelegate for CarPlay
19+
20+
Once your project is configured to support multiple scenes, and you are setting up a dedicated scene for CarPlay, you can leverage the `BaseCarSceneDelegate` provided by the SDK. This base class simplifies the setup by handling initialization, teardown, and rendering the map on the CarPlay display.
21+
22+
Please refer to the `CarSceneDelegate.h` and `CarSceneDelegate.m` files in the iOS example app for guidance.
23+
24+
To customize the CarPlay experience, override the `getTemplate` method in your custom `CarSceneDelegate` class, providing your own `CPMapTemplate`:
25+
26+
```objc
27+
- (CPMapTemplate *)getTemplate {
28+
  CPMapTemplate *template = [[CPMapTemplate alloc] init];
29+
  [template showPanningInterfaceAnimated:YES];
30+
 
31+
  CPBarButton *customButton = [[CPBarButton alloc]
32+
      initWithTitle:@"Custom Event"
33+
            handler:^(CPBarButton ***_Nonnull** button) {
34+
              NSMutableDictionary *dictionary = [
35+
              [NSMutableDictionary alloc] init
36+
          ];
37+
              dictionary[@"sampleDataKey"] = @"sampleDataContent";
38+
              [[NavAutoModule getOrCreateSharedInstance]
39+
              onCustomNavigationAutoEvent:@"sampleEvent"
40+
              data:dictionary
41+
          ];
42+
            }];
43+
44+
  template.leadingNavigationBarButtons = @[ customButton ];
45+
  template.trailingNavigationBarButtons = @[];
46+
  return template;
47+
}
48+
```
49+
50+
For advanced customization, you can bypass the base class and implement your own delegate inheriting `CPTemplateApplicationSceneDelegate`. You can use the provided `BaseCarSceneDelegate` base class as a reference on how to do that.
51+
52+
### React Native Setup
53+
54+
On the React Native side, you can use the `useNavigationAuto` hook to interface with the CarPlay instance. The `mapViewAutoController` allows you to call map functions on the CarPlay map view, and you can manage listeners using the provided functions.
55+
56+
```tsx
57+
const {
58+
mapViewAutoController,
59+
addListeners: addAutoListener,
60+
removeListeners: removeAutoListeners,
61+
} = useNavigationAuto();
62+
63+
const navigationAutoCallbacks: NavigationAutoCallbacks = useMemo(
64+
() => ({
65+
onCustomNavigationAutoEvent: (event: CustomNavigationAutoEvent) => {
66+
console.log('onCustomNavigationAutoEvent:', event);
67+
},
68+
onAutoScreenAvailabilityChanged: (available: boolean) => {
69+
console.log('onAutoScreenAvailabilityChanged:', available);
70+
setMapViewAutoAvailable(available);
71+
},
72+
}),
73+
[]
74+
);
75+
76+
const setMapType = (mapType: MapType) => {
77+
console.log('setMapType', mapType);
78+
mapViewAutoController.setMapType(mapType);
79+
};
80+
```
81+
82+
For a more detailed example, refer to the `NavigationScreen.tsx` in the React Native example application.
83+
84+
## Example Project
85+
86+
For a fully functional CarPlay implementation, check out the [SampleApp](./example/ios/) Xcode project, which includes the `SampleAppCarPlay` build target. The sample already contains test entitlement so you don't need to request one from Apple to run it.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ By default, `NavigationView` uses all the available space provided to it. To adj
159159
/>
160160
```
161161

162+
## Support for Android Auto and Apple CarPlay
163+
This plugin is compatible with both Android Auto and Apple CarPlay infotainment systems. For more details, please refer to the respective platform documentation:
164+
165+
- [Android Auto documentation](./ANDROIDAUTO.md)
166+
- [CarPlay documentation](./CARPLAY.md)
167+
162168
## Known issues
163169

164170
### Compatibility with other libraries

android/build.gradle

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Copyright 2023 Google LLC
2-
//
2+
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
55
// You may obtain a copy of the License at
6-
//
6+
//
77
// http://www.apache.org/licenses/LICENSE-2.0
8-
//
8+
//
99
// Unless required by applicable law or agreed to in writing, software
1010
// distributed under the License is distributed on an "AS IS" BASIS,
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -37,7 +37,7 @@ if (isNewArchitectureEnabled()) {
3737

3838
android {
3939
namespace "com.google.android.react.navsdk"
40-
40+
4141
compileSdkVersion 31
4242

4343
compileOptions {
@@ -71,6 +71,8 @@ repositories {
7171
}
7272

7373
dependencies {
74+
implementation "androidx.car.app:app:1.4.0"
75+
implementation "androidx.car.app:app-projected:1.4.0"
7476
implementation 'com.facebook.react:react-native:+'
7577
implementation 'com.android.support:multidex:1.0.3'
7678
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

0 commit comments

Comments
 (0)