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.
- package/README.md +54 -2
- package/android/build.gradle +4 -0
- package/android/src/main/AndroidManifest.xml +2 -1
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviView.kt +501 -27
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviViewModule.kt +35 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNavigationModule.kt +10 -23
- package/android/src/main/java/expo/modules/gaodemap/navigation/listeners/IndependentRouteListener.kt +24 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/managers/IndependentRouteManager.kt +24 -7
- package/android/src/main/java/expo/modules/gaodemap/navigation/routes/drive/DriveTruckRouteCalculator.kt +22 -35
- package/android/src/main/java/expo/modules/gaodemap/navigation/services/IndependentRouteService.kt +45 -35
- package/android/src/main/java/expo/modules/gaodemap/navigation/services/NavigationForegroundService.kt +661 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/utils/Converters.kt +2 -2
- package/android/src/main/res/drawable/ic_nav_notification_small.xml +10 -0
- package/android/src/main/res/drawable/nav_notification_brand_icon.xml +16 -0
- package/android/src/main/res/drawable/navi_lane_shape_bg_center.xml +4 -4
- package/android/src/main/res/drawable/navi_lane_shape_bg_left.xml +7 -7
- package/android/src/main/res/drawable/navi_lane_shape_bg_over.xml +5 -5
- package/android/src/main/res/drawable/navi_lane_shape_bg_right.xml +7 -7
- package/android/src/main/res/drawable-nodpi/nav_tracker_car.png +0 -0
- package/build/ExpoGaodeMapNaviView.d.ts +9 -1
- package/build/ExpoGaodeMapNaviView.d.ts.map +1 -1
- package/build/ExpoGaodeMapNaviView.js +39 -3
- package/build/ExpoGaodeMapNaviView.js.map +1 -1
- package/build/index.d.ts +32 -6
- package/build/index.d.ts.map +1 -1
- package/build/index.js +32 -6
- package/build/index.js.map +1 -1
- package/build/types/independent.types.d.ts +18 -3
- package/build/types/independent.types.d.ts.map +1 -1
- package/build/types/independent.types.js.map +1 -1
- package/build/types/naviview.types.d.ts +49 -3
- package/build/types/naviview.types.d.ts.map +1 -1
- package/build/types/naviview.types.js.map +1 -1
- package/build/types/route.types.d.ts +10 -2
- package/build/types/route.types.d.ts.map +1 -1
- package/build/types/route.types.js.map +1 -1
- package/ios/ExpoGaodeMapNaviView.swift +1526 -246
- package/ios/ExpoGaodeMapNaviViewModule.swift +22 -0
- package/ios/ExpoGaodeMapNavigationModule.swift +6 -4
- package/ios/managers/IndependentRouteManager.swift +89 -26
- package/ios/map/ExpoGaodeMapModule.swift +25 -11
- package/ios/map/modules/LocationManager.swift +10 -1
- package/ios/map/utils/PermissionManager.swift +104 -0
- package/ios/routes/drive/DriveTruckRouteCalculator.swift +157 -78
- package/ios/routes/walkride/WalkRideRouteCalculator.swift +97 -1
- package/ios/services/IndependentRouteService.swift +165 -32
- package/ios/services/NavigationLiveActivityAttributes.swift +48 -0
- package/ios/services/NavigationLiveActivityManager.swift +359 -0
- package/package.json +2 -1
- package/plugin/build/withGaodeMap.d.ts +8 -0
- package/plugin/build/withGaodeMap.js +48 -4
- package/widget-template/README.md +46 -0
- package/widget-template/ios/NavigationLiveActivityWidget.swift +367 -0
|
@@ -4,7 +4,11 @@ import android.annotation.SuppressLint
|
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.graphics.Bitmap
|
|
6
6
|
import android.graphics.BitmapFactory
|
|
7
|
+
import android.graphics.Canvas
|
|
7
8
|
import android.graphics.Color
|
|
9
|
+
import android.graphics.Paint
|
|
10
|
+
import android.graphics.RectF
|
|
11
|
+
import android.graphics.Typeface
|
|
8
12
|
import android.net.Uri
|
|
9
13
|
import android.os.Bundle
|
|
10
14
|
import android.os.Handler
|
|
@@ -17,11 +21,17 @@ import com.amap.api.navi.AMapNaviListener
|
|
|
17
21
|
import com.amap.api.navi.AMapNaviView
|
|
18
22
|
import com.amap.api.navi.AMapNaviViewListener
|
|
19
23
|
import com.amap.api.navi.AMapNaviViewOptions
|
|
24
|
+
import com.amap.api.maps.model.BitmapDescriptorFactory
|
|
25
|
+
import com.amap.api.maps.model.LatLng
|
|
26
|
+
import com.amap.api.maps.model.Marker
|
|
27
|
+
import com.amap.api.maps.model.MarkerOptions
|
|
20
28
|
import com.amap.api.navi.enums.MapStyle
|
|
21
29
|
import com.amap.api.navi.enums.NaviType
|
|
22
30
|
import com.amap.api.navi.model.*
|
|
23
31
|
import expo.modules.gaodemap.map.modules.SDKInitializer
|
|
24
32
|
import expo.modules.gaodemap.navigation.managers.IndependentRouteManager
|
|
33
|
+
import expo.modules.gaodemap.navigation.services.NavigationForegroundService
|
|
34
|
+
import expo.modules.gaodemap.navigation.services.NavigationNotificationSnapshot
|
|
25
35
|
import expo.modules.kotlin.AppContext
|
|
26
36
|
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
27
37
|
import expo.modules.kotlin.views.ExpoView
|
|
@@ -32,6 +42,14 @@ import java.security.MessageDigest
|
|
|
32
42
|
import java.util.Collections
|
|
33
43
|
import java.util.WeakHashMap
|
|
34
44
|
import java.net.URL
|
|
45
|
+
import kotlin.math.roundToInt
|
|
46
|
+
|
|
47
|
+
private data class NaviCustomWaypointMarkerModel(
|
|
48
|
+
val latitude: Double,
|
|
49
|
+
val longitude: Double,
|
|
50
|
+
val title: String,
|
|
51
|
+
val arrived: Boolean = false
|
|
52
|
+
)
|
|
35
53
|
|
|
36
54
|
@SuppressLint("ViewConstructor")
|
|
37
55
|
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
|
@@ -44,11 +62,11 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
44
62
|
synchronized(activeViews) { activeViews.toList() }
|
|
45
63
|
|
|
46
64
|
fun resumeActiveViews() {
|
|
47
|
-
snapshotActiveViews().forEach { it.
|
|
65
|
+
snapshotActiveViews().forEach { it.onHostActivityForeground() }
|
|
48
66
|
}
|
|
49
67
|
|
|
50
68
|
fun pauseActiveViews() {
|
|
51
|
-
snapshotActiveViews().forEach { it.
|
|
69
|
+
snapshotActiveViews().forEach { it.onHostActivityBackground() }
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
fun destroyActiveViews() {
|
|
@@ -98,7 +116,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
98
116
|
internal var isEyrieCrossDisplayVisible: Boolean = true
|
|
99
117
|
internal var isSecondActionVisible: Boolean = true
|
|
100
118
|
internal var isBackupOverlayVisible: Boolean = true
|
|
101
|
-
internal var isAfterRouteAutoGray: Boolean =
|
|
119
|
+
internal var isAfterRouteAutoGray: Boolean = true
|
|
102
120
|
internal var isVectorLineShow: Boolean = true
|
|
103
121
|
internal var isNaviTravelView : Boolean = false
|
|
104
122
|
internal var isCompassEnabled: Boolean = true
|
|
@@ -109,12 +127,19 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
109
127
|
internal var pointToCenterX: Double = 0.0
|
|
110
128
|
internal var pointToCenterY: Double = 0.0
|
|
111
129
|
internal var hideNativeTopInfoLayout: Boolean = false
|
|
130
|
+
internal var androidBackgroundNavigationNotificationEnabled: Boolean = false
|
|
112
131
|
internal var naviModeValue: Int = AMapNaviView.CAR_UP_MODE
|
|
132
|
+
internal var mapViewModeTypeValue: Int = 0
|
|
113
133
|
internal var carImageUri: String? = null
|
|
134
|
+
internal var carImageWidthDp: Double? = null
|
|
135
|
+
internal var carImageHeightDp: Double? = null
|
|
114
136
|
internal var fourCornersImageUri: String? = null
|
|
115
137
|
internal var startPointImageUri: String? = null
|
|
116
138
|
internal var wayPointImageUri: String? = null
|
|
117
139
|
internal var endPointImageUri: String? = null
|
|
140
|
+
private var customWaypointMarkers: List<NaviCustomWaypointMarkerModel> = emptyList()
|
|
141
|
+
private val renderedCustomWaypointMarkers = mutableListOf<Marker>()
|
|
142
|
+
private var activeIndependentRouteId: Int? = null
|
|
118
143
|
private val naviView: AMapNaviView by lazy(LazyThreadSafetyMode.NONE) {
|
|
119
144
|
AMapNaviView(context)
|
|
120
145
|
}
|
|
@@ -128,6 +153,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
128
153
|
private var isModeCrossVisible = false
|
|
129
154
|
private var isLaneInfoCurrentlyVisible = false
|
|
130
155
|
private var currentRouteTotalLength: Int? = null
|
|
156
|
+
private var sourceCarBitmap: Bitmap? = null
|
|
131
157
|
private var customCarBitmap: Bitmap? = null
|
|
132
158
|
private var customFourCornersBitmap: Bitmap? = null
|
|
133
159
|
private var customStartPointBitmap: Bitmap? = null
|
|
@@ -141,6 +167,11 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
141
167
|
private var cachedTurnIconImageUri: String? = null
|
|
142
168
|
private var cachedTurnIconContentHash: String? = null
|
|
143
169
|
private var hasLoggedMissingTurnIconBitmapApi = false
|
|
170
|
+
private var hasLoggedMissingNaviStatusBarApi = false
|
|
171
|
+
private var hasLoggedMissingNaviModeApi = false
|
|
172
|
+
private var isHostActivityInBackground: Boolean = false
|
|
173
|
+
private var isNavigationRunning: Boolean = false
|
|
174
|
+
private var latestNavigationNotificationSnapshot: NavigationNotificationSnapshot? = null
|
|
144
175
|
|
|
145
176
|
private fun registerActiveView() {
|
|
146
177
|
synchronized(activeViews) {
|
|
@@ -154,6 +185,87 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
154
185
|
}
|
|
155
186
|
}
|
|
156
187
|
|
|
188
|
+
private fun buildNavigationNotificationSnapshot(naviInfo: NaviInfo?): NavigationNotificationSnapshot {
|
|
189
|
+
if (naviInfo == null) {
|
|
190
|
+
return latestNavigationNotificationSnapshot ?: NavigationNotificationSnapshot(
|
|
191
|
+
pathRetainDistance = currentRouteTotalLength,
|
|
192
|
+
routeTotalDistance = currentRouteTotalLength,
|
|
193
|
+
turnIconImageUri = cachedTurnIconImageUri
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return NavigationNotificationSnapshot(
|
|
198
|
+
currentRoadName = naviInfo.currentRoadName,
|
|
199
|
+
nextRoadName = naviInfo.nextRoadName,
|
|
200
|
+
pathRetainDistance = naviInfo.pathRetainDistance,
|
|
201
|
+
routeTotalDistance = currentRouteTotalLength,
|
|
202
|
+
pathRetainTime = naviInfo.pathRetainTime,
|
|
203
|
+
curStepRetainDistance = naviInfo.curStepRetainDistance,
|
|
204
|
+
iconType = naviInfo.iconType,
|
|
205
|
+
turnIconImageUri = cachedTurnIconImageUri
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private fun shouldRunBackgroundNavigationNotification(): Boolean {
|
|
210
|
+
return androidBackgroundNavigationNotificationEnabled &&
|
|
211
|
+
isNavigationRunning &&
|
|
212
|
+
isHostActivityInBackground
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private fun syncNavigationForegroundService(reason: String) {
|
|
216
|
+
val shouldRun = shouldRunBackgroundNavigationNotification()
|
|
217
|
+
Log.d(
|
|
218
|
+
"ExpoGaodeMapNaviView",
|
|
219
|
+
"syncNavigationForegroundService reason=$reason, shouldRun=$shouldRun, " +
|
|
220
|
+
"propEnabled=$androidBackgroundNavigationNotificationEnabled, " +
|
|
221
|
+
"isNavigationRunning=$isNavigationRunning, isHostActivityInBackground=$isHostActivityInBackground"
|
|
222
|
+
)
|
|
223
|
+
if (shouldRunBackgroundNavigationNotification()) {
|
|
224
|
+
val snapshot = latestNavigationNotificationSnapshot ?: buildNavigationNotificationSnapshot(null)
|
|
225
|
+
Log.d(
|
|
226
|
+
"ExpoGaodeMapNaviView",
|
|
227
|
+
"startOrUpdate notification snapshot: stepDistance=${snapshot.curStepRetainDistance}, " +
|
|
228
|
+
"remainDistance=${snapshot.pathRetainDistance}, routeTotal=${snapshot.routeTotalDistance}, " +
|
|
229
|
+
"remainTime=${snapshot.pathRetainTime}, " +
|
|
230
|
+
"nextRoad=${snapshot.nextRoadName}, turnIconUri=${snapshot.turnIconImageUri}"
|
|
231
|
+
)
|
|
232
|
+
NavigationForegroundService.startOrUpdate(context, snapshot)
|
|
233
|
+
Log.d("ExpoGaodeMapNaviView", "Navigation foreground notification enabled: $reason")
|
|
234
|
+
} else {
|
|
235
|
+
NavigationForegroundService.stop(context)
|
|
236
|
+
Log.d("ExpoGaodeMapNaviView", "Navigation foreground notification disabled: $reason")
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private fun updateNavigationNotification(naviInfo: NaviInfo) {
|
|
241
|
+
latestNavigationNotificationSnapshot = buildNavigationNotificationSnapshot(naviInfo)
|
|
242
|
+
Log.d(
|
|
243
|
+
"ExpoGaodeMapNaviView",
|
|
244
|
+
"updateNavigationNotification: stepDistance=${naviInfo.curStepRetainDistance}, " +
|
|
245
|
+
"remainDistance=${naviInfo.pathRetainDistance}, routeTotal=${latestNavigationNotificationSnapshot?.routeTotalDistance}, " +
|
|
246
|
+
"remainTime=${naviInfo.pathRetainTime}, " +
|
|
247
|
+
"currentRoad=${naviInfo.currentRoadName}, nextRoad=${naviInfo.nextRoadName}, " +
|
|
248
|
+
"turnIconUri=${latestNavigationNotificationSnapshot?.turnIconImageUri}"
|
|
249
|
+
)
|
|
250
|
+
if (shouldRunBackgroundNavigationNotification()) {
|
|
251
|
+
NavigationForegroundService.startOrUpdate(context, latestNavigationNotificationSnapshot)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
fun onHostActivityForeground() {
|
|
256
|
+
Log.d("ExpoGaodeMapNaviView", "onHostActivityForeground")
|
|
257
|
+
isHostActivityInBackground = false
|
|
258
|
+
onResume()
|
|
259
|
+
syncNavigationForegroundService("host_foreground")
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
fun onHostActivityBackground() {
|
|
263
|
+
Log.d("ExpoGaodeMapNaviView", "onHostActivityBackground")
|
|
264
|
+
isHostActivityInBackground = true
|
|
265
|
+
onPause()
|
|
266
|
+
syncNavigationForegroundService("host_background")
|
|
267
|
+
}
|
|
268
|
+
|
|
157
269
|
private fun applyNaviStatusBarEnabledCompat(
|
|
158
270
|
options: AMapNaviViewOptions,
|
|
159
271
|
enabled: Boolean
|
|
@@ -165,10 +277,13 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
165
277
|
)
|
|
166
278
|
method.invoke(options, enabled)
|
|
167
279
|
} catch (_: NoSuchMethodException) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
280
|
+
if (!hasLoggedMissingNaviStatusBarApi) {
|
|
281
|
+
hasLoggedMissingNaviStatusBarApi = true
|
|
282
|
+
Log.w(
|
|
283
|
+
"ExpoGaodeMapNaviView",
|
|
284
|
+
"AMapNaviViewOptions#setNaviStatusBarEnabled is unavailable in the current AMap SDK; skip applying naviStatusBarEnabled"
|
|
285
|
+
)
|
|
286
|
+
}
|
|
172
287
|
} catch (error: Throwable) {
|
|
173
288
|
Log.w(
|
|
174
289
|
"ExpoGaodeMapNaviView",
|
|
@@ -188,20 +303,114 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
188
303
|
Integer.TYPE
|
|
189
304
|
)
|
|
190
305
|
method.invoke(options, mode)
|
|
306
|
+
} catch (_: NoSuchMethodException) {
|
|
307
|
+
if (!hasLoggedMissingNaviModeApi) {
|
|
308
|
+
hasLoggedMissingNaviModeApi = true
|
|
309
|
+
Log.w(
|
|
310
|
+
"ExpoGaodeMapNaviView",
|
|
311
|
+
"AMapNaviViewOptions#setNaviMode is unavailable in the current AMap SDK; skip applying naviMode on options"
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
} catch (error: Throwable) {
|
|
315
|
+
Log.w(
|
|
316
|
+
"ExpoGaodeMapNaviView",
|
|
317
|
+
"Failed to apply naviMode compatibly",
|
|
318
|
+
error
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private fun applyAutoNaviViewNightModeCompat(
|
|
324
|
+
options: AMapNaviViewOptions,
|
|
325
|
+
enabled: Boolean
|
|
326
|
+
) {
|
|
327
|
+
try {
|
|
328
|
+
val method = options.javaClass.getMethod(
|
|
329
|
+
"setAutoNaviViewNightMode",
|
|
330
|
+
java.lang.Boolean.TYPE
|
|
331
|
+
)
|
|
332
|
+
method.invoke(options, enabled)
|
|
191
333
|
} catch (_: NoSuchMethodException) {
|
|
192
334
|
Log.w(
|
|
193
335
|
"ExpoGaodeMapNaviView",
|
|
194
|
-
"AMapNaviViewOptions#
|
|
336
|
+
"AMapNaviViewOptions#setAutoNaviViewNightMode is unavailable in the current AMap SDK; skip applying auto night mode"
|
|
195
337
|
)
|
|
196
338
|
} catch (error: Throwable) {
|
|
197
339
|
Log.w(
|
|
198
340
|
"ExpoGaodeMapNaviView",
|
|
199
|
-
"Failed to apply
|
|
341
|
+
"Failed to apply auto navi night mode compatibly",
|
|
200
342
|
error
|
|
201
343
|
)
|
|
202
344
|
}
|
|
203
345
|
}
|
|
204
346
|
|
|
347
|
+
private fun applyNaviNightCompat(
|
|
348
|
+
options: AMapNaviViewOptions,
|
|
349
|
+
enabled: Boolean
|
|
350
|
+
) {
|
|
351
|
+
try {
|
|
352
|
+
val method = options.javaClass.getMethod(
|
|
353
|
+
"setNaviNight",
|
|
354
|
+
java.lang.Boolean.TYPE
|
|
355
|
+
)
|
|
356
|
+
method.invoke(options, enabled)
|
|
357
|
+
return
|
|
358
|
+
} catch (_: NoSuchMethodException) {
|
|
359
|
+
Log.w(
|
|
360
|
+
"ExpoGaodeMapNaviView",
|
|
361
|
+
"AMapNaviViewOptions#setNaviNight is unavailable in the current AMap SDK; fallback to setMapStyle"
|
|
362
|
+
)
|
|
363
|
+
} catch (error: Throwable) {
|
|
364
|
+
Log.w(
|
|
365
|
+
"ExpoGaodeMapNaviView",
|
|
366
|
+
"Failed to apply navi night compatibly, fallback to setMapStyle",
|
|
367
|
+
error
|
|
368
|
+
)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (enabled) {
|
|
372
|
+
options.setMapStyle(MapStyle.NIGHT, null)
|
|
373
|
+
} else {
|
|
374
|
+
options.setMapStyle(MapStyle.DAY, null)
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private fun applyMapViewModeTypeCompat(
|
|
379
|
+
options: AMapNaviViewOptions,
|
|
380
|
+
mode: Int
|
|
381
|
+
) {
|
|
382
|
+
when (mode) {
|
|
383
|
+
0 -> {
|
|
384
|
+
applyAutoNaviViewNightModeCompat(options, false)
|
|
385
|
+
applyNaviNightCompat(options, false)
|
|
386
|
+
}
|
|
387
|
+
1 -> {
|
|
388
|
+
applyAutoNaviViewNightModeCompat(options, false)
|
|
389
|
+
applyNaviNightCompat(options, true)
|
|
390
|
+
}
|
|
391
|
+
2 -> {
|
|
392
|
+
applyAutoNaviViewNightModeCompat(options, true)
|
|
393
|
+
}
|
|
394
|
+
3 -> {
|
|
395
|
+
// Android custom map style requires style path API that is not exposed yet.
|
|
396
|
+
applyAutoNaviViewNightModeCompat(options, false)
|
|
397
|
+
applyNaviNightCompat(options, false)
|
|
398
|
+
Log.w(
|
|
399
|
+
"ExpoGaodeMapNaviView",
|
|
400
|
+
"mapViewModeType=3 (custom) requires custom map style path support on Android; fallback to day mode"
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
else -> {
|
|
404
|
+
applyAutoNaviViewNightModeCompat(options, false)
|
|
405
|
+
applyNaviNightCompat(options, false)
|
|
406
|
+
Log.w(
|
|
407
|
+
"ExpoGaodeMapNaviView",
|
|
408
|
+
"Unknown mapViewModeType=$mode; fallback to day mode"
|
|
409
|
+
)
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
205
414
|
private fun createInitialViewOptions(): AMapNaviViewOptions {
|
|
206
415
|
return AMapNaviViewOptions().also { options ->
|
|
207
416
|
applyAllViewOptions(options)
|
|
@@ -247,7 +456,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
247
456
|
|
|
248
457
|
options.isAfterRouteAutoGray = isAfterRouteAutoGray
|
|
249
458
|
options.isSensorEnable = true
|
|
250
|
-
options
|
|
459
|
+
applyMapViewModeTypeCompat(options, mapViewModeTypeValue)
|
|
251
460
|
options.isEagleMapVisible = isEagleMapVisible
|
|
252
461
|
applyCustomAnnotationBitmaps(options)
|
|
253
462
|
}
|
|
@@ -318,6 +527,25 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
318
527
|
}
|
|
319
528
|
}
|
|
320
529
|
|
|
530
|
+
private fun resizeCarBitmapIfNeeded(source: Bitmap?): Bitmap? {
|
|
531
|
+
val rawBitmap = source ?: return null
|
|
532
|
+
val widthDp = carImageWidthDp?.takeIf { it > 0.0 }
|
|
533
|
+
val heightDp = carImageHeightDp?.takeIf { it > 0.0 }
|
|
534
|
+
if (widthDp == null || heightDp == null) {
|
|
535
|
+
return rawBitmap
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
val density = context.resources.displayMetrics.density
|
|
539
|
+
val widthPx = (widthDp * density).roundToInt().coerceAtLeast(1)
|
|
540
|
+
val heightPx = (heightDp * density).roundToInt().coerceAtLeast(1)
|
|
541
|
+
|
|
542
|
+
if (rawBitmap.width == widthPx && rawBitmap.height == heightPx) {
|
|
543
|
+
return rawBitmap
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return Bitmap.createScaledBitmap(rawBitmap, widthPx, heightPx, true)
|
|
547
|
+
}
|
|
548
|
+
|
|
321
549
|
private fun updateCustomAnnotationBitmap(
|
|
322
550
|
uri: String?,
|
|
323
551
|
getCurrentUri: () -> String?,
|
|
@@ -363,6 +591,43 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
363
591
|
refreshNaviUILayout("commitViewOptions")
|
|
364
592
|
}
|
|
365
593
|
|
|
594
|
+
private fun logCurrentNaviPathState(reason: String) {
|
|
595
|
+
val naviPath = aMapNavi?.naviPath
|
|
596
|
+
val waypointCount = naviPath?.wayPoint?.size ?: 0
|
|
597
|
+
val waypointIndexCount = naviPath?.wayPointIndex?.size ?: 0
|
|
598
|
+
Log.d(
|
|
599
|
+
"ExpoGaodeMapNaviView",
|
|
600
|
+
"pathState[$reason]: routeType=${naviPath?.routeType} length=${naviPath?.allLength} time=${naviPath?.allTime} labels=${naviPath?.labels} labelId=${naviPath?.labelId} waypointCount=$waypointCount waypointIndexCount=$waypointIndexCount start=${naviPath?.startPoint} end=${naviPath?.endPoint}"
|
|
601
|
+
)
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
private fun stabilizeIndependentRouteRendering(reason: String) {
|
|
605
|
+
val routeId = activeIndependentRouteId ?: return
|
|
606
|
+
val delays = longArrayOf(0L, 180L, 420L)
|
|
607
|
+
delays.forEach { delayMillis ->
|
|
608
|
+
naviView.postDelayed({
|
|
609
|
+
if (isDestroyed) {
|
|
610
|
+
return@postDelayed
|
|
611
|
+
}
|
|
612
|
+
try {
|
|
613
|
+
val selected = aMapNavi?.selectRouteId(routeId)
|
|
614
|
+
Log.d(
|
|
615
|
+
"ExpoGaodeMapNaviView",
|
|
616
|
+
"stabilizeIndependentRouteRendering[$reason/$delayMillis]: routeId=$routeId selected=$selected"
|
|
617
|
+
)
|
|
618
|
+
applyRouteMarkerVisibleFromState()
|
|
619
|
+
logCurrentNaviPathState("stabilize-$reason-$delayMillis")
|
|
620
|
+
} catch (error: Exception) {
|
|
621
|
+
Log.e(
|
|
622
|
+
"ExpoGaodeMapNaviView",
|
|
623
|
+
"Failed to stabilize independent route rendering: reason=$reason delay=$delayMillis routeId=$routeId",
|
|
624
|
+
error
|
|
625
|
+
)
|
|
626
|
+
}
|
|
627
|
+
}, delayMillis)
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
366
631
|
private fun refreshNaviUILayout(reason: String) {
|
|
367
632
|
if (isDestroyed) {
|
|
368
633
|
return
|
|
@@ -374,14 +639,23 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
374
639
|
}
|
|
375
640
|
|
|
376
641
|
updateTopInsetPadding()
|
|
377
|
-
naviView.requestLayout()
|
|
378
|
-
naviView.forceLayout()
|
|
379
|
-
naviView.invalidate()
|
|
380
|
-
naviView.postInvalidateOnAnimation()
|
|
381
|
-
requestLayout()
|
|
382
|
-
invalidate()
|
|
383
|
-
postInvalidateOnAnimation()
|
|
384
642
|
updateNativeTopInfoLayoutVisibility()
|
|
643
|
+
|
|
644
|
+
val needsAggressiveRefresh =
|
|
645
|
+
hideNativeTopInfoLayout ||
|
|
646
|
+
!showUIElements ||
|
|
647
|
+
androidStatusBarPaddingTopDp != null
|
|
648
|
+
|
|
649
|
+
if (needsAggressiveRefresh) {
|
|
650
|
+
naviView.requestLayout()
|
|
651
|
+
naviView.forceLayout()
|
|
652
|
+
naviView.invalidate()
|
|
653
|
+
naviView.postInvalidateOnAnimation()
|
|
654
|
+
requestLayout()
|
|
655
|
+
invalidate()
|
|
656
|
+
postInvalidateOnAnimation()
|
|
657
|
+
}
|
|
658
|
+
|
|
385
659
|
Log.d("ExpoGaodeMapNaviView", "refreshNaviUILayout: $reason")
|
|
386
660
|
}
|
|
387
661
|
}
|
|
@@ -397,8 +671,12 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
397
671
|
return
|
|
398
672
|
}
|
|
399
673
|
|
|
674
|
+
if (!hideNativeTopInfoLayout) {
|
|
675
|
+
return
|
|
676
|
+
}
|
|
677
|
+
|
|
400
678
|
val queue = ArrayDeque<View>()
|
|
401
|
-
val targetVisibility =
|
|
679
|
+
val targetVisibility = View.GONE
|
|
402
680
|
queue.add(naviView)
|
|
403
681
|
|
|
404
682
|
while (queue.isNotEmpty()) {
|
|
@@ -684,6 +962,10 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
684
962
|
|
|
685
963
|
override fun onStartNavi(type: Int) {
|
|
686
964
|
Log.d("ExpoGaodeMapNaviView", "导航开始: type=$type")
|
|
965
|
+
isNavigationRunning = true
|
|
966
|
+
syncNavigationForegroundService("on_start_navi")
|
|
967
|
+
logCurrentNaviPathState("onStartNavi")
|
|
968
|
+
stabilizeIndependentRouteRendering("onStartNavi")
|
|
687
969
|
onNavigationStarted(mapOf(
|
|
688
970
|
"type" to type,
|
|
689
971
|
"isEmulator" to (type == 1)
|
|
@@ -725,10 +1007,18 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
725
1007
|
}
|
|
726
1008
|
|
|
727
1009
|
override fun onEndEmulatorNavi() {
|
|
1010
|
+
isNavigationRunning = false
|
|
1011
|
+
syncNavigationForegroundService("on_end_emulator_navi")
|
|
1012
|
+
resetCustomWaypointMarkerArrivalState()
|
|
1013
|
+
activeIndependentRouteId = null
|
|
728
1014
|
onNavigationEnded(emptyMap())
|
|
729
1015
|
}
|
|
730
1016
|
|
|
731
1017
|
override fun onArriveDestination() {
|
|
1018
|
+
isNavigationRunning = false
|
|
1019
|
+
syncNavigationForegroundService("on_arrive_destination")
|
|
1020
|
+
resetCustomWaypointMarkerArrivalState()
|
|
1021
|
+
activeIndependentRouteId = null
|
|
732
1022
|
onArriveDestination(emptyMap())
|
|
733
1023
|
}
|
|
734
1024
|
|
|
@@ -749,6 +1039,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
749
1039
|
Handler(Looper.getMainLooper()).post {
|
|
750
1040
|
try {
|
|
751
1041
|
applyRouteMarkerVisibleFromState()
|
|
1042
|
+
refreshCustomWaypointMarkers("calculate-route-success")
|
|
752
1043
|
} catch (e: Exception) {
|
|
753
1044
|
Log.e("ExpoGaodeMapNaviView", "Failed to reapply route marker visibility after route success", e)
|
|
754
1045
|
}
|
|
@@ -772,6 +1063,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
772
1063
|
Handler(Looper.getMainLooper()).post {
|
|
773
1064
|
try {
|
|
774
1065
|
applyRouteMarkerVisibleFromState()
|
|
1066
|
+
refreshCustomWaypointMarkers("calculate-route-success-result")
|
|
775
1067
|
} catch (e: Exception) {
|
|
776
1068
|
Log.e("ExpoGaodeMapNaviView", "Failed to reapply route marker visibility after route success", e)
|
|
777
1069
|
}
|
|
@@ -779,6 +1071,8 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
779
1071
|
}
|
|
780
1072
|
|
|
781
1073
|
override fun onCalculateRouteFailure(errorCode: Int) {
|
|
1074
|
+
isNavigationRunning = false
|
|
1075
|
+
syncNavigationForegroundService("calculate_route_failure_code")
|
|
782
1076
|
onRouteCalculated(mapOf(
|
|
783
1077
|
"success" to false,
|
|
784
1078
|
"errorCode" to errorCode
|
|
@@ -786,6 +1080,8 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
786
1080
|
}
|
|
787
1081
|
|
|
788
1082
|
override fun onCalculateRouteFailure(result: AMapCalcRouteResult?) {
|
|
1083
|
+
isNavigationRunning = false
|
|
1084
|
+
syncNavigationForegroundService("calculate_route_failure_result")
|
|
789
1085
|
onRouteCalculated(mapOf(
|
|
790
1086
|
"success" to false,
|
|
791
1087
|
"errorInfo" to (result?.errorDescription ?: "Unknown error")
|
|
@@ -805,6 +1101,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
805
1101
|
}
|
|
806
1102
|
|
|
807
1103
|
override fun onArrivedWayPoint(wayPointIndex: Int) {
|
|
1104
|
+
markCustomWaypointArrived(wayPointIndex)
|
|
808
1105
|
onWayPointArrived(mapOf(
|
|
809
1106
|
"index" to wayPointIndex
|
|
810
1107
|
))
|
|
@@ -818,11 +1115,17 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
818
1115
|
|
|
819
1116
|
override fun onNaviInfoUpdate(naviInfo: NaviInfo?) {
|
|
820
1117
|
naviInfo?.let {
|
|
821
|
-
|
|
1118
|
+
val allLength = try {
|
|
822
1119
|
aMapNavi?.naviPath?.allLength
|
|
823
1120
|
} catch (_: Throwable) {
|
|
824
1121
|
null
|
|
825
|
-
}
|
|
1122
|
+
}
|
|
1123
|
+
val safeRetainDistance = it.pathRetainDistance.coerceAtLeast(0)
|
|
1124
|
+
currentRouteTotalLength = maxOf(
|
|
1125
|
+
currentRouteTotalLength ?: 0,
|
|
1126
|
+
allLength ?: 0,
|
|
1127
|
+
safeRetainDistance
|
|
1128
|
+
).takeIf { total -> total > 0 } ?: currentRouteTotalLength
|
|
826
1129
|
val nextIconType = resolveNextTurnIconType(it.curStep)
|
|
827
1130
|
val turnIconImage = updateCachedTurnIconImage(it)
|
|
828
1131
|
val payload = mutableMapOf<String, Any>(
|
|
@@ -850,6 +1153,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
850
1153
|
payload["turnIconImage"] = turnIconImage
|
|
851
1154
|
}
|
|
852
1155
|
onNavigationInfoUpdate(payload)
|
|
1156
|
+
updateNavigationNotification(it)
|
|
853
1157
|
emitTrafficStatusesUpdate(it.pathRetainDistance)
|
|
854
1158
|
refreshNaviUILayout("onNaviInfoUpdate")
|
|
855
1159
|
}
|
|
@@ -1106,6 +1410,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1106
1410
|
fun startNavigation(startLat: Double, startLng: Double, endLat: Double, endLng: Double, promise: expo.modules.kotlin.Promise) {
|
|
1107
1411
|
Log.d("ExpoGaodeMapNaviView", "startNavigation: $startLat, $startLng, $endLat, $endLng, naviType: $naviType")
|
|
1108
1412
|
try {
|
|
1413
|
+
resetCustomWaypointMarkerArrivalState()
|
|
1109
1414
|
startCoordinate = NaviLatLng(startLat, startLng)
|
|
1110
1415
|
endCoordinate = NaviLatLng(endLat, endLng)
|
|
1111
1416
|
|
|
@@ -1150,9 +1455,11 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1150
1455
|
promise: expo.modules.kotlin.Promise
|
|
1151
1456
|
) {
|
|
1152
1457
|
try {
|
|
1458
|
+
resetCustomWaypointMarkerArrivalState()
|
|
1153
1459
|
val finalNaviType = requestedNaviType ?: naviType
|
|
1154
1460
|
val result = independentRouteManager.start(context, token, finalNaviType, routeId, routeIndex)
|
|
1155
1461
|
if (result.success) {
|
|
1462
|
+
activeIndependentRouteId = result.resolvedRouteId
|
|
1156
1463
|
promise.resolve(
|
|
1157
1464
|
mapOf(
|
|
1158
1465
|
"success" to true,
|
|
@@ -1166,9 +1473,11 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1166
1473
|
)
|
|
1167
1474
|
)
|
|
1168
1475
|
} else {
|
|
1476
|
+
activeIndependentRouteId = null
|
|
1169
1477
|
promise.reject("START_INDEPENDENT_NAVI_FAILED", result.message, null)
|
|
1170
1478
|
}
|
|
1171
1479
|
} catch (e: Exception) {
|
|
1480
|
+
activeIndependentRouteId = null
|
|
1172
1481
|
promise.reject("START_INDEPENDENT_NAVI_ERROR", e.message, e)
|
|
1173
1482
|
}
|
|
1174
1483
|
}
|
|
@@ -1176,6 +1485,9 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1176
1485
|
fun stopNavigation(promise: expo.modules.kotlin.Promise) {
|
|
1177
1486
|
try {
|
|
1178
1487
|
aMapNavi?.stopNavi()
|
|
1488
|
+
isNavigationRunning = false
|
|
1489
|
+
syncNavigationForegroundService("stop_navigation")
|
|
1490
|
+
resetCustomWaypointMarkerArrivalState()
|
|
1179
1491
|
promise.resolve(mapOf(
|
|
1180
1492
|
"success" to true,
|
|
1181
1493
|
"message" to "导航已停止"
|
|
@@ -1193,6 +1505,12 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1193
1505
|
}
|
|
1194
1506
|
}
|
|
1195
1507
|
|
|
1508
|
+
fun applyAndroidBackgroundNavigationNotificationEnabled(enabled: Boolean) {
|
|
1509
|
+
androidBackgroundNavigationNotificationEnabled = enabled
|
|
1510
|
+
Log.d("ExpoGaodeMapNaviView", "applyAndroidBackgroundNavigationNotificationEnabled=$enabled")
|
|
1511
|
+
syncNavigationForegroundService("prop_update")
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1196
1514
|
fun applyNaviType(type: Int) {
|
|
1197
1515
|
naviType = type
|
|
1198
1516
|
// 导航类型会在 startNavigation 时使用
|
|
@@ -1352,19 +1670,26 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1352
1670
|
}
|
|
1353
1671
|
|
|
1354
1672
|
fun applyNightMode(enabled: Boolean) {
|
|
1355
|
-
|
|
1673
|
+
mapViewModeTypeValue = if (enabled) 1 else 0
|
|
1356
1674
|
try {
|
|
1357
1675
|
commitViewOptions { options ->
|
|
1358
|
-
|
|
1359
|
-
options.setMapStyle(MapStyle.NIGHT, null)
|
|
1360
|
-
}else{
|
|
1361
|
-
options.setMapStyle(MapStyle.DAY, null)
|
|
1362
|
-
}
|
|
1676
|
+
applyMapViewModeTypeCompat(options, mapViewModeTypeValue)
|
|
1363
1677
|
}
|
|
1364
1678
|
} catch (e: Exception) {
|
|
1365
1679
|
Log.e("ExpoGaodeMapNaviView", "Failed to set night mode", e)
|
|
1366
1680
|
}
|
|
1367
1681
|
}
|
|
1682
|
+
|
|
1683
|
+
fun applyMapViewModeType(mode: Int) {
|
|
1684
|
+
mapViewModeTypeValue = mode
|
|
1685
|
+
try {
|
|
1686
|
+
commitViewOptions { options ->
|
|
1687
|
+
applyMapViewModeTypeCompat(options, mode)
|
|
1688
|
+
}
|
|
1689
|
+
} catch (e: Exception) {
|
|
1690
|
+
Log.e("ExpoGaodeMapNaviView", "Failed to apply mapViewModeType=$mode", e)
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1368
1693
|
|
|
1369
1694
|
/**
|
|
1370
1695
|
* 设置是否显示自车和罗盘
|
|
@@ -1385,11 +1710,21 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1385
1710
|
uri = uri,
|
|
1386
1711
|
getCurrentUri = { carImageUri },
|
|
1387
1712
|
setCurrentUri = { carImageUri = it },
|
|
1388
|
-
setBitmap = {
|
|
1713
|
+
setBitmap = {
|
|
1714
|
+
sourceCarBitmap = it
|
|
1715
|
+
customCarBitmap = resizeCarBitmapIfNeeded(it)
|
|
1716
|
+
},
|
|
1389
1717
|
reason = "carBitmap"
|
|
1390
1718
|
)
|
|
1391
1719
|
}
|
|
1392
1720
|
|
|
1721
|
+
fun applyCarImageSize(widthDp: Double?, heightDp: Double?) {
|
|
1722
|
+
carImageWidthDp = widthDp
|
|
1723
|
+
carImageHeightDp = heightDp
|
|
1724
|
+
customCarBitmap = resizeCarBitmapIfNeeded(sourceCarBitmap)
|
|
1725
|
+
refreshViewOptionsFromState("apply-carBitmap-size")
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1393
1728
|
fun applyFourCornersImage(uri: String?) {
|
|
1394
1729
|
updateCustomAnnotationBitmap(
|
|
1395
1730
|
uri = uri,
|
|
@@ -1430,6 +1765,140 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1430
1765
|
)
|
|
1431
1766
|
}
|
|
1432
1767
|
|
|
1768
|
+
fun applyCustomWaypointMarkers(markers: List<Map<String, Any?>>?) {
|
|
1769
|
+
customWaypointMarkers = markers?.mapNotNull { item ->
|
|
1770
|
+
val latitude = (item["latitude"] as? Number)?.toDouble() ?: return@mapNotNull null
|
|
1771
|
+
val longitude = (item["longitude"] as? Number)?.toDouble() ?: return@mapNotNull null
|
|
1772
|
+
val rawTitle = (item["title"] as? String)?.trim()
|
|
1773
|
+
NaviCustomWaypointMarkerModel(
|
|
1774
|
+
latitude = latitude,
|
|
1775
|
+
longitude = longitude,
|
|
1776
|
+
title = rawTitle?.takeIf { it.isNotEmpty() } ?: "途经"
|
|
1777
|
+
)
|
|
1778
|
+
} ?: emptyList()
|
|
1779
|
+
refreshCustomWaypointMarkers("apply-custom-waypoint-markers")
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
private fun clearRenderedCustomWaypointMarkers() {
|
|
1783
|
+
renderedCustomWaypointMarkers.forEach { marker ->
|
|
1784
|
+
try {
|
|
1785
|
+
marker.remove()
|
|
1786
|
+
} catch (_: Throwable) {
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
renderedCustomWaypointMarkers.clear()
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
private fun refreshCustomWaypointMarkers(reason: String) {
|
|
1793
|
+
Handler(Looper.getMainLooper()).post {
|
|
1794
|
+
clearRenderedCustomWaypointMarkers()
|
|
1795
|
+
if (isDestroyed || customWaypointMarkers.isEmpty()) {
|
|
1796
|
+
return@post
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
val map = try {
|
|
1800
|
+
naviView.map
|
|
1801
|
+
} catch (error: Throwable) {
|
|
1802
|
+
Log.w("ExpoGaodeMapNaviView", "Failed to access AMap for custom waypoint markers: $reason", error)
|
|
1803
|
+
null
|
|
1804
|
+
} ?: return@post
|
|
1805
|
+
|
|
1806
|
+
customWaypointMarkers.forEach { marker ->
|
|
1807
|
+
if (marker.arrived) {
|
|
1808
|
+
return@forEach
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
val bitmap = createCustomWaypointBubbleBitmap(marker.title)
|
|
1812
|
+
val options = MarkerOptions()
|
|
1813
|
+
.position(LatLng(marker.latitude, marker.longitude))
|
|
1814
|
+
.anchor(0.5f, 1f)
|
|
1815
|
+
.zIndex(130f)
|
|
1816
|
+
.icon(BitmapDescriptorFactory.fromBitmap(bitmap))
|
|
1817
|
+
val renderedMarker = map.addMarker(options)
|
|
1818
|
+
if (renderedMarker != null) {
|
|
1819
|
+
renderedCustomWaypointMarkers.add(renderedMarker)
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
private fun resetCustomWaypointMarkerArrivalState() {
|
|
1826
|
+
customWaypointMarkers = customWaypointMarkers.map { marker ->
|
|
1827
|
+
marker.copy(arrived = false)
|
|
1828
|
+
}
|
|
1829
|
+
refreshCustomWaypointMarkers("reset-custom-waypoint-arrival-state")
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
private fun markCustomWaypointArrived(rawIndex: Int) {
|
|
1833
|
+
if (customWaypointMarkers.isEmpty()) {
|
|
1834
|
+
return
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
val resolvedIndex = when {
|
|
1838
|
+
rawIndex in customWaypointMarkers.indices -> rawIndex
|
|
1839
|
+
(rawIndex - 1) in customWaypointMarkers.indices -> rawIndex - 1
|
|
1840
|
+
else -> null
|
|
1841
|
+
} ?: return
|
|
1842
|
+
|
|
1843
|
+
customWaypointMarkers = customWaypointMarkers.mapIndexed { index, marker ->
|
|
1844
|
+
if (index == resolvedIndex) marker.copy(arrived = true) else marker
|
|
1845
|
+
}
|
|
1846
|
+
refreshCustomWaypointMarkers("arrived-waypoint-$rawIndex")
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
private fun createCustomWaypointBubbleBitmap(title: String): Bitmap {
|
|
1850
|
+
val density = context.resources.displayMetrics.density
|
|
1851
|
+
val fontSize = 16f * density
|
|
1852
|
+
val horizontalPadding = 14f * density
|
|
1853
|
+
val bodyHeight = 34f * density
|
|
1854
|
+
val strokeWidth = 2.5f * density
|
|
1855
|
+
|
|
1856
|
+
val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
1857
|
+
color = Color.WHITE
|
|
1858
|
+
textSize = fontSize
|
|
1859
|
+
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
|
|
1860
|
+
textAlign = Paint.Align.CENTER
|
|
1861
|
+
}
|
|
1862
|
+
val bodyWidth = maxOf(
|
|
1863
|
+
62f * density,
|
|
1864
|
+
textPaint.measureText(title) + horizontalPadding * 2
|
|
1865
|
+
)
|
|
1866
|
+
val width = bodyWidth.roundToInt()
|
|
1867
|
+
val height = (bodyHeight + 2f * density).roundToInt()
|
|
1868
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
1869
|
+
val canvas = Canvas(bitmap)
|
|
1870
|
+
|
|
1871
|
+
val fillPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
1872
|
+
color = Color.parseColor("#2F67FF")
|
|
1873
|
+
style = Paint.Style.FILL
|
|
1874
|
+
}
|
|
1875
|
+
val strokePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
1876
|
+
color = Color.WHITE
|
|
1877
|
+
style = Paint.Style.STROKE
|
|
1878
|
+
this.strokeWidth = strokeWidth
|
|
1879
|
+
}
|
|
1880
|
+
val shadowPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
1881
|
+
color = Color.parseColor("#2D15357F")
|
|
1882
|
+
style = Paint.Style.FILL
|
|
1883
|
+
setShadowLayer(6f * density, 0f, 3f * density, Color.parseColor("#2D15357F"))
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
val bodyRect = RectF(
|
|
1887
|
+
strokeWidth,
|
|
1888
|
+
strokeWidth,
|
|
1889
|
+
width - strokeWidth,
|
|
1890
|
+
bodyHeight
|
|
1891
|
+
)
|
|
1892
|
+
val cornerRadius = 17f * density
|
|
1893
|
+
canvas.drawRoundRect(bodyRect, cornerRadius, cornerRadius, shadowPaint)
|
|
1894
|
+
canvas.drawRoundRect(bodyRect, cornerRadius, cornerRadius, fillPaint)
|
|
1895
|
+
canvas.drawRoundRect(bodyRect, cornerRadius, cornerRadius, strokePaint)
|
|
1896
|
+
|
|
1897
|
+
val textY = bodyRect.centerY() - (textPaint.descent() + textPaint.ascent()) / 2f
|
|
1898
|
+
canvas.drawText(title, bodyRect.centerX(), textY, textPaint)
|
|
1899
|
+
return bitmap
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1433
1902
|
|
|
1434
1903
|
/**
|
|
1435
1904
|
* 设置是否显示交通信号灯
|
|
@@ -1574,7 +2043,12 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1574
2043
|
return
|
|
1575
2044
|
}
|
|
1576
2045
|
isDestroyed = true
|
|
2046
|
+
isNavigationRunning = false
|
|
2047
|
+
isHostActivityInBackground = false
|
|
2048
|
+
latestNavigationNotificationSnapshot = null
|
|
2049
|
+
NavigationForegroundService.stop(context)
|
|
1577
2050
|
unregisterActiveView()
|
|
2051
|
+
clearRenderedCustomWaypointMarkers()
|
|
1578
2052
|
try {
|
|
1579
2053
|
naviView.onPause()
|
|
1580
2054
|
naviView.onDestroy()
|