@iternio/react-native-auto-play 0.1.16 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +429 -14
  2. package/android/build.gradle +15 -1
  3. package/android/gradle.properties +1 -1
  4. package/android/src/{main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoTelemetryObserver.kt → auto/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidTelemetryObserver.kt} +31 -76
  5. package/android/src/automotive/AndroidManifest.xml +91 -0
  6. package/android/src/automotive/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidTelemetryObserver.kt +191 -0
  7. package/android/src/main/AndroidManifest.xml +0 -10
  8. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoScreen.kt +3 -0
  9. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/AndroidAutoTelemetryHolder.kt +97 -19
  10. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAndroidAutoTelemetry.kt +39 -3
  11. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridSignInTemplate.kt +22 -0
  12. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/TelemetryObserver.kt +56 -0
  13. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VirtualRenderer.kt +15 -10
  14. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/AutomotivePermissionRequestTemplate.kt +103 -0
  15. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/GridTemplate.kt +0 -2
  16. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/Parser.kt +8 -2
  17. package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/SignInTemplate.kt +159 -0
  18. package/ios/extensions/CarPlayExtensions.swift +4 -2
  19. package/ios/extensions/NitroImageExtensions.swift +4 -4
  20. package/ios/hybrid/HybridAutoPlay.swift +31 -42
  21. package/ios/hybrid/HybridCluster.swift +4 -2
  22. package/ios/hybrid/HybridGridTemplate.swift +11 -11
  23. package/ios/hybrid/HybridInformationTemplate.swift +12 -13
  24. package/ios/hybrid/HybridListTemplate.swift +12 -13
  25. package/ios/hybrid/HybridMapTemplate.swift +13 -16
  26. package/ios/hybrid/HybridMessageTemplate.swift +7 -4
  27. package/ios/hybrid/HybridSearchTemplate.swift +12 -13
  28. package/ios/scenes/AutoPlayInterfaceController.swift +44 -13
  29. package/ios/scenes/AutoPlayScene.swift +2 -1
  30. package/ios/scenes/AutoPlaySceneViewController.swift +8 -2
  31. package/ios/scenes/DashboardSceneDelegate.swift +15 -7
  32. package/ios/scenes/HeadUnitSceneDelegate.swift +12 -7
  33. package/ios/scenes/WindowApplicationSceneDelegate.swift +1 -1
  34. package/ios/templates/AutoPlayTemplate.swift +23 -15
  35. package/ios/templates/GridTemplate.swift +23 -16
  36. package/ios/templates/InformationTemplate.swift +12 -11
  37. package/ios/templates/ListTemplate.swift +11 -11
  38. package/ios/templates/MapTemplate.swift +40 -32
  39. package/ios/templates/MessageTemplate.swift +8 -12
  40. package/ios/templates/Parser.swift +2 -1
  41. package/ios/templates/SearchTemplate.swift +19 -17
  42. package/ios/templates/TemplateStore.swift +17 -9
  43. package/ios/utils/RootModule.swift +19 -12
  44. package/ios/utils/SymbolFont.swift +2 -1
  45. package/ios/utils/ViewUtils.swift +2 -2
  46. package/lib/hooks/useAndroidAutoTelemetry.d.ts +22 -4
  47. package/lib/hooks/useAndroidAutoTelemetry.js +52 -24
  48. package/lib/index.d.ts +2 -0
  49. package/lib/index.js +2 -0
  50. package/lib/specs/AndroidAutoTelemetry.nitro.d.ts +14 -1
  51. package/lib/specs/SignInTemplate.nitro.d.ts +12 -0
  52. package/lib/templates/SignInTemplate.d.ts +49 -0
  53. package/lib/templates/SignInTemplate.js +51 -0
  54. package/lib/types/SignInMethod.d.ts +38 -0
  55. package/lib/types/SignInMethod.js +19 -0
  56. package/lib/types/Telemetry.d.ts +27 -0
  57. package/lib/types/Telemetry.js +7 -0
  58. package/nitro.json +3 -0
  59. package/nitrogen/generated/android/ReactNativeAutoPlay+autolinking.cmake +3 -0
  60. package/nitrogen/generated/android/ReactNativeAutoPlayOnLoad.cpp +12 -2
  61. package/nitrogen/generated/android/c++/JBooleanTelemetryItem.hpp +61 -0
  62. package/nitrogen/generated/android/c++/JFunc_void_std__optional_Telemetry_.hpp +87 -0
  63. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +10 -10
  64. package/nitrogen/generated/android/c++/JHybridAndroidAutoTelemetrySpec.cpp +41 -5
  65. package/nitrogen/generated/android/c++/JHybridAndroidAutoTelemetrySpec.hpp +2 -1
  66. package/nitrogen/generated/android/c++/JHybridSignInTemplateSpec.cpp +133 -0
  67. package/nitrogen/generated/android/c++/JHybridSignInTemplateSpec.hpp +66 -0
  68. package/nitrogen/generated/android/c++/JInputSignIn.hpp +103 -0
  69. package/nitrogen/generated/android/c++/JKeyboardType.hpp +65 -0
  70. package/nitrogen/generated/android/c++/JPermissionRequestResult.hpp +98 -0
  71. package/nitrogen/generated/android/c++/JPinSignIn.hpp +63 -0
  72. package/nitrogen/generated/android/c++/JQrSignIn.hpp +63 -0
  73. package/nitrogen/generated/android/c++/JSignInMethods.hpp +65 -0
  74. package/nitrogen/generated/android/c++/JSignInTemplateConfig.hpp +217 -0
  75. package/nitrogen/generated/android/c++/JTelemetry.hpp +25 -3
  76. package/nitrogen/generated/android/c++/JTextInputType.hpp +59 -0
  77. package/nitrogen/generated/android/c++/JVariant_QrSignIn_PinSignIn_InputSignIn.cpp +30 -0
  78. package/nitrogen/generated/android/c++/JVariant_QrSignIn_PinSignIn_InputSignIn.hpp +99 -0
  79. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/AssetImage.kt +1 -1
  80. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/AutoText.kt +2 -2
  81. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/BooleanTelemetryItem.kt +41 -0
  82. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/{Func_void_std__optional_Telemetry__std__optional_std__string_.kt → Func_void_std__optional_Telemetry_.kt} +14 -14
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Func_void_std__string.kt +9 -9
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GlyphImage.kt +1 -1
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GridTemplateConfig.kt +8 -8
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAndroidAutoTelemetrySpec.kt +7 -2
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridSignInTemplateSpec.kt +62 -0
  88. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/InformationTemplateConfig.kt +9 -9
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/InputSignIn.kt +63 -0
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/KeyboardType.kt +23 -0
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ListTemplateConfig.kt +9 -9
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/MapTemplateConfig.kt +17 -17
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/MessageTemplateConfig.kt +11 -11
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NavigationAlertAction.kt +1 -1
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroAction.kt +6 -6
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroAttributedString.kt +1 -1
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroBaseMapTemplateConfig.kt +9 -9
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroMapButton.kt +1 -1
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroMessageManeuver.kt +2 -2
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroNavigationAlert.kt +5 -5
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroRoutingManeuver.kt +12 -12
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroRow.kt +6 -6
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroSection.kt +1 -1
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/PermissionRequestResult.kt +41 -0
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/PinSignIn.kt +41 -0
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/QrSignIn.kt +41 -0
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SafeAreaInsets.kt +1 -1
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SearchTemplateConfig.kt +9 -9
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SignInMethods.kt +23 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SignInTemplateConfig.kt +78 -0
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Telemetry.kt +23 -8
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TextInputType.kt +21 -0
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TravelEstimates.kt +1 -1
  114. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Variant_QrSignIn_PinSignIn_InputSignIn.kt +72 -0
  115. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/VehicleTelemetryItem.kt +3 -3
  116. package/nitrogen/generated/shared/c++/BooleanTelemetryItem.hpp +79 -0
  117. package/nitrogen/generated/shared/c++/HybridAndroidAutoTelemetrySpec.cpp +1 -0
  118. package/nitrogen/generated/shared/c++/HybridAndroidAutoTelemetrySpec.hpp +7 -1
  119. package/nitrogen/generated/shared/c++/HybridSignInTemplateSpec.cpp +22 -0
  120. package/nitrogen/generated/shared/c++/HybridSignInTemplateSpec.hpp +66 -0
  121. package/nitrogen/generated/shared/c++/InputSignIn.hpp +113 -0
  122. package/nitrogen/generated/shared/c++/KeyboardType.hpp +64 -0
  123. package/nitrogen/generated/shared/c++/PermissionRequestResult.hpp +80 -0
  124. package/nitrogen/generated/shared/c++/PinSignIn.hpp +81 -0
  125. package/nitrogen/generated/shared/c++/QrSignIn.hpp +81 -0
  126. package/nitrogen/generated/shared/c++/SignInMethods.hpp +64 -0
  127. package/nitrogen/generated/shared/c++/SignInTemplateConfig.hpp +138 -0
  128. package/nitrogen/generated/shared/c++/Telemetry.hpp +25 -2
  129. package/nitrogen/generated/shared/c++/TextInputType.hpp +62 -0
  130. package/package.json +4 -2
  131. package/src/hooks/useAndroidAutoTelemetry.ts +80 -27
  132. package/src/index.ts +2 -0
  133. package/src/specs/AndroidAutoTelemetry.nitro.ts +19 -1
  134. package/src/specs/SignInTemplate.nitro.ts +10 -0
  135. package/src/templates/SignInTemplate.ts +117 -0
  136. package/src/types/SignInMethod.ts +41 -0
  137. package/src/types/Telemetry.ts +29 -0
  138. package/lib/specs/VoiceInput.nitro.d.ts +0 -8
  139. package/nitrogen/generated/android/c++/JFunc_void_std__optional_Telemetry__std__optional_std__string_.hpp +0 -85
  140. /package/lib/specs/{VoiceInput.nitro.js → SignInTemplate.nitro.js} +0 -0
package/README.md CHANGED
@@ -220,6 +220,84 @@ You can customize certain behaviors of the library on Android Auto by setting pr
220
220
  ```
221
221
  The default values are `1000` for the delay and `500` for the duration.
222
222
 
223
+ ### Android Automotive
224
+
225
+ This library also supports Android Automotive. To enable Android Automotive support, you need to configure a few properties in your Android project.
226
+
227
+ - **`minSdkVersion`**: The minimum API level for Android Automotive is 29. You must set `minSdkVersion` to at least `29`. For Android Auto, the minimum is `24`.
228
+
229
+ - **`isAutomotiveApp` flag**: You need to inform the library if this is an Automotive app by setting the `isAutomotiveApp` property to `true`. For Android Auto, it should be `false`.
230
+
231
+ You can set these properties directly in your `android/gradle.properties` file:
232
+ ```properties
233
+ # For Android Automotive
234
+ minSdkVersion=29
235
+ isAutomotiveApp=true
236
+ ```
237
+
238
+ Alternatively, if you need to support different build variants (e.g., for both Android Auto and Android Automotive from the same codebase), using `react-native-config` is the recommended approach.
239
+
240
+ 1. Install `react-native-config`:
241
+ ```bash
242
+ yarn add react-native-config
243
+ ```
244
+
245
+ 2. Create different `.env` files for your variants. Create a default `.env` for Android Auto:
246
+ ```
247
+ # .env (for Android Auto)
248
+ isAutomotiveApp=false
249
+ minSdkVersion=24
250
+ ```
251
+ And an `.env.automotive` for Android Automotive:
252
+ ```
253
+ # .env.automotive
254
+ minSdkVersion=29
255
+ isAutomotiveApp=true
256
+ ```
257
+
258
+ 3. In your `android/app/build.gradle`, apply the configuration from `react-native-config` based on your build flavors.
259
+ ```groovy
260
+ // android/app/build.gradle
261
+
262
+ project.ext.envConfigFiles = [
263
+ automotive: ".env.automotive",
264
+ // other flavors...
265
+ ]
266
+ apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
267
+
268
+ if (project.ext.has("env")) {
269
+ rootProject.ext.minSdkVersion = project.ext.env.minSdkVersion
270
+ rootProject.ext.isAutomotiveApp = project.ext.env.isAutomotiveApp
271
+ }
272
+ ```
273
+ Adjust to the build variants your app provides. Check the example app for details.
274
+
275
+ This approach allows you to dynamically set the required flags based on your build variant, which is demonstrated in the example app.
276
+
277
+ #### App launch on Android Automotive
278
+
279
+ Android Automotive requires you to remove your app activity since it invokes the libraries Android Auto service in a different way. Not doing so will bring up 2 app icons on the Android Automotive launcher.
280
+ To get rid of your default activity, do an automotive specific build variant and add this AndroidManifest.xml for that variant.
281
+ ```xml
282
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
283
+ xmlns:tools="http://schemas.android.com/tools">
284
+
285
+ <application>
286
+ <activity
287
+ android:name=".MainActivity"
288
+ tools:node="remove" /> <!-- remove main activity -->
289
+ </application>
290
+
291
+ </manifest>
292
+ ```
293
+ For details check the example app and its build variants.
294
+
295
+ #### A Note on Android Studio
296
+
297
+ When using build variants, Android Studio may not be aware of the selected variant during a Gradle sync. This can cause the IDE to show the incorrect implementation of native classes like `AndroidTelemetryObserver` (e.g., it might show the Android Auto version instead of the Automotive version).
298
+
299
+ To work around this and allow for debugging or enhancing the Android Automotive-specific implementation, you can temporarily set the automotive flags in your `gradle.properties` file or your default `.env` file before running a Gradle sync.
300
+
223
301
  ## Icons
224
302
  The library is using [Material Symbols](https://fonts.google.com/icons) for iconography. The font is bundled with the library, so no extra setup is required. You can use these icons on both Android Auto and CarPlay.
225
303
 
@@ -347,6 +425,258 @@ export default registerAutoPlay;
347
425
 
348
426
  - `HybridAutoPlay`: The primary interface for interacting with the native module, handling connection status and events.
349
427
 
428
+ ### Core Types
429
+
430
+ #### AutoText
431
+ Most text props accept `AutoText` so you can localize and provide variants. You can pass either a string or an object with `text`/`variants` as used throughout the example app.
432
+
433
+ #### AutoImage
434
+ Images are provided as `AutoImage` objects with a `type` and `name`. The built-in icon set is Material Symbols (see **Icons**). You can also use bundled images from your native project.
435
+
436
+ #### RootComponentInitialProps
437
+ All root components rendered by templates/scenes receive `RootComponentInitialProps`:
438
+
439
+ - `id`: Module identifier (e.g. `AutoPlayRoot`, `CarPlayDashboard`, or a cluster UUID).
440
+ - `rootTag`: React Native root tag.
441
+ - `colorScheme`: `'light' | 'dark'` initial color scheme (listen to `onAppearanceDidChange` on `MapTemplate` for updates).
442
+ - `window`: `{ width, height, scale }`.
443
+
444
+ ### Template Configs (Props)
445
+
446
+ Below is a concise overview of the most important props per template. Optional props are marked as **optional**. Required props are marked as **required**.
447
+
448
+ #### MapTemplateConfig
449
+
450
+ | Prop | Type | Required | Notes |
451
+ | --- | --- | --- | --- |
452
+ | `component` | `React.ComponentType<RootComponentInitialProps>` | ✅ | React component to render on the map surface. |
453
+ | `onStopNavigation` | `(template: MapTemplate) => void` | ✅ | Called when navigation is stopped by the system. |
454
+ | `headerActions` | `MapHeaderActions<MapTemplate>` | ❌ | Top action strip. See **Header Actions** below. |
455
+ | `mapButtons` | `MapButtons<MapTemplate>` | ❌ | 1–4 map buttons shown on the map. |
456
+ | `visibleTravelEstimate` | `'first'` `'last'` | ❌ | Which travel estimate to display. |
457
+ | `onDidPan` / `onDidUpdateZoomGestureWithCenter` | callbacks | ❌ | Map gesture events. |
458
+ | `onAppearanceDidChange` | `(colorScheme) => void` | ❌ | Listen for light/dark mode changes. |
459
+ | `onAutoDriveEnabled` | `(template) => void` | ⚠️ | Android-only auto drive callback. Make sure to take action when receiving this and simulate a drive to the set destination. [Check Android docs for details](https://developer.android.com/reference/androidx/car/app/navigation/NavigationManagerCallback#onAutoDriveEnabled()) |
460
+
461
+ #### ListTemplateConfig
462
+
463
+ | Prop | Type | Required | Notes |
464
+ | --- | --- | --- | --- |
465
+ | `title` | `AutoText` | ✅ | Header title. |
466
+ | `sections` | `Section<ListTemplate>` | ❌ | List sections/rows. Not providing anything here will result in a loading indicator on Android and an empty list on iOS. |
467
+ | `headerActions` | `HeaderActions<ListTemplate>` | ❌ | Header actions. See **Header Actions** below. |
468
+ | `mapConfig` | `BaseMapTemplateConfig<ListTemplate>` | ❌ | Android map-with-content layout. |
469
+
470
+ #### GridTemplateConfig
471
+
472
+ | Prop | Type | Required | Notes |
473
+ | --- | --- | --- | --- |
474
+ | `title` | `AutoText` | ✅ | Header title. |
475
+ | `buttons` | `GridButton<GridTemplate>[]` | ✅ | Grid items. Providing an empty array will result in a loading indicator on Android and an empty template on iOS. |
476
+ | `headerActions` | `HeaderActions<GridTemplate>` | ❌ | Header actions. See **Header Actions** below. |
477
+ | `mapConfig` | `BaseMapTemplateConfig<GridTemplate>` | ❌ | Android map-with-content layout. |
478
+
479
+ #### SearchTemplateConfig
480
+
481
+ | Prop | Type | Required | Notes |
482
+ | --- | --- | --- | --- |
483
+ | `title` | `AutoText` | ✅ | Header title. |
484
+ | `results` | `SearchSection<SearchTemplate>` | ❌ | Initial results. |
485
+ | `headerActions` | `HeaderActions<SearchTemplate>` | ❌ | Header actions. See **Header Actions** below. |
486
+ | `searchHint` | `string` | ❌ | Android-only placeholder. |
487
+ | `initialSearchText` | `string` | ❌ | Android-only initial value. |
488
+ | `onSearchTextChanged` | `(text) => void` | ✅ | Fired on text input changes. |
489
+ | `onSearchTextSubmitted` | `(text) => void` | ✅ | Fired on submit. |
490
+
491
+ #### InformationTemplateConfig
492
+
493
+ | Prop | Type | Required | Notes |
494
+ | --- | --- | --- | --- |
495
+ | `title` | `AutoText` | ✅ | Header title. |
496
+ | `items` | `InformationItems` | ❌ | 1–4 rows. |
497
+ | `actions` | platform-specific | ❌ | Up to 2 buttons on Android, up to 3 on iOS. |
498
+ | `headerActions` | `HeaderActions<InformationTemplate>` | ❌ | Header actions. See **Header Actions** below. |
499
+ | `mapConfig` | `BaseMapTemplateConfig<InformationTemplate>` | ❌ | Android map-with-content layout. |
500
+
501
+ #### MessageTemplateConfig
502
+
503
+ | Prop | Type | Required | Notes |
504
+ | --- | --- | --- | --- |
505
+ | `message` | `AutoText` | ✅ | Main message text. |
506
+ | `title` | `AutoText` | ❌ | Android header title. |
507
+ | `image` | `AutoImage` | ❌ | Android-only image above the message. |
508
+ | `actions` | platform-specific | ❌ | Up to 2 buttons on Android, up to 3 on iOS. |
509
+ | `headerActions` | `HeaderActionsAndroid<MessageTemplate>` | ❌ | Android-only header actions. |
510
+ | `mapConfig` | `BaseMapTemplateConfig<MessageTemplate>` | ❌ | Android map-with-content layout. |
511
+
512
+ #### SignInTemplateConfig (Android-only)
513
+
514
+ | Prop | Type | Required | Notes |
515
+ | --- | --- | --- | --- |
516
+ | `signInMethod` | `SignInMethod` | ✅ | The sign-in method configuration. Can be QRSignIn, PinSignIn, InputSignIn. |
517
+ | `title` | `string` | ❌ | Header title. |
518
+ | `additionalText` | `string` | ❌ | Additional descriptive text. |
519
+ | `instructions` | `string` | ❌ | Sign-in Instructions text. |
520
+ | `actions` | `ActionButton<SignInTemplate>[]` | ❌ | Up to 2 buttons. |
521
+ | `headerActions` | `SignInHeaderActions<SignInTemplate>` | ❌ | Header actions. See **Header Actions** below. |
522
+
523
+ **SignInMethod**
524
+
525
+ | Method | Type | Notes |
526
+ | --- | --- | --- |
527
+ | QR | `QrSignIn` | QR Code sign in |
528
+ | PIN | `PinSignIn` | PIN Code sign in (1–12 characters) |
529
+ | Input | `InputSignIn` | Text sign in, for example mail/username and password |
530
+
531
+ For InputSignIn the keyboard and input fields can be configured with following properties:
532
+
533
+ **KeyboardType enum:** `DEFAULT`, `EMAIL`, `PHONE`, `NUMBER`
534
+
535
+ **TextInputType enum:** `PASSWORD`, `DEFAULT`
536
+
537
+
538
+ ### Header Actions (Important)
539
+
540
+ On Android, header actions may be omitted, although this is not recommended. If `headerActions` is `undefined`, the system automatically renders the app icon in the header. Because Android Auto enforces monochrome icons, this can result in a poor-looking button.
541
+
542
+ **Use these rules to avoid crashes:**
543
+
544
+ 1. **For List/Grid/Information/Search/Message/SignIn templates on Android**, always pass the structured object format (alignment is implicit via `startHeaderAction`/`endHeaderActions`):
545
+
546
+ ```ts
547
+ const headerActions: HeaderActions<MyTemplate> = {
548
+ android: {
549
+ startHeaderAction: { type: 'back', onPress: (t) => HybridAutoPlay.popTemplate() },
550
+ endHeaderActions: [
551
+ { type: 'image', image: { name: 'help', type: 'glyph' }, onPress: () => {} },
552
+ ],
553
+ },
554
+ ios: {
555
+ backButton: { type: 'back', onPress: (t) => HybridAutoPlay.popTemplate() },
556
+ trailingNavigationBarButtons: [
557
+ { type: 'image', image: { name: 'close', type: 'glyph' }, onPress: () => {} },
558
+ ],
559
+ },
560
+ };
561
+ ```
562
+
563
+ ⚠️ **Do not pass a raw array of actions** to `headerActions` on Android for these templates. Arrays are only valid for **MapTemplate** header actions (see below). Passing an array for header-based templates results in actions without alignment and can crash on Android.
564
+
565
+ 2. **For MapTemplate on Android**, you can use the array format (1–4 actions) for the action strip:
566
+
567
+ ```ts
568
+ const mapHeaderActions: MapTemplateConfig['headerActions'] = {
569
+ android: [
570
+ { type: 'image', image: { name: 'list', type: 'glyph' }, onPress: () => {} },
571
+ { type: 'image', image: { name: 'search', type: 'glyph' }, onPress: () => {} },
572
+ ],
573
+ ios: {
574
+ leadingNavigationBarButtons: [
575
+ { type: 'image', image: { name: 'list', type: 'glyph' }, onPress: () => {} },
576
+ ],
577
+ },
578
+ };
579
+ ```
580
+
581
+ **Header action shapes (structured overview):**
582
+
583
+ | Platform | Property | Shape | Limits / Notes |
584
+ | --- | --- | --- | --- |
585
+ | Android (header templates) | `headerActions.android` | `{ startHeaderAction?, endHeaderActions? }` | `endHeaderActions`: 1–2 buttons. `startHeaderAction` can be `appIcon`/`back`/custom. |
586
+ | Android (MapTemplate) | `headerActions.android` | `ActionButton[]` | 1–4 action strip buttons. |
587
+ | iOS | `headerActions.ios` | `{ backButton?, leadingNavigationBarButtons?, trailingNavigationBarButtons? }` | Each list supports 1–2 buttons. `backButton` optional (system back is added if omitted). |
588
+
589
+ ### Actions & Button Types (Quick Reference)
590
+
591
+ - **Android header actions** use `startHeaderAction` + `endHeaderActions`:
592
+ - `startHeaderAction`: `AppButton | BackButton | ActionButton`
593
+ - `endHeaderActions`: 1–2 buttons
594
+ - **If `headerActions` is omitted**: Android renders the **app icon** automatically.
595
+ - **iOS header actions** use:
596
+ - `backButton` (optional, otherwise iOS provides a default back action)
597
+ - `leadingNavigationBarButtons` (1–2)
598
+ - `trailingNavigationBarButtons` (1–2)
599
+ - **MapTemplate map buttons**: 1–4 buttons, including the special `pan` button.
600
+
601
+ ### Event & Listener APIs
602
+
603
+ This section lists the available listeners and lifecycle callbacks so you can wire up connection state, visibility, cluster settings, and system events.
604
+
605
+ #### HybridAutoPlay listeners
606
+
607
+ | API | Payload | Notes |
608
+ | --- | --- | --- |
609
+ | `HybridAutoPlay.addListener(event, cb)` | event: `'didConnect'` `'didDisconnect'` | Connection changes for the head unit. |
610
+ | `HybridAutoPlay.addListenerRenderState(moduleName, cb)` | `cb(visibility: 'willAppear' \| 'didAppear' \| 'willDisappear' \| 'didDisappear')` | Use `AutoPlayModules.*` or a cluster UUID. |
611
+ | `HybridAutoPlay.addListenerVoiceInput(cb)` | `cb(location?, query?)` | Android-only voice input. |
612
+ | `HybridAutoPlay.addSafeAreaInsetsListener(moduleName, cb)` | `cb(insets)` | Safe area inset changes for any module. |
613
+
614
+ ```ts
615
+ import { AutoPlayModules, HybridAutoPlay } from '@iternio/react-native-auto-play';
616
+
617
+ const cleanup = HybridAutoPlay.addListener('didConnect', () => {
618
+ console.log('Head unit connected');
619
+ });
620
+
621
+ const removeVisibility = HybridAutoPlay.addListenerRenderState(
622
+ AutoPlayModules.AutoPlayRoot,
623
+ (state) => console.log('AutoPlayRoot state', state)
624
+ );
625
+ ```
626
+
627
+ #### Template lifecycle callbacks
628
+
629
+ All templates accept these lifecycle callbacks in their config:
630
+
631
+ - `onWillAppear(animated?)`
632
+ - `onDidAppear(animated?)`
633
+ - `onWillDisappear(animated?)`
634
+ - `onDidDisappear(animated?)`
635
+ - `onPopped()` (not supported on all iOS templates, see notes in code)
636
+
637
+ ```ts
638
+ const template = new ListTemplate({
639
+ title: { text: 'Menu' },
640
+ onWillAppear: () => console.log('will appear'),
641
+ onPopped: () => console.log('popped forever'),
642
+ });
643
+ ```
644
+
645
+ #### MapTemplate callbacks
646
+
647
+ Map-specific callbacks live on `MapTemplateConfig`:
648
+
649
+ - `onDidPan({ x, y })`
650
+ - `onDidUpdateZoomGestureWithCenter({ x, y }, scale)`
651
+ - `onClick({ x, y })` (Android)
652
+ - `onDoubleClick({ x, y })` (Android)
653
+ - `onAppearanceDidChange(colorScheme)`
654
+ - `onAutoDriveEnabled(template)` (Android)
655
+ - `onStopNavigation(template)` (**required**)
656
+
657
+ #### AutoPlayCluster listeners (instrument cluster)
658
+
659
+ | API | Payload | Notes |
660
+ | --- | --- | --- |
661
+ | `AutoPlayCluster.addListenerColorScheme(cb)` | `(clusterId, colorScheme)` | iOS + Android. |
662
+ | `AutoPlayCluster.addListenerZoom(cb)` | `(clusterId, zoomEvent)` | iOS only. |
663
+ | `AutoPlayCluster.addListenerCompass(cb)` | `(clusterId, enabled)` | iOS only. |
664
+ | `AutoPlayCluster.addListenerSpeedLimit(cb)` | `(clusterId, enabled)` | iOS only. |
665
+
666
+ ```ts
667
+ const removeCompass = AutoPlayCluster.addListenerCompass((clusterId, enabled) => {
668
+ console.log('Cluster', clusterId, 'compass', enabled);
669
+ });
670
+ ```
671
+
672
+ #### CarPlayDashboard listeners (iOS)
673
+
674
+ | API | Payload | Notes |
675
+ | --- | --- | --- |
676
+ | `CarPlayDashboard.addListener(event, cb)` | event: `'didConnect'` `'didDisconnect'` | Connection changes for the dashboard scene. |
677
+ | `CarPlayDashboard.addListenerRenderState(cb)` | `cb(visibility)` | Scene visibility changes. |
678
+ | `CarPlayDashboard.addListenerColorScheme(cb)` | `cb(colorScheme)` | Light/dark changes. |
679
+
350
680
  ### Localization
351
681
  The library allows you to pass distances and durations and formats them according to the system defaults.
352
682
  For iOS make sure to provide all supported app languages in Info.plist CFBundleLocalizations for this to work properly, missing languages will use CFBundleDevelopmentRegion as fallback which is **en** most of the time. This results in a mix up with the region which might result in **en**_AT instead of **de**_AT for example.
@@ -397,12 +727,33 @@ useEffect(() => {
397
727
 
398
728
  ### Templates
399
729
 
400
- - `MapTemplate`: For navigation apps.
401
- - `ListTemplate`: To display a list of items.
402
- - `GridTemplate`: To display a grid of items.
403
- - `SearchTemplate`: For search functionality.
404
- - `InformationTemplate`: For showing information with actions.
405
- - `MessageTemplate`: For displaying messages.
730
+ | Template | Purpose | Notes |
731
+ | --- | --- | --- |
732
+ | `MapTemplate` | Navigation, map rendering | Use as root; supports map buttons & navigation APIs. |
733
+ | `ListTemplate` | Lists/menus | Supports sections, radio/toggle rows. |
734
+ | `GridTemplate` | Action grid | Use `GridButton` items. |
735
+ | `SearchTemplate` | Search UI | Android-only search bar callbacks. |
736
+ | `InformationTemplate` | Info panels | Android uses PaneTemplate; iOS uses InformationTemplate. |
737
+ | `MessageTemplate` | Modal messages | Always shown on top until popped. |
738
+
739
+ **Template quick examples:**
740
+
741
+ ```ts
742
+ // MapTemplate
743
+ const map = new MapTemplate({
744
+ component: MapScreen,
745
+ onStopNavigation: () => {},
746
+ headerActions: { android: [{ type: 'image', image: { name: 'list', type: 'glyph' }, onPress: () => {} }] },
747
+ });
748
+ map.setRootTemplate();
749
+
750
+ // ListTemplate
751
+ new ListTemplate({
752
+ title: { text: 'Destinations' },
753
+ sections: [{ type: 'default', title: 'Recent', items: [{ type: 'default', title: { text: 'Home' }, onPress: () => {} }] }],
754
+ headerActions: { android: { startHeaderAction: { type: 'back', onPress: () => {} } } },
755
+ }).push();
756
+ ```
406
757
 
407
758
  ### Hooks
408
759
 
@@ -410,20 +761,39 @@ useEffect(() => {
410
761
  - `useVoiceInput()`: Access voice input functionality - Android Auto only.
411
762
  - `useSafeAreaInsets()`: Get safe area insets for any root component.
412
763
  - `useFocusedEffect()`: A useEffect alternative that executes when the specified component is visible to the user - use any of the `AutoPlayModules` enum or a cluster uuid to sepcify the component the effect should listen for.
413
- - `useAndroidAutoTelemetry()`: Access to car telemetry data on Android Auto.
764
+ - `useAndroidAutoTelemetry()`: Access to car telemetry data on Android Auto and Android Automotive.
414
765
  ```tsx
415
766
  import {
416
767
  useAndroidAutoTelemetry,
417
768
  AndroidAutoTelemetryPermissions,
769
+ AndroidAutomotiveTelemetryPermissions,
418
770
  } from '@iternio/react-native-auto-play';
771
+ import Config from 'react-native-config';
419
772
 
420
773
  const MyComponent = () => {
421
774
  const { telemetry, permissionsGranted, error } = useAndroidAutoTelemetry({
422
- requiredPermissions: [
423
- AndroidAutoTelemetryPermissions.Speed,
424
- AndroidAutoTelemetryPermissions.Energy,
425
- AndroidAutoTelemetryPermissions.Odometer,
426
- ],
775
+ requiredPermissions:
776
+ Config.isAutomotiveApp === 'true'
777
+ ? [
778
+ AndroidAutomotiveTelemetryPermissions.Info,
779
+ AndroidAutomotiveTelemetryPermissions.Speed,
780
+ AndroidAutomotiveTelemetryPermissions.Energy,
781
+ AndroidAutomotiveTelemetryPermissions.ExteriorEnvironment,
782
+ AndroidAutomotiveTelemetryPermissions.EnergyPorts,
783
+ ]
784
+ : [
785
+ AndroidAutoTelemetryPermissions.Speed,
786
+ AndroidAutoTelemetryPermissions.Energy,
787
+ AndroidAutoTelemetryPermissions.Odometer,
788
+ ],
789
+ automotivePermissionRequest:
790
+ Config.isAutomotiveApp === 'true'
791
+ ? {
792
+ cancelButtonText: 'Cancel',
793
+ grantButtonText: 'Grant',
794
+ message: 'Grant permission for vehicle telemetry access.',
795
+ }
796
+ : undefined,
427
797
  });
428
798
 
429
799
  if (!permissionsGranted) {
@@ -441,6 +811,14 @@ useEffect(() => {
441
811
  <Text>Battery Level: {telemetry?.batteryLevel?.value}%</Text>
442
812
  <Text>Range: {telemetry?.range?.value} km</Text>
443
813
  <Text>Odometer: {telemetry?.odometer?.value} km</Text>
814
+ <Text>Selected Gear: {telemetry?.selectedGear?.value}</Text>
815
+ <Text>Outside Temperature: {telemetry?.envOutsideTemperature?.value}°C</Text>
816
+ <Text>EV Charge Port Connected: {String(telemetry?.evChargePortConnected?.value)}</Text>
817
+ <Text>EV Battery Charge Rate: {telemetry?.evBatteryInstantaneousChargeRate?.value} kW</Text>
818
+ <Text>Parking Brake On: {String(telemetry?.parkingBrakeOn?.value)}</Text>
819
+ <Text>Vehicle Name: {telemetry?.vehicle?.name?.value}</Text>
820
+ <Text>Vehicle Manufacturer: {telemetry?.vehicle?.manufacturer?.value}</Text>
821
+ <Text>Vehicle Year: {telemetry?.vehicle?.year?.value}</Text>
444
822
  </View>
445
823
  );
446
824
  }
@@ -452,6 +830,15 @@ useEffect(() => {
452
830
  - `range`: Range in km.
453
831
  - `odometer`: Odometer in km.
454
832
  - `vehicle`: Vehicle information (model name, model year, manufacturer).
833
+ - `selectedGear`: The currently selected gear, one of the `VehicleGear` enum:
834
+ - Neutral = 1
835
+ - Reverse = 2
836
+ - Park = 4
837
+ - Drive = 8
838
+ - `envOutsideTemperature`: The outside temperature in °C.
839
+ - `evChargePortConnected`: Whether the EV charge port is connected.
840
+ - `evBatteryInstantaneousChargeRate`: The instantaneous charge rate of the EV battery in kW.
841
+ - `parkingBrakeOn`: Whether the parking brake is on.
455
842
 
456
843
 
457
844
  ### Scenes
@@ -459,11 +846,36 @@ useEffect(() => {
459
846
  - `CarPlayDashboard`: A component to render content on the CarPlay dashboard (CarPlay only).
460
847
  - `AutoPlayCluster`: A component to render content on the instrument cluster (CarPlay & Android Auto).
461
848
 
849
+ **Scene APIs (overview):**
850
+
851
+ **CarPlayDashboard (iOS)**
852
+ - `setComponent(component)` — register the React component (call once).
853
+ - `setButtons(buttons)` — **required** to make the dashboard visible.
854
+ - `addListener(event, cb)` — `didConnect` / `didDisconnect`.
855
+ - `addListenerRenderState(cb)` — scene visibility callbacks.
856
+ - `addListenerColorScheme(cb)` — light/dark changes.
857
+
858
+ ```ts
859
+ CarPlayDashboard.setButtons([
860
+ {
861
+ titleVariants: ['Open App'],
862
+ subtitleVariants: ['Dashboard shortcut'],
863
+ image: { name: 'directions_car', type: 'glyph' },
864
+ onPress: () => console.log('open app'),
865
+ },
866
+ ]);
867
+ ```
868
+
869
+ **AutoPlayCluster**
870
+ - `setComponent(component)` — register the cluster component.
871
+ - `setAttributedInactiveDescriptionVariants(variants)` — iOS only inactive text.
872
+ - `addListenerColorScheme(cb)` / `addListenerZoom(cb)` / `addListenerCompass(cb)` / `addListenerSpeedLimit(cb)`.
873
+
462
874
  ## Known Issues
463
875
 
464
876
  ### iOS
465
877
 
466
- - **Broken exceptions with `react-native-skia`**: When using `react-native-skia` up to version `2.4.7`, exceptions on iOS are not reported correctly. This is fixed in newer versions of `react-native-skia`. For more details, see this [pull request](https://github.com/Shopify/react-native-skia/pull/3595).
878
+ - **Broken exceptions with `react-native-skia`**: When using `react-native-skia` up to version `2.4.14`, exceptions on iOS are not reported correctly. This is fixed in newer versions of `react-native-skia`. For more details, see this [pull request](https://github.com/Shopify/react-native-skia/pull/3595) and [issue](https://github.com/Shopify/react-native-skia/issues/3635).
467
879
  - **AppState on iOS**: The `AppState` module from React Native does not work correctly on iOS because this library uses scenes, which are not supported by the stock `AppState` module. This library provides a custom state listener that works for both Android and iOS. Use `HybridAutoPlay.addListenerRenderState` instead of `AppState`.
468
880
  - **Timers stop on screen lock**: iOS stops all timers when the device's main screen is turned off. To ensure timers continue to run (which is often necessary for background tasks related to autoplay), a patch for `react-native` is required. A patch is included in the root `patches/` directory and can be applied using `patch-package`.
469
881
  - **expo-splash-screen stuck on iOS**: The `expo-splash-screen` module is broken on iOS because it does not support scenes, which are used by this library. This can cause the splash screen to be stuck on either the mobile device or on CarPlay. To fix this, a patch for `expo-splash-screen` is included in the root `patches/` directory and can be applied using `patch-package`. After applying the patch, you can hide the splash screen for a specific scene by passing the module name to the `hide` or `hideAsync` function. The module name can be one of the values from the `AutoPlayModules` enum or the UUID of a cluster screen.
@@ -477,6 +889,10 @@ useEffect(() => {
477
889
  // Hide the splash screen for the CarPlay screen
478
890
  hideAsync(AutoPlayModules.AutoPlayRoot);
479
891
  ```
892
+ ### Android
893
+ - **Broken exceptions with `react-native`** up to version 0.79
894
+ When using react-native before 0.80.0 exceptions are broken and are reported as `Unknown runtime_error` or similar.
895
+ See [this issue](https://github.com/mrousavy/nitro/issues/382) for details.
480
896
 
481
897
  ## Contributing
482
898
 
@@ -485,4 +901,3 @@ Contributions are welcome! Please submit a pull request.
485
901
  ## License
486
902
 
487
903
  This project is licensed under the MIT License - see the [LICENSE](../../LICENSE.md) file for details.
488
-
@@ -124,8 +124,20 @@ android {
124
124
  "${project.buildDir}/generated/source/codegen/java"
125
125
  ]
126
126
  }
127
+
128
+ if (getExtOrDefault("isAutomotiveApp") == "true") {
129
+ java.srcDirs += 'src/automotive/java'
130
+ manifest.srcFile 'src/automotive/AndroidManifest.xml'
131
+ } else {
132
+ java.srcDirs += 'src/auto/java'
133
+ manifest.srcFile 'src/main/AndroidManifest.xml'
134
+ }
127
135
  }
128
136
  }
137
+
138
+ if (getExtOrDefault("isAutomotiveApp") == "true") {
139
+ useLibrary 'android.car'
140
+ }
129
141
  }
130
142
 
131
143
  repositories {
@@ -133,7 +145,6 @@ repositories {
133
145
  google()
134
146
  }
135
147
 
136
-
137
148
  dependencies {
138
149
  // For < 0.71, this will be from the local maven repo
139
150
  // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
@@ -151,5 +162,8 @@ dependencies {
151
162
  println("☎️ Enjoy your nitro powered Android Auto app!")
152
163
  implementation "androidx.car.app:app-projected:1.7.0"
153
164
  }
165
+
166
+ implementation 'com.google.android.gms:play-services-base:18.3.0'
167
+ implementation 'com.google.android.gms:play-services-auth:21.0.0'
154
168
  }
155
169
 
@@ -1,5 +1,5 @@
1
1
  ReactNativeAutoPlay_kotlinVersion=2.1.20
2
- ReactNativeAutoPlay_minSdkVersion=23
2
+ ReactNativeAutoPlay_minSdkVersion=24
3
3
  ReactNativeAutoPlay_targetSdkVersion=36
4
4
  ReactNativeAutoPlay_compileSdkVersion=36
5
5
  ReactNativeAutoPlay_ndkVersion=27.1.12297006