expo-gaode-map-navigation 2.0.6 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +25 -0
  2. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +71 -45
  3. package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +35 -0
  4. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +0 -1
  5. package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviView.kt +13 -2
  6. package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNavigationModule.kt +385 -1
  7. package/android/src/main/java/expo/modules/gaodemap/navigation/routes/drive/DriveTruckRouteCalculator.kt +180 -4
  8. package/android/src/main/java/expo/modules/gaodemap/navigation/services/IndependentRouteService.kt +182 -7
  9. package/android/src/main/java/expo/modules/gaodemap/navigation/utils/Converters.kt +31 -1
  10. package/build/index.d.ts +7 -2
  11. package/build/index.d.ts.map +1 -1
  12. package/build/index.js +5 -0
  13. package/build/index.js.map +1 -1
  14. package/build/types/independent.types.d.ts +7 -0
  15. package/build/types/independent.types.d.ts.map +1 -1
  16. package/build/types/independent.types.js.map +1 -1
  17. package/build/types/native-module.types.d.ts +5 -1
  18. package/build/types/native-module.types.d.ts.map +1 -1
  19. package/build/types/native-module.types.js.map +1 -1
  20. package/build/types/route.types.d.ts +112 -0
  21. package/build/types/route.types.d.ts.map +1 -1
  22. package/build/types/route.types.js.map +1 -1
  23. package/ios/ExpoGaodeMapNaviView.swift +56 -4
  24. package/ios/ExpoGaodeMapNavigationModule.swift +585 -12
  25. package/ios/map/ExpoGaodeMapOfflineModule.swift +58 -34
  26. package/ios/map/GaodeMapPrivacyManager.swift +23 -1
  27. package/ios/map/overlays/MarkerView.swift +148 -11
  28. package/ios/services/IndependentRouteService.swift +186 -44
  29. package/package.json +1 -1
  30. package/plugin/build/withGaodeMap.js +28 -0
@@ -2,8 +2,9 @@
2
2
  // IndependentRouteService.swift
3
3
  // expo-gaode-map-navigation
4
4
  //
5
- // 独立路径规划服务 - 简化实现,使用标准路径规划 API
6
- // 注意:iOS SDK 的独立算路 API 可能不支持 callback 方式,使用标准代理方式
5
+ // 独立路径规划服务
6
+ // 驾车/货车/摩托车:优先使用官方独立算路回调(返回 AMapNaviRouteGroup)
7
+ // 步行/骑行:沿用对应 Manager 的标准算路回调
7
8
  //
8
9
 
9
10
  import Foundation
@@ -47,59 +48,61 @@ class IndependentRouteService: NSObject {
47
48
  promise.reject("INVALID_PARAMS", "from and to are required")
48
49
  return
49
50
  }
50
-
51
- guard let startPoint = Converters.parseNaviPoint(from),
52
- let endPoint = Converters.parseNaviPoint(to) else {
53
- promise.reject("INVALID_COORDS", "Invalid coordinates")
51
+
52
+ guard let startPOIInfo = Converters.parseNaviPOIInfo(from),
53
+ let endPOIInfo = Converters.parseNaviPOIInfo(to) else {
54
+ promise.reject("INVALID_COORDS", "Invalid coordinates or POI info")
54
55
  return
55
56
  }
56
-
57
- // 解析途经点
58
- var wayPoints: [AMapNaviPoint]? = nil
59
- if let waypoints = options["waypoints"] as? [[String: Any]] {
60
- wayPoints = waypoints.compactMap { Converters.parseNaviPoint($0) }
57
+
58
+ let wayPOIInfos: [AMapNaviPOIInfo]? = {
59
+ guard let waypoints = options["waypoints"] as? [[String: Any]] else { return nil }
60
+ return Converters.parseNaviPOIInfos(waypoints)
61
+ }()
62
+
63
+ if let vehicleInfo = buildVehicleInfo(options: options) {
64
+ driveManager?.setVehicleInfo(vehicleInfo)
61
65
  }
62
-
63
- // 解析策略
64
- let strategyValue = options["strategy"] as? Int ?? 10
65
- let strategy: AMapNaviDrivingStrategy = AMapNaviDrivingStrategy(rawValue: strategyValue) ?? AMapNaviDrivingStrategy.drivingStrategySingleDefault
66
-
67
- currentScene = "drive"
68
- currentPromise = promise
69
- currentToken = independentRouteManager.generateToken()
70
-
71
- let success = driveManager?.calculateDriveRoute(
72
- withStart: [startPoint],
73
- end: [endPoint],
74
- wayPoints: wayPoints,
75
- drivingStrategy: strategy
66
+
67
+ let strategyValue = resolveDriveStrategyValue(options: options)
68
+ let strategy = AMapNaviDrivingStrategy(rawValue: strategyValue)
69
+ ?? AMapNaviDrivingStrategy.drivingStrategySingleDefault
70
+ let token = independentRouteManager.generateToken()
71
+
72
+ let success = driveManager?.independentCalculateDriveRoute(
73
+ withStart: startPOIInfo,
74
+ end: endPOIInfo,
75
+ wayPOIInfos: wayPOIInfos,
76
+ drivingStrategy: strategy,
77
+ callback: { [weak self] routeGroup, error in
78
+ guard let self else { return }
79
+ if let error = error {
80
+ promise.reject("CALCULATE_FAILED", error.localizedDescription)
81
+ return
82
+ }
83
+ guard let routeGroup = routeGroup else {
84
+ promise.reject("CALCULATE_FAILED", "独立驾车算路成功回调未返回 routeGroup")
85
+ return
86
+ }
87
+
88
+ self.independentRouteManager.storeRouteGroup(token: token, routeGroup: routeGroup)
89
+ let result = self.convertIndependentDriveResult(routeGroup: routeGroup, token: token)
90
+ promise.resolve(result)
91
+ }
76
92
  ) ?? false
77
-
93
+
78
94
  if !success {
79
- currentPromise = nil
80
- currentToken = nil
81
95
  promise.reject("CALCULATE_FAILED", "独立驾车路线规划启动失败")
82
96
  }
83
97
  }
84
98
 
85
99
  // MARK: - 独立货车路线规划
86
100
  func independentTruckRoute(options: [String: Any], promise: Promise) {
87
- // 设置货车信息
88
- if let vehicleInfo = options["vehicleInfo"] as? [String: Any] {
89
- let naviVehicleInfo = AMapNaviVehicleInfo()
90
- naviVehicleInfo.type = vehicleInfo["type"] as? Int ?? 1
91
- naviVehicleInfo.size = vehicleInfo["size"] as? Int ?? 2
92
- naviVehicleInfo.width = vehicleInfo["width"] as? Double ?? 2.5
93
- naviVehicleInfo.height = vehicleInfo["height"] as? Double ?? 3.0
94
- naviVehicleInfo.length = vehicleInfo["length"] as? Double ?? 10.0
95
- naviVehicleInfo.load = vehicleInfo["load"] as? Double ?? 10.0
96
- naviVehicleInfo.weight = vehicleInfo["weight"] as? Double ?? 15.0
97
- naviVehicleInfo.axisNums = vehicleInfo["axisNums"] as? Int ?? 2
98
- driveManager?.setVehicleInfo(naviVehicleInfo)
101
+ var truckOptions = options
102
+ if truckOptions["carType"] == nil && (truckOptions["vehicleInfo"] as? [String: Any]) == nil {
103
+ truckOptions["carType"] = 1
99
104
  }
100
-
101
- // 复用驾车路线规划
102
- independentDriveRoute(options: options, promise: promise)
105
+ independentDriveRoute(options: truckOptions, promise: promise)
103
106
  }
104
107
 
105
108
  // MARK: - 独立步行路线规划
@@ -158,7 +161,146 @@ class IndependentRouteService: NSObject {
158
161
 
159
162
  // MARK: - 独立摩托车路线规划(使用驾车接口)
160
163
  func independentMotorcycleRoute(options: [String: Any], promise: Promise) {
161
- independentDriveRoute(options: options, promise: promise)
164
+ var motorcycleOptions = options
165
+ if motorcycleOptions["carType"] == nil {
166
+ motorcycleOptions["carType"] = 11
167
+ }
168
+ independentDriveRoute(options: motorcycleOptions, promise: promise)
169
+ }
170
+
171
+ private func resolveDriveStrategyValue(options: [String: Any]) -> Int {
172
+ if let strategy = options["strategy"] as? Int {
173
+ return strategy
174
+ }
175
+ return Converters.convertDrivingPreferenceToStrategy(
176
+ multipleRoute: true,
177
+ avoidCongestion: options["avoidCongestion"] as? Bool ?? false,
178
+ avoidHighway: options["avoidHighway"] as? Bool ?? false,
179
+ avoidCost: options["avoidCost"] as? Bool ?? false,
180
+ prioritiseHighway: options["prioritiseHighway"] as? Bool ?? false
181
+ )
182
+ }
183
+
184
+ private func buildVehicleInfo(options: [String: Any]) -> AMapNaviVehicleInfo? {
185
+ let naviVehicleInfo = AMapNaviVehicleInfo()
186
+ var hasAnyValue = false
187
+
188
+ if let vehicleInfo = options["vehicleInfo"] as? [String: Any] {
189
+ if let type = intValue(vehicleInfo["type"]) {
190
+ naviVehicleInfo.type = type
191
+ hasAnyValue = true
192
+ }
193
+ if let size = intValue(vehicleInfo["size"]) {
194
+ naviVehicleInfo.size = size
195
+ hasAnyValue = true
196
+ }
197
+ if let width = doubleValue(vehicleInfo["width"]) {
198
+ naviVehicleInfo.width = width
199
+ hasAnyValue = true
200
+ }
201
+ if let height = doubleValue(vehicleInfo["height"]) {
202
+ naviVehicleInfo.height = height
203
+ hasAnyValue = true
204
+ }
205
+ if let length = doubleValue(vehicleInfo["length"]) {
206
+ naviVehicleInfo.length = length
207
+ hasAnyValue = true
208
+ }
209
+ if let load = doubleValue(vehicleInfo["load"]) {
210
+ naviVehicleInfo.load = load
211
+ hasAnyValue = true
212
+ }
213
+ if let weight = doubleValue(vehicleInfo["weight"]) {
214
+ naviVehicleInfo.weight = weight
215
+ hasAnyValue = true
216
+ }
217
+ if let axisNums = intValue(vehicleInfo["axisNums"]) {
218
+ naviVehicleInfo.axisNums = axisNums
219
+ hasAnyValue = true
220
+ }
221
+ }
222
+
223
+ if let carType = intValue(options["carType"]) {
224
+ naviVehicleInfo.type = carType
225
+ hasAnyValue = true
226
+ }
227
+ if let carNumber = options["carNumber"] as? String, !carNumber.isEmpty {
228
+ naviVehicleInfo.vehicleId = carNumber
229
+ hasAnyValue = true
230
+ }
231
+ if let restriction = options["restriction"] as? Bool {
232
+ naviVehicleInfo.isETARestriction = restriction
233
+ hasAnyValue = true
234
+ }
235
+ if let motorcycleCC = intValue(options["motorcycleCC"]) {
236
+ naviVehicleInfo.motorcycleCC = motorcycleCC
237
+ hasAnyValue = true
238
+ }
239
+
240
+ return hasAnyValue ? naviVehicleInfo : nil
241
+ }
242
+
243
+ private func convertIndependentDriveResult(
244
+ routeGroup: AMapNaviRouteGroup,
245
+ token: Int
246
+ ) -> [String: Any] {
247
+ let orderedRouteIds = routeGroup.naviRouteIDs?.map { $0.intValue } ?? []
248
+ var routes: [[String: Any]] = []
249
+
250
+ if let naviRoutes = routeGroup.naviRoutes {
251
+ let fallbackIds = naviRoutes.keys.map { $0.intValue }.sorted()
252
+ let routeIds = orderedRouteIds.isEmpty ? fallbackIds : orderedRouteIds
253
+ for routeId in routeIds {
254
+ let key = NSNumber(value: routeId)
255
+ guard let route = naviRoutes[key] else { continue }
256
+ routes.append([
257
+ "routeId": routeId,
258
+ "distance": route.routeLength,
259
+ "duration": route.routeTime,
260
+ "tollCost": route.routeTollCost,
261
+ "strategy": "推荐路线",
262
+ "polyline": extractCoordinates(from: route)
263
+ ])
264
+ }
265
+ } else if let route = routeGroup.naviRoute {
266
+ let routeId = routeGroup.naviRouteID
267
+ routes.append([
268
+ "routeId": routeId,
269
+ "distance": route.routeLength,
270
+ "duration": route.routeTime,
271
+ "tollCost": route.routeTollCost,
272
+ "strategy": "推荐路线",
273
+ "polyline": extractCoordinates(from: route)
274
+ ])
275
+ }
276
+
277
+ let finalRouteIds = orderedRouteIds.isEmpty ? routes.compactMap { $0["routeId"] as? Int } : orderedRouteIds
278
+ let mainRouteId = routeGroup.naviRouteID
279
+ let mainPathIndex = finalRouteIds.firstIndex(of: mainRouteId) ?? 0
280
+
281
+ return [
282
+ "success": true,
283
+ "independent": true,
284
+ "token": token,
285
+ "count": routes.count,
286
+ "mainPathIndex": mainPathIndex,
287
+ "routeIds": finalRouteIds,
288
+ "routes": routes
289
+ ]
290
+ }
291
+
292
+ private func intValue(_ raw: Any?) -> Int? {
293
+ if let value = raw as? Int { return value }
294
+ if let value = raw as? NSNumber { return value.intValue }
295
+ if let value = raw as? String { return Int(value) }
296
+ return nil
297
+ }
298
+
299
+ private func doubleValue(_ raw: Any?) -> Double? {
300
+ if let value = raw as? Double { return value }
301
+ if let value = raw as? NSNumber { return value.doubleValue }
302
+ if let value = raw as? String { return Double(value) }
303
+ return nil
162
304
  }
163
305
 
164
306
  func destroy() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-gaode-map-navigation",
3
- "version": "2.0.6",
3
+ "version": "2.0.7",
4
4
  "description": "高德地图导航功能模块 - 路径规划、导航引导,独立版本包含完整地图功能",
5
5
  "author": "TomWq <582752848@qq.com> (https://github.com/TomWq)",
6
6
  "repository": {
@@ -106,6 +106,34 @@ const withGaodeMapAndroidManifest = (config, props) => {
106
106
  });
107
107
  }
108
108
  }
109
+ // 导航组件 Activity(AmapNaviPage.showRouteActivity 依赖)
110
+ if (mainApplication) {
111
+ if (!mainApplication['activity']) {
112
+ mainApplication['activity'] = [];
113
+ }
114
+ const naviActivityName = 'com.amap.api.navi.AmapRouteActivity';
115
+ const naviConfigChanges = 'orientation|keyboardHidden|screenSize|navigation';
116
+ const naviTheme = '@android:style/Theme.NoTitleBar';
117
+ const activityIndex = mainApplication['activity'].findIndex((item) => item.$?.['android:name'] === naviActivityName);
118
+ if (activityIndex === -1) {
119
+ mainApplication['activity'].push({
120
+ $: {
121
+ 'android:name': naviActivityName,
122
+ 'android:theme': naviTheme,
123
+ 'android:configChanges': naviConfigChanges,
124
+ },
125
+ });
126
+ }
127
+ else {
128
+ const existing = mainApplication['activity'][activityIndex];
129
+ existing.$ = {
130
+ ...(existing.$ || {}),
131
+ 'android:name': naviActivityName,
132
+ 'android:theme': existing.$?.['android:theme'] || naviTheme,
133
+ 'android:configChanges': existing.$?.['android:configChanges'] || naviConfigChanges,
134
+ };
135
+ }
136
+ }
109
137
  // 添加 API Key 到 application 标签
110
138
  if (mainApplication && props.androidKey) {
111
139
  if (!mainApplication['meta-data']) {