expo-gaode-map-navigation 2.0.12-next.0 → 2.0.12
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 +289 -5
- package/android/build.gradle +4 -0
- package/android/src/main/AndroidManifest.xml +2 -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/modules/SDKInitializer.kt +23 -17
- 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/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/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 +1 -20
- 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 +6 -2
- package/build/map/index.d.ts.map +1 -1
- package/build/map/index.js +6 -2
- package/build/map/index.js.map +1 -1
- 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/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/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/ios/ExpoGaodeMapNaviView.swift +2335 -204
- package/ios/ExpoGaodeMapNaviViewModule.swift +109 -1
- package/ios/ExpoGaodeMapNavigationModule.swift +7 -5
- package/ios/managers/IndependentRouteManager.swift +90 -26
- package/ios/map/ExpoGaodeMapModule.swift +72 -21
- 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 +28 -2
- package/ios/map/overlays/MarkerView.swift +11 -11
- package/ios/map/overlays/MarkerViewModule.swift +4 -4
- 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 +48 -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/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- 🗺️ **地图渲染**:内置完整地图能力,支持 Marker、Polyline、Polygon、Circle、Cluster、HeatMap 等覆盖物。
|
|
8
8
|
- 🚗 **多模式路径规划**:支持驾车、步行、骑行、电动车、货车、摩托车等多种出行方式。
|
|
9
|
-
- 🧭 **实时导航 UI**:提供 `NaviView`
|
|
9
|
+
- 🧭 **实时导航 UI**:提供 `NaviView` 官方嵌入视图,并暴露完整事件与原生参数,方便你自行定制导航界面。
|
|
10
10
|
- 🛣️ **独立路径规划**:支持“先算路、再导航”的高级模式,可实现多路线对比与选择。
|
|
11
11
|
- ⚙️ **策略丰富**:支持速度优先、避让拥堵、少收费、不走高速等多种算路策略。
|
|
12
12
|
- ✅ **开箱即用**:封装了 Android/iOS 原生导航 SDK,统一 JS 接口。
|
|
@@ -29,6 +29,13 @@ npm install expo-gaode-map-navigation
|
|
|
29
29
|
**⚠️ 重要提示:**
|
|
30
30
|
如果项目中已安装 `expo-gaode-map`,请务必先卸载,否则会导致 Android 端二进制冲突(`3dmap` vs `navi-3dmap`)。`expo-gaode-map` 和 `expo-gaode-map-navigation` 由于 SDK 冲突不能同时安装,二选一使用。
|
|
31
31
|
|
|
32
|
+
> ⚠️ **版本兼容性说明**:
|
|
33
|
+
> - 如果你的项目使用 **Expo SDK 54 及以上**,请安装 默认的 版本。
|
|
34
|
+
> - 如果你的项目使用 **Expo SDK 53 及以下**(如 50, 51, 52, 53),请使用 **V1** 版本(Tag: `v1`)。
|
|
35
|
+
> ```bash
|
|
36
|
+
> npm install expo-gaode-map-navigation@1.1.8
|
|
37
|
+
> ```
|
|
38
|
+
|
|
32
39
|
|
|
33
40
|
### Config Plugin 配置(推荐)
|
|
34
41
|
|
|
@@ -42,7 +49,12 @@ npm install expo-gaode-map-navigation
|
|
|
42
49
|
"expo-gaode-map-navigation",
|
|
43
50
|
{
|
|
44
51
|
"androidKey": "your-android-key",
|
|
45
|
-
"iosKey": "your-ios-key"
|
|
52
|
+
"iosKey": "your-ios-key",
|
|
53
|
+
"enableBackgroundLocation": true,
|
|
54
|
+
"enableBackgroundAudio": true,
|
|
55
|
+
"enableNavigationNotification": true,
|
|
56
|
+
"enableIOSLiveActivity": true,
|
|
57
|
+
"enableIOSLiveActivityFrequentUpdates": true
|
|
46
58
|
}
|
|
47
59
|
]
|
|
48
60
|
]
|
|
@@ -57,6 +69,68 @@ npx expo run:android
|
|
|
57
69
|
npx expo run:ios
|
|
58
70
|
```
|
|
59
71
|
|
|
72
|
+
说明:
|
|
73
|
+
|
|
74
|
+
- `enableNavigationNotification` 仅 Android 生效,用于注入导航前台通知所需权限与 `NavigationForegroundService` 声明。
|
|
75
|
+
- `enableBackgroundAudio` 仅 iOS 生效(默认随 `enableBackgroundLocation` 自动开启),用于注入 `UIBackgroundModes: audio`,保障后台导航语音持续播报。
|
|
76
|
+
- `enableIOSLiveActivity` 仅 iOS 生效,用于注入 `NSSupportsLiveActivities`。
|
|
77
|
+
- `enableIOSLiveActivityFrequentUpdates` 仅 iOS 生效,用于注入 `NSSupportsLiveActivitiesFrequentUpdates`。
|
|
78
|
+
- 运行时还需要在 `NaviView` 里显式传 `androidBackgroundNavigationNotificationEnabled={true}` 才会在应用退到后台后显示导航常驻通知。
|
|
79
|
+
- iOS 运行时还需要在 `NaviView` 里显式传 `iosLiveActivityEnabled={true}` 才会持续更新 Live Activity。
|
|
80
|
+
|
|
81
|
+
## 示例工程
|
|
82
|
+
|
|
83
|
+
仓库内提供了可直接运行的 [`example-navigation`](/Volumes/xinxin/expo-gaode-map/example-navigation/README.md) 示例工程,专门用于验证导航能力。
|
|
84
|
+
|
|
85
|
+
推荐场景:
|
|
86
|
+
|
|
87
|
+
- 调试 `NaviView` 与示例工程里的自定义 HUD / 车道 HUD / 路况光柱
|
|
88
|
+
- 对比官方黑盒页、官方嵌入式页、自绘嵌入式页
|
|
89
|
+
- 验证独立算路、多路线选择、近似跟线导航
|
|
90
|
+
|
|
91
|
+
快速运行:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cd example-navigation
|
|
95
|
+
cp .env.example .env
|
|
96
|
+
npm install
|
|
97
|
+
npx expo run:android
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
如需 iOS:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
cd example-navigation
|
|
104
|
+
cp .env.example .env
|
|
105
|
+
npm install
|
|
106
|
+
npx pod-install ios
|
|
107
|
+
npx expo run:ios
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### iOS Live Activity Widget Extension
|
|
111
|
+
|
|
112
|
+
`iosLiveActivityEnabled` 只负责从导航回调里请求/更新 ActivityKit 状态。
|
|
113
|
+
真正显示在锁屏/灵动岛的 UI,需要你在 App 里提供 Widget Extension 的 `ActivityConfiguration`。
|
|
114
|
+
|
|
115
|
+
仓库已提供模板:
|
|
116
|
+
|
|
117
|
+
- [`packages/navigation/widget-template/README.md`](/Volumes/xinxin/expo-gaode-map/packages/navigation/widget-template/README.md)
|
|
118
|
+
- [`packages/navigation/widget-template/ios/NavigationLiveActivityWidget.swift`](/Volumes/xinxin/expo-gaode-map/packages/navigation/widget-template/ios/NavigationLiveActivityWidget.swift)
|
|
119
|
+
|
|
120
|
+
模板里直接使用库导出的 `NavigationLiveActivityAttributes`(`import ExpoGaodeMapNavigation`)。
|
|
121
|
+
|
|
122
|
+
#### iOS Live Activity 行为说明(补充)
|
|
123
|
+
|
|
124
|
+
- 导航进行中会持续推送实时状态到锁屏/灵动岛(前提是已启用 `iosLiveActivityEnabled` 且 Widget Extension 配置正确)。
|
|
125
|
+
- 到达目的地后,模块会先更新卡片为“到达目的地”,再延时约 6 秒自动结束 Live Activity。
|
|
126
|
+
- 为避免 ActivityKit `Payload maximum size exceeded`:
|
|
127
|
+
- 模块会优先保留转向图标,先裁剪文案字段;
|
|
128
|
+
- 如仍超限,才会降级去掉图标,确保状态更新不中断。
|
|
129
|
+
- 调试日志关键字:
|
|
130
|
+
- `payload ... keeping turn icon`
|
|
131
|
+
- `payload still too large ... dropped turn icon`
|
|
132
|
+
- `arrived destination card displayed for ... stopping activity`
|
|
133
|
+
|
|
60
134
|
|
|
61
135
|
## 快速开始
|
|
62
136
|
|
|
@@ -122,12 +196,30 @@ export default function NavigationScreen() {
|
|
|
122
196
|
style={{ flex: 1 }}
|
|
123
197
|
showCamera={true} // 显示摄像头
|
|
124
198
|
enableVoice={true} // 开启语音
|
|
199
|
+
androidBackgroundNavigationNotificationEnabled={true} // Android 后台导航常驻通知(需配合插件 enableNavigationNotification)
|
|
200
|
+
iosLiveActivityEnabled={true} // iOS Live Activity 状态更新(需配合插件 enableIOSLiveActivity + Widget Extension)
|
|
125
201
|
/>
|
|
126
202
|
</View>
|
|
127
203
|
);
|
|
128
204
|
}
|
|
129
205
|
```
|
|
130
206
|
|
|
207
|
+
### 3. 自定义嵌入式导航 UI
|
|
208
|
+
|
|
209
|
+
如果你要做“嵌入在自己页面里的导航页”,库本身提供的是底层 `NaviView`、导航事件和原生参数;完整的自定义 HUD / 车道 HUD / 路况光柱参考实现,已经迁移到仓库内的 [`example-navigation`](/Volumes/xinxin/expo-gaode-map/example-navigation/README.md)。
|
|
210
|
+
|
|
211
|
+
建议做法:
|
|
212
|
+
|
|
213
|
+
- 用 `NaviView` 负责底层导航地图、语音、车道事件、路况事件、路口大图事件
|
|
214
|
+
- 用 `onNaviInfoUpdate`、`onLaneInfoUpdate`、`onTrafficStatusesUpdate`、`onNaviVisualStateChange` 在业务侧自绘 HUD
|
|
215
|
+
- 直接参考 `example-navigation/lib/navigation-ui/EmbeddedNaviView.tsx` 及配套 UI 文件,按你的产品需求裁剪
|
|
216
|
+
|
|
217
|
+
注意:
|
|
218
|
+
|
|
219
|
+
- Android 官方嵌入式 `NaviView` 在部分 React Native / Expo 宿主中,顶部信息区、车道条、路口大图联动效果可能与高德官方 Demo 不完全一致
|
|
220
|
+
- 如果你要验证官方嵌入式 UI 本身,请直接跑 `example-navigation` 里的 `official-embedded` 示例页
|
|
221
|
+
- 如果你要交付稳定的嵌入式导航页,建议以示例工程里的“自定义 UI 导航界面”作为起点
|
|
222
|
+
|
|
131
223
|
## 详细用法
|
|
132
224
|
|
|
133
225
|
### 路径规划 (API)
|
|
@@ -145,12 +237,26 @@ const result = await calculateRoute({
|
|
|
145
237
|
to: { latitude: 39.91, longitude: 116.41 },
|
|
146
238
|
strategy: DriveStrategy.FASTEST, // 速度优先
|
|
147
239
|
avoidRoad: '京通快速路', // 避让道路名称
|
|
240
|
+
avoidPolygons: [
|
|
241
|
+
[
|
|
242
|
+
{ latitude: 39.905, longitude: 116.395 },
|
|
243
|
+
{ latitude: 39.905, longitude: 116.405 },
|
|
244
|
+
{ latitude: 39.915, longitude: 116.405 },
|
|
245
|
+
{ latitude: 39.915, longitude: 116.395 },
|
|
246
|
+
],
|
|
247
|
+
],
|
|
148
248
|
});
|
|
149
249
|
|
|
150
250
|
console.log(`总距离: ${result.routes[0].distance}米`);
|
|
151
251
|
console.log(`预计耗时: ${result.routes[0].duration}秒`);
|
|
152
252
|
```
|
|
153
253
|
|
|
254
|
+
说明:
|
|
255
|
+
|
|
256
|
+
- 当传入 `avoidRoad` 或 `avoidPolygons` 时,`calculateRoute` / `calculateDriveRoute` 会优先尝试通过 `expo-gaode-map-web-api` 获取官方“规避后路线预览”结果。
|
|
257
|
+
- 该回退仅用于路线预览与地图绘制;Web API 返回的是 polyline,不是导航 SDK 可直接启动的 `routeGroup/path`。
|
|
258
|
+
- 如果未安装 `expo-gaode-map-web-api`,则保持原有原生驾车算路逻辑不变。Android 仍可能命中底层 SDK 的避让重载;iOS 则没有官方导航 SDK 接口可直接消费任意规避道路/区域。
|
|
259
|
+
|
|
154
260
|
#### 步行/骑行路径规划
|
|
155
261
|
|
|
156
262
|
```typescript
|
|
@@ -192,6 +298,8 @@ const truckResult = await calculateRoute({
|
|
|
192
298
|
|
|
193
299
|
“独立路径规划”允许你先计算路线,并在地图上展示多条方案,用户选择其中一条后再开始导航。这通常比直接开始导航体验更好。
|
|
194
300
|
|
|
301
|
+
注意:`independentDriveRoute` 仍然依赖导航 SDK 自身的独立算路能力,因此这里不接 Web API 的规避预览结果。`avoidRoad` / `avoidPolygons` 不再作为 `IndependentDriveRouteOptions` 的标准公开参数暴露。若你需要“规避道路/区域后再开始导航”,建议先用 `calculateRoute` 做预览与确认,再按终点重新发起原生导航。
|
|
302
|
+
|
|
195
303
|
```typescript
|
|
196
304
|
import {
|
|
197
305
|
independentDriveRoute,
|
|
@@ -210,13 +318,71 @@ const result = await independentDriveRoute({
|
|
|
210
318
|
// 2. 选择某一条路线(例如 index=1 的路线)
|
|
211
319
|
// 这通常配合地图上的点击事件,高亮显示某条路线
|
|
212
320
|
await selectIndependentRoute({
|
|
321
|
+
token: result.token,
|
|
213
322
|
routeId: result.routes[1].id
|
|
214
323
|
});
|
|
215
324
|
|
|
216
325
|
// 3. 使用当前选中的路线开始导航
|
|
217
326
|
await startNaviWithIndependentPath({
|
|
218
|
-
|
|
327
|
+
token: result.token,
|
|
328
|
+
naviType: 1, // 1 = 模拟导航
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### 近似跟线导航(第一版)
|
|
333
|
+
|
|
334
|
+
当你已经通过 Web API 拿到一条想要的路线,但导航 SDK 不能直接吃这条 `polyline` 时,可以使用 `followWebPlannedRoute`。
|
|
335
|
+
|
|
336
|
+
它会:
|
|
337
|
+
|
|
338
|
+
- 从 Web 路线提炼一组途经锚点
|
|
339
|
+
- 用这些锚点重新发起原生独立算路
|
|
340
|
+
- 选择最接近 Web 路线的一条原生路线
|
|
341
|
+
- 仅在匹配足够接近时才启动导航
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
import { followWebPlannedRoute } from 'expo-gaode-map-navigation';
|
|
345
|
+
|
|
346
|
+
const result = await followWebPlannedRoute({
|
|
347
|
+
from: { latitude: 39.9, longitude: 116.4 },
|
|
348
|
+
to: { latitude: 39.91, longitude: 116.41 },
|
|
349
|
+
webRoute: {
|
|
350
|
+
polyline: webResult.routes[0].polyline ?? [],
|
|
351
|
+
},
|
|
352
|
+
maxViaPoints: 8,
|
|
353
|
+
maxDeviationMeters: 120,
|
|
354
|
+
startNavigation: true,
|
|
355
|
+
naviType: 1, // 1 = 模拟导航
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
console.log(result.mode); // matched | approximate | preview_only
|
|
359
|
+
console.log(result.anchorWaypoints);
|
|
360
|
+
console.log(result.candidateMatches);
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
说明:
|
|
364
|
+
|
|
365
|
+
- 这不是“强制按 Web 线导航”,而是“尽量贴近 Web 线”。
|
|
366
|
+
- 若返回 `preview_only`,说明原生导航 SDK 算出的路线与 Web 线路偏差过大,建议仅做预览,不要直接开导航。
|
|
367
|
+
- 若你只想拿锚点,不立即导航,可以单独使用 `buildAnchorWaypointsFromWebRoute`。
|
|
368
|
+
|
|
369
|
+
如果你希望继续使用嵌入式官方导航 UI,可以先完成近似跟线选路,再通过 `ExpoGaodeMapNaviView` 的 ref 使用独立路径启动:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
const matchResult = await followWebPlannedRoute({
|
|
373
|
+
from,
|
|
374
|
+
to,
|
|
375
|
+
webRoute,
|
|
376
|
+
startNavigation: false,
|
|
219
377
|
});
|
|
378
|
+
|
|
379
|
+
if (matchResult.mode !== 'preview_only') {
|
|
380
|
+
await naviRef.current?.startNavigationWithIndependentPath(matchResult.token, {
|
|
381
|
+
routeId: matchResult.selectedRouteId,
|
|
382
|
+
routeIndex: matchResult.selectedRouteIndex,
|
|
383
|
+
naviType: 1,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
220
386
|
```
|
|
221
387
|
|
|
222
388
|
### 官方导航页(openOfficialNaviPage)
|
|
@@ -336,23 +502,141 @@ const result = await calculateTransitRoute({
|
|
|
336
502
|
| `AVOID_CONGESTION` (4) | 躲避拥堵 |
|
|
337
503
|
| ... | 更多策略请参考类型定义 |
|
|
338
504
|
|
|
505
|
+
### 自定义嵌入式 UI 参考实现
|
|
506
|
+
|
|
507
|
+
库不再直接导出 `EmbeddedNaviView` 这类成品 UI 组件;这部分实现现在放在示例工程里,便于你直接查看和复制。
|
|
508
|
+
|
|
509
|
+
参考文件:
|
|
510
|
+
|
|
511
|
+
- `example-navigation/lib/navigation-ui/EmbeddedNaviView.tsx`
|
|
512
|
+
- `example-navigation/lib/navigation-ui/EmbeddedNaviHud.tsx`
|
|
513
|
+
- `example-navigation/lib/navigation-ui/EmbeddedNaviLaneView.tsx`
|
|
514
|
+
- `example-navigation/lib/navigation-ui/EmbeddedNaviTrafficBar.tsx`
|
|
515
|
+
|
|
516
|
+
这套示例实现演示了:
|
|
517
|
+
|
|
518
|
+
- 默认 `showUIElements={false}` 的完整自定义 UI 模式
|
|
519
|
+
- 基于 `driveViewEdgePadding` / `screenAnchor` 的嵌入式地图可视区域管理
|
|
520
|
+
- 基于 `onNaviInfoUpdate` 的顶部 HUD
|
|
521
|
+
- 基于 `onLaneInfoUpdate` 的自绘车道 HUD
|
|
522
|
+
- 基于 `onTrafficStatusesUpdate` 的自绘路况光柱
|
|
523
|
+
- “全览 / 锁车”与路况开关等浮层控制按钮
|
|
524
|
+
|
|
339
525
|
### NaviView Props
|
|
340
526
|
|
|
341
527
|
| 属性 | 类型 | 说明 |
|
|
342
528
|
|---|---|---|
|
|
343
529
|
| `naviType` | number | 导航类型(0: GPS, 1: 模拟) |
|
|
344
|
-
| `
|
|
530
|
+
| `realCrossDisplay` | boolean | 是否显示路口放大图 |
|
|
345
531
|
| `showCamera` | boolean | 是否显示摄像头 |
|
|
346
|
-
| `
|
|
532
|
+
| `carImage` | string \| ImageSourcePropType | 自定义导航车标;iOS 映射 `setCarImage`,Android 映射 `setCarBitmap` |
|
|
533
|
+
| `carImageSize` | object | 自定义导航车标尺寸,格式 `{ width, height }`(单位 dp/pt,需同时传宽高) |
|
|
534
|
+
| `startPointImage` | string \| ImageSourcePropType | 自定义起点标注图 |
|
|
535
|
+
| `wayPointImage` | string \| ImageSourcePropType | 自定义途经点标注图 |
|
|
536
|
+
| `endPointImage` | string \| ImageSourcePropType | 自定义终点标注图 |
|
|
537
|
+
| `trafficLayerEnabled` | boolean | 是否显示实时交通路况线 |
|
|
538
|
+
| `showTrafficButton` | boolean | 是否显示交通按钮/交通图层开关 |
|
|
539
|
+
| `showDriveCongestion` | boolean | 是否显示拥堵气泡 |
|
|
540
|
+
| `showTrafficLightView` | boolean | 是否显示红绿灯倒计时气泡 |
|
|
541
|
+
| `mapViewModeType` | number | 地图样式模式:`0` 白天、`1` 黑夜、`2` 自动、`3` 自定义(Android 当前未开放样式路径时会降级为白天) |
|
|
542
|
+
| `isNightMode` | boolean | 兼容属性,等价于 `mapViewModeType` 的 `1/0`;若同时传 `mapViewModeType`,以后者为准 |
|
|
543
|
+
| `showUIElements` | boolean | Android / iOS 均支持整体 UI 显隐 |
|
|
544
|
+
| `laneInfoVisible` | boolean | Android 是否显示官方车道信息 |
|
|
545
|
+
| `hideNativeLaneInfoLayout` | boolean | iOS 是否隐藏官方车道信息条,交给 RN 自绘 |
|
|
546
|
+
| `iosLiveActivityEnabled` | boolean | iOS 是否启用导航 Live Activity 状态更新(需已配置 Widget Extension) |
|
|
547
|
+
| `modeCrossDisplay` | boolean | Android 是否显示 3D 路口模型;iOS 当前不支持,会忽略 |
|
|
548
|
+
| `eyrieCrossDisplay` | boolean | Android 是否显示鹰眼路口图 |
|
|
549
|
+
| `secondActionVisible` | boolean | Android 是否显示辅助操作区域 |
|
|
550
|
+
| `backupOverlayVisible` | boolean | Android 是否显示备用路线覆盖物 |
|
|
551
|
+
| `androidStatusBarPaddingTop` | number | Android 顶部额外间距;若显示官方原生顶部信息区且未显式传值,封装会自动补系统状态栏高度 |
|
|
552
|
+
| `naviStatusBarEnabled` | boolean | Android 是否启用高德官方导航状态栏;若当前 AMap SDK 不支持该接口,则自动降级为 no-op |
|
|
553
|
+
| `lockZoom` | number | Android 锁车态缩放级别 |
|
|
554
|
+
| `lockTilt` | number | Android 锁车态倾斜角度 |
|
|
555
|
+
| `eagleMapVisible` | boolean | Android 是否显示鹰眼小地图 |
|
|
556
|
+
| `pointToCenter` | object | Android 锁车态自车锚点位置 |
|
|
557
|
+
| `androidBackgroundNavigationNotificationEnabled` | boolean | Android 退到后台时是否启用前台服务导航常驻通知(默认 false) |
|
|
558
|
+
| `driveViewEdgePadding` | object | iOS 导航内容边距 |
|
|
559
|
+
| `screenAnchor` | object | iOS 地图视图锚点 |
|
|
560
|
+
| `showBackupRoute` | boolean | iOS 是否显示备选路线 |
|
|
561
|
+
| `showEagleMap` | boolean | iOS 是否显示鹰眼小地图 |
|
|
347
562
|
| `enableVoice` | boolean | 是否开启语音播报 |
|
|
348
563
|
| `onArrive` | function | 到达目的地回调 |
|
|
349
564
|
| `onNaviInfoUpdate` | function | 导航信息更新(剩余距离、时间等) |
|
|
565
|
+
| `onLaneInfoUpdate` | function | Android / iOS 车道信息更新,用于自绘车道 HUD |
|
|
566
|
+
|
|
567
|
+
### NaviView UI 能力清单
|
|
568
|
+
|
|
569
|
+
已开放且两端都有实现:
|
|
570
|
+
|
|
571
|
+
- `showCamera`
|
|
572
|
+
- `autoLockCar`
|
|
573
|
+
- `autoChangeZoom`
|
|
574
|
+
- `trafficLayerEnabled`
|
|
575
|
+
- `realCrossDisplay`
|
|
576
|
+
- `naviMode`
|
|
577
|
+
- `showMode`
|
|
578
|
+
- `mapViewModeType`
|
|
579
|
+
- `isNightMode`
|
|
580
|
+
- `showTrafficBar`
|
|
581
|
+
- `showTrafficButton`
|
|
582
|
+
- `showUIElements`
|
|
583
|
+
- `showGreyAfterPass`
|
|
584
|
+
- `showVectorline`
|
|
585
|
+
- `showCompassEnabled`
|
|
586
|
+
- `showDriveCongestion`
|
|
587
|
+
- `showTrafficLightView`
|
|
588
|
+
|
|
589
|
+
仅 Android 已开放:
|
|
590
|
+
|
|
591
|
+
- `carOverlayVisible`
|
|
592
|
+
- `fourCornersImage`
|
|
593
|
+
- `routeMarkerVisible`
|
|
594
|
+
- `naviArrowVisible`
|
|
595
|
+
- `laneInfoVisible`
|
|
596
|
+
- `modeCrossDisplay`
|
|
597
|
+
- `eyrieCrossDisplay`
|
|
598
|
+
- `secondActionVisible`
|
|
599
|
+
- `backupOverlayVisible`
|
|
600
|
+
- `androidStatusBarPaddingTop`
|
|
601
|
+
- `naviStatusBarEnabled`
|
|
602
|
+
- `lockZoom`
|
|
603
|
+
- `lockTilt`
|
|
604
|
+
- `eagleMapVisible`
|
|
605
|
+
- `pointToCenter`
|
|
606
|
+
- `isNaviTravelView`
|
|
607
|
+
|
|
608
|
+
仅 iOS 已开放:
|
|
609
|
+
|
|
610
|
+
- `hideNativeLaneInfoLayout`
|
|
611
|
+
- `showRoute`
|
|
612
|
+
- `carCompassImage`
|
|
613
|
+
- `cameraImage`
|
|
614
|
+
- `trafficBarFrame`
|
|
615
|
+
- `trafficBarColors`
|
|
616
|
+
- `showMoreButton`
|
|
617
|
+
- `lineWidth`
|
|
618
|
+
- `driveViewEdgePadding`
|
|
619
|
+
- `screenAnchor`
|
|
620
|
+
|
|
621
|
+
关于 iOS 路口放大图能力:
|
|
622
|
+
|
|
623
|
+
- iOS 官方公开的是 `showCrossImage / hideCrossImage`
|
|
624
|
+
- 因此库里的 `realCrossDisplay` 对应 iOS 实景路口放大图显示控制
|
|
625
|
+
- Android 的 `modeCrossDisplay` 没有 iOS 对等公开接口,传入 iOS 时会被忽略
|
|
626
|
+
- `showBackupRoute`
|
|
627
|
+
- `showEagleMap`
|
|
628
|
+
|
|
629
|
+
当前这份清单里此前列出的“剩余代表项”已全部开放。
|
|
630
|
+
|
|
631
|
+
如果后续还要继续往下包,更适合继续补的是更底层的样式类配置,而不是核心导航 UI 能力。
|
|
350
632
|
|
|
351
633
|
## 注意事项
|
|
352
634
|
|
|
353
635
|
1. **二进制冲突**:严禁与 `expo-gaode-map` 共存。本模块已包含 `3dmap` SDK。
|
|
354
636
|
2. **Web API**:如果需要更灵活的 HTTP 算路(如公交跨城规划、Web端展示),推荐配合 `expo-gaode-map-web-api` 使用。
|
|
355
637
|
3. **权限**:使用导航功能前,请确保应用已获取定位权限(`ACCESS_FINE_LOCATION`)。
|
|
638
|
+
4. **Android 状态栏兼容性**:`naviStatusBarEnabled` 依赖高德 Android 导航 SDK 某些版本才提供的 `AMapNaviViewOptions.setNaviStatusBarEnabled(...)`。当前封装已做兼容处理:若宿主工程解析到的 SDK 不包含该方法,则不会再编译失败,而是在运行时跳过该设置并输出 warning。此时该 prop 在 Android 上等价于 no-op。
|
|
639
|
+
5. **嵌入式 UI 边界**:库导出的是底层 `NaviView` 能力;完整自定义导航界面请参考 `example-navigation` 里的示例实现,它也不是高德官方黑盒导航页的 UI 替代品。
|
|
356
640
|
|
|
357
641
|
|
|
358
642
|
## 📚 文档与资源
|
package/android/build.gradle
CHANGED
|
@@ -65,4 +65,8 @@ dependencies {
|
|
|
65
65
|
} else {
|
|
66
66
|
implementation 'com.amap.api:navi-3dmap:latest.integration'
|
|
67
67
|
}
|
|
68
|
+
|
|
69
|
+
// Live Update APIs on NotificationCompat.Builder
|
|
70
|
+
// setRequestPromotedOngoing / setShortCriticalText were added in androidx.core 1.17.0.
|
|
71
|
+
implementation 'androidx.core:core-ktx:1.17.0'
|
|
68
72
|
}
|
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
|
|
17
17
|
<!-- 设备信息权限 - SDK 初始化必需 -->
|
|
18
18
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
|
19
|
+
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
19
20
|
|
|
20
21
|
<!-- 蓝牙权限 - 用于室内定位 (可选) -->
|
|
21
22
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
|
22
23
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
|
23
|
-
</manifest>
|
|
24
|
+
</manifest>
|
|
@@ -653,6 +653,62 @@ Java_expo_modules_gaodemap_map_utils_GeometryUtils_nativeCalculateCentroid(
|
|
|
653
653
|
#endif
|
|
654
654
|
}
|
|
655
655
|
|
|
656
|
+
extern "C" JNIEXPORT jdouble JNICALL
|
|
657
|
+
Java_expo_modules_gaodemap_map_utils_GeometryUtils_nativeCalculateFitZoom(
|
|
658
|
+
JNIEnv* env,
|
|
659
|
+
jclass,
|
|
660
|
+
jdoubleArray latitudes,
|
|
661
|
+
jdoubleArray longitudes,
|
|
662
|
+
jdouble viewportWidthPx,
|
|
663
|
+
jdouble viewportHeightPx,
|
|
664
|
+
jdouble paddingPx,
|
|
665
|
+
jint minZoom,
|
|
666
|
+
jint maxZoom
|
|
667
|
+
) {
|
|
668
|
+
#if GAODE_HAVE_JNI
|
|
669
|
+
if (!latitudes || !longitudes) {
|
|
670
|
+
return static_cast<jdouble>(minZoom);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const jsize countLat = env->GetArrayLength(latitudes);
|
|
674
|
+
const jsize countLon = env->GetArrayLength(longitudes);
|
|
675
|
+
if (countLat == 0 || countLat != countLon) {
|
|
676
|
+
return static_cast<jdouble>(minZoom);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
jdouble* latValues = env->GetDoubleArrayElements(latitudes, nullptr);
|
|
680
|
+
jdouble* lonValues = env->GetDoubleArrayElements(longitudes, nullptr);
|
|
681
|
+
|
|
682
|
+
std::vector<gaodemap::GeoPoint> points;
|
|
683
|
+
points.reserve(static_cast<size_t>(countLat));
|
|
684
|
+
for (jsize i = 0; i < countLat; ++i) {
|
|
685
|
+
points.push_back({latValues[i], lonValues[i]});
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
env->ReleaseDoubleArrayElements(latitudes, latValues, JNI_ABORT);
|
|
689
|
+
env->ReleaseDoubleArrayElements(longitudes, lonValues, JNI_ABORT);
|
|
690
|
+
|
|
691
|
+
return static_cast<jdouble>(gaodemap::calculateFitZoomForPoints(
|
|
692
|
+
points,
|
|
693
|
+
static_cast<double>(viewportWidthPx),
|
|
694
|
+
static_cast<double>(viewportHeightPx),
|
|
695
|
+
static_cast<double>(paddingPx),
|
|
696
|
+
static_cast<int>(minZoom),
|
|
697
|
+
static_cast<int>(maxZoom)
|
|
698
|
+
));
|
|
699
|
+
#else
|
|
700
|
+
(void)env;
|
|
701
|
+
(void)latitudes;
|
|
702
|
+
(void)longitudes;
|
|
703
|
+
(void)viewportWidthPx;
|
|
704
|
+
(void)viewportHeightPx;
|
|
705
|
+
(void)paddingPx;
|
|
706
|
+
(void)minZoom;
|
|
707
|
+
(void)maxZoom;
|
|
708
|
+
return 3.0;
|
|
709
|
+
#endif
|
|
710
|
+
}
|
|
711
|
+
|
|
656
712
|
extern "C" JNIEXPORT jstring JNICALL
|
|
657
713
|
Java_expo_modules_gaodemap_map_utils_GeometryUtils_nativeEncodeGeoHash(
|
|
658
714
|
JNIEnv* env,
|
|
@@ -51,7 +51,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
51
51
|
} else if (!SDKInitializer.isPrivacyReady()) {
|
|
52
52
|
throw expo.modules.kotlin.exception.CodedException(
|
|
53
53
|
"PRIVACY_NOT_AGREED",
|
|
54
|
-
"隐私协议未完成确认,请先调用
|
|
54
|
+
"隐私协议未完成确认,请先调用 setPrivacyConfig",
|
|
55
55
|
null
|
|
56
56
|
)
|
|
57
57
|
} else {
|
|
@@ -68,12 +68,20 @@ class ExpoGaodeMapModule : Module() {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
Function("
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
Function("setPrivacyConfig") { config: Map<String, Any?> ->
|
|
72
|
+
val hasShow = config["hasShow"] as? Boolean ?: false
|
|
73
|
+
val hasContainsPrivacy = config["hasContainsPrivacy"] as? Boolean ?: hasShow
|
|
74
|
+
val hasAgree = config["hasAgree"] as? Boolean ?: false
|
|
75
|
+
val privacyVersion = config["privacyVersion"] as? String
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
SDKInitializer.setPrivacyConfig(
|
|
78
|
+
appContext.reactContext!!,
|
|
79
|
+
hasShow,
|
|
80
|
+
hasContainsPrivacy,
|
|
81
|
+
hasAgree,
|
|
82
|
+
privacyVersion,
|
|
83
|
+
config.containsKey("privacyVersion")
|
|
84
|
+
)
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
Function("setPrivacyVersion") { version: String ->
|
|
@@ -186,6 +194,37 @@ class ExpoGaodeMapModule : Module() {
|
|
|
186
194
|
}
|
|
187
195
|
}
|
|
188
196
|
|
|
197
|
+
/**
|
|
198
|
+
* 根据多个坐标点计算可同时可见的推荐缩放级别
|
|
199
|
+
* @param points 坐标点(至少 1 个)
|
|
200
|
+
* @param viewportWidthPx 视口宽度(像素)
|
|
201
|
+
* @param viewportHeightPx 视口高度(像素)
|
|
202
|
+
* @param paddingPx 内边距(像素)
|
|
203
|
+
* @param minZoom 最小缩放
|
|
204
|
+
* @param maxZoom 最大缩放
|
|
205
|
+
*/
|
|
206
|
+
Function("calculateFitZoom") {
|
|
207
|
+
points: List<Any>?,
|
|
208
|
+
viewportWidthPx: Double?,
|
|
209
|
+
viewportHeightPx: Double?,
|
|
210
|
+
paddingPx: Double?,
|
|
211
|
+
minZoom: Int?,
|
|
212
|
+
maxZoom: Int? ->
|
|
213
|
+
val normalized = LatLngParser.parseLatLngList(points)
|
|
214
|
+
val safeMinZoom = minZoom ?: 3
|
|
215
|
+
val safeMaxZoom = maxZoom ?: 20
|
|
216
|
+
if (normalized.isEmpty()) return@Function safeMinZoom.toDouble()
|
|
217
|
+
|
|
218
|
+
GeometryUtils.calculateFitZoom(
|
|
219
|
+
normalized,
|
|
220
|
+
viewportWidthPx ?: 390.0,
|
|
221
|
+
viewportHeightPx ?: 844.0,
|
|
222
|
+
paddingPx ?: 48.0,
|
|
223
|
+
safeMinZoom,
|
|
224
|
+
safeMaxZoom
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
189
228
|
/**
|
|
190
229
|
* 计算多边形面积
|
|
191
230
|
* @param points 多边形顶点坐标数组,支持嵌套数组(多边形空洞)
|
|
@@ -771,7 +810,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
771
810
|
// 使用 WeakReference 避免内存泄露
|
|
772
811
|
val contextRef = java.lang.ref.WeakReference(appContext.reactContext)
|
|
773
812
|
val handler = android.os.Handler(android.os.Looper.getMainLooper())
|
|
774
|
-
|
|
813
|
+
var attempts = 0
|
|
775
814
|
val maxAttempts = 50 // 增加到 5 秒 / 100ms,给用户足够时间操作
|
|
776
815
|
|
|
777
816
|
val checkPermission = object : Runnable {
|
|
@@ -783,6 +822,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
783
822
|
}
|
|
784
823
|
|
|
785
824
|
val status = PermissionHelper.checkForegroundLocationPermission(context)
|
|
825
|
+
attempts += 1
|
|
786
826
|
|
|
787
827
|
// 如果权限已授予或达到最大尝试次数,返回结果并清理 Handler
|
|
788
828
|
if (status.granted || attempts >= maxAttempts) {
|
|
@@ -842,7 +882,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
842
882
|
// 轮询检查权限状态
|
|
843
883
|
val contextRef = java.lang.ref.WeakReference(appContext.reactContext)
|
|
844
884
|
val handler = android.os.Handler(android.os.Looper.getMainLooper())
|
|
845
|
-
|
|
885
|
+
var attempts = 0
|
|
846
886
|
val maxAttempts = 30
|
|
847
887
|
|
|
848
888
|
val checkPermission = object : Runnable {
|
|
@@ -854,6 +894,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
854
894
|
}
|
|
855
895
|
|
|
856
896
|
val status = PermissionHelper.checkBackgroundLocationPermission(context)
|
|
897
|
+
attempts += 1
|
|
857
898
|
|
|
858
899
|
if (status.granted || attempts >= maxAttempts) {
|
|
859
900
|
handler.removeCallbacks(this)
|
|
@@ -56,22 +56,6 @@ object SDKInitializer {
|
|
|
56
56
|
applyPrivacyState(appContext)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
fun setPrivacyShow(context: Context, hasShow: Boolean, hasContainsPrivacy: Boolean) {
|
|
60
|
-
privacyShown = hasShow
|
|
61
|
-
privacyContains = hasContainsPrivacy
|
|
62
|
-
val appContext = resolveContext(context)
|
|
63
|
-
persistState(appContext)
|
|
64
|
-
applyPrivacyState(appContext)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
fun setPrivacyAgree(context: Context, hasAgree: Boolean) {
|
|
68
|
-
privacyAgreed = hasAgree
|
|
69
|
-
agreedPrivacyVersion = if (hasAgree) privacyVersion else null
|
|
70
|
-
val appContext = resolveContext(context)
|
|
71
|
-
persistState(appContext)
|
|
72
|
-
applyPrivacyState(appContext)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
59
|
fun setPrivacyVersion(context: Context, version: String) {
|
|
76
60
|
val sanitizedVersion = version.trim().takeIf { it.isNotEmpty() }
|
|
77
61
|
privacyVersion = sanitizedVersion
|
|
@@ -89,6 +73,28 @@ object SDKInitializer {
|
|
|
89
73
|
applyPrivacyState(appContext)
|
|
90
74
|
}
|
|
91
75
|
|
|
76
|
+
fun setPrivacyConfig(
|
|
77
|
+
context: Context,
|
|
78
|
+
hasShow: Boolean,
|
|
79
|
+
hasContainsPrivacy: Boolean,
|
|
80
|
+
hasAgree: Boolean,
|
|
81
|
+
version: String?,
|
|
82
|
+
shouldUpdateVersion: Boolean
|
|
83
|
+
) {
|
|
84
|
+
val appContext = resolveContext(context)
|
|
85
|
+
|
|
86
|
+
if (shouldUpdateVersion) {
|
|
87
|
+
privacyVersion = version?.trim()?.takeIf { it.isNotEmpty() }
|
|
88
|
+
}
|
|
89
|
+
privacyShown = hasShow
|
|
90
|
+
privacyContains = hasContainsPrivacy
|
|
91
|
+
privacyAgreed = hasAgree
|
|
92
|
+
agreedPrivacyVersion = if (hasAgree) privacyVersion else null
|
|
93
|
+
|
|
94
|
+
persistState(appContext)
|
|
95
|
+
applyPrivacyState(appContext)
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
fun resetPrivacyConsent(context: Context) {
|
|
93
99
|
val appContext = resolveContext(context)
|
|
94
100
|
clearConsentPersistedState(appContext, keepCurrentVersion = false)
|
|
@@ -138,7 +144,7 @@ object SDKInitializer {
|
|
|
138
144
|
if (!isPrivacyReady()) {
|
|
139
145
|
throw expo.modules.kotlin.exception.CodedException(
|
|
140
146
|
"PRIVACY_NOT_AGREED",
|
|
141
|
-
"隐私协议未完成确认,请先调用
|
|
147
|
+
"隐私协议未完成确认,请先调用 setPrivacyConfig",
|
|
142
148
|
null
|
|
143
149
|
)
|
|
144
150
|
}
|