expo-gaode-map-navigation 2.0.12-next.0 → 2.0.13
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 +296 -7
- package/android/build.gradle +12 -4
- package/android/src/main/AndroidManifest.xml +10 -1
- package/android/src/main/cpp/cluster_jni.cpp +56 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +49 -8
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +83 -15
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +13 -3
- package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +36 -39
- package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +23 -17
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +5 -2
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +122 -10
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +2 -2
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +37 -25
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +6 -6
- package/android/src/main/java/expo/modules/gaodemap/map/search/ExpoGaodeMapSearchModule.kt +751 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +103 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviView.kt +1408 -394
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviViewModule.kt +121 -1
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNavigationModule.kt +14 -28
- package/android/src/main/java/expo/modules/gaodemap/navigation/listeners/IndependentRouteListener.kt +28 -3
- package/android/src/main/java/expo/modules/gaodemap/navigation/listeners/RouteCalculateListener.kt +2 -2
- package/android/src/main/java/expo/modules/gaodemap/navigation/managers/IndependentRouteManager.kt +114 -15
- package/android/src/main/java/expo/modules/gaodemap/navigation/routes/drive/DriveTruckRouteCalculator.kt +24 -35
- package/android/src/main/java/expo/modules/gaodemap/navigation/services/IndependentRouteService.kt +50 -36
- 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 +21 -12
- package/android/src/main/res/drawable/ic_nav_notification_small.xml +10 -0
- package/android/src/main/res/drawable/landback_0.png +0 -0
- package/android/src/main/res/drawable/landback_1.png +0 -0
- package/android/src/main/res/drawable/landback_2.png +0 -0
- package/android/src/main/res/drawable/landback_3.png +0 -0
- package/android/src/main/res/drawable/landback_4.png +0 -0
- package/android/src/main/res/drawable/landback_5.png +0 -0
- package/android/src/main/res/drawable/landback_6.png +0 -0
- package/android/src/main/res/drawable/landback_7.png +0 -0
- package/android/src/main/res/drawable/landback_8.png +0 -0
- package/android/src/main/res/drawable/landback_9.png +0 -0
- package/android/src/main/res/drawable/landback_a.png +0 -0
- package/android/src/main/res/drawable/landback_b.png +0 -0
- package/android/src/main/res/drawable/landback_c.png +0 -0
- package/android/src/main/res/drawable/landback_d.png +0 -0
- package/android/src/main/res/drawable/landback_e.png +0 -0
- package/android/src/main/res/drawable/landback_f.png +0 -0
- package/android/src/main/res/drawable/landback_g.png +0 -0
- package/android/src/main/res/drawable/landback_h.png +0 -0
- package/android/src/main/res/drawable/landback_i.png +0 -0
- package/android/src/main/res/drawable/landback_j.png +0 -0
- package/android/src/main/res/drawable/landback_k.png +0 -0
- package/android/src/main/res/drawable/landback_l.png +0 -0
- package/android/src/main/res/drawable/landfront_0.png +0 -0
- package/android/src/main/res/drawable/landfront_00.png +0 -0
- package/android/src/main/res/drawable/landfront_1.png +0 -0
- package/android/src/main/res/drawable/landfront_11.png +0 -0
- package/android/src/main/res/drawable/landfront_20.png +0 -0
- package/android/src/main/res/drawable/landfront_21.png +0 -0
- package/android/src/main/res/drawable/landfront_22.png +0 -0
- package/android/src/main/res/drawable/landfront_3.png +0 -0
- package/android/src/main/res/drawable/landfront_33.png +0 -0
- package/android/src/main/res/drawable/landfront_40.png +0 -0
- package/android/src/main/res/drawable/landfront_43.png +0 -0
- package/android/src/main/res/drawable/landfront_44.png +0 -0
- package/android/src/main/res/drawable/landfront_5.png +0 -0
- package/android/src/main/res/drawable/landfront_55.png +0 -0
- package/android/src/main/res/drawable/landfront_61.png +0 -0
- package/android/src/main/res/drawable/landfront_63.png +0 -0
- package/android/src/main/res/drawable/landfront_66.png +0 -0
- package/android/src/main/res/drawable/landfront_70.png +0 -0
- package/android/src/main/res/drawable/landfront_71.png +0 -0
- package/android/src/main/res/drawable/landfront_73.png +0 -0
- package/android/src/main/res/drawable/landfront_77.png +0 -0
- package/android/src/main/res/drawable/landfront_8.png +0 -0
- package/android/src/main/res/drawable/landfront_88.png +0 -0
- package/android/src/main/res/drawable/landfront_90.png +0 -0
- package/android/src/main/res/drawable/landfront_95.png +0 -0
- package/android/src/main/res/drawable/landfront_99.png +0 -0
- package/android/src/main/res/drawable/landfront_a0.png +0 -0
- package/android/src/main/res/drawable/landfront_a8.png +0 -0
- package/android/src/main/res/drawable/landfront_aa.png +0 -0
- package/android/src/main/res/drawable/landfront_b1.png +0 -0
- package/android/src/main/res/drawable/landfront_b5.png +0 -0
- package/android/src/main/res/drawable/landfront_bb.png +0 -0
- package/android/src/main/res/drawable/landfront_c3.png +0 -0
- package/android/src/main/res/drawable/landfront_c8.png +0 -0
- package/android/src/main/res/drawable/landfront_cc.png +0 -0
- package/android/src/main/res/drawable/landfront_d.png +0 -0
- package/android/src/main/res/drawable/landfront_dd.png +0 -0
- package/android/src/main/res/drawable/landfront_e1.png +0 -0
- package/android/src/main/res/drawable/landfront_e5.png +0 -0
- package/android/src/main/res/drawable/landfront_ee.png +0 -0
- package/android/src/main/res/drawable/landfront_f0.png +0 -0
- package/android/src/main/res/drawable/landfront_f1.png +0 -0
- package/android/src/main/res/drawable/landfront_f5.png +0 -0
- package/android/src/main/res/drawable/landfront_ff.png +0 -0
- package/android/src/main/res/drawable/landfront_g3.png +0 -0
- package/android/src/main/res/drawable/landfront_g5.png +0 -0
- package/android/src/main/res/drawable/landfront_gg.png +0 -0
- package/android/src/main/res/drawable/landfront_h1.png +0 -0
- package/android/src/main/res/drawable/landfront_h3.png +0 -0
- package/android/src/main/res/drawable/landfront_h5.png +0 -0
- package/android/src/main/res/drawable/landfront_hh.png +0 -0
- package/android/src/main/res/drawable/landfront_i0.png +0 -0
- package/android/src/main/res/drawable/landfront_i3.png +0 -0
- package/android/src/main/res/drawable/landfront_i5.png +0 -0
- package/android/src/main/res/drawable/landfront_ii.png +0 -0
- package/android/src/main/res/drawable/landfront_j1.png +0 -0
- package/android/src/main/res/drawable/landfront_j8.png +0 -0
- package/android/src/main/res/drawable/landfront_jj.png +0 -0
- package/android/src/main/res/drawable/landfront_kk.png +0 -0
- package/android/src/main/res/drawable/landfront_ll.png +0 -0
- package/android/src/main/res/drawable/nav_notification_brand_icon.xml +16 -0
- package/android/src/main/res/drawable/navi_arrow_leftline.png +0 -0
- package/android/src/main/res/drawable/navi_lane_shape_bg_center.xml +5 -0
- package/android/src/main/res/drawable/navi_lane_shape_bg_left.xml +8 -0
- package/android/src/main/res/drawable/navi_lane_shape_bg_over.xml +6 -0
- package/android/src/main/res/drawable/navi_lane_shape_bg_right.xml +8 -0
- package/android/src/main/res/drawable-nodpi/nav_tracker_car.png +0 -0
- package/build/ExpoGaodeMapNaviView.d.ts +16 -0
- package/build/ExpoGaodeMapNaviView.d.ts.map +1 -1
- package/build/ExpoGaodeMapNaviView.js +74 -1
- package/build/ExpoGaodeMapNaviView.js.map +1 -1
- package/build/index.d.ts +56 -8
- package/build/index.d.ts.map +1 -1
- package/build/index.js +452 -10
- package/build/index.js.map +1 -1
- package/build/map/ExpoGaodeMapModule.d.ts +15 -13
- package/build/map/ExpoGaodeMapModule.d.ts.map +1 -1
- package/build/map/ExpoGaodeMapModule.js +31 -39
- package/build/map/ExpoGaodeMapModule.js.map +1 -1
- package/build/map/ExpoGaodeMapOfflineModule.d.ts +5 -0
- package/build/map/ExpoGaodeMapOfflineModule.d.ts.map +1 -1
- package/build/map/ExpoGaodeMapOfflineModule.js.map +1 -1
- package/build/map/ExpoGaodeMapView.d.ts +3 -4
- package/build/map/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/map/ExpoGaodeMapView.js +28 -25
- package/build/map/ExpoGaodeMapView.js.map +1 -1
- package/build/map/components/overlays/Circle.d.ts.map +1 -1
- package/build/map/components/overlays/Circle.js +1 -30
- package/build/map/components/overlays/Circle.js.map +1 -1
- package/build/map/components/overlays/Cluster.d.ts.map +1 -1
- package/build/map/components/overlays/Cluster.js +1 -42
- package/build/map/components/overlays/Cluster.js.map +1 -1
- package/build/map/components/overlays/HeatMap.d.ts.map +1 -1
- package/build/map/components/overlays/HeatMap.js +21 -21
- package/build/map/components/overlays/HeatMap.js.map +1 -1
- package/build/map/components/overlays/Marker.d.ts.map +1 -1
- package/build/map/components/overlays/Marker.js +76 -80
- package/build/map/components/overlays/Marker.js.map +1 -1
- package/build/map/components/overlays/Polygon.d.ts.map +1 -1
- package/build/map/components/overlays/Polygon.js +1 -25
- package/build/map/components/overlays/Polygon.js.map +1 -1
- package/build/map/components/overlays/Polyline.d.ts.map +1 -1
- package/build/map/components/overlays/Polyline.js +1 -31
- package/build/map/components/overlays/Polyline.js.map +1 -1
- package/build/map/index.d.ts +9 -2
- package/build/map/index.d.ts.map +1 -1
- package/build/map/index.js +9 -2
- package/build/map/index.js.map +1 -1
- package/build/map/search/ExpoGaodeMapSearch.types.d.ts +340 -0
- package/build/map/search/ExpoGaodeMapSearch.types.d.ts.map +1 -0
- package/build/map/search/ExpoGaodeMapSearch.types.js +19 -0
- package/build/map/search/ExpoGaodeMapSearch.types.js.map +1 -0
- package/build/map/search/ExpoGaodeMapSearchModule.d.ts +74 -0
- package/build/map/search/ExpoGaodeMapSearchModule.d.ts.map +1 -0
- package/build/map/search/ExpoGaodeMapSearchModule.js +47 -0
- package/build/map/search/ExpoGaodeMapSearchModule.js.map +1 -0
- package/build/map/search/index.d.ts +156 -0
- package/build/map/search/index.d.ts.map +1 -0
- package/build/map/search/index.js +171 -0
- package/build/map/search/index.js.map +1 -0
- package/build/map/types/index.d.ts +2 -2
- package/build/map/types/index.d.ts.map +1 -1
- package/build/map/types/index.js.map +1 -1
- package/build/map/types/map-view.types.d.ts +4 -2
- package/build/map/types/map-view.types.d.ts.map +1 -1
- package/build/map/types/map-view.types.js.map +1 -1
- package/build/map/types/native-module.types.d.ts +11 -12
- package/build/map/types/native-module.types.d.ts.map +1 -1
- package/build/map/types/native-module.types.js.map +1 -1
- package/build/map/types/overlays.types.d.ts +9 -14
- package/build/map/types/overlays.types.d.ts.map +1 -1
- package/build/map/types/overlays.types.js.map +1 -1
- package/build/map/types/route-playback.types.d.ts +16 -0
- package/build/map/types/route-playback.types.d.ts.map +1 -1
- package/build/map/types/route-playback.types.js.map +1 -1
- package/build/map/utils/ErrorHandler.js +11 -11
- package/build/map/utils/ErrorHandler.js.map +1 -1
- package/build/map/utils/OfflineMapManager.d.ts +4 -0
- package/build/map/utils/OfflineMapManager.d.ts.map +1 -1
- package/build/map/utils/OfflineMapManager.js +6 -0
- package/build/map/utils/OfflineMapManager.js.map +1 -1
- package/build/types/coordinates.types.d.ts +3 -0
- package/build/types/coordinates.types.d.ts.map +1 -1
- package/build/types/coordinates.types.js.map +1 -1
- package/build/types/independent.types.d.ts +111 -12
- package/build/types/independent.types.d.ts.map +1 -1
- package/build/types/independent.types.js.map +1 -1
- package/build/types/native-module.types.d.ts +1 -1
- package/build/types/native-module.types.js.map +1 -1
- package/build/types/naviview.types.d.ts +304 -14
- 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 +12 -2
- package/build/types/route.types.d.ts.map +1 -1
- package/build/types/route.types.js.map +1 -1
- package/expo-module.config.json +4 -2
- package/ios/ExpoGaodeMapNaviView.swift +2331 -201
- package/ios/ExpoGaodeMapNaviViewModule.swift +109 -1
- package/ios/ExpoGaodeMapNavigation.podspec +2 -1
- package/ios/ExpoGaodeMapNavigationModule.swift +7 -5
- package/ios/managers/IndependentRouteManager.swift +90 -26
- package/ios/map/ExpoGaodeMapModule.swift +72 -21
- package/ios/map/ExpoGaodeMapOfflineModule.swift +61 -0
- package/ios/map/ExpoGaodeMapSearchModule.swift +773 -0
- package/ios/map/ExpoGaodeMapView.swift +23 -5
- package/ios/map/GaodeMapPrivacyManager.swift +26 -18
- package/ios/map/cpp/GeometryEngine.cpp +112 -0
- package/ios/map/cpp/GeometryEngine.hpp +21 -0
- package/ios/map/modules/LocationManager.swift +37 -5
- package/ios/map/overlays/MarkerView.swift +11 -11
- package/ios/map/overlays/MarkerViewModule.swift +4 -4
- package/ios/map/overlays/PolylineView.swift +6 -12
- package/ios/map/utils/ClusterNative.h +8 -0
- package/ios/map/utils/ClusterNative.mm +27 -0
- package/ios/map/utils/PermissionManager.swift +115 -6
- package/ios/routes/drive/DriveTruckRouteCalculator.swift +165 -77
- package/ios/routes/walkride/WalkRideRouteCalculator.swift +127 -1
- package/ios/services/IndependentRouteService.swift +198 -39
- package/ios/services/NavigationLiveActivityAttributes.swift +48 -0
- package/ios/services/NavigationLiveActivityManager.swift +359 -0
- package/package.json +22 -7
- package/plugin/build/withGaodeMap.d.ts +8 -0
- package/plugin/build/withGaodeMap.js +60 -4
- package/scripts/check-expo-modules.js +68 -0
- package/shared/cpp/GeometryEngine.cpp +112 -0
- package/shared/cpp/GeometryEngine.hpp +21 -0
- package/widget-template/README.md +46 -0
- package/widget-template/ios/NavigationLiveActivityWidget.swift +367 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/managers/RouteCalculator.kt +0 -173
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
#if canImport(ActivityKit)
|
|
5
|
+
import ActivityKit
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
struct NavigationLiveActivitySnapshot {
|
|
9
|
+
let appName: String
|
|
10
|
+
let currentRoadName: String
|
|
11
|
+
let nextRoadName: String
|
|
12
|
+
let pathRetainDistance: Int
|
|
13
|
+
let routeTotalDistance: Int
|
|
14
|
+
let pathRetainTime: Int
|
|
15
|
+
let curStepRetainDistance: Int
|
|
16
|
+
let iconType: Int
|
|
17
|
+
let turnIconBase64: String?
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
final class NavigationLiveActivityManager {
|
|
21
|
+
static let shared = NavigationLiveActivityManager()
|
|
22
|
+
|
|
23
|
+
private var currentActivityId: String?
|
|
24
|
+
private var hasLoggedMissingPlistSupport = false
|
|
25
|
+
private var hasLoggedSystemDisabled = false
|
|
26
|
+
private var lastSnapshot: NavigationLiveActivitySnapshot?
|
|
27
|
+
private var autoStopWorkItem: DispatchWorkItem?
|
|
28
|
+
private var delayedStopWorkItem: DispatchWorkItem?
|
|
29
|
+
private let staleTimeoutSeconds: TimeInterval = 45
|
|
30
|
+
private let maxEstimatedContentStateBytes = 3900
|
|
31
|
+
private let maxRoadNameCharacters = 22
|
|
32
|
+
private let maxAppNameCharacters = 18
|
|
33
|
+
|
|
34
|
+
private init() {}
|
|
35
|
+
|
|
36
|
+
func startOrUpdate(snapshot: NavigationLiveActivitySnapshot) {
|
|
37
|
+
#if canImport(ActivityKit)
|
|
38
|
+
guard #available(iOS 16.1, *) else {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
guard supportsLiveActivityByPlist() else {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
guard ActivityAuthorizationInfo().areActivitiesEnabled else {
|
|
47
|
+
if !hasLoggedSystemDisabled {
|
|
48
|
+
hasLoggedSystemDisabled = true
|
|
49
|
+
NSLog("[ExpoGaodeMapNaviView][LiveActivity] Activities are disabled by system settings")
|
|
50
|
+
}
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
hasLoggedSystemDisabled = false
|
|
54
|
+
|
|
55
|
+
let normalizedSnapshot = NavigationLiveActivitySnapshot(
|
|
56
|
+
appName: snapshot.appName,
|
|
57
|
+
currentRoadName: snapshot.currentRoadName,
|
|
58
|
+
nextRoadName: snapshot.nextRoadName,
|
|
59
|
+
pathRetainDistance: max(snapshot.pathRetainDistance, 0),
|
|
60
|
+
routeTotalDistance: max(snapshot.routeTotalDistance, 0),
|
|
61
|
+
pathRetainTime: max(snapshot.pathRetainTime, 0),
|
|
62
|
+
curStepRetainDistance: max(snapshot.curStepRetainDistance, 0),
|
|
63
|
+
iconType: snapshot.iconType,
|
|
64
|
+
turnIconBase64: snapshot.turnIconBase64
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
let payloadSafeSnapshot = snapshotForPayloadBudget(from: normalizedSnapshot)
|
|
68
|
+
let contentState = makeContentState(from: payloadSafeSnapshot)
|
|
69
|
+
let attributes = NavigationLiveActivityAttributes(appName: payloadSafeSnapshot.appName)
|
|
70
|
+
|
|
71
|
+
if let activity = resolveCurrentActivity() {
|
|
72
|
+
lastSnapshot = payloadSafeSnapshot
|
|
73
|
+
Task {
|
|
74
|
+
if #available(iOS 16.2, *) {
|
|
75
|
+
let content = ActivityContent(state: contentState, staleDate: nil)
|
|
76
|
+
await activity.update(content)
|
|
77
|
+
} else {
|
|
78
|
+
await activity.update(using: contentState)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
scheduleAutoStop()
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
do {
|
|
86
|
+
let activity: Activity<NavigationLiveActivityAttributes>
|
|
87
|
+
if #available(iOS 16.2, *) {
|
|
88
|
+
let content = ActivityContent(state: contentState, staleDate: nil)
|
|
89
|
+
activity = try Activity.request(attributes: attributes, content: content, pushType: nil)
|
|
90
|
+
} else {
|
|
91
|
+
activity = try Activity.request(attributes: attributes, contentState: contentState, pushType: nil)
|
|
92
|
+
}
|
|
93
|
+
currentActivityId = activity.id
|
|
94
|
+
lastSnapshot = payloadSafeSnapshot
|
|
95
|
+
scheduleAutoStop()
|
|
96
|
+
} catch {
|
|
97
|
+
NSLog("[ExpoGaodeMapNaviView][LiveActivity] request failed: \(error.localizedDescription)")
|
|
98
|
+
}
|
|
99
|
+
#endif
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
func stop() {
|
|
103
|
+
#if canImport(ActivityKit)
|
|
104
|
+
cancelAutoStop()
|
|
105
|
+
cancelDelayedStop()
|
|
106
|
+
|
|
107
|
+
guard #available(iOS 16.1, *) else {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
guard let activity = resolveCurrentActivity() else {
|
|
112
|
+
currentActivityId = nil
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let fallbackSnapshot = lastSnapshot ?? NavigationLiveActivitySnapshot(
|
|
117
|
+
appName: "",
|
|
118
|
+
currentRoadName: "",
|
|
119
|
+
nextRoadName: "",
|
|
120
|
+
pathRetainDistance: 0,
|
|
121
|
+
routeTotalDistance: 0,
|
|
122
|
+
pathRetainTime: 0,
|
|
123
|
+
curStepRetainDistance: 0,
|
|
124
|
+
iconType: 0,
|
|
125
|
+
turnIconBase64: nil
|
|
126
|
+
)
|
|
127
|
+
let fallback = NavigationLiveActivityAttributes.ContentState(
|
|
128
|
+
currentRoadName: fallbackSnapshot.currentRoadName,
|
|
129
|
+
nextRoadName: fallbackSnapshot.nextRoadName,
|
|
130
|
+
pathRetainDistance: fallbackSnapshot.pathRetainDistance,
|
|
131
|
+
routeTotalDistance: fallbackSnapshot.routeTotalDistance,
|
|
132
|
+
pathRetainTime: fallbackSnapshot.pathRetainTime,
|
|
133
|
+
curStepRetainDistance: fallbackSnapshot.curStepRetainDistance,
|
|
134
|
+
iconType: fallbackSnapshot.iconType,
|
|
135
|
+
turnIconBase64: fallbackSnapshot.turnIconBase64,
|
|
136
|
+
updatedAt: Date()
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
Task {
|
|
140
|
+
if #available(iOS 16.2, *) {
|
|
141
|
+
let content = ActivityContent(state: fallback, staleDate: nil)
|
|
142
|
+
await activity.end(content, dismissalPolicy: .immediate)
|
|
143
|
+
} else {
|
|
144
|
+
await activity.end(using: fallback, dismissalPolicy: .immediate)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
currentActivityId = nil
|
|
149
|
+
lastSnapshot = nil
|
|
150
|
+
#endif
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
func showArrivedAndStop(snapshot: NavigationLiveActivitySnapshot, dismissAfter seconds: TimeInterval = 6) {
|
|
154
|
+
#if canImport(ActivityKit)
|
|
155
|
+
guard #available(iOS 16.1, *) else {
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
guard let activity = resolveCurrentActivity() else {
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
cancelAutoStop()
|
|
164
|
+
cancelDelayedStop()
|
|
165
|
+
|
|
166
|
+
let normalized = NavigationLiveActivitySnapshot(
|
|
167
|
+
appName: snapshot.appName,
|
|
168
|
+
currentRoadName: "",
|
|
169
|
+
nextRoadName: "",
|
|
170
|
+
pathRetainDistance: 0,
|
|
171
|
+
routeTotalDistance: max(snapshot.routeTotalDistance, 0),
|
|
172
|
+
pathRetainTime: 0,
|
|
173
|
+
curStepRetainDistance: 0,
|
|
174
|
+
iconType: 15,
|
|
175
|
+
turnIconBase64: nil
|
|
176
|
+
)
|
|
177
|
+
let payloadSafeSnapshot = snapshotForPayloadBudget(from: normalized)
|
|
178
|
+
let contentState = makeContentState(from: payloadSafeSnapshot)
|
|
179
|
+
lastSnapshot = payloadSafeSnapshot
|
|
180
|
+
|
|
181
|
+
Task {
|
|
182
|
+
if #available(iOS 16.2, *) {
|
|
183
|
+
let content = ActivityContent(state: contentState, staleDate: nil)
|
|
184
|
+
await activity.update(content)
|
|
185
|
+
} else {
|
|
186
|
+
await activity.update(using: contentState)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let delay = max(seconds, 1)
|
|
191
|
+
let workItem = DispatchWorkItem { [weak self] in
|
|
192
|
+
guard let self else {
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
NSLog(
|
|
196
|
+
"[ExpoGaodeMapNaviView][LiveActivity] arrived destination card displayed for %.0fs, stopping activity",
|
|
197
|
+
delay
|
|
198
|
+
)
|
|
199
|
+
self.stop()
|
|
200
|
+
}
|
|
201
|
+
delayedStopWorkItem = workItem
|
|
202
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem)
|
|
203
|
+
#endif
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private func scheduleAutoStop() {
|
|
207
|
+
cancelAutoStop()
|
|
208
|
+
let workItem = DispatchWorkItem { [weak self] in
|
|
209
|
+
guard let self else {
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
NSLog(
|
|
213
|
+
"[ExpoGaodeMapNaviView][LiveActivity] no updates for %.0fs, auto stopping activity",
|
|
214
|
+
self.staleTimeoutSeconds
|
|
215
|
+
)
|
|
216
|
+
self.stop()
|
|
217
|
+
}
|
|
218
|
+
autoStopWorkItem = workItem
|
|
219
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + staleTimeoutSeconds, execute: workItem)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private func cancelAutoStop() {
|
|
223
|
+
autoStopWorkItem?.cancel()
|
|
224
|
+
autoStopWorkItem = nil
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private func cancelDelayedStop() {
|
|
228
|
+
delayedStopWorkItem?.cancel()
|
|
229
|
+
delayedStopWorkItem = nil
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private func supportsLiveActivityByPlist() -> Bool {
|
|
233
|
+
let enabled = (Bundle.main.object(forInfoDictionaryKey: "NSSupportsLiveActivities") as? Bool) == true
|
|
234
|
+
if !enabled && !hasLoggedMissingPlistSupport {
|
|
235
|
+
hasLoggedMissingPlistSupport = true
|
|
236
|
+
NSLog("[ExpoGaodeMapNaviView][LiveActivity] NSSupportsLiveActivities is not enabled in Info.plist")
|
|
237
|
+
}
|
|
238
|
+
return enabled
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
#if canImport(ActivityKit)
|
|
242
|
+
@available(iOS 16.1, *)
|
|
243
|
+
private func makeContentState(from snapshot: NavigationLiveActivitySnapshot) -> NavigationLiveActivityAttributes.ContentState {
|
|
244
|
+
NavigationLiveActivityAttributes.ContentState(
|
|
245
|
+
currentRoadName: snapshot.currentRoadName,
|
|
246
|
+
nextRoadName: snapshot.nextRoadName,
|
|
247
|
+
pathRetainDistance: snapshot.pathRetainDistance,
|
|
248
|
+
routeTotalDistance: snapshot.routeTotalDistance,
|
|
249
|
+
pathRetainTime: snapshot.pathRetainTime,
|
|
250
|
+
curStepRetainDistance: snapshot.curStepRetainDistance,
|
|
251
|
+
iconType: snapshot.iconType,
|
|
252
|
+
turnIconBase64: snapshot.turnIconBase64,
|
|
253
|
+
updatedAt: Date()
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@available(iOS 16.1, *)
|
|
258
|
+
private func estimateContentStateSizeBytes(snapshot: NavigationLiveActivitySnapshot) -> Int {
|
|
259
|
+
let state = makeContentState(from: snapshot)
|
|
260
|
+
guard let encoded = try? JSONEncoder().encode(state) else {
|
|
261
|
+
return Int.max
|
|
262
|
+
}
|
|
263
|
+
return encoded.count
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private func truncateCharacters(_ value: String, maxCharacters: Int) -> String {
|
|
267
|
+
guard maxCharacters > 0, value.count > maxCharacters else {
|
|
268
|
+
return value
|
|
269
|
+
}
|
|
270
|
+
return String(value.prefix(maxCharacters))
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@available(iOS 16.1, *)
|
|
274
|
+
private func snapshotForPayloadBudget(from snapshot: NavigationLiveActivitySnapshot) -> NavigationLiveActivitySnapshot {
|
|
275
|
+
let originalEstimated = estimateContentStateSizeBytes(snapshot: snapshot)
|
|
276
|
+
var candidate = snapshot
|
|
277
|
+
var estimated = originalEstimated
|
|
278
|
+
if estimated <= maxEstimatedContentStateBytes {
|
|
279
|
+
return candidate
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Keep turn icon as long as possible; trim text first.
|
|
283
|
+
candidate = NavigationLiveActivitySnapshot(
|
|
284
|
+
appName: truncateCharacters(candidate.appName, maxCharacters: maxAppNameCharacters),
|
|
285
|
+
currentRoadName: truncateCharacters(candidate.currentRoadName, maxCharacters: maxRoadNameCharacters),
|
|
286
|
+
nextRoadName: truncateCharacters(candidate.nextRoadName, maxCharacters: maxRoadNameCharacters),
|
|
287
|
+
pathRetainDistance: candidate.pathRetainDistance,
|
|
288
|
+
routeTotalDistance: candidate.routeTotalDistance,
|
|
289
|
+
pathRetainTime: candidate.pathRetainTime,
|
|
290
|
+
curStepRetainDistance: candidate.curStepRetainDistance,
|
|
291
|
+
iconType: candidate.iconType,
|
|
292
|
+
turnIconBase64: candidate.turnIconBase64
|
|
293
|
+
)
|
|
294
|
+
estimated = estimateContentStateSizeBytes(snapshot: candidate)
|
|
295
|
+
if estimated <= maxEstimatedContentStateBytes {
|
|
296
|
+
NSLog(
|
|
297
|
+
"[ExpoGaodeMapNaviView][LiveActivity] payload %dB exceeds budget, trimmed text to %dB while keeping turn icon",
|
|
298
|
+
originalEstimated,
|
|
299
|
+
estimated
|
|
300
|
+
)
|
|
301
|
+
return candidate
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
let strippedText = NavigationLiveActivitySnapshot(
|
|
305
|
+
appName: truncateCharacters(candidate.appName, maxCharacters: maxAppNameCharacters),
|
|
306
|
+
currentRoadName: "",
|
|
307
|
+
nextRoadName: "",
|
|
308
|
+
pathRetainDistance: candidate.pathRetainDistance,
|
|
309
|
+
routeTotalDistance: candidate.routeTotalDistance,
|
|
310
|
+
pathRetainTime: candidate.pathRetainTime,
|
|
311
|
+
curStepRetainDistance: candidate.curStepRetainDistance,
|
|
312
|
+
iconType: candidate.iconType,
|
|
313
|
+
turnIconBase64: candidate.turnIconBase64
|
|
314
|
+
)
|
|
315
|
+
let strippedTextEstimated = estimateContentStateSizeBytes(snapshot: strippedText)
|
|
316
|
+
if strippedTextEstimated <= maxEstimatedContentStateBytes {
|
|
317
|
+
NSLog(
|
|
318
|
+
"[ExpoGaodeMapNaviView][LiveActivity] payload %dB exceeds budget, cleared road text to %dB while keeping turn icon",
|
|
319
|
+
originalEstimated,
|
|
320
|
+
strippedTextEstimated
|
|
321
|
+
)
|
|
322
|
+
return strippedText
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
let droppedIcon = NavigationLiveActivitySnapshot(
|
|
326
|
+
appName: strippedText.appName,
|
|
327
|
+
currentRoadName: strippedText.currentRoadName,
|
|
328
|
+
nextRoadName: strippedText.nextRoadName,
|
|
329
|
+
pathRetainDistance: strippedText.pathRetainDistance,
|
|
330
|
+
routeTotalDistance: strippedText.routeTotalDistance,
|
|
331
|
+
pathRetainTime: strippedText.pathRetainTime,
|
|
332
|
+
curStepRetainDistance: strippedText.curStepRetainDistance,
|
|
333
|
+
iconType: strippedText.iconType,
|
|
334
|
+
turnIconBase64: nil
|
|
335
|
+
)
|
|
336
|
+
let droppedIconEstimated = estimateContentStateSizeBytes(snapshot: droppedIcon)
|
|
337
|
+
NSLog(
|
|
338
|
+
"[ExpoGaodeMapNaviView][LiveActivity] payload still too large after text trim (%dB), dropped turn icon to %dB",
|
|
339
|
+
strippedTextEstimated,
|
|
340
|
+
droppedIconEstimated
|
|
341
|
+
)
|
|
342
|
+
return droppedIcon
|
|
343
|
+
}
|
|
344
|
+
#endif
|
|
345
|
+
|
|
346
|
+
#if canImport(ActivityKit)
|
|
347
|
+
@available(iOS 16.1, *)
|
|
348
|
+
private func resolveCurrentActivity() -> Activity<NavigationLiveActivityAttributes>? {
|
|
349
|
+
if let id = currentActivityId,
|
|
350
|
+
let matched = Activity<NavigationLiveActivityAttributes>.activities.first(where: { $0.id == id }) {
|
|
351
|
+
return matched
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
let first = Activity<NavigationLiveActivityAttributes>.activities.first
|
|
355
|
+
currentActivityId = first?.id
|
|
356
|
+
return first
|
|
357
|
+
}
|
|
358
|
+
#endif
|
|
359
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-gaode-map-navigation",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.13",
|
|
4
|
+
"description": "React Native AMap (Gaode Map) navigation module for Expo: route planning and turn-by-turn navigation, includes full map features.",
|
|
5
5
|
"author": "TomWq <582752848@qq.com> (https://github.com/TomWq)",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -17,22 +17,26 @@
|
|
|
17
17
|
"lint": "expo-module lint",
|
|
18
18
|
"test": "expo-module test",
|
|
19
19
|
"prepare": "expo-module prepare && yarn build:plugin",
|
|
20
|
+
"postinstall": "node scripts/check-expo-modules.js",
|
|
20
21
|
"prepublishOnly": "echo 'Skipping proofread check' && exit 0",
|
|
21
22
|
"expo-module": "expo-module",
|
|
22
23
|
"android": "expo run:android",
|
|
23
24
|
"ios": "expo run:ios"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
27
|
+
"@expo/vector-icons": "^15.0.3",
|
|
26
28
|
"@types/react": "~19.1.0",
|
|
27
|
-
"expo": "^
|
|
28
|
-
"expo-module-scripts": "^
|
|
29
|
-
"react-native": "0.
|
|
29
|
+
"expo": "^55.0.8",
|
|
30
|
+
"expo-module-scripts": "^55.0.2",
|
|
31
|
+
"react-native": "0.83.2",
|
|
30
32
|
"typescript": "^5.9.3"
|
|
31
33
|
},
|
|
32
34
|
"peerDependencies": {
|
|
35
|
+
"@expo/vector-icons": "*",
|
|
33
36
|
"expo": "*",
|
|
34
37
|
"react": "*",
|
|
35
|
-
"react-native": "*"
|
|
38
|
+
"react-native": "*",
|
|
39
|
+
"react-native-safe-area-context": "*"
|
|
36
40
|
},
|
|
37
41
|
"peerDependenciesMeta": {
|
|
38
42
|
"expo": {
|
|
@@ -46,7 +50,9 @@
|
|
|
46
50
|
"build",
|
|
47
51
|
"android",
|
|
48
52
|
"ios",
|
|
53
|
+
"widget-template",
|
|
49
54
|
"shared",
|
|
55
|
+
"scripts",
|
|
50
56
|
"app.plugin.js",
|
|
51
57
|
"expo-module.config.json",
|
|
52
58
|
"plugin/build"
|
|
@@ -56,11 +62,20 @@
|
|
|
56
62
|
"react-native",
|
|
57
63
|
"expo",
|
|
58
64
|
"expo-gaode-map",
|
|
65
|
+
"expo-gaode-map-navigation",
|
|
66
|
+
"expo-amap",
|
|
67
|
+
"react-native-amap",
|
|
68
|
+
"react-native-gaode-map",
|
|
69
|
+
"rn-amap-navigation",
|
|
59
70
|
"amap",
|
|
71
|
+
"gaode-map",
|
|
60
72
|
"navigation",
|
|
73
|
+
"route-planning",
|
|
74
|
+
"turn-by-turn",
|
|
61
75
|
"route",
|
|
62
76
|
"高德地图",
|
|
63
|
-
"导航"
|
|
77
|
+
"导航",
|
|
78
|
+
"路径规划"
|
|
64
79
|
],
|
|
65
80
|
"license": "MIT"
|
|
66
81
|
}
|
|
@@ -13,6 +13,14 @@ export type GaodeMapPluginProps = {
|
|
|
13
13
|
locationDescription?: string;
|
|
14
14
|
/** 是否启用后台定位(Android & iOS) */
|
|
15
15
|
enableBackgroundLocation?: boolean;
|
|
16
|
+
/** iOS 是否启用后台音频(用于后台导航语音播报) */
|
|
17
|
+
enableBackgroundAudio?: boolean;
|
|
18
|
+
/** 是否启用后台导航常驻通知(Android) */
|
|
19
|
+
enableNavigationNotification?: boolean;
|
|
20
|
+
/** 是否启用 iOS Live Activity(锁屏/灵动岛) */
|
|
21
|
+
enableIOSLiveActivity?: boolean;
|
|
22
|
+
/** 是否启用 iOS Live Activity 高频更新能力 */
|
|
23
|
+
enableIOSLiveActivityFrequentUpdates?: boolean;
|
|
16
24
|
/**
|
|
17
25
|
* 自定义高德地图 SDK 路径(例如 Google Play 版本)
|
|
18
26
|
* 相对于项目根目录的路径,例如 "./libs/AMap_3DMap_V9.0.0_GooglePlay.aar"
|
|
@@ -27,8 +27,19 @@ const withGaodeMapInfoPlist = (config, props) => {
|
|
|
27
27
|
if (!config.modResults.UIBackgroundModes.includes('location')) {
|
|
28
28
|
config.modResults.UIBackgroundModes.push('location');
|
|
29
29
|
}
|
|
30
|
+
const shouldEnableBackgroundAudio = props.enableBackgroundAudio ?? true;
|
|
31
|
+
if (shouldEnableBackgroundAudio && !config.modResults.UIBackgroundModes.includes('audio')) {
|
|
32
|
+
config.modResults.UIBackgroundModes.push('audio');
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
35
|
}
|
|
36
|
+
if (props.enableIOSLiveActivity !== undefined) {
|
|
37
|
+
config.modResults.NSSupportsLiveActivities = !!props.enableIOSLiveActivity;
|
|
38
|
+
}
|
|
39
|
+
if (props.enableIOSLiveActivityFrequentUpdates !== undefined) {
|
|
40
|
+
config.modResults.NSSupportsLiveActivitiesFrequentUpdates =
|
|
41
|
+
!!props.enableIOSLiveActivityFrequentUpdates;
|
|
42
|
+
}
|
|
32
43
|
return config;
|
|
33
44
|
});
|
|
34
45
|
};
|
|
@@ -54,6 +65,7 @@ const withGaodeMapAndroidManifest = (config, props) => {
|
|
|
54
65
|
'android.permission.ACCESS_NETWORK_STATE',
|
|
55
66
|
'android.permission.ACCESS_WIFI_STATE',
|
|
56
67
|
'android.permission.READ_PHONE_STATE',
|
|
68
|
+
'android.permission.WAKE_LOCK',
|
|
57
69
|
'android.permission.BLUETOOTH',
|
|
58
70
|
'android.permission.BLUETOOTH_ADMIN',
|
|
59
71
|
];
|
|
@@ -68,8 +80,9 @@ const withGaodeMapAndroidManifest = (config, props) => {
|
|
|
68
80
|
});
|
|
69
81
|
}
|
|
70
82
|
});
|
|
71
|
-
|
|
72
|
-
|
|
83
|
+
const requiresForegroundLocationService = props.enableBackgroundLocation || props.enableNavigationNotification;
|
|
84
|
+
// 后台定位/导航前台服务权限(可选)
|
|
85
|
+
if (requiresForegroundLocationService) {
|
|
73
86
|
const backgroundPermissions = [
|
|
74
87
|
'android.permission.ACCESS_BACKGROUND_LOCATION',
|
|
75
88
|
'android.permission.FOREGROUND_SERVICE',
|
|
@@ -87,6 +100,21 @@ const withGaodeMapAndroidManifest = (config, props) => {
|
|
|
87
100
|
}
|
|
88
101
|
});
|
|
89
102
|
}
|
|
103
|
+
// Android 13+ 通知权限(仅在启用导航常驻通知时添加)
|
|
104
|
+
if (props.enableNavigationNotification) {
|
|
105
|
+
const notificationPermissions = [
|
|
106
|
+
'android.permission.POST_NOTIFICATIONS',
|
|
107
|
+
'android.permission.POST_PROMOTED_NOTIFICATIONS',
|
|
108
|
+
];
|
|
109
|
+
notificationPermissions.forEach((permission) => {
|
|
110
|
+
const hasPermission = androidManifest['uses-permission']?.some((item) => item.$?.['android:name'] === permission);
|
|
111
|
+
if (!hasPermission) {
|
|
112
|
+
androidManifest['uses-permission']?.push({
|
|
113
|
+
$: { 'android:name': permission },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
90
118
|
// 添加前台服务(如果启用后台定位)
|
|
91
119
|
const mainApplication = androidManifest.application?.[0];
|
|
92
120
|
if (mainApplication && props.enableBackgroundLocation) {
|
|
@@ -94,11 +122,27 @@ const withGaodeMapAndroidManifest = (config, props) => {
|
|
|
94
122
|
mainApplication['service'] = [];
|
|
95
123
|
}
|
|
96
124
|
// 检查是否已存在 LocationForegroundService
|
|
97
|
-
const hasService = mainApplication['service'].some((item) => item.$?.['android:name'] === 'expo.modules.gaodemap.services.LocationForegroundService');
|
|
125
|
+
const hasService = mainApplication['service'].some((item) => item.$?.['android:name'] === 'expo.modules.gaodemap.map.services.LocationForegroundService');
|
|
98
126
|
if (!hasService) {
|
|
99
127
|
mainApplication['service'].push({
|
|
100
128
|
$: {
|
|
101
|
-
'android:name': 'expo.modules.gaodemap.services.LocationForegroundService',
|
|
129
|
+
'android:name': 'expo.modules.gaodemap.map.services.LocationForegroundService',
|
|
130
|
+
'android:enabled': 'true',
|
|
131
|
+
'android:exported': 'false',
|
|
132
|
+
'android:foregroundServiceType': 'location',
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (mainApplication && props.enableNavigationNotification) {
|
|
138
|
+
if (!mainApplication['service']) {
|
|
139
|
+
mainApplication['service'] = [];
|
|
140
|
+
}
|
|
141
|
+
const hasNavigationService = mainApplication['service'].some((item) => item.$?.['android:name'] === 'expo.modules.gaodemap.navigation.services.NavigationForegroundService');
|
|
142
|
+
if (!hasNavigationService) {
|
|
143
|
+
mainApplication['service'].push({
|
|
144
|
+
$: {
|
|
145
|
+
'android:name': 'expo.modules.gaodemap.navigation.services.NavigationForegroundService',
|
|
102
146
|
'android:enabled': 'true',
|
|
103
147
|
'android:exported': 'false',
|
|
104
148
|
'android:foregroundServiceType': 'location',
|
|
@@ -192,6 +236,18 @@ configurations.all {
|
|
|
192
236
|
*/
|
|
193
237
|
const withGaodeMapAndroidSdk = (config, props) => {
|
|
194
238
|
return (0, config_plugins_1.withGradleProperties)(config, (config) => {
|
|
239
|
+
const jetifierKey = 'android.enableJetifier';
|
|
240
|
+
const jetifier = config.modResults.find((item) => item.type === 'property' && item.key === jetifierKey);
|
|
241
|
+
if (jetifier && jetifier.type === 'property') {
|
|
242
|
+
jetifier.value = 'true';
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
config.modResults.push({
|
|
246
|
+
type: 'property',
|
|
247
|
+
key: jetifierKey,
|
|
248
|
+
value: 'true',
|
|
249
|
+
});
|
|
250
|
+
}
|
|
195
251
|
if (props.customMapSdkPath) {
|
|
196
252
|
const key = 'EXPO_GAODE_MAP_CUSTOM_SDK_PATH';
|
|
197
253
|
const existing = config.modResults.find((item) => item.type === 'property' && item.key === key);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
function resolveProjectRoot() {
|
|
7
|
+
return process.env.INIT_CWD || process.env.npm_config_local_prefix || process.cwd();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function hasPackage(pkgName, projectRoot) {
|
|
11
|
+
try {
|
|
12
|
+
require.resolve(`${pkgName}/package.json`, { paths: [projectRoot] });
|
|
13
|
+
return true;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function printWarning(lines) {
|
|
20
|
+
const prefix = '[expo-gaode-map-navigation]';
|
|
21
|
+
console.warn(`${prefix} WARNING: Expo Modules infrastructure was not detected in this React Native project.`);
|
|
22
|
+
for (const line of lines) {
|
|
23
|
+
console.warn(`${prefix} ${line}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function main() {
|
|
28
|
+
const projectRoot = resolveProjectRoot();
|
|
29
|
+
|
|
30
|
+
// Skip non-React Native consumers.
|
|
31
|
+
if (!hasPackage('react-native', projectRoot)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const hasExpo = hasPackage('expo', projectRoot);
|
|
36
|
+
const hasExpoModulesCore = hasPackage('expo-modules-core', projectRoot);
|
|
37
|
+
const podfilePath = path.join(projectRoot, 'ios', 'Podfile');
|
|
38
|
+
const hasPodfile = fs.existsSync(podfilePath);
|
|
39
|
+
const hasUseExpoModules = hasPodfile
|
|
40
|
+
? /\buse_expo_modules!\b/m.test(fs.readFileSync(podfilePath, 'utf8'))
|
|
41
|
+
: true;
|
|
42
|
+
|
|
43
|
+
if (hasExpo && hasExpoModulesCore && hasUseExpoModules) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const details = [];
|
|
48
|
+
if (!hasExpo) {
|
|
49
|
+
details.push('Missing dependency: expo');
|
|
50
|
+
}
|
|
51
|
+
if (!hasExpoModulesCore) {
|
|
52
|
+
details.push('Missing dependency: expo-modules-core');
|
|
53
|
+
}
|
|
54
|
+
if (!hasUseExpoModules) {
|
|
55
|
+
details.push('iOS Podfile does not contain use_expo_modules!');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
printWarning([
|
|
59
|
+
...details,
|
|
60
|
+
'This package requires Expo Modules infrastructure even in bare React Native apps.',
|
|
61
|
+
'Suggested fix:',
|
|
62
|
+
' npx install-expo-modules@latest',
|
|
63
|
+
hasPodfile ? ' (then) cd ios && pod install' : null,
|
|
64
|
+
'Docs: https://docs.expo.dev/bare/installing-expo-modules/',
|
|
65
|
+
].filter(Boolean));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
main();
|