@iternio/react-native-auto-play 0.1.18 → 0.2.0-alpha.2

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 (162) hide show
  1. package/README.md +152 -8
  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 +41 -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 +7 -5
  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 +44 -42
  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/types/Telemetry.d.ts +27 -0
  52. package/lib/types/Telemetry.js +7 -0
  53. package/nitro.json +3 -0
  54. package/nitrogen/generated/android/ReactNativeAutoPlay+autolinking.cmake +3 -0
  55. package/nitrogen/generated/android/ReactNativeAutoPlayOnLoad.cpp +12 -2
  56. package/nitrogen/generated/android/c++/JBooleanTelemetryItem.hpp +61 -0
  57. package/nitrogen/generated/android/c++/JFunc_void_std__optional_Telemetry_.hpp +87 -0
  58. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +10 -10
  59. package/nitrogen/generated/android/c++/JHybridAndroidAutoTelemetrySpec.cpp +41 -5
  60. package/nitrogen/generated/android/c++/JHybridAndroidAutoTelemetrySpec.hpp +2 -1
  61. package/nitrogen/generated/android/c++/JHybridSignInTemplateSpec.cpp +133 -0
  62. package/nitrogen/generated/android/c++/JHybridSignInTemplateSpec.hpp +66 -0
  63. package/nitrogen/generated/android/c++/JInputSignIn.hpp +103 -0
  64. package/nitrogen/generated/android/c++/JKeyboardType.hpp +65 -0
  65. package/nitrogen/generated/android/c++/JPermissionRequestResult.hpp +98 -0
  66. package/nitrogen/generated/android/c++/JPinSignIn.hpp +63 -0
  67. package/nitrogen/generated/android/c++/JQrSignIn.hpp +63 -0
  68. package/nitrogen/generated/android/c++/JSignInMethods.hpp +65 -0
  69. package/nitrogen/generated/android/c++/JSignInTemplateConfig.hpp +217 -0
  70. package/nitrogen/generated/android/c++/JTelemetry.hpp +25 -3
  71. package/nitrogen/generated/android/c++/JTextInputType.hpp +59 -0
  72. package/nitrogen/generated/android/c++/JVariant_QrSignIn_PinSignIn_InputSignIn.cpp +30 -0
  73. package/nitrogen/generated/android/c++/JVariant_QrSignIn_PinSignIn_InputSignIn.hpp +99 -0
  74. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/AssetImage.kt +2 -2
  75. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/AutoText.kt +3 -3
  76. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/BooleanTelemetryItem.kt +41 -0
  77. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Distance.kt +1 -1
  78. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/DurationWithTimeZone.kt +1 -1
  79. 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
  80. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Func_void_std__string.kt +9 -9
  81. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GlyphImage.kt +2 -2
  82. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GridTemplateConfig.kt +9 -9
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAndroidAutoTelemetrySpec.kt +7 -2
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridSignInTemplateSpec.kt +62 -0
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ImageLane.kt +1 -1
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/InformationTemplateConfig.kt +10 -10
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/InputSignIn.kt +63 -0
  88. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/KeyboardType.kt +23 -0
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/LaneGuidance.kt +1 -1
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/ListTemplateConfig.kt +10 -10
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Location.kt +1 -1
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/MapTemplateConfig.kt +18 -18
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/MessageTemplateConfig.kt +12 -12
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NavigationAlertAction.kt +2 -2
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroAction.kt +7 -7
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroAttributedString.kt +2 -2
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroAttributedStringImage.kt +1 -1
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroBaseMapTemplateConfig.kt +10 -10
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroColor.kt +1 -1
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroGridButton.kt +1 -1
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroLoadingManeuver.kt +1 -1
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroMapButton.kt +2 -2
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroMessageManeuver.kt +3 -3
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroNavigationAlert.kt +6 -6
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroRoutingManeuver.kt +13 -13
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroRow.kt +7 -7
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroSection.kt +2 -2
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NumericTelemetryItem.kt +1 -1
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/PermissionRequestResult.kt +41 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/PinSignIn.kt +41 -0
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Point.kt +1 -1
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/PreferredImageLane.kt +1 -1
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/QrSignIn.kt +41 -0
  114. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/RouteChoice.kt +1 -1
  115. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SafeAreaInsets.kt +2 -2
  116. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SearchTemplateConfig.kt +10 -10
  117. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SignInMethods.kt +23 -0
  118. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/SignInTemplateConfig.kt +78 -0
  119. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/StringTelemetryItem.kt +1 -1
  120. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Telemetry.kt +24 -9
  121. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TextInputType.kt +21 -0
  122. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TravelEstimates.kt +2 -2
  123. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TripConfig.kt +1 -1
  124. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TripPoint.kt +1 -1
  125. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TripPreviewTextConfiguration.kt +1 -1
  126. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TripSelectorCallback.kt +1 -1
  127. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/TripsConfig.kt +1 -1
  128. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Variant_QrSignIn_PinSignIn_InputSignIn.kt +72 -0
  129. package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/VehicleTelemetryItem.kt +4 -4
  130. package/nitrogen/generated/shared/c++/BooleanTelemetryItem.hpp +79 -0
  131. package/nitrogen/generated/shared/c++/HybridAndroidAutoTelemetrySpec.cpp +1 -0
  132. package/nitrogen/generated/shared/c++/HybridAndroidAutoTelemetrySpec.hpp +7 -1
  133. package/nitrogen/generated/shared/c++/HybridSignInTemplateSpec.cpp +22 -0
  134. package/nitrogen/generated/shared/c++/HybridSignInTemplateSpec.hpp +66 -0
  135. package/nitrogen/generated/shared/c++/InputSignIn.hpp +113 -0
  136. package/nitrogen/generated/shared/c++/KeyboardType.hpp +64 -0
  137. package/nitrogen/generated/shared/c++/PermissionRequestResult.hpp +80 -0
  138. package/nitrogen/generated/shared/c++/PinSignIn.hpp +81 -0
  139. package/nitrogen/generated/shared/c++/QrSignIn.hpp +81 -0
  140. package/nitrogen/generated/shared/c++/SignInMethods.hpp +64 -0
  141. package/nitrogen/generated/shared/c++/SignInTemplateConfig.hpp +138 -0
  142. package/nitrogen/generated/shared/c++/Telemetry.hpp +25 -2
  143. package/nitrogen/generated/shared/c++/TextInputType.hpp +62 -0
  144. package/package.json +3 -2
  145. package/src/hooks/useAndroidAutoTelemetry.ts +80 -27
  146. package/src/index.ts +2 -0
  147. package/src/specs/AndroidAutoTelemetry.nitro.ts +19 -1
  148. package/src/specs/SignInTemplate.nitro.ts +10 -0
  149. package/src/templates/SignInTemplate.ts +117 -0
  150. package/src/types/SignInMethod.ts +41 -0
  151. package/src/types/Telemetry.ts +29 -0
  152. package/lib/hooks/useIsAutoPlayFocused.d.ts +0 -7
  153. package/lib/hooks/useIsAutoPlayFocused.js +0 -20
  154. package/lib/hybrid.d.ts +0 -2
  155. package/lib/hybrid.js +0 -2
  156. package/lib/specs/AutomotivePermissionRequestTemplate.d.ts +0 -11
  157. package/lib/specs/AutomotivePermissionRequestTemplate.js +0 -1
  158. package/lib/specs/AutomotivePermissionRequestTemplate.nitro.d.ts +0 -11
  159. package/lib/specs/AutomotivePermissionRequestTemplate.nitro.js +0 -1
  160. package/lib/templates/AutomotivePermissionRequestTemplate.d.ts +0 -23
  161. package/lib/templates/AutomotivePermissionRequestTemplate.js +0 -18
  162. package/nitrogen/generated/android/c++/JFunc_void_std__optional_Telemetry__std__optional_std__string_.hpp +0 -85
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
 
@@ -431,13 +509,39 @@ Below is a concise overview of the most important props per template. Optional p
431
509
  | `headerActions` | `HeaderActionsAndroid<MessageTemplate>` | ❌ | Android-only header actions. |
432
510
  | `mapConfig` | `BaseMapTemplateConfig<MessageTemplate>` | ❌ | Android map-with-content layout. |
433
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
+
434
538
  ### Header Actions (Important)
435
539
 
436
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.
437
541
 
438
542
  **Use these rules to avoid crashes:**
439
543
 
440
- 1. **For List/Grid/Information/Search/Message templates on Android**, always pass the structured object format (alignment is implicit via `startHeaderAction`/`endHeaderActions`):
544
+ 1. **For List/Grid/Information/Search/Message/SignIn templates on Android**, always pass the structured object format (alignment is implicit via `startHeaderAction`/`endHeaderActions`):
441
545
 
442
546
  ```ts
443
547
  const headerActions: HeaderActions<MyTemplate> = {
@@ -657,20 +761,39 @@ new ListTemplate({
657
761
  - `useVoiceInput()`: Access voice input functionality - Android Auto only.
658
762
  - `useSafeAreaInsets()`: Get safe area insets for any root component.
659
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.
660
- - `useAndroidAutoTelemetry()`: Access to car telemetry data on Android Auto.
764
+ - `useAndroidAutoTelemetry()`: Access to car telemetry data on Android Auto and Android Automotive.
661
765
  ```tsx
662
766
  import {
663
767
  useAndroidAutoTelemetry,
664
768
  AndroidAutoTelemetryPermissions,
769
+ AndroidAutomotiveTelemetryPermissions,
665
770
  } from '@iternio/react-native-auto-play';
771
+ import Config from 'react-native-config';
666
772
 
667
773
  const MyComponent = () => {
668
774
  const { telemetry, permissionsGranted, error } = useAndroidAutoTelemetry({
669
- requiredPermissions: [
670
- AndroidAutoTelemetryPermissions.Speed,
671
- AndroidAutoTelemetryPermissions.Energy,
672
- AndroidAutoTelemetryPermissions.Odometer,
673
- ],
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,
674
797
  });
675
798
 
676
799
  if (!permissionsGranted) {
@@ -688,6 +811,14 @@ new ListTemplate({
688
811
  <Text>Battery Level: {telemetry?.batteryLevel?.value}%</Text>
689
812
  <Text>Range: {telemetry?.range?.value} km</Text>
690
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>
691
822
  </View>
692
823
  );
693
824
  }
@@ -699,6 +830,15 @@ new ListTemplate({
699
830
  - `range`: Range in km.
700
831
  - `odometer`: Odometer in km.
701
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.
702
842
 
703
843
 
704
844
  ### Scenes
@@ -735,7 +875,7 @@ CarPlayDashboard.setButtons([
735
875
 
736
876
  ### iOS
737
877
 
738
- - **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).
739
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`.
740
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`.
741
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.
@@ -749,6 +889,10 @@ CarPlayDashboard.setButtons([
749
889
  // Hide the splash screen for the CarPlay screen
750
890
  hideAsync(AutoPlayModules.AutoPlayRoot);
751
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.
752
896
 
753
897
  ## Contributing
754
898
 
@@ -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
@@ -1,9 +1,5 @@
1
1
  package com.margelo.nitro.swe.iternio.reactnativeautoplay
2
2
 
3
-
4
- import android.os.Handler
5
- import android.os.Looper
6
- import android.util.Log
7
3
  import androidx.car.app.CarContext
8
4
  import androidx.car.app.hardware.CarHardwareManager
9
5
  import androidx.car.app.hardware.common.CarValue
@@ -15,23 +11,27 @@ import androidx.car.app.hardware.info.Speed
15
11
  import androidx.car.app.versioning.CarAppApiLevels
16
12
  import androidx.core.content.ContextCompat
17
13
 
18
- object AndroidAutoTelemetryObserver {
19
- private var telemetryCallbacks: MutableList<(telemetry: Telemetry?, error: String?) -> Unit> =
20
- ArrayList();
21
-
22
- private var isRunning = false
14
+ object AndroidTelemetryObserver : TelemetryObserver() {
23
15
  private var carContext: CarContext? = null
24
16
 
25
- private val telemetryHolder = AndroidAutoTelemetryHolder()
26
- private val handler = Handler(Looper.getMainLooper())
17
+ private val mModelListener = OnCarDataAvailableListener<Model> { model ->
18
+ val name = if (model.name.status == CarValue.STATUS_SUCCESS) {
19
+ model.name.value
20
+ } else null
21
+
22
+ val manufacturer = if (model.manufacturer.status == CarValue.STATUS_SUCCESS) {
23
+ model.manufacturer.value
24
+ } else null
25
+
26
+ val year = if (model.year.status == CarValue.STATUS_SUCCESS) {
27
+ model.year.value
28
+ } else null
27
29
 
28
- private val mModelListener = OnCarDataAvailableListener<Model> {
29
- telemetryHolder.updateVehicle(it)
30
+ telemetryHolder.updateVehicle(name, manufacturer, year)
30
31
 
31
- val tlm = telemetryHolder.toTelemetry()
32
- tlm?.let {
32
+ telemetryHolder.toTelemetry()?.let {
33
33
  telemetryCallbacks.forEach { callback ->
34
- callback(tlm, null)
34
+ callback(it)
35
35
  }
36
36
  }
37
37
  }
@@ -70,51 +70,13 @@ object AndroidAutoTelemetryObserver {
70
70
  }
71
71
  }
72
72
 
73
- private val emitter = object : Runnable {
74
- override fun run() {
75
- val tlm = telemetryHolder.toTelemetry()
76
-
77
- if (tlm != null) {
78
- telemetryCallbacks.forEach { callback ->
79
- callback(tlm, null)
80
- }
81
- }
82
-
83
- handler.postDelayed(this, BuildConfig.TELEMETRY_UPDATE_INTERVAL)
84
- }
85
- }
86
-
87
- fun addListener(callback: (Telemetry?, String?) -> Unit): () -> Unit {
88
- telemetryCallbacks.add(callback)
89
-
90
-
91
- // start is called every time a new listener is registered, so the single shot values are still requested and returned immediately
92
- try {
93
- startTelemetryObserver()
94
- } catch (err: Exception) {
95
- callback(null, err.message)
96
- }
97
-
98
-
99
- return {
100
- telemetryCallbacks.remove(callback)
101
- if (telemetryCallbacks.isEmpty()) {
102
- stopTelemetryObserver()
103
- }
104
- }
105
- }
106
-
107
-
108
- fun startTelemetryObserver(
109
- ) {
110
- val carContext =
111
- AndroidAutoSession.Companion.getCarContext(AndroidAutoSession.Companion.ROOT_SESSION)
112
- ?: throw IllegalArgumentException(
113
- "Car context not available, failed to start telemetry"
114
- )
73
+ override fun startTelemetryObserver(): Boolean {
74
+ val carContext = AndroidAutoSession.getRootContext() ?: throw IllegalArgumentException(
75
+ "Car context not available, failed to start telemetry"
76
+ )
115
77
 
116
78
 
117
- AndroidAutoTelemetryObserver.carContext = carContext
79
+ AndroidTelemetryObserver.carContext = carContext
118
80
  if (carContext.carAppApiLevel < CarAppApiLevels.LEVEL_3) {
119
81
  throw UnsupportedOperationException("Telemetry not supported for this API level ${carContext.carAppApiLevel}")
120
82
  }
@@ -133,13 +95,10 @@ object AndroidAutoTelemetryObserver {
133
95
  } catch (_: NullPointerException) {
134
96
  }
135
97
 
136
- if (isRunning) {
137
- // we stop here to not re-register multiple listeners, only the single shot values can be requested multiple times by registering another tlm listener on RN side
138
- Log.d(
139
- AndroidAutoTelemetryObserver.javaClass.name,
140
- "Telemetry observer is already running"
141
- )
142
- return
98
+ if (isObserverRunning) {
99
+ // we stop here to not re-register multiple listeners
100
+ // only the single shot values can be requested multiple times by registering another tlm listener on RN side
101
+ return false
143
102
  }
144
103
 
145
104
  try {
@@ -160,19 +119,17 @@ object AndroidAutoTelemetryObserver {
160
119
  } catch (_: NullPointerException) {
161
120
  }
162
121
 
163
- handler.post(emitter)
164
-
165
- isRunning = true
166
122
 
167
- Log.d(AndroidAutoTelemetryObserver.javaClass.name, "Telemetry observer started")
123
+ isObserverRunning = true
124
+ return true
168
125
  }
169
126
 
170
- fun stopTelemetryObserver() {
171
- if (!isRunning) {
127
+ override fun stopTelemetryObserver() {
128
+ if (!isObserverRunning) {
172
129
  return
173
130
  }
174
131
 
175
- isRunning = false
132
+ isObserverRunning = false
176
133
 
177
134
  carContext?.let {
178
135
  val carHardwareManager = it.getCarService(
@@ -195,7 +152,5 @@ object AndroidAutoTelemetryObserver {
195
152
  } catch (_: SecurityException) {
196
153
  }
197
154
  }
198
-
199
- handler.removeCallbacks(emitter)
200
155
  }
201
- }
156
+ }
@@ -0,0 +1,91 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+
3
+ <uses-feature
4
+ android:name="android.hardware.type.automotive"
5
+ android:required="true" />
6
+
7
+ <uses-feature
8
+ android:name="android.software.car.templates_host"
9
+ android:required="true" />
10
+
11
+ <uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES" />
12
+ <uses-permission android:name="androidx.car.app.MAP_TEMPLATES" />
13
+ <uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
14
+
15
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
16
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
17
+
18
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
19
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
20
+
21
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
22
+
23
+
24
+ <!-- Android Automotive specific permissions -->
25
+ <uses-permission android:name="android.car.permission.CAR_ENERGY" />
26
+ <uses-permission android:name="android.car.permission.CAR_ENERGY_PORTS" />
27
+ <uses-permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT" />
28
+ <uses-permission android:name="android.car.permission.CAR_IDENTIFICATION" />
29
+ <uses-permission android:name="android.car.permission.CAR_INFO" />
30
+ <uses-permission android:name="android.car.permission.CAR_POWERTRAIN" />
31
+ <uses-permission android:name="android.car.permission.CAR_SPEED" />
32
+
33
+ <application>
34
+ <activity
35
+ android:name="androidx.car.app.activity.CarAppActivity"
36
+ android:exported="true"
37
+ android:launchMode="singleTask"
38
+ android:theme="@android:style/Theme.DeviceDefault.NoActionBar">
39
+
40
+ <intent-filter>
41
+ <action android:name="android.intent.action.MAIN" />
42
+
43
+ <category android:name="android.intent.category.LAUNCHER" />
44
+ <category android:name="android.intent.category.APP_MAPS" />
45
+ </intent-filter>
46
+
47
+ <intent-filter>
48
+ <action android:name="androidx.car.app.action.NAVIGATE" />
49
+ <category android:name="android.intent.category.DEFAULT" />
50
+ <data android:scheme="geo" />
51
+ </intent-filter>
52
+
53
+ <meta-data
54
+ android:name="distractionOptimized"
55
+ android:value="true" />
56
+
57
+ </activity>
58
+
59
+ <service
60
+ android:name="com.margelo.nitro.swe.iternio.reactnativeautoplay.AndroidAutoService"
61
+ android:exported="true"
62
+ android:foregroundServiceType="location">
63
+ <intent-filter>
64
+ <action android:name="androidx.car.app.CarAppService" />
65
+
66
+ <category android:name="androidx.car.app.category.NAVIGATION" />
67
+ <category android:name="androidx.car.app.category.FEATURE_CLUSTER" />
68
+ </intent-filter>
69
+ <intent-filter>
70
+ <action android:name="androidx.car.app.action.NAVIGATE" />
71
+ <category android:name="android.intent.category.DEFAULT" />
72
+ <data android:scheme="geo" />
73
+ </intent-filter>
74
+ </service>
75
+
76
+ <service android:name="com.margelo.nitro.swe.iternio.reactnativeautoplay.HeadlessTaskService" />
77
+
78
+ <provider
79
+ android:name="com.margelo.nitro.swe.iternio.reactnativeautoplay.ActivityRenderStateProvider"
80
+ android:authorities="${applicationId}.ActivityRenderStateProvider"
81
+ android:exported="false" />
82
+
83
+ <meta-data
84
+ android:name="com.android.automotive"
85
+ android:resource="@xml/automotive_app_desc" />
86
+ <meta-data
87
+ android:name="androidx.car.app.minCarApiLevel"
88
+ android:value="1" />
89
+ </application>
90
+
91
+ </manifest>