expo-gaode-map-navigation 2.0.10 → 2.0.11

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 (53) hide show
  1. package/README.md +54 -2
  2. package/android/build.gradle +4 -0
  3. package/android/src/main/AndroidManifest.xml +2 -1
  4. package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviView.kt +501 -27
  5. package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviViewModule.kt +35 -0
  6. package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNavigationModule.kt +10 -23
  7. package/android/src/main/java/expo/modules/gaodemap/navigation/listeners/IndependentRouteListener.kt +24 -0
  8. package/android/src/main/java/expo/modules/gaodemap/navigation/managers/IndependentRouteManager.kt +24 -7
  9. package/android/src/main/java/expo/modules/gaodemap/navigation/routes/drive/DriveTruckRouteCalculator.kt +22 -35
  10. package/android/src/main/java/expo/modules/gaodemap/navigation/services/IndependentRouteService.kt +45 -35
  11. package/android/src/main/java/expo/modules/gaodemap/navigation/services/NavigationForegroundService.kt +661 -0
  12. package/android/src/main/java/expo/modules/gaodemap/navigation/utils/Converters.kt +2 -2
  13. package/android/src/main/res/drawable/ic_nav_notification_small.xml +10 -0
  14. package/android/src/main/res/drawable/nav_notification_brand_icon.xml +16 -0
  15. package/android/src/main/res/drawable/navi_lane_shape_bg_center.xml +4 -4
  16. package/android/src/main/res/drawable/navi_lane_shape_bg_left.xml +7 -7
  17. package/android/src/main/res/drawable/navi_lane_shape_bg_over.xml +5 -5
  18. package/android/src/main/res/drawable/navi_lane_shape_bg_right.xml +7 -7
  19. package/android/src/main/res/drawable-nodpi/nav_tracker_car.png +0 -0
  20. package/build/ExpoGaodeMapNaviView.d.ts +9 -1
  21. package/build/ExpoGaodeMapNaviView.d.ts.map +1 -1
  22. package/build/ExpoGaodeMapNaviView.js +39 -3
  23. package/build/ExpoGaodeMapNaviView.js.map +1 -1
  24. package/build/index.d.ts +32 -6
  25. package/build/index.d.ts.map +1 -1
  26. package/build/index.js +32 -6
  27. package/build/index.js.map +1 -1
  28. package/build/types/independent.types.d.ts +18 -3
  29. package/build/types/independent.types.d.ts.map +1 -1
  30. package/build/types/independent.types.js.map +1 -1
  31. package/build/types/naviview.types.d.ts +49 -3
  32. package/build/types/naviview.types.d.ts.map +1 -1
  33. package/build/types/naviview.types.js.map +1 -1
  34. package/build/types/route.types.d.ts +10 -2
  35. package/build/types/route.types.d.ts.map +1 -1
  36. package/build/types/route.types.js.map +1 -1
  37. package/ios/ExpoGaodeMapNaviView.swift +1526 -246
  38. package/ios/ExpoGaodeMapNaviViewModule.swift +22 -0
  39. package/ios/ExpoGaodeMapNavigationModule.swift +6 -4
  40. package/ios/managers/IndependentRouteManager.swift +89 -26
  41. package/ios/map/ExpoGaodeMapModule.swift +25 -11
  42. package/ios/map/modules/LocationManager.swift +10 -1
  43. package/ios/map/utils/PermissionManager.swift +104 -0
  44. package/ios/routes/drive/DriveTruckRouteCalculator.swift +157 -78
  45. package/ios/routes/walkride/WalkRideRouteCalculator.swift +97 -1
  46. package/ios/services/IndependentRouteService.swift +165 -32
  47. package/ios/services/NavigationLiveActivityAttributes.swift +48 -0
  48. package/ios/services/NavigationLiveActivityManager.swift +359 -0
  49. package/package.json +2 -1
  50. package/plugin/build/withGaodeMap.d.ts +8 -0
  51. package/plugin/build/withGaodeMap.js +48 -4
  52. package/widget-template/README.md +46 -0
  53. package/widget-template/ios/NavigationLiveActivityWidget.swift +367 -0
@@ -59,6 +59,12 @@ class ExpoGaodeMapNaviViewModule : Module() {
59
59
  view.applyCarImage(uri)
60
60
  }
61
61
 
62
+ Prop<Map<String, Double>?>("carImageSize") { view, value ->
63
+ val width = value?.get("width")
64
+ val height = value?.get("height")
65
+ view.applyCarImageSize(width, height)
66
+ }
67
+
62
68
  Prop<String?>("fourCornersImage") { view, uri ->
63
69
  view.applyFourCornersImage(uri)
64
70
  }
@@ -71,6 +77,10 @@ class ExpoGaodeMapNaviViewModule : Module() {
71
77
  view.applyWayPointImage(uri)
72
78
  }
73
79
 
80
+ Prop<List<Map<String, Any?>>?>("customWaypointMarkers") { view, markers ->
81
+ view.applyCustomWaypointMarkers(markers)
82
+ }
83
+
74
84
  Prop<String?>("endPointImage") { view, uri ->
75
85
  view.applyEndPointImage(uri)
76
86
  }
@@ -102,6 +112,10 @@ class ExpoGaodeMapNaviViewModule : Module() {
102
112
  Prop<Boolean>("isNightMode") { view, enabled ->
103
113
  view.applyNightMode(enabled)
104
114
  }
115
+
116
+ Prop<Int>("mapViewModeType") { view, mode ->
117
+ view.applyMapViewModeType(mode)
118
+ }
105
119
 
106
120
  Prop<Boolean>("carOverlayVisible") { view, visible ->
107
121
  view.applyCarOverlayVisible(visible)
@@ -204,6 +218,14 @@ class ExpoGaodeMapNaviViewModule : Module() {
204
218
  view.applyShowUIElements(visible)
205
219
  }
206
220
 
221
+ Prop<Boolean>("androidBackgroundNavigationNotificationEnabled") { view, enabled ->
222
+ view.applyAndroidBackgroundNavigationNotificationEnabled(enabled)
223
+ }
224
+
225
+ // iOS-only prop, keep a no-op mapping on Android for cross-platform prop compatibility.
226
+ Prop<Boolean>("iosLiveActivityEnabled") { _: ExpoGaodeMapNaviView, _: Boolean ->
227
+ }
228
+
207
229
  Prop<Boolean>("showTrafficBar") { view, enabled ->
208
230
  view.applyAndroidTrafficBarEnabled(enabled)
209
231
  }
@@ -236,6 +258,19 @@ class ExpoGaodeMapNaviViewModule : Module() {
236
258
  AsyncFunction("stopNavigation") { view: ExpoGaodeMapNaviView, promise: expo.modules.kotlin.Promise ->
237
259
  view.stopNavigation(promise)
238
260
  }
261
+
262
+ AsyncFunction("playCustomTTS") { view: ExpoGaodeMapNaviView, text: String, forcePlay: Boolean, promise: expo.modules.kotlin.Promise ->
263
+ val success = view.playCustomTTS(text, forcePlay)
264
+ if (success) {
265
+ promise.resolve(
266
+ mapOf(
267
+ "success" to true
268
+ )
269
+ )
270
+ } else {
271
+ promise.reject("PLAY_TTS_FAILED", "当前场景暂不支持或正在播报其他导航语音", null)
272
+ }
273
+ }
239
274
  }
240
275
  }
241
276
  }
@@ -2,9 +2,9 @@ package expo.modules.gaodemap.navigation
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
- import com.amap.api.navi.AMapNavi
6
5
  import com.amap.api.navi.model.AMapCarInfo
7
6
  import com.amap.api.navi.model.AMapNaviPathGroup
7
+ import expo.modules.core.arguments.ReadableArguments
8
8
  import expo.modules.kotlin.Promise
9
9
  import expo.modules.kotlin.modules.Module
10
10
  import expo.modules.kotlin.modules.ModuleDefinition
@@ -135,7 +135,7 @@ class ExpoGaodeMapNavigationModule : Module() {
135
135
  // 使用 AMapNavi.independentCalculateRoute,不影响当前导航状态
136
136
  // 委托给 IndependentRouteService 处理,避免 Module 文件臃肿
137
137
 
138
- AsyncFunction("independentDriveRoute") { options: Map<String, Any?>, promise: Promise ->
138
+ AsyncFunction("independentDriveRoute") { options: ReadableArguments, promise: Promise ->
139
139
  try {
140
140
  ensureIndependentService().independentDriveRoute(options, promise)
141
141
  } catch (e: Exception) {
@@ -143,7 +143,7 @@ class ExpoGaodeMapNavigationModule : Module() {
143
143
  }
144
144
  }
145
145
 
146
- AsyncFunction("independentTruckRoute") { options: Map<String, Any?>, promise: Promise ->
146
+ AsyncFunction("independentTruckRoute") { options: ReadableArguments, promise: Promise ->
147
147
  try {
148
148
  ensureIndependentService().independentTruckRoute(options, promise)
149
149
  } catch (e: Exception) {
@@ -151,7 +151,7 @@ class ExpoGaodeMapNavigationModule : Module() {
151
151
  }
152
152
  }
153
153
 
154
- AsyncFunction("independentWalkRoute") { options: Map<String, Any?>, promise: Promise ->
154
+ AsyncFunction("independentWalkRoute") { options: ReadableArguments, promise: Promise ->
155
155
  try {
156
156
  ensureIndependentService().independentWalkRoute(options, promise)
157
157
  } catch (e: Exception) {
@@ -159,7 +159,7 @@ class ExpoGaodeMapNavigationModule : Module() {
159
159
  }
160
160
  }
161
161
 
162
- AsyncFunction("independentRideRoute") { options: Map<String, Any?>, promise: Promise ->
162
+ AsyncFunction("independentRideRoute") { options: ReadableArguments, promise: Promise ->
163
163
  try {
164
164
  ensureIndependentService().independentRideRoute(options, promise)
165
165
  } catch (e: Exception) {
@@ -168,7 +168,7 @@ class ExpoGaodeMapNavigationModule : Module() {
168
168
  }
169
169
 
170
170
  // 独立摩托车 路线规划(与驾车一致,依赖车辆信息 carType=11)
171
- AsyncFunction("independentMotorcycleRoute") { options: Map<String, Any?>, promise: Promise ->
171
+ AsyncFunction("independentMotorcycleRoute") { options: ReadableArguments, promise: Promise ->
172
172
  try {
173
173
  ensureIndependentService().independentMotorcycleRoute(options, promise)
174
174
  } catch (e: Exception) {
@@ -262,26 +262,13 @@ class ExpoGaodeMapNavigationModule : Module() {
262
262
  AsyncFunction("calculateMotorcycleRoute") { options: Map<String, Any?>, promise: Promise ->
263
263
  try {
264
264
  ensureNavigationPrivacyReady()
265
- // 设置摩托车车辆信息(车牌可选、排量可选)
266
- try {
267
- val carNumber = options["carNumber"] as? String
268
- val motorcycleCC = (options["motorcycleCC"] as? Number)?.toInt()
269
- val carInfo = AMapCarInfo().apply {
270
- if (carNumber != null) setCarNumber(carNumber)
271
- carType = "11" // 11 = 摩托车
272
- if (motorcycleCC != null) {
273
- try {
274
- this.motorcycleCC = motorcycleCC
275
- } catch (_: Exception) {}
276
- }
277
- }
278
- AMapNavi.getInstance(context).setCarInfo(carInfo)
279
- } catch (_: Exception) {
280
- // ignore
265
+ val motorcycleOptions = options.toMutableMap()
266
+ if (motorcycleOptions["carType"] == null) {
267
+ motorcycleOptions["carType"] = "11"
281
268
  }
282
269
 
283
270
  // 复用驾车算路逻辑(含 strategyConvert / 途经点等)
284
- ensureDriveTruck().calculateDriveRoute(options, promise)
271
+ ensureDriveTruck().calculateDriveRoute(motorcycleOptions, promise)
285
272
  } catch (e: Exception) {
286
273
  promise.reject("CALCULATE_ERROR", e.message, e)
287
274
  }
@@ -1,5 +1,6 @@
1
1
  package expo.modules.gaodemap.navigation.listeners
2
2
 
3
+ import android.util.Log
3
4
  import com.amap.api.navi.AMapNaviIndependentRouteListener
4
5
  import com.amap.api.navi.model.AMapCalcRouteResult
5
6
  import com.amap.api.navi.model.AMapNaviPathGroup
@@ -17,6 +18,9 @@ class IndependentRouteListener(
17
18
  private val module: ExpoGaodeMapNavigationModule,
18
19
  private val promise: Promise
19
20
  ) : AMapNaviIndependentRouteListener {
21
+ companion object {
22
+ private const val TAG = "IndependentRouteListener"
23
+ }
20
24
 
21
25
  override fun onIndependentCalculateSuccess(group: AMapNaviPathGroup?) {
22
26
  try {
@@ -28,6 +32,7 @@ class IndependentRouteListener(
28
32
 
29
33
  // 将路径组存储在模块内,返回一个可供后续操作(选路/启动导航/清理)的 token
30
34
  val token = module.storeIndependentGroup(group)
35
+ logGroupSummary(group, token)
31
36
 
32
37
  val result = convertGroupToResult(group).toMutableMap().apply {
33
38
  put("token", token)
@@ -42,11 +47,30 @@ class IndependentRouteListener(
42
47
 
43
48
  override fun onIndependentCalculateFail(routeResult: AMapCalcRouteResult?) {
44
49
  val errorCode = routeResult?.errorCode ?: -1
50
+ Log.e(TAG, "independentCalculateRoute failed: errorCode=$errorCode result=$routeResult")
45
51
  val errorMsg = "Independent route calculation failed with code: $errorCode"
46
52
  promise.reject("INDEPENDENT_CALCULATE_ERROR", errorMsg, null)
47
53
  module.sendEvent("onCalculateRouteFailure", mapOf("errorCode" to errorCode))
48
54
  }
49
55
 
56
+ private fun logGroupSummary(group: AMapNaviPathGroup, token: Int) {
57
+ val count = try { group.pathCount } catch (_: Exception) { -1 }
58
+ val mainIndex = try { group.mainPathIndex } catch (_: Exception) { -1 }
59
+ Log.d(TAG, "independentCalculateRoute success: token=$token pathCount=$count mainPathIndex=$mainIndex")
60
+
61
+ for (index in 0 until maxOf(count, 0)) {
62
+ try {
63
+ val path = group.getPath(index)
64
+ Log.d(
65
+ TAG,
66
+ "path[$index]: routeId=${12 + index} length=${path.allLength} time=${path.allTime} toll=${path.tollCost} trafficLights=${path.trafficLightCount} coordCount=${path.coordList?.size ?: 0}"
67
+ )
68
+ } catch (error: Exception) {
69
+ Log.e(TAG, "failed to inspect path[$index]", error)
70
+ }
71
+ }
72
+ }
73
+
50
74
  /**
51
75
  * 将 AMapNaviPathGroup 转换为轻量结构:
52
76
  * {
@@ -1,6 +1,7 @@
1
1
  package expo.modules.gaodemap.navigation.managers
2
2
 
3
3
  import android.content.Context
4
+ import android.util.Log
4
5
  import com.amap.api.navi.AMapNavi
5
6
  import com.amap.api.navi.enums.NaviType
6
7
  import com.amap.api.navi.model.AMapNaviPathGroup
@@ -12,6 +13,11 @@ import com.amap.api.navi.model.AMapNaviPathGroup
12
13
  * - 提供线程安全的 token 管理
13
14
  */
14
15
  class IndependentRouteManager {
16
+ companion object {
17
+ val shared: IndependentRouteManager by lazy { IndependentRouteManager() }
18
+ private const val TAG = "IndependentRouteManager"
19
+ }
20
+
15
21
  data class StartResult(
16
22
  val success: Boolean,
17
23
  val message: String,
@@ -22,10 +28,6 @@ class IndependentRouteManager {
22
28
  val mainPathIndex: Int
23
29
  )
24
30
 
25
- companion object {
26
- val shared: IndependentRouteManager by lazy { IndependentRouteManager() }
27
- }
28
-
29
31
  private val groups = mutableMapOf<Int, AMapNaviPathGroup>()
30
32
  private var nextToken = 1
31
33
 
@@ -76,14 +78,27 @@ class IndependentRouteManager {
76
78
  }
77
79
  }
78
80
 
81
+ private fun logGroupPathState(group: AMapNaviPathGroup, reason: String) {
82
+ val mainPath = group.mainPath
83
+ Log.d(
84
+ TAG,
85
+ "groupState[$reason]: pathCount=${group.pathCount} mainPathIndex=${group.mainPathIndex} mainLength=${mainPath?.allLength} mainTime=${mainPath?.allTime} labels=${mainPath?.labels} labelId=${mainPath?.labelId} waypointCount=${mainPath?.wayPoint?.size ?: 0} waypointIndexCount=${mainPath?.wayPointIndex?.size ?: 0}"
86
+ )
87
+ }
88
+
79
89
  @Synchronized
80
90
  fun start(context: Context, token: Int, naviType: Int, routeId: Int?, routeIndex: Int?): StartResult {
81
91
  try {
82
92
  val group = get(token)
83
93
  val navi = AMapNavi.getInstance(context)
94
+ logGroupPathState(group, "before-start")
84
95
 
85
96
  val resolvedRouteId = resolveRouteId(group, routeId, routeIndex)
86
97
  val sdkNaviType = resolveSdkNaviType(naviType)
98
+ Log.d(
99
+ TAG,
100
+ "startNaviWithPath request: token=$token requestedNaviType=$naviType sdkNaviType=$sdkNaviType routeId=$routeId routeIndex=$routeIndex resolvedRouteId=$resolvedRouteId pathCount=${group.pathCount} mainPathIndex=${group.mainPathIndex}"
101
+ )
87
102
 
88
103
  if (resolvedRouteId == Int.MIN_VALUE) {
89
104
  return StartResult(
@@ -99,6 +114,8 @@ class IndependentRouteManager {
99
114
 
100
115
  if (resolvedRouteId != null) {
101
116
  val selected = group.selectRouteWithIndex(resolvedRouteId)
117
+ Log.d(TAG, "selectRouteWithIndex($resolvedRouteId) => $selected")
118
+ logGroupPathState(group, "after-select")
102
119
  if (!selected) {
103
120
  return StartResult(
104
121
  success = false,
@@ -114,8 +131,8 @@ class IndependentRouteManager {
114
131
 
115
132
  val result = navi.startNaviWithPath(sdkNaviType, group)
116
133
  if (!result) {
117
- android.util.Log.e(
118
- "IndependentRouteManager",
134
+ Log.e(
135
+ TAG,
119
136
  "startNaviWithPath failed: token=$token requestedNaviType=$naviType sdkNaviType=$sdkNaviType routeId=$resolvedRouteId pathCount=${group.pathCount} mainPathIndex=${group.mainPathIndex}"
120
137
  )
121
138
  return StartResult(
@@ -139,7 +156,7 @@ class IndependentRouteManager {
139
156
  mainPathIndex = group.mainPathIndex
140
157
  )
141
158
  } catch (e: Exception) {
142
- android.util.Log.e("IndependentRouteManager", "Start navigation failed", e)
159
+ Log.e(TAG, "Start navigation failed", e)
143
160
  return StartResult(
144
161
  success = false,
145
162
  message = "独立路径导航启动失败:${e.message ?: "unknown"}",
@@ -123,20 +123,28 @@ class DriveTruckRouteCalculator(
123
123
  }
124
124
  }
125
125
 
126
- // 小客车可选设置:车牌/限行
126
+ val explicitCarType = when (val rawCarType = options["carType"]) {
127
+ is String -> rawCarType.trim().takeIf { it.isNotEmpty() }
128
+ is Number -> rawCarType.toInt().toString()
129
+ else -> null
130
+ }
127
131
  val carNumber = options["carNumber"] as? String
128
132
  val restriction = options["restriction"] as? Boolean
129
- if (carNumber != null || restriction != null) {
130
- try {
131
- val carInfo = AMapCarInfo().apply {
132
- if (carNumber != null) setCarNumber(carNumber)
133
- carType = "0" // 0=小客车
134
- if (restriction != null) isRestriction = restriction
133
+ val motorcycleCC = (options["motorcycleCC"] as? Number)?.toInt()
134
+ try {
135
+ val carInfo = AMapCarInfo().apply {
136
+ carType = explicitCarType ?: "0"
137
+ if (carNumber != null) setCarNumber(carNumber)
138
+ if (restriction != null) isRestriction = restriction
139
+ if (motorcycleCC != null) {
140
+ try {
141
+ this.motorcycleCC = motorcycleCC
142
+ } catch (_: Exception) {}
135
143
  }
136
- aMapNavi?.setCarInfo(carInfo)
137
- } catch (_: Exception) {
138
- // ignore
139
144
  }
145
+ aMapNavi?.setCarInfo(carInfo)
146
+ } catch (_: Exception) {
147
+ // ignore
140
148
  }
141
149
 
142
150
  // 标注场景与多路线期望(默认 drive;若上层已指定 scene 则尊重)
@@ -177,36 +185,15 @@ class DriveTruckRouteCalculator(
177
185
  * 注意:该能力为收费接口;需要商务开通。未开通可能算路失败。
178
186
  */
179
187
  fun calculateTruckRoute(options: Map<String, Any?>, promise: Promise) {
180
- // 先设置货车信息,再复用驾车算路流程
181
- try {
182
- val carNumber = options["carNumber"] as? String
183
- val restriction = options["restriction"] as? Boolean
184
-
185
- val carInfo = AMapCarInfo().apply {
186
- if (carNumber != null) setCarNumber(carNumber)
187
- carType = "1" // 1/3/5 视为货车,这里取 1
188
- if (restriction != null) isRestriction = restriction
189
-
190
- // 可按需扩展更详细的货车参数(示例):
191
- // setVehicleAxis("6")
192
- // setVehicleHeight("3.5")
193
- // setVehicleLength("7.3")
194
- // setVehicleWidth("2.5")
195
- // setVehicleSize("4")
196
- // setVehicleLoad("25.99")
197
- // setVehicleWeight("20")
198
- // setVehicleLoadSwitch(true)
199
- }
200
- aMapNavi?.setCarInfo(carInfo)
201
- } catch (_: Exception) {
202
- // ignore
188
+ val truckOptions = options.toMutableMap()
189
+ if (truckOptions["carType"] == null) {
190
+ truckOptions["carType"] = "1"
203
191
  }
204
192
 
205
- // 标注场景(truck),并期望多路线
206
193
  routeListener?.scene = "truck"
207
194
  routeListener?.multiple = true
208
195
 
209
- calculateDriveRoute(options, promise)
196
+ calculateDriveRoute(truckOptions, promise)
210
197
  }
211
198
 
212
199
  fun destroy() {
@@ -5,6 +5,7 @@ import com.amap.api.navi.AMapNavi
5
5
  import com.amap.api.navi.model.AMapCarInfo
6
6
  import com.amap.api.navi.model.NaviLatLng
7
7
  import com.amap.api.navi.model.NaviPoi
8
+ import expo.modules.core.arguments.ReadableArguments
8
9
  import expo.modules.gaodemap.navigation.ExpoGaodeMapNavigationModule
9
10
  import expo.modules.gaodemap.navigation.listeners.IndependentRouteListener
10
11
  import expo.modules.gaodemap.navigation.utils.Converters
@@ -25,32 +26,33 @@ class IndependentRouteService(
25
26
  }
26
27
 
27
28
  // 驾车(小客车)
28
- fun independentDriveRoute(options: Map<String, Any?>, promise: Promise) {
29
+ fun independentDriveRoute(options: ReadableArguments, promise: Promise) {
29
30
  try {
31
+ val rawOptions = options.toPlainMap()
30
32
  val navi = AMapNavi.getInstance(context)
31
33
 
32
34
  @Suppress("UNCHECKED_CAST")
33
- val from = options["from"] as? Map<String, Any?>
35
+ val from = rawOptions["from"] as? Map<String, Any?>
34
36
  @Suppress("UNCHECKED_CAST")
35
- val to = options["to"] as? Map<String, Any?> ?: throw Exception("to is required")
37
+ val to = rawOptions["to"] as? Map<String, Any?> ?: throw Exception("to is required")
36
38
 
37
39
  val fromPoi = from?.let { Converters.parseNaviPoi(it) }
38
40
  val toPoi = Converters.parseNaviPoi(to)
39
41
  @Suppress("UNCHECKED_CAST")
40
- val waypointsRaw = options["waypoints"] as? List<Map<String, Any?>>
42
+ val waypointsRaw = rawOptions["waypoints"] as? List<Map<String, Any?>>
41
43
  val waypointsPoi = Converters.parseWaypoints(waypointsRaw)
42
44
 
43
- val strategy = resolveDriveStrategy(navi, options)
45
+ val strategy = resolveDriveStrategy(navi, rawOptions)
44
46
 
45
- val carNumber = options["carNumber"] as? String
46
- val restriction = options["restriction"] as? Boolean
47
+ val carNumber = rawOptions["carNumber"] as? String
48
+ val restriction = rawOptions["restriction"] as? Boolean
47
49
  if (carNumber != null || restriction != null) {
48
50
  setCarInfo(navi, "0", carNumber, restriction)
49
51
  }
50
52
 
51
53
  val listener = IndependentRouteListener(module, promise)
52
- val avoidPolygons = Converters.parseAvoidPolygons(options["avoidPolygons"])
53
- val avoidRoad = (options["avoidRoad"] as? String)?.trim()?.takeIf { it.isNotEmpty() }
54
+ val avoidPolygons = Converters.parseAvoidPolygons(rawOptions["avoidPolygons"])
55
+ val avoidRoad = (rawOptions["avoidRoad"] as? String)?.trim()?.takeIf { it.isNotEmpty() }
54
56
  val hasAvoidPolygon = avoidPolygons.isNotEmpty()
55
57
  val hasAvoidRoad = !avoidRoad.isNullOrBlank()
56
58
 
@@ -110,25 +112,26 @@ class IndependentRouteService(
110
112
  }
111
113
 
112
114
  // 货车
113
- fun independentTruckRoute(options: Map<String, Any?>, promise: Promise) {
115
+ fun independentTruckRoute(options: ReadableArguments, promise: Promise) {
114
116
  try {
117
+ val rawOptions = options.toPlainMap()
115
118
  val navi = AMapNavi.getInstance(context)
116
119
 
117
- val carNumber = options["carNumber"] as? String
118
- val restriction = options["restriction"] as? Boolean
120
+ val carNumber = rawOptions["carNumber"] as? String
121
+ val restriction = rawOptions["restriction"] as? Boolean
119
122
  setCarInfo(navi, "1", carNumber, restriction)
120
123
 
121
124
  @Suppress("UNCHECKED_CAST")
122
- val from = options["from"] as? Map<String, Any?>
125
+ val from = rawOptions["from"] as? Map<String, Any?>
123
126
  @Suppress("UNCHECKED_CAST")
124
- val to = options["to"] as? Map<String, Any?> ?: throw Exception("to is required")
127
+ val to = rawOptions["to"] as? Map<String, Any?> ?: throw Exception("to is required")
125
128
 
126
129
  val fromPoi = from?.let { Converters.parseNaviPoi(it) }
127
130
  val toPoi = Converters.parseNaviPoi(to)
128
131
  @Suppress("UNCHECKED_CAST")
129
- val waypoints = Converters.parseWaypoints(options["waypoints"] as? List<Map<String, Any?>>)
132
+ val waypoints = Converters.parseWaypoints(rawOptions["waypoints"] as? List<Map<String, Any?>>)
130
133
 
131
- val strategy = resolveDriveStrategy(navi, options)
134
+ val strategy = resolveDriveStrategy(navi, rawOptions)
132
135
 
133
136
  navi.independentCalculateRoute(
134
137
  fromPoi, toPoi, waypoints, strategy,
@@ -141,23 +144,24 @@ class IndependentRouteService(
141
144
  }
142
145
 
143
146
  // 步行
144
- fun independentWalkRoute(options: Map<String, Any?>, promise: Promise) {
147
+ fun independentWalkRoute(options: ReadableArguments, promise: Promise) {
145
148
  try {
149
+ val rawOptions = options.toPlainMap()
146
150
  val navi = AMapNavi.getInstance(context)
147
151
 
148
152
  @Suppress("UNCHECKED_CAST")
149
- val from = options["from"] as? Map<String, Any?>
153
+ val from = rawOptions["from"] as? Map<String, Any?>
150
154
  @Suppress("UNCHECKED_CAST")
151
- val to = options["to"] as? Map<String, Any?> ?: throw Exception("to is required")
155
+ val to = rawOptions["to"] as? Map<String, Any?> ?: throw Exception("to is required")
152
156
 
153
157
  val fromPoi = from?.let { Converters.parseNaviPoi(it) }
154
158
  val toPoi = Converters.parseNaviPoi(to)
155
159
  @Suppress("UNCHECKED_CAST")
156
- val waypoints = Converters.parseWaypoints(options["waypoints"] as? List<Map<String, Any?>>)
160
+ val waypoints = Converters.parseWaypoints(rawOptions["waypoints"] as? List<Map<String, Any?>>)
157
161
 
158
162
  val travelStrategy: Int = when {
159
- options["travelStrategy"] is Number -> (options["travelStrategy"] as Number).toInt()
160
- options["multiple"] as? Boolean == true -> 1001
163
+ rawOptions["travelStrategy"] is Number -> (rawOptions["travelStrategy"] as Number).toInt()
164
+ rawOptions["multiple"] as? Boolean == true -> 1001
161
165
  else -> 1000
162
166
  }
163
167
 
@@ -172,23 +176,24 @@ class IndependentRouteService(
172
176
  }
173
177
 
174
178
  // 骑行
175
- fun independentRideRoute(options: Map<String, Any?>, promise: Promise) {
179
+ fun independentRideRoute(options: ReadableArguments, promise: Promise) {
176
180
  try {
181
+ val rawOptions = options.toPlainMap()
177
182
  val navi = AMapNavi.getInstance(context)
178
183
 
179
184
  @Suppress("UNCHECKED_CAST")
180
- val from = options["from"] as? Map<String, Any?>
185
+ val from = rawOptions["from"] as? Map<String, Any?>
181
186
  @Suppress("UNCHECKED_CAST")
182
- val to = options["to"] as? Map<String, Any?> ?: throw Exception("to is required")
187
+ val to = rawOptions["to"] as? Map<String, Any?> ?: throw Exception("to is required")
183
188
 
184
189
  val fromPoi = from?.let { Converters.parseNaviPoi(it) }
185
190
  val toPoi = Converters.parseNaviPoi(to)
186
191
  @Suppress("UNCHECKED_CAST")
187
- val waypoints = Converters.parseWaypoints(options["waypoints"] as? List<Map<String, Any?>>)
192
+ val waypoints = Converters.parseWaypoints(rawOptions["waypoints"] as? List<Map<String, Any?>>)
188
193
 
189
194
  val travelStrategy: Int = when {
190
- options["travelStrategy"] is Number -> (options["travelStrategy"] as Number).toInt()
191
- options["multiple"] as? Boolean == true -> 1001
195
+ rawOptions["travelStrategy"] is Number -> (rawOptions["travelStrategy"] as Number).toInt()
196
+ rawOptions["multiple"] as? Boolean == true -> 1001
192
197
  else -> 1000
193
198
  }
194
199
 
@@ -203,25 +208,26 @@ class IndependentRouteService(
203
208
  }
204
209
 
205
210
  // 摩托车(carType=11)
206
- fun independentMotorcycleRoute(options: Map<String, Any?>, promise: Promise) {
211
+ fun independentMotorcycleRoute(options: ReadableArguments, promise: Promise) {
207
212
  try {
213
+ val rawOptions = options.toPlainMap()
208
214
  val navi = AMapNavi.getInstance(context)
209
215
 
210
- val carNumber = options["carNumber"] as? String
211
- val motorcycleCC = (options["motorcycleCC"] as? Number)?.toInt()
216
+ val carNumber = rawOptions["carNumber"] as? String
217
+ val motorcycleCC = (rawOptions["motorcycleCC"] as? Number)?.toInt()
212
218
  setCarInfo(navi, "11", carNumber, null, motorcycleCC)
213
219
 
214
220
  @Suppress("UNCHECKED_CAST")
215
- val from = options["from"] as? Map<String, Any?>
221
+ val from = rawOptions["from"] as? Map<String, Any?>
216
222
  @Suppress("UNCHECKED_CAST")
217
- val to = options["to"] as? Map<String, Any?> ?: throw Exception("to is required")
223
+ val to = rawOptions["to"] as? Map<String, Any?> ?: throw Exception("to is required")
218
224
 
219
225
  val fromPoi = from?.let { Converters.parseNaviPoi(it) }
220
226
  val toPoi = Converters.parseNaviPoi(to)
221
227
  @Suppress("UNCHECKED_CAST")
222
- val waypoints = Converters.parseWaypoints(options["waypoints"] as? List<Map<String, Any?>>)
228
+ val waypoints = Converters.parseWaypoints(rawOptions["waypoints"] as? List<Map<String, Any?>>)
223
229
 
224
- val strategy = resolveDriveStrategy(navi, options)
230
+ val strategy = resolveDriveStrategy(navi, rawOptions)
225
231
 
226
232
  navi.independentCalculateRoute(
227
233
  fromPoi, toPoi, waypoints, strategy,
@@ -397,4 +403,8 @@ class IndependentRouteService(
397
403
  else -> type
398
404
  }
399
405
  }
406
+
407
+ private fun ReadableArguments.toPlainMap(): Map<String, Any?> {
408
+ return keys().associateWith { key -> get(key) }
409
+ }
400
410
  }