@santoshpk/react-native-carplay 1.0.3

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 (269) hide show
  1. package/README.md +119 -0
  2. package/android/.idea/compiler.xml +6 -0
  3. package/android/.idea/gradle.xml +17 -0
  4. package/android/.idea/jarRepositories.xml +25 -0
  5. package/android/.idea/misc.xml +10 -0
  6. package/android/.idea/vcs.xml +6 -0
  7. package/android/build.gradle +63 -0
  8. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  9. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  10. package/android/gradle.properties +20 -0
  11. package/android/gradlew +234 -0
  12. package/android/gradlew.bat +89 -0
  13. package/android/local.properties +8 -0
  14. package/android/src/main/AndroidManifest.xml +31 -0
  15. package/android/src/main/AndroidManifestNew.xml +31 -0
  16. package/android/src/main/java/org/birkir/carplay/CarPlayModule.kt +348 -0
  17. package/android/src/main/java/org/birkir/carplay/CarPlayPackage.kt +18 -0
  18. package/android/src/main/java/org/birkir/carplay/CarPlayService.kt +34 -0
  19. package/android/src/main/java/org/birkir/carplay/CarPlaySession.kt +114 -0
  20. package/android/src/main/java/org/birkir/carplay/parser/Ext.kt +11 -0
  21. package/android/src/main/java/org/birkir/carplay/parser/Parser.kt +18 -0
  22. package/android/src/main/java/org/birkir/carplay/parser/RCTGridTemplate.kt +28 -0
  23. package/android/src/main/java/org/birkir/carplay/parser/RCTListTemplate.kt +64 -0
  24. package/android/src/main/java/org/birkir/carplay/parser/RCTMapTemplate.kt +185 -0
  25. package/android/src/main/java/org/birkir/carplay/parser/RCTMessageTemplate.kt +36 -0
  26. package/android/src/main/java/org/birkir/carplay/parser/RCTPaneTemplate.kt +24 -0
  27. package/android/src/main/java/org/birkir/carplay/parser/RCTSearchTemplate.kt +41 -0
  28. package/android/src/main/java/org/birkir/carplay/parser/RCTTabTemplate.kt +52 -0
  29. package/android/src/main/java/org/birkir/carplay/parser/RCTTemplate.kt +434 -0
  30. package/android/src/main/java/org/birkir/carplay/parser/TemplateParser.kt +35 -0
  31. package/android/src/main/java/org/birkir/carplay/screens/CarScreen.kt +69 -0
  32. package/android/src/main/java/org/birkir/carplay/screens/CarScreenContext.kt +10 -0
  33. package/android/src/main/java/org/birkir/carplay/utils/EventEmitter.kt +174 -0
  34. package/android/src/main/java/org/birkir/carplay/utils/VirtualRenderer.kt +75 -0
  35. package/ios/RCTConvert+RNCarPlay.h +18 -0
  36. package/ios/RCTConvert+RNCarPlay.m +96 -0
  37. package/ios/RNCPStore.h +24 -0
  38. package/ios/RNCPStore.m +68 -0
  39. package/ios/RNCarPlay.h +29 -0
  40. package/ios/RNCarPlay.m +1839 -0
  41. package/ios/RNCarPlay.xcodeproj/project.pbxproj +300 -0
  42. package/lib/CarPlay.d.ts +196 -0
  43. package/lib/CarPlay.d.ts.map +1 -0
  44. package/lib/CarPlay.js +176 -0
  45. package/lib/CarPlay.js.map +1 -0
  46. package/lib/index.d.ts +44 -0
  47. package/lib/index.d.ts.map +1 -0
  48. package/lib/index.js +64 -0
  49. package/lib/index.js.map +1 -0
  50. package/lib/interfaces/Action.d.ts +13 -0
  51. package/lib/interfaces/Action.d.ts.map +1 -0
  52. package/lib/interfaces/Action.js +3 -0
  53. package/lib/interfaces/Action.js.map +1 -0
  54. package/lib/interfaces/AlertAction.d.ts +6 -0
  55. package/lib/interfaces/AlertAction.d.ts.map +1 -0
  56. package/lib/interfaces/AlertAction.js +3 -0
  57. package/lib/interfaces/AlertAction.js.map +1 -0
  58. package/lib/interfaces/BarButton.d.ts +39 -0
  59. package/lib/interfaces/BarButton.d.ts.map +1 -0
  60. package/lib/interfaces/BarButton.js +3 -0
  61. package/lib/interfaces/BarButton.js.map +1 -0
  62. package/lib/interfaces/CarColor.d.ts +2 -0
  63. package/lib/interfaces/CarColor.d.ts.map +1 -0
  64. package/lib/interfaces/CarColor.js +3 -0
  65. package/lib/interfaces/CarColor.js.map +1 -0
  66. package/lib/interfaces/GridButton.d.ts +24 -0
  67. package/lib/interfaces/GridButton.d.ts.map +1 -0
  68. package/lib/interfaces/GridButton.js +3 -0
  69. package/lib/interfaces/GridButton.js.map +1 -0
  70. package/lib/interfaces/Header.d.ts +15 -0
  71. package/lib/interfaces/Header.d.ts.map +1 -0
  72. package/lib/interfaces/Header.js +3 -0
  73. package/lib/interfaces/Header.js.map +1 -0
  74. package/lib/interfaces/ListItem.d.ts +61 -0
  75. package/lib/interfaces/ListItem.d.ts.map +1 -0
  76. package/lib/interfaces/ListItem.js +3 -0
  77. package/lib/interfaces/ListItem.js.map +1 -0
  78. package/lib/interfaces/ListItemUpdate.d.ts +15 -0
  79. package/lib/interfaces/ListItemUpdate.d.ts.map +1 -0
  80. package/lib/interfaces/ListItemUpdate.js +3 -0
  81. package/lib/interfaces/ListItemUpdate.js.map +1 -0
  82. package/lib/interfaces/ListSection.d.ts +21 -0
  83. package/lib/interfaces/ListSection.d.ts.map +1 -0
  84. package/lib/interfaces/ListSection.js +3 -0
  85. package/lib/interfaces/ListSection.js.map +1 -0
  86. package/lib/interfaces/Maneuver.d.ts +31 -0
  87. package/lib/interfaces/Maneuver.d.ts.map +1 -0
  88. package/lib/interfaces/Maneuver.js +3 -0
  89. package/lib/interfaces/Maneuver.js.map +1 -0
  90. package/lib/interfaces/MapButton.d.ts +27 -0
  91. package/lib/interfaces/MapButton.d.ts.map +1 -0
  92. package/lib/interfaces/MapButton.js +3 -0
  93. package/lib/interfaces/MapButton.js.map +1 -0
  94. package/lib/interfaces/NavigationAlert.d.ts +44 -0
  95. package/lib/interfaces/NavigationAlert.d.ts.map +1 -0
  96. package/lib/interfaces/NavigationAlert.js +10 -0
  97. package/lib/interfaces/NavigationAlert.js.map +1 -0
  98. package/lib/interfaces/NavigationInfo.d.ts +17 -0
  99. package/lib/interfaces/NavigationInfo.d.ts.map +1 -0
  100. package/lib/interfaces/NavigationInfo.js +3 -0
  101. package/lib/interfaces/NavigationInfo.js.map +1 -0
  102. package/lib/interfaces/NavigationStep.d.ts +17 -0
  103. package/lib/interfaces/NavigationStep.d.ts.map +1 -0
  104. package/lib/interfaces/NavigationStep.js +3 -0
  105. package/lib/interfaces/NavigationStep.js.map +1 -0
  106. package/lib/interfaces/Pane.d.ts +29 -0
  107. package/lib/interfaces/Pane.d.ts.map +1 -0
  108. package/lib/interfaces/Pane.js +3 -0
  109. package/lib/interfaces/Pane.js.map +1 -0
  110. package/lib/interfaces/PauseReason.d.ts +8 -0
  111. package/lib/interfaces/PauseReason.d.ts.map +1 -0
  112. package/lib/interfaces/PauseReason.js +12 -0
  113. package/lib/interfaces/PauseReason.js.map +1 -0
  114. package/lib/interfaces/Place.d.ts +11 -0
  115. package/lib/interfaces/Place.d.ts.map +1 -0
  116. package/lib/interfaces/Place.js +3 -0
  117. package/lib/interfaces/Place.js.map +1 -0
  118. package/lib/interfaces/TextConfiguration.d.ts +6 -0
  119. package/lib/interfaces/TextConfiguration.d.ts.map +1 -0
  120. package/lib/interfaces/TextConfiguration.js +3 -0
  121. package/lib/interfaces/TextConfiguration.js.map +1 -0
  122. package/lib/interfaces/TimeRemainingColor.d.ts +2 -0
  123. package/lib/interfaces/TimeRemainingColor.d.ts.map +1 -0
  124. package/lib/interfaces/TimeRemainingColor.js +3 -0
  125. package/lib/interfaces/TimeRemainingColor.js.map +1 -0
  126. package/lib/interfaces/TravelEstimates.d.ts +37 -0
  127. package/lib/interfaces/TravelEstimates.d.ts.map +1 -0
  128. package/lib/interfaces/TravelEstimates.js +3 -0
  129. package/lib/interfaces/TravelEstimates.js.map +1 -0
  130. package/lib/interfaces/VoiceControlState.d.ts +8 -0
  131. package/lib/interfaces/VoiceControlState.d.ts.map +1 -0
  132. package/lib/interfaces/VoiceControlState.js +3 -0
  133. package/lib/interfaces/VoiceControlState.js.map +1 -0
  134. package/lib/navigation/NavigationSession.d.ts +18 -0
  135. package/lib/navigation/NavigationSession.d.ts.map +1 -0
  136. package/lib/navigation/NavigationSession.js +51 -0
  137. package/lib/navigation/NavigationSession.js.map +1 -0
  138. package/lib/navigation/Trip.d.ts +22 -0
  139. package/lib/navigation/Trip.d.ts.map +1 -0
  140. package/lib/navigation/Trip.js +18 -0
  141. package/lib/navigation/Trip.js.map +1 -0
  142. package/lib/templates/ActionSheetTemplate.d.ts +18 -0
  143. package/lib/templates/ActionSheetTemplate.d.ts.map +1 -0
  144. package/lib/templates/ActionSheetTemplate.js +16 -0
  145. package/lib/templates/ActionSheetTemplate.js.map +1 -0
  146. package/lib/templates/AlertTemplate.d.ts +17 -0
  147. package/lib/templates/AlertTemplate.d.ts.map +1 -0
  148. package/lib/templates/AlertTemplate.js +16 -0
  149. package/lib/templates/AlertTemplate.js.map +1 -0
  150. package/lib/templates/ContactTemplate.d.ts +36 -0
  151. package/lib/templates/ContactTemplate.d.ts.map +1 -0
  152. package/lib/templates/ContactTemplate.js +16 -0
  153. package/lib/templates/ContactTemplate.js.map +1 -0
  154. package/lib/templates/GridTemplate.d.ts +38 -0
  155. package/lib/templates/GridTemplate.d.ts.map +1 -0
  156. package/lib/templates/GridTemplate.js +17 -0
  157. package/lib/templates/GridTemplate.js.map +1 -0
  158. package/lib/templates/InformationTemplate.d.ts +28 -0
  159. package/lib/templates/InformationTemplate.d.ts.map +1 -0
  160. package/lib/templates/InformationTemplate.js +28 -0
  161. package/lib/templates/InformationTemplate.js.map +1 -0
  162. package/lib/templates/ListTemplate.d.ts +112 -0
  163. package/lib/templates/ListTemplate.d.ts.map +1 -0
  164. package/lib/templates/ListTemplate.js +57 -0
  165. package/lib/templates/ListTemplate.js.map +1 -0
  166. package/lib/templates/MapTemplate.d.ts +171 -0
  167. package/lib/templates/MapTemplate.d.ts.map +1 -0
  168. package/lib/templates/MapTemplate.js +115 -0
  169. package/lib/templates/MapTemplate.js.map +1 -0
  170. package/lib/templates/NowPlayingTemplate.d.ts +31 -0
  171. package/lib/templates/NowPlayingTemplate.d.ts.map +1 -0
  172. package/lib/templates/NowPlayingTemplate.js +18 -0
  173. package/lib/templates/NowPlayingTemplate.js.map +1 -0
  174. package/lib/templates/PointOfInterestTemplate.d.ts +38 -0
  175. package/lib/templates/PointOfInterestTemplate.d.ts.map +1 -0
  176. package/lib/templates/PointOfInterestTemplate.js +18 -0
  177. package/lib/templates/PointOfInterestTemplate.js.map +1 -0
  178. package/lib/templates/SearchTemplate.d.ts +32 -0
  179. package/lib/templates/SearchTemplate.d.ts.map +1 -0
  180. package/lib/templates/SearchTemplate.js +41 -0
  181. package/lib/templates/SearchTemplate.js.map +1 -0
  182. package/lib/templates/TabBarTemplate.d.ts +27 -0
  183. package/lib/templates/TabBarTemplate.d.ts.map +1 -0
  184. package/lib/templates/TabBarTemplate.js +26 -0
  185. package/lib/templates/TabBarTemplate.js.map +1 -0
  186. package/lib/templates/Template.d.ts +83 -0
  187. package/lib/templates/Template.d.ts.map +1 -0
  188. package/lib/templates/Template.js +71 -0
  189. package/lib/templates/Template.js.map +1 -0
  190. package/lib/templates/VoiceControlTemplate.d.ts +18 -0
  191. package/lib/templates/VoiceControlTemplate.d.ts.map +1 -0
  192. package/lib/templates/VoiceControlTemplate.js +20 -0
  193. package/lib/templates/VoiceControlTemplate.js.map +1 -0
  194. package/lib/templates/android/AndroidNavigationBaseTemplate.d.ts +19 -0
  195. package/lib/templates/android/AndroidNavigationBaseTemplate.d.ts.map +1 -0
  196. package/lib/templates/android/AndroidNavigationBaseTemplate.js +29 -0
  197. package/lib/templates/android/AndroidNavigationBaseTemplate.js.map +1 -0
  198. package/lib/templates/android/MessageTemplate.d.ts +16 -0
  199. package/lib/templates/android/MessageTemplate.d.ts.map +1 -0
  200. package/lib/templates/android/MessageTemplate.js +11 -0
  201. package/lib/templates/android/MessageTemplate.js.map +1 -0
  202. package/lib/templates/android/NavigationTemplate.d.ts +44 -0
  203. package/lib/templates/android/NavigationTemplate.d.ts.map +1 -0
  204. package/lib/templates/android/NavigationTemplate.js +17 -0
  205. package/lib/templates/android/NavigationTemplate.js.map +1 -0
  206. package/lib/templates/android/PaneTemplate.d.ts +20 -0
  207. package/lib/templates/android/PaneTemplate.d.ts.map +1 -0
  208. package/lib/templates/android/PaneTemplate.js +17 -0
  209. package/lib/templates/android/PaneTemplate.js.map +1 -0
  210. package/lib/templates/android/PlaceListMapTemplate.d.ts +78 -0
  211. package/lib/templates/android/PlaceListMapTemplate.d.ts.map +1 -0
  212. package/lib/templates/android/PlaceListMapTemplate.js +25 -0
  213. package/lib/templates/android/PlaceListMapTemplate.js.map +1 -0
  214. package/lib/templates/android/PlaceListNavigationTemplate.d.ts +51 -0
  215. package/lib/templates/android/PlaceListNavigationTemplate.d.ts.map +1 -0
  216. package/lib/templates/android/PlaceListNavigationTemplate.js +20 -0
  217. package/lib/templates/android/PlaceListNavigationTemplate.js.map +1 -0
  218. package/lib/templates/android/RoutePreviewNavigationTemplate.d.ts +60 -0
  219. package/lib/templates/android/RoutePreviewNavigationTemplate.d.ts.map +1 -0
  220. package/lib/templates/android/RoutePreviewNavigationTemplate.js +23 -0
  221. package/lib/templates/android/RoutePreviewNavigationTemplate.js.map +1 -0
  222. package/lib/tsconfig.tsbuildinfo +1 -0
  223. package/package.json +49 -0
  224. package/react-native-carplay.podspec +21 -0
  225. package/src/CarPlay.ts +320 -0
  226. package/src/index.ts +50 -0
  227. package/src/interfaces/Action.ts +15 -0
  228. package/src/interfaces/AlertAction.ts +5 -0
  229. package/src/interfaces/BarButton.ts +41 -0
  230. package/src/interfaces/CarColor.ts +1 -0
  231. package/src/interfaces/GridButton.ts +25 -0
  232. package/src/interfaces/Header.ts +16 -0
  233. package/src/interfaces/ListItem.ts +61 -0
  234. package/src/interfaces/ListItemUpdate.ts +14 -0
  235. package/src/interfaces/ListSection.ts +21 -0
  236. package/src/interfaces/Maneuver.ts +30 -0
  237. package/src/interfaces/MapButton.ts +27 -0
  238. package/src/interfaces/NavigationAlert.ts +46 -0
  239. package/src/interfaces/NavigationInfo.ts +19 -0
  240. package/src/interfaces/NavigationStep.ts +17 -0
  241. package/src/interfaces/Pane.ts +29 -0
  242. package/src/interfaces/PauseReason.ts +7 -0
  243. package/src/interfaces/Place.ts +12 -0
  244. package/src/interfaces/TextConfiguration.ts +5 -0
  245. package/src/interfaces/TimeRemainingColor.ts +1 -0
  246. package/src/interfaces/TravelEstimates.ts +39 -0
  247. package/src/interfaces/VoiceControlState.ts +8 -0
  248. package/src/navigation/NavigationSession.ts +57 -0
  249. package/src/navigation/Trip.ts +36 -0
  250. package/src/templates/ActionSheetTemplate.ts +21 -0
  251. package/src/templates/AlertTemplate.ts +20 -0
  252. package/src/templates/ContactTemplate.ts +45 -0
  253. package/src/templates/GridTemplate.ts +45 -0
  254. package/src/templates/InformationTemplate.ts +42 -0
  255. package/src/templates/ListTemplate.ts +150 -0
  256. package/src/templates/MapTemplate.ts +231 -0
  257. package/src/templates/NowPlayingTemplate.ts +38 -0
  258. package/src/templates/PointOfInterestTemplate.ts +42 -0
  259. package/src/templates/SearchTemplate.ts +70 -0
  260. package/src/templates/TabBarTemplate.ts +56 -0
  261. package/src/templates/Template.ts +165 -0
  262. package/src/templates/VoiceControlTemplate.ts +25 -0
  263. package/src/templates/android/AndroidNavigationBaseTemplate.ts +46 -0
  264. package/src/templates/android/MessageTemplate.ts +19 -0
  265. package/src/templates/android/NavigationTemplate.ts +50 -0
  266. package/src/templates/android/PaneTemplate.ts +26 -0
  267. package/src/templates/android/PlaceListMapTemplate.ts +94 -0
  268. package/src/templates/android/PlaceListNavigationTemplate.ts +57 -0
  269. package/src/templates/android/RoutePreviewNavigationTemplate.ts +66 -0
@@ -0,0 +1,348 @@
1
+ package org.birkir.carplay
2
+
3
+ import android.content.Intent
4
+ import android.net.Uri
5
+ import android.os.Handler
6
+ import android.os.Looper
7
+ import android.util.Log
8
+ import androidx.activity.OnBackPressedCallback
9
+ import androidx.car.app.AppManager
10
+ import androidx.car.app.CarContext
11
+ import androidx.car.app.CarToast
12
+ import androidx.car.app.ScreenManager
13
+ import androidx.car.app.SessionInfo
14
+ import androidx.car.app.model.Alert
15
+ import androidx.car.app.model.AlertCallback
16
+ import androidx.car.app.model.CarText
17
+ import androidx.car.app.model.Distance
18
+ import androidx.car.app.model.Template
19
+ import com.facebook.react.bridge.Arguments
20
+ import com.facebook.react.bridge.Callback
21
+ import com.facebook.react.bridge.LifecycleEventListener
22
+ import com.facebook.react.bridge.Promise
23
+ import com.facebook.react.bridge.ReactApplicationContext
24
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
25
+ import com.facebook.react.bridge.ReactMethod
26
+ import com.facebook.react.bridge.ReadableMap
27
+ import com.facebook.react.bridge.WritableNativeMap
28
+ import com.facebook.react.module.annotations.ReactModule
29
+ import com.facebook.react.modules.debug.DevSettingsModule
30
+ import org.birkir.carplay.parser.Parser
31
+ import org.birkir.carplay.parser.TemplateParser
32
+ import org.birkir.carplay.screens.CarScreen
33
+ import org.birkir.carplay.screens.CarScreenContext
34
+ import org.birkir.carplay.utils.EventEmitter
35
+ import java.util.WeakHashMap
36
+
37
+
38
+ @ReactModule(name = CarPlayModule.NAME)
39
+ class CarPlayModule internal constructor(private val reactContext: ReactApplicationContext) :
40
+ ReactContextBaseJavaModule(reactContext) {
41
+
42
+ private lateinit var carContext: CarContext
43
+ private lateinit var parser: Parser;
44
+
45
+ private var currentCarScreen: CarScreen? = null
46
+ private var screenManager: ScreenManager? = null
47
+ private val carScreens: WeakHashMap<String, CarScreen> = WeakHashMap()
48
+ private val carTemplates: WeakHashMap<String, ReadableMap> = WeakHashMap()
49
+ private val carScreenContexts: WeakHashMap<CarScreen, CarScreenContext> =
50
+ WeakHashMap()
51
+ private val handler: Handler = Handler(Looper.getMainLooper())
52
+
53
+
54
+ // Global event emitter (no templateId's)
55
+ private var eventEmitter: EventEmitter? = null
56
+
57
+ init {
58
+ reactContext.addLifecycleEventListener(object : LifecycleEventListener {
59
+ override fun onHostResume() {
60
+ eventEmitter = EventEmitter(reactContext)
61
+ reactContext.getNativeModule(DevSettingsModule::class.java)
62
+ ?.addMenuItem("Reload Android Auto")
63
+ }
64
+
65
+ override fun onHostPause() {}
66
+ override fun onHostDestroy() {}
67
+ })
68
+ }
69
+
70
+ override fun getName(): String {
71
+ return NAME
72
+ }
73
+
74
+ fun setCarContext(carContext: CarContext, currentCarScreen: CarScreen) {
75
+ try {
76
+ parser = Parser(carContext, CarScreenContext("", eventEmitter!!, carScreens));
77
+ }
78
+ catch (e: Exception){
79
+ e.printStackTrace()
80
+ eventEmitter?.didConnect()
81
+ }
82
+ this.carContext = carContext
83
+ this.currentCarScreen = currentCarScreen
84
+ screenManager = currentCarScreen.screenManager
85
+ carScreens["root"] = this.currentCarScreen
86
+ carContext.onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
87
+ override fun handleOnBackPressed() {
88
+ eventEmitter?.backButtonPressed(screenManager?.top?.marker)
89
+ }
90
+ })
91
+ eventEmitter?.didConnect()
92
+ }
93
+
94
+ private fun parseTemplate(
95
+ config: ReadableMap,
96
+ carScreenContext: CarScreenContext
97
+ ): Template {
98
+ val factory = TemplateParser(carContext, carScreenContext)
99
+ return factory.parse(config)
100
+ }
101
+
102
+ @ReactMethod
103
+ fun checkForConnection() {
104
+ eventEmitter?.didConnect()
105
+ }
106
+
107
+ @ReactMethod
108
+ fun createTemplate(templateId: String, config: ReadableMap, callback: Callback?) {
109
+ handler.post {
110
+ Log.d(TAG, "Creating template $templateId")
111
+
112
+ // Store the template
113
+ carTemplates[templateId] = config;
114
+
115
+ try {
116
+ createScreen(templateId);
117
+ callback?.invoke()
118
+ } catch (err: IllegalArgumentException) {
119
+ val args = Arguments.createMap()
120
+ args.putString("error", "Failed to parse template '$templateId': ${err.message}")
121
+ callback?.invoke(args)
122
+ }
123
+ }
124
+ }
125
+
126
+ @ReactMethod
127
+ fun updateTemplate(templateId: String, config: ReadableMap) {
128
+ handler.post {
129
+ carTemplates[templateId] = config;
130
+ val screen = carScreens[templateId]
131
+ if (screen != null) {
132
+ val carScreenContext = carScreenContexts[screen];
133
+ if (carScreenContext != null) {
134
+ val template = parseTemplate(config, carScreenContext);
135
+ screen.setTemplate(template, templateId, config);
136
+ screen.invalidate()
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ @ReactMethod
143
+ fun setRootTemplate(templateId: String, animated: Boolean?) {
144
+ Log.d(TAG, "set Root Template for $templateId")
145
+ handler.post {
146
+ val screen = getScreen(templateId)
147
+ if (screen != null) {
148
+ currentCarScreen = screen
149
+ screenManager?.popToRoot()
150
+ screenManager?.push(screen)
151
+ }
152
+ }
153
+ }
154
+
155
+ @ReactMethod
156
+ fun pushTemplate(templateId: String, animated: Boolean?) {
157
+ handler.post {
158
+ val screen = getScreen(templateId)
159
+ if (screen != null) {
160
+ currentCarScreen = screen;
161
+ screenManager?.push(screen)
162
+ }
163
+ }
164
+ }
165
+
166
+ @ReactMethod
167
+ fun popToTemplate(templateId: String, animated: Boolean?) {
168
+ handler.post {
169
+ screenManager?.popTo(templateId);
170
+ }
171
+ }
172
+
173
+ @ReactMethod
174
+ fun popTemplate(animated: Boolean?) {
175
+ handler.post {
176
+ screenManager!!.pop()
177
+ removeScreen(currentCarScreen)
178
+ currentCarScreen = screenManager!!.top as CarScreen
179
+ currentCarScreen?.invalidate()
180
+ }
181
+ }
182
+
183
+ @ReactMethod
184
+ fun presentTemplate(templateId: String?, animated: Boolean?) {
185
+ // void
186
+ }
187
+
188
+ @ReactMethod
189
+ fun dismissTemplate(templateId: String?, animated: Boolean?) {
190
+ // void
191
+ }
192
+
193
+ // pragma: Android Auto only stuff
194
+
195
+ @ReactMethod
196
+ fun toast(text: String, duration: Int) {
197
+ if (!::carContext.isInitialized) {
198
+ Log.e(TAG, "carContext is not initialized. Cannot show toast.")
199
+ return
200
+ }
201
+ CarToast.makeText(carContext, text, duration).show()
202
+ }
203
+
204
+ @ReactMethod
205
+ fun alert(props: ReadableMap) {
206
+ if (!::carContext.isInitialized) {
207
+ Log.e(TAG, "carContext is not initialized. Cannot show alert.")
208
+ return
209
+ }
210
+ handler.post {
211
+ val id = props.getInt("id");
212
+ val title = parser.parseCarText(props.getString("title")!!, props);
213
+ val duration = props.getInt("duration").toLong();
214
+ val alert = Alert.Builder(id, title, duration).apply {
215
+ setCallback(object : AlertCallback {
216
+ override fun onCancel(reason: Int) {
217
+ val reasonString = when (reason) {
218
+ AlertCallback.REASON_TIMEOUT -> "timeout"
219
+ AlertCallback.REASON_USER_ACTION -> "userAction"
220
+ AlertCallback.REASON_NOT_SUPPORTED -> "notSupported"
221
+ else -> "unknown"
222
+ }
223
+ eventEmitter?.alertActionPressed("cancel", reasonString);
224
+ }
225
+ override fun onDismiss() {
226
+ eventEmitter?.alertActionPressed("dismiss" );
227
+ }
228
+ })
229
+ props.getString("subtitle")?.let { setSubtitle(parser.parseCarText(it, props)) }
230
+ props.getMap("icon")?.let { setIcon(parser.parseCarIcon(it)) }
231
+ props.getArray("actions")?.let {
232
+ for (i in 0 until it.size()) {
233
+ addAction(parser.parseAction(it.getMap(i)));
234
+ }
235
+ }
236
+ }.build()
237
+ carContext.getCarService(AppManager::class.java).showAlert(alert)
238
+ }
239
+ }
240
+
241
+ @ReactMethod
242
+ fun dismissAlert(alertId: Int) {
243
+ if (!::carContext.isInitialized) {
244
+ Log.e(TAG, "carContext is not initialized. Cannot dismiss alert.")
245
+ return
246
+ }
247
+ carContext.getCarService(AppManager::class.java).dismissAlert(alertId)
248
+ }
249
+
250
+ @ReactMethod
251
+ fun invalidate(templateId: String) {
252
+ handler.post {
253
+ val screen = getScreen(templateId)
254
+ if (screen === screenManager!!.top) {
255
+ Log.d(TAG, "Invalidated screen $templateId")
256
+ screen.invalidate()
257
+ }
258
+ }
259
+ }
260
+
261
+ @ReactMethod
262
+ fun reload() {
263
+ val intent = Intent("org.birkir.carplay.APP_RELOAD")
264
+ reactContext.sendBroadcast(intent)
265
+ }
266
+
267
+ @ReactMethod
268
+ fun getHostInfo(promise: Promise) {
269
+ if (!::carContext.isInitialized) {
270
+ Log.e(TAG, "carContext is not initialized. Cannot get host info.")
271
+ promise.resolve(null)
272
+ return
273
+ }
274
+ return promise.resolve(Arguments.createMap().apply {
275
+ carContext.hostInfo?.packageName?.let { putString("packageName", it) }
276
+ carContext.hostInfo?.uid?.let { putInt("uid", it) }
277
+ });
278
+ }
279
+
280
+ @ReactMethod
281
+ fun launchGoogleMaps(url: String) {
282
+ if (!::carContext.isInitialized) {
283
+ Log.e(TAG, "carContext is not initialized. Cannot launch Google Maps.")
284
+ return
285
+ }
286
+ Log.d(TAG, "open maps with $url");
287
+ val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse(url));
288
+ intent.setPackage("com.google.android.apps.maps");
289
+ carContext.startCarApp(intent)
290
+
291
+ }
292
+
293
+ // Others
294
+
295
+ @ReactMethod
296
+ fun addListener(eventName: String) {
297
+ Log.d(TAG, "listener added $eventName")
298
+ }
299
+
300
+ @ReactMethod
301
+ fun removeListeners(count: Int) {
302
+ Log.d(TAG, "remove listeners $count")
303
+ }
304
+
305
+ private fun createCarScreenContext(screen: CarScreen): CarScreenContext {
306
+ val templateId = screen.marker!!
307
+ return CarScreenContext(templateId, EventEmitter(reactContext, templateId), carScreens)
308
+ }
309
+
310
+ private fun createScreen(templateId: String): CarScreen? {
311
+ if (!::carContext.isInitialized) {
312
+ Log.e(TAG, "carContext not initialized")
313
+ return null
314
+ }
315
+ val config = carTemplates[templateId];
316
+ if (config != null) {
317
+ val screen = CarScreen(carContext)
318
+ screen.marker = templateId;
319
+
320
+ // context
321
+ carScreenContexts.remove(screen)
322
+ val carScreenContext = createCarScreenContext(screen)
323
+ carScreenContexts[screen] = carScreenContext
324
+
325
+ val template = parseTemplate(config, carScreenContext);
326
+ screen.setTemplate(template, templateId, config)
327
+ carScreens[templateId] = screen;
328
+
329
+ return screen;
330
+ }
331
+ return null;
332
+ }
333
+
334
+ private fun getScreen(name: String): CarScreen? {
335
+ return carScreens[name] ?: createScreen(name);
336
+ }
337
+
338
+ private fun removeScreen(screen: CarScreen?) {
339
+ val params = WritableNativeMap()
340
+ params.putString("screen", screen!!.marker)
341
+ carScreens.values.remove(screen)
342
+ }
343
+
344
+ companion object {
345
+ const val NAME = "RNCarPlay"
346
+ const val TAG = "CarPlay"
347
+ }
348
+ }
@@ -0,0 +1,18 @@
1
+ package org.birkir.carplay
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class CarPlayPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ val modules: MutableList<NativeModule> = ArrayList()
11
+ modules.add(CarPlayModule(reactContext))
12
+ return modules
13
+ }
14
+
15
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
16
+ return emptyList()
17
+ }
18
+ }
@@ -0,0 +1,34 @@
1
+ package org.birkir.carplay
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import android.content.IntentFilter
7
+ import android.util.Log
8
+ import androidx.car.app.CarAppService
9
+ import androidx.car.app.Session
10
+ import androidx.car.app.SessionInfo
11
+ import androidx.car.app.validation.HostValidator
12
+ import com.facebook.react.ReactApplication
13
+ import com.facebook.react.ReactHost
14
+
15
+ class CarPlayService : CarAppService() {
16
+ private var reactHost: ReactHost? = null
17
+ override fun onCreate() {
18
+ super.onCreate()
19
+ reactHost = (application as ReactApplication).reactHost
20
+ }
21
+
22
+ override fun createHostValidator(): HostValidator {
23
+ return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
24
+ }
25
+
26
+ override fun onCreateSession(sessionInfo: SessionInfo): Session {
27
+ Log.d(TAG, "onCreateSession: sessionId = ${sessionInfo.sessionId}, display = ${sessionInfo.displayType}")
28
+ return CarPlaySession(reactHost!!)
29
+ }
30
+
31
+ companion object {
32
+ var TAG = "CarPlayService"
33
+ }
34
+ }
@@ -0,0 +1,114 @@
1
+ package org.birkir.carplay
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.content.BroadcastReceiver
5
+ import android.content.Context
6
+ import android.content.Intent
7
+ import android.os.Build
8
+ import android.content.IntentFilter
9
+ import android.content.res.Configuration
10
+ import android.os.Bundle
11
+ import android.util.Log
12
+ import androidx.car.app.CarContext.SCREEN_SERVICE
13
+ import androidx.car.app.Screen
14
+ import androidx.car.app.ScreenManager
15
+ import androidx.car.app.Session
16
+ import androidx.lifecycle.DefaultLifecycleObserver
17
+ import androidx.lifecycle.LifecycleOwner
18
+ import com.facebook.react.ReactHost
19
+ import com.facebook.react.ReactInstanceEventListener
20
+ import com.facebook.react.bridge.Arguments
21
+ import com.facebook.react.bridge.ReactContext
22
+ import com.facebook.react.bridge.WritableNativeMap
23
+ import com.facebook.react.modules.appregistry.AppRegistry
24
+ import com.facebook.react.modules.core.TimingModule
25
+ import com.facebook.react.modules.debug.DevSettingsModule
26
+ import org.birkir.carplay.screens.CarScreen
27
+
28
+
29
+ class CarPlaySession(private val reactHost: ReactHost) : Session(), DefaultLifecycleObserver {
30
+ private lateinit var screen: CarScreen
31
+
32
+ @SuppressLint("UnspecifiedRegisterReceiverFlag")
33
+ override fun onCreateScreen(intent: Intent): Screen {
34
+ Log.d(TAG, "On create screen " + intent.action + " - " + intent.dataString)
35
+ val lifecycle = lifecycle
36
+ lifecycle.addObserver(this)
37
+ screen = CarScreen(carContext)
38
+ screen.marker = "root"
39
+
40
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
41
+ carContext.registerReceiver(object : BroadcastReceiver() {
42
+ override fun onReceive(context: Context, intent: Intent) {
43
+ if ("org.birkir.carplay.APP_RELOAD" == intent.action) {
44
+ reactHost.currentReactContext?.let { invokeStartTask(it) }
45
+ }
46
+ }
47
+ }, IntentFilter("org.birkir.carplay.APP_RELOAD"), 2)
48
+ } else {
49
+ carContext.registerReceiver(object : BroadcastReceiver() {
50
+ override fun onReceive(context: Context, intent: Intent) {
51
+ if ("org.birkir.carplay.APP_RELOAD" == intent.action) {
52
+ reactHost.currentReactContext?.let { invokeStartTask(it) }
53
+ }
54
+ }
55
+ }, IntentFilter("org.birkir.carplay.APP_RELOAD"))
56
+ }
57
+
58
+ runJsApplication()
59
+ return screen
60
+ }
61
+
62
+ private fun runJsApplication() {
63
+ val reactContext = reactHost.currentReactContext
64
+ if (reactContext == null) {
65
+ reactHost.addReactInstanceEventListener(
66
+ object : ReactInstanceEventListener {
67
+ override fun onReactContextInitialized(reactContext: ReactContext) {
68
+ invokeStartTask(reactContext)
69
+ reactHost.removeReactInstanceEventListener(this)
70
+ }
71
+ })
72
+ } else {
73
+ invokeStartTask(reactContext)
74
+ }
75
+ }
76
+
77
+ private fun invokeStartTask(reactContext: ReactContext) {
78
+ try {
79
+ val catalystInstance = reactContext.catalystInstance
80
+ val jsAppModuleName = "AndroidAuto"
81
+ val appParams = WritableNativeMap()
82
+ appParams.putDouble("rootTag", 1.0)
83
+ val appProperties = Bundle.EMPTY
84
+ if (appProperties != null) {
85
+ appParams.putMap("initialProps", Arguments.fromBundle(appProperties))
86
+ }
87
+
88
+ catalystInstance.getJSModule(AppRegistry::class.java)?.runApplication(jsAppModuleName, appParams)
89
+
90
+ val carModule = reactHost.currentReactContext?.getNativeModule(CarPlayModule::class.java)
91
+ carModule!!.setCarContext(carContext, screen)
92
+
93
+ } catch (e: Exception) {
94
+ e.printStackTrace()
95
+ }
96
+ }
97
+
98
+ override fun onDestroy(owner: LifecycleOwner) {
99
+ Log.i(TAG, "onDestroy")
100
+ val context = carContext
101
+ }
102
+
103
+ override fun onNewIntent(intent: Intent) {
104
+ Log.d(TAG, "CarPlaySession.onNewIntent")
105
+ }
106
+
107
+ override fun onCarConfigurationChanged(configuration: Configuration) {
108
+ Log.d(TAG, "CarPlaySession.onCarConfigurationChanged")
109
+ }
110
+
111
+ companion object {
112
+ const val TAG = "CarPlaySession"
113
+ }
114
+ }
@@ -0,0 +1,11 @@
1
+ package org.birkir.carplay.parser
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ fun ReadableMap.isLoading(): Boolean {
6
+ return try {
7
+ getBoolean("loading")
8
+ } catch (e: Exception) {
9
+ return false
10
+ }
11
+ }
@@ -0,0 +1,18 @@
1
+ package org.birkir.carplay.parser
2
+
3
+ import androidx.car.app.CarContext
4
+ import androidx.car.app.model.Pane
5
+ import androidx.car.app.model.PaneTemplate
6
+ import androidx.car.app.model.Template
7
+ import com.facebook.react.bridge.ReadableMap
8
+ import org.birkir.carplay.screens.CarScreenContext
9
+
10
+ class Parser(
11
+ context: CarContext,
12
+ carScreenContext: CarScreenContext
13
+ ) : RCTTemplate(context, carScreenContext) {
14
+ override fun parse(props: ReadableMap): Template {
15
+ return PaneTemplate.Builder(Pane.Builder().build()).build()
16
+ }
17
+
18
+ }
@@ -0,0 +1,28 @@
1
+ package org.birkir.carplay.parser
2
+
3
+ import androidx.car.app.CarContext
4
+ import androidx.car.app.model.GridTemplate
5
+ import com.facebook.react.bridge.ReadableMap
6
+ import org.birkir.carplay.screens.CarScreenContext
7
+
8
+ class RCTGridTemplate(
9
+ context: CarContext,
10
+ carScreenContext: CarScreenContext
11
+ ) : RCTTemplate(context, carScreenContext) {
12
+
13
+ override fun parse(props: ReadableMap): GridTemplate {
14
+ return GridTemplate.Builder().apply {
15
+ setLoading(props.isLoading())
16
+ props.getString("title")?.let { setTitle(it) }
17
+ props.getMap("headerAction")?.let { setHeaderAction(parseAction(it)) }
18
+ props.getArray("actions")?.let { setActionStrip(parseActionStrip(it)) }
19
+ this.setSingleList(
20
+ parseItemList(props.getArray("buttons"), "grid")
21
+ )
22
+ }.build()
23
+ }
24
+
25
+ companion object {
26
+ const val TAG = "RCTGridTemplate"
27
+ }
28
+ }
@@ -0,0 +1,64 @@
1
+ package org.birkir.carplay.parser
2
+
3
+ import androidx.car.app.CarContext
4
+ import androidx.car.app.model.ListTemplate
5
+ import androidx.car.app.model.SectionedItemList
6
+ import com.facebook.react.bridge.ReadableMap
7
+ import org.birkir.carplay.screens.CarScreenContext
8
+
9
+ class RCTListTemplate(
10
+ context: CarContext,
11
+ screenContext: CarScreenContext
12
+ ) : RCTTemplate(context, screenContext) {
13
+
14
+ override fun parse(props: ReadableMap): ListTemplate {
15
+ return ListTemplate.Builder().apply {
16
+ props.getString("title")?.let { setTitle(it) }
17
+
18
+ // Actions
19
+ props.getArray("actions")?.let {
20
+ setActionStrip(
21
+ parseActionStrip(it)
22
+ )
23
+ }
24
+
25
+ // Header Action
26
+ props.getMap("headerAction")?.let {
27
+ setHeaderAction(
28
+ parseAction(it)
29
+ )
30
+ }
31
+
32
+ // Loading
33
+ setLoading(props.isLoading())
34
+
35
+ // Sections
36
+ props.getArray("sections")?.let {
37
+ for (i in 0 until it.size()) {
38
+ val section = it.getMap(i)
39
+ val header = section?.getString("header")
40
+ addSectionedList(
41
+ SectionedItemList.create(
42
+ parseItemList(section?.getArray("items")),
43
+ header ?: "Missing title"
44
+ )
45
+ )
46
+ }
47
+ }
48
+
49
+ // Single List
50
+ // @todo handle when sections and items are defined at once.
51
+ props.getArray("items")?.let {
52
+ setSingleList(
53
+ parseItemList(it)
54
+ )
55
+ }
56
+
57
+ }.build()
58
+ }
59
+
60
+
61
+ companion object {
62
+ const val TAG = "RCTListTemplate"
63
+ }
64
+ }