expo-gaode-map-navigation 1.1.5-next.1 → 1.1.5-next.2

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 (131) hide show
  1. package/android/build.gradle +10 -0
  2. package/android/src/main/cpp/CMakeLists.txt +24 -0
  3. package/android/src/main/cpp/cluster_jni.cpp +848 -0
  4. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +616 -92
  5. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +493 -0
  6. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +230 -14
  7. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapViewModule.kt +37 -27
  8. package/android/src/main/java/expo/modules/gaodemap/map/MapPreloadManager.kt +494 -0
  9. package/android/src/main/java/expo/modules/gaodemap/map/companion/BitmapDescriptorCache.kt +30 -0
  10. package/android/src/main/java/expo/modules/gaodemap/map/companion/IconBitmapCache.kt +37 -0
  11. package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +76 -0
  12. package/android/src/main/java/expo/modules/gaodemap/map/modules/LocationManager.kt +15 -3
  13. package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +4 -59
  14. package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleView.kt +9 -12
  15. package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleViewModule.kt +5 -6
  16. package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +539 -66
  17. package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterViewModule.kt +17 -1
  18. package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +165 -33
  19. package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +15 -3
  20. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +1249 -672
  21. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +40 -17
  22. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointView.kt +177 -22
  23. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointViewModule.kt +11 -3
  24. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonView.kt +57 -14
  25. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonViewModule.kt +9 -5
  26. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineView.kt +90 -63
  27. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineViewModule.kt +7 -3
  28. package/android/src/main/java/expo/modules/gaodemap/map/services/LocationForegroundService.kt +3 -2
  29. package/android/src/main/java/expo/modules/gaodemap/map/utils/BitmapDescriptorCache.kt +20 -0
  30. package/android/src/main/java/expo/modules/gaodemap/map/utils/ClusterNative.kt +13 -0
  31. package/android/src/main/java/expo/modules/gaodemap/map/utils/ColorParser.kt +20 -0
  32. package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +515 -0
  33. package/android/src/main/java/expo/modules/gaodemap/map/utils/LatLngParser.kt +91 -0
  34. package/android/src/main/java/expo/modules/gaodemap/map/utils/PermissionHelper.kt +248 -0
  35. package/build/ExpoGaodeMapNaviView.d.ts +7 -7
  36. package/build/ExpoGaodeMapNaviView.js +8 -8
  37. package/build/index.d.ts +1 -1
  38. package/build/index.js +2 -2
  39. package/build/map/ExpoGaodeMapModule.d.ts +2 -201
  40. package/build/map/ExpoGaodeMapModule.js +584 -14
  41. package/build/map/ExpoGaodeMapOfflineModule.d.ts +139 -0
  42. package/build/map/ExpoGaodeMapOfflineModule.js +8 -0
  43. package/build/map/ExpoGaodeMapView.js +66 -58
  44. package/build/map/components/FoldableMapView.d.ts +38 -0
  45. package/build/map/components/FoldableMapView.js +209 -0
  46. package/build/map/components/MapContext.d.ts +12 -0
  47. package/build/map/components/MapContext.js +54 -0
  48. package/build/map/components/MapUI.d.ts +18 -0
  49. package/build/map/components/MapUI.js +29 -0
  50. package/build/map/components/overlays/Circle.js +34 -3
  51. package/build/map/components/overlays/Cluster.d.ts +3 -1
  52. package/build/map/components/overlays/Cluster.js +31 -2
  53. package/build/map/components/overlays/HeatMap.d.ts +3 -1
  54. package/build/map/components/overlays/HeatMap.js +33 -3
  55. package/build/map/components/overlays/Marker.d.ts +1 -1
  56. package/build/map/components/overlays/Marker.js +37 -32
  57. package/build/map/components/overlays/MultiPoint.js +1 -1
  58. package/build/map/components/overlays/Polygon.js +30 -3
  59. package/build/map/components/overlays/Polyline.js +36 -3
  60. package/build/map/index.d.ts +25 -5
  61. package/build/map/index.js +59 -18
  62. package/build/map/types/common.types.d.ts +40 -0
  63. package/build/map/types/common.types.js +0 -4
  64. package/build/map/types/index.d.ts +3 -2
  65. package/build/map/types/map-view.types.d.ts +108 -3
  66. package/build/map/types/native-module.types.d.ts +363 -0
  67. package/build/map/types/native-module.types.js +5 -0
  68. package/build/map/types/offline.types.d.ts +132 -0
  69. package/build/map/types/offline.types.js +5 -0
  70. package/build/map/types/overlays.types.d.ts +137 -24
  71. package/build/map/utils/ErrorHandler.d.ts +110 -0
  72. package/build/map/utils/ErrorHandler.js +421 -0
  73. package/build/map/utils/GeoUtils.d.ts +20 -0
  74. package/build/map/utils/GeoUtils.js +76 -0
  75. package/build/map/utils/OfflineMapManager.d.ts +148 -0
  76. package/build/map/utils/OfflineMapManager.js +217 -0
  77. package/build/map/utils/PermissionUtils.d.ts +91 -0
  78. package/build/map/utils/PermissionUtils.js +255 -0
  79. package/build/map/utils/PlatformDetector.d.ts +102 -0
  80. package/build/map/utils/PlatformDetector.js +186 -0
  81. package/build/types/naviview.types.d.ts +1 -1
  82. package/expo-module.config.json +12 -10
  83. package/ios/ExpoGaodeMapNavigation.podspec +9 -0
  84. package/ios/map/ExpoGaodeMapModule.swift +485 -75
  85. package/ios/map/ExpoGaodeMapOfflineModule.swift +479 -0
  86. package/ios/map/ExpoGaodeMapView.swift +611 -62
  87. package/ios/map/ExpoGaodeMapViewModule.swift +48 -26
  88. package/ios/map/MapPreloadManager.swift +348 -0
  89. package/ios/map/cpp/ClusterEngine.cpp +110 -0
  90. package/ios/map/cpp/ClusterEngine.hpp +20 -0
  91. package/ios/map/cpp/ColorParser.cpp +135 -0
  92. package/ios/map/cpp/ColorParser.hpp +14 -0
  93. package/ios/map/cpp/GeometryEngine.cpp +574 -0
  94. package/ios/map/cpp/GeometryEngine.hpp +159 -0
  95. package/ios/map/cpp/QuadTree.cpp +92 -0
  96. package/ios/map/cpp/QuadTree.hpp +42 -0
  97. package/ios/map/cpp/README.md +55 -0
  98. package/ios/map/cpp/tests/benchmark_js.js +41 -0
  99. package/ios/map/cpp/tests/run.sh +17 -0
  100. package/ios/map/cpp/tests/test_main.cpp +276 -0
  101. package/ios/map/managers/UIManager.swift +72 -1
  102. package/ios/map/modules/LocationManager.swift +114 -165
  103. package/ios/map/overlays/CircleView.swift +16 -32
  104. package/ios/map/overlays/CircleViewModule.swift +12 -12
  105. package/ios/map/overlays/ClusterAnnotation.swift +32 -0
  106. package/ios/map/overlays/ClusterView.swift +331 -45
  107. package/ios/map/overlays/ClusterViewModule.swift +20 -6
  108. package/ios/map/overlays/HeatMapView.swift +135 -32
  109. package/ios/map/overlays/HeatMapViewModule.swift +20 -8
  110. package/ios/map/overlays/MarkerView.swift +613 -130
  111. package/ios/map/overlays/MarkerViewModule.swift +38 -18
  112. package/ios/map/overlays/MultiPointView.swift +168 -10
  113. package/ios/map/overlays/MultiPointViewModule.swift +27 -5
  114. package/ios/map/overlays/PolygonView.swift +62 -23
  115. package/ios/map/overlays/PolygonViewModule.swift +18 -12
  116. package/ios/map/overlays/PolylineView.swift +21 -13
  117. package/ios/map/overlays/PolylineViewModule.swift +18 -12
  118. package/ios/map/utils/ClusterNative.h +96 -0
  119. package/ios/map/utils/ClusterNative.mm +377 -0
  120. package/ios/map/utils/ColorParser.swift +12 -1
  121. package/ios/map/utils/CppBridging.mm +13 -0
  122. package/ios/map/utils/GeometryUtils.swift +34 -0
  123. package/ios/map/utils/LatLngParser.swift +87 -0
  124. package/ios/map/utils/PermissionManager.swift +135 -6
  125. package/package.json +1 -1
  126. package/build/map/ExpoGaodeMap.types.d.ts +0 -41
  127. package/build/map/ExpoGaodeMap.types.js +0 -24
  128. package/build/map/utils/EventManager.d.ts +0 -10
  129. package/build/map/utils/EventManager.js +0 -26
  130. package/build/map/utils/ModuleLoader.d.ts +0 -73
  131. package/build/map/utils/ModuleLoader.js +0 -112
@@ -0,0 +1,493 @@
1
+ package expo.modules.gaodemap.map
2
+
3
+ import android.os.Bundle
4
+ import android.os.StatFs
5
+ import android.os.Environment
6
+ import com.amap.api.maps.offlinemap.OfflineMapCity
7
+ import com.amap.api.maps.offlinemap.OfflineMapManager
8
+ import com.amap.api.maps.offlinemap.OfflineMapProvince
9
+ import com.amap.api.maps.offlinemap.OfflineMapStatus
10
+ import expo.modules.kotlin.modules.Module
11
+ import expo.modules.kotlin.modules.ModuleDefinition
12
+
13
+ /**
14
+ * 高德地图离线地图模块 (Android)
15
+ */
16
+ class ExpoGaodeMapOfflineModule : Module() {
17
+
18
+ private var offlineMapManager: OfflineMapManager? = null
19
+ private val downloadingCities = mutableSetOf<String>()
20
+ private val pausedCities = mutableSetOf<String>()
21
+
22
+ // 线程安全锁
23
+ private val lock = Any()
24
+
25
+ override fun definition() = ModuleDefinition {
26
+ Name("ExpoGaodeMapOffline")
27
+
28
+ // ==================== 事件定义 ====================
29
+
30
+ Events(
31
+ "onDownloadProgress",
32
+ "onDownloadComplete",
33
+ "onDownloadError",
34
+ "onUnzipProgress",
35
+ "onDownloadPaused",
36
+ "onDownloadCancelled"
37
+ )
38
+
39
+ // ==================== 模块生命周期 ====================
40
+
41
+ OnCreate {
42
+ // 初始化离线地图管理器
43
+ offlineMapManager = OfflineMapManager(appContext.reactContext, object : OfflineMapManager.OfflineMapDownloadListener {
44
+ override fun onDownload(status: Int, completeCode: Int, downName: String?) {
45
+ handleDownloadStatus(status, completeCode, downName)
46
+ }
47
+
48
+ override fun onCheckUpdate(hasNew: Boolean, name: String?) {
49
+ // 更新检查回调
50
+ }
51
+
52
+ override fun onRemove(success: Boolean, name: String?, describe: String?) {
53
+ // 删除回调
54
+ }
55
+ })
56
+ }
57
+
58
+ OnDestroy {
59
+ offlineMapManager?.destroy()
60
+ offlineMapManager = null
61
+ downloadingCities.clear()
62
+ }
63
+
64
+ // ==================== 地图列表管理 ====================
65
+
66
+ AsyncFunction("getAvailableCities") {
67
+ val cities = offlineMapManager?.offlineMapCityList ?: emptyList()
68
+ cities.map { city -> convertCityToMap(city) }
69
+ }
70
+
71
+ AsyncFunction("getAvailableProvinces") {
72
+ val provinces = offlineMapManager?.offlineMapProvinceList ?: emptyList()
73
+ provinces.map { province -> convertProvinceToMap(province) }
74
+ }
75
+
76
+ AsyncFunction("getCitiesByProvince") { provinceCode: String ->
77
+ val province = offlineMapManager?.offlineMapProvinceList?.find {
78
+ it.provinceCode == provinceCode
79
+ }
80
+ province?.cityList?.map { city -> convertCityToMap(city) } ?: emptyList()
81
+ }
82
+
83
+ AsyncFunction("getDownloadedMaps") {
84
+ val cities = offlineMapManager?.downloadOfflineMapCityList ?: emptyList()
85
+ cities.map { city -> convertCityToMap(city) }
86
+ }
87
+
88
+ // ==================== 下载管理 ====================
89
+
90
+ AsyncFunction("startDownload") { config: Map<String, Any?> ->
91
+ val cityCode = config["cityCode"] as? String
92
+ ?: throw IllegalArgumentException("cityCode is required")
93
+
94
+ synchronized(lock) {
95
+ downloadingCities.add(cityCode)
96
+ pausedCities.remove(cityCode)
97
+ }
98
+ offlineMapManager?.downloadByCityCode(cityCode)
99
+ }
100
+
101
+ AsyncFunction("pauseDownload") { cityCode: String ->
102
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
103
+
104
+ synchronized(lock) {
105
+ pausedCities.add(cityCode)
106
+ downloadingCities.remove(cityCode)
107
+ }
108
+
109
+ // 使用 pauseByName 暂停指定城市
110
+ city?.city?.let { cityName ->
111
+ offlineMapManager?.pauseByName(cityName)
112
+ }
113
+
114
+ if (city != null) {
115
+ sendEvent("onDownloadPaused", Bundle().apply {
116
+ putString("cityCode", cityCode)
117
+ putString("cityName", city.city)
118
+ })
119
+ }
120
+ }
121
+
122
+ AsyncFunction("resumeDownload") { cityCode: String ->
123
+ synchronized(lock) {
124
+ downloadingCities.add(cityCode)
125
+ pausedCities.remove(cityCode)
126
+ }
127
+ // Android SDK 没有针对单个城市的恢复方法
128
+ // 需要重新调用 downloadByCityCode 来继续下载
129
+ offlineMapManager?.downloadByCityCode(cityCode)
130
+ }
131
+
132
+ AsyncFunction("cancelDownload") { cityCode: String ->
133
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
134
+
135
+ synchronized(lock) {
136
+ downloadingCities.remove(cityCode)
137
+ pausedCities.remove(cityCode)
138
+ }
139
+
140
+ // 使用 stop() 停止所有下载(包括队列)
141
+ offlineMapManager?.stop()
142
+
143
+ if (city != null) {
144
+ sendEvent("onDownloadCancelled", Bundle().apply {
145
+ putString("cityCode", cityCode)
146
+ putString("cityName", city.city)
147
+ })
148
+ }
149
+ }
150
+
151
+ AsyncFunction("deleteMap") { cityCode: String ->
152
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
153
+ ?: throw IllegalArgumentException("City not found: $cityCode")
154
+
155
+ // 官方文档:remove() 需要传入城市名称,不是城市代码
156
+ offlineMapManager?.remove(city.city)
157
+
158
+ synchronized(lock) {
159
+ downloadingCities.remove(cityCode)
160
+ pausedCities.remove(cityCode)
161
+ }
162
+ }
163
+
164
+ AsyncFunction("updateMap") { cityCode: String ->
165
+ synchronized(lock) {
166
+ downloadingCities.add(cityCode)
167
+ }
168
+ offlineMapManager?.updateOfflineCityByCode(cityCode)
169
+ }
170
+
171
+ AsyncFunction("checkUpdate") { cityCode: String ->
172
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
173
+ city?.state == OfflineMapStatus.NEW_VERSION
174
+ }
175
+
176
+ // ==================== 状态查询 ====================
177
+
178
+ AsyncFunction("isMapDownloaded") { cityCode: String ->
179
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
180
+ city?.state == OfflineMapStatus.SUCCESS ||
181
+ city?.state == OfflineMapStatus.CHECKUPDATES
182
+ }
183
+
184
+ AsyncFunction("getMapStatus") { cityCode: String ->
185
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
186
+ city?.let { convertCityToMap(it) } ?: Bundle()
187
+ }
188
+
189
+ AsyncFunction("getTotalProgress") {
190
+ val downloadedCities = offlineMapManager?.downloadOfflineMapCityList ?: emptyList()
191
+ if (downloadedCities.isEmpty()) {
192
+ 0.0
193
+ } else {
194
+ val totalProgress = downloadedCities.sumOf { it.getcompleteCode().toDouble() }
195
+ totalProgress / downloadedCities.size
196
+ }
197
+ }
198
+
199
+ AsyncFunction("getDownloadingCities") {
200
+ downloadingCities.toList()
201
+ }
202
+
203
+ // ==================== 存储管理 ====================
204
+
205
+ AsyncFunction("getStorageSize") {
206
+ // 计算所有已下载地图的大小
207
+ val cities = offlineMapManager?.downloadOfflineMapCityList ?: emptyList()
208
+ cities.sumOf { it.size }
209
+ }
210
+
211
+ AsyncFunction("getStorageInfo") {
212
+ val cities = offlineMapManager?.downloadOfflineMapCityList ?: emptyList()
213
+ val offlineMapSize = cities.sumOf { it.size }
214
+
215
+ // 获取存储路径的统计信息
216
+ val stat = StatFs(Environment.getDataDirectory().path)
217
+ val blockSize = stat.blockSizeLong
218
+ val totalBlocks = stat.blockCountLong
219
+ val availableBlocks = stat.availableBlocksLong
220
+
221
+ val totalSpace = totalBlocks * blockSize
222
+ val availableSpace = availableBlocks * blockSize
223
+ val usedSpace = totalSpace - availableSpace
224
+
225
+ Bundle().apply {
226
+ putLong("totalSpace", totalSpace)
227
+ putLong("usedSpace", usedSpace)
228
+ putLong("availableSpace", availableSpace)
229
+ putLong("offlineMapSize", offlineMapSize)
230
+ }
231
+ }
232
+
233
+ AsyncFunction("clearAllMaps") {
234
+ offlineMapManager?.downloadOfflineMapCityList?.forEach { city ->
235
+ // 使用城市名称删除
236
+ offlineMapManager?.remove(city.city)
237
+ }
238
+ synchronized(lock) {
239
+ downloadingCities.clear()
240
+ pausedCities.clear()
241
+ }
242
+ }
243
+
244
+ Function("setStoragePath") { _: String ->
245
+ // Android 离线地图路径由系统管理,此方法不可用
246
+ }
247
+
248
+ AsyncFunction("getStoragePath") {
249
+ // Android 离线地图路径由系统管理
250
+ ""
251
+ }
252
+
253
+ // ==================== 批量操作 ====================
254
+
255
+ AsyncFunction("batchDownload") { cityCodes: List<String>, _: Boolean? ->
256
+ synchronized(lock) {
257
+ cityCodes.forEach { cityCode ->
258
+ downloadingCities.add(cityCode)
259
+ pausedCities.remove(cityCode)
260
+ }
261
+ }
262
+ cityCodes.forEach { cityCode ->
263
+ offlineMapManager?.downloadByCityCode(cityCode)
264
+ }
265
+ }
266
+
267
+ AsyncFunction("batchDelete") { cityCodes: List<String> ->
268
+ cityCodes.forEach { cityCode ->
269
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
270
+ // 使用城市名称删除,不是城市代码
271
+ city?.city?.let { cityName ->
272
+ offlineMapManager?.remove(cityName)
273
+ }
274
+ }
275
+ synchronized(lock) {
276
+ cityCodes.forEach { cityCode ->
277
+ downloadingCities.remove(cityCode)
278
+ pausedCities.remove(cityCode)
279
+ }
280
+ }
281
+ }
282
+
283
+ AsyncFunction("batchUpdate") { cityCodes: List<String> ->
284
+ synchronized(lock) {
285
+ cityCodes.forEach { cityCode ->
286
+ downloadingCities.add(cityCode)
287
+ }
288
+ }
289
+ cityCodes.forEach { cityCode ->
290
+ offlineMapManager?.updateOfflineCityByCode(cityCode)
291
+ }
292
+ }
293
+
294
+ AsyncFunction("pauseAllDownloads") {
295
+ // pause() 只暂停正在下载的,不包括队列
296
+ offlineMapManager?.pause()
297
+
298
+ synchronized(lock) {
299
+ pausedCities.addAll(downloadingCities)
300
+ downloadingCities.forEach { cityCode ->
301
+ val city = offlineMapManager?.getItemByCityCode(cityCode)
302
+ if (city != null) {
303
+ sendEvent("onDownloadPaused", Bundle().apply {
304
+ putString("cityCode", cityCode)
305
+ putString("cityName", city.city)
306
+ })
307
+ }
308
+ }
309
+ downloadingCities.clear()
310
+ }
311
+ }
312
+
313
+ AsyncFunction("resumeAllDownloads") {
314
+ val pausedList = synchronized(lock) {
315
+ pausedCities.toList()
316
+ }
317
+
318
+ // 重新下载所有暂停的城市
319
+ pausedList.forEach { cityCode ->
320
+ synchronized(lock) {
321
+ downloadingCities.add(cityCode)
322
+ pausedCities.remove(cityCode)
323
+ }
324
+ offlineMapManager?.downloadByCityCode(cityCode)
325
+ }
326
+ }
327
+ }
328
+
329
+ // ==================== 辅助方法 ====================
330
+
331
+ /**
332
+ * 处理下载状态回调
333
+ */
334
+ private fun handleDownloadStatus(status: Int, completeCode: Int, downName: String?) {
335
+ if (downName == null) return
336
+
337
+ // downName 可能是城市代码或城市名称,尝试两种方式查找
338
+ var city = offlineMapManager?.getItemByCityCode(downName)
339
+ if (city == null) {
340
+ city = offlineMapManager?.offlineMapCityList?.find { it.city == downName }
341
+ }
342
+
343
+ if (city == null) return
344
+
345
+ val cityCode = city.code
346
+ val cityName = city.city
347
+
348
+ when (status) {
349
+ OfflineMapStatus.SUCCESS -> {
350
+ synchronized(lock) {
351
+ downloadingCities.remove(cityCode)
352
+ pausedCities.remove(cityCode)
353
+ }
354
+ sendEvent("onDownloadComplete", Bundle().apply {
355
+ putString("cityCode", cityCode)
356
+ putString("cityName", cityName)
357
+ })
358
+ }
359
+
360
+ OfflineMapStatus.LOADING -> {
361
+ sendEvent("onDownloadProgress", Bundle().apply {
362
+ putString("cityCode", cityCode)
363
+ putString("cityName", cityName)
364
+ putInt("progress", completeCode)
365
+ putLong("receivedSize", (city.size * completeCode / 100))
366
+ putLong("expectedSize", city.size)
367
+ })
368
+ }
369
+
370
+ OfflineMapStatus.UNZIP -> {
371
+ sendEvent("onUnzipProgress", Bundle().apply {
372
+ putString("cityCode", cityCode)
373
+ putString("cityName", cityName)
374
+ })
375
+ }
376
+
377
+ OfflineMapStatus.ERROR -> {
378
+ synchronized(lock) {
379
+ downloadingCities.remove(cityCode)
380
+ }
381
+ sendEvent("onDownloadError", Bundle().apply {
382
+ putString("cityCode", cityCode)
383
+ putString("cityName", cityName)
384
+ putString("error", "解压失败,数据可能有问题")
385
+ })
386
+ }
387
+
388
+ OfflineMapStatus.EXCEPTION_NETWORK_LOADING -> {
389
+ sendEvent("onDownloadError", Bundle().apply {
390
+ putString("cityCode", cityCode)
391
+ putString("cityName", cityName)
392
+ putString("error", "网络异常")
393
+ })
394
+ }
395
+
396
+ OfflineMapStatus.EXCEPTION_AMAP -> {
397
+ synchronized(lock) {
398
+ downloadingCities.remove(cityCode)
399
+ }
400
+ sendEvent("onDownloadError", Bundle().apply {
401
+ putString("cityCode", cityCode)
402
+ putString("cityName", cityName)
403
+ putString("error", "认证异常,请检查Key")
404
+ })
405
+ }
406
+
407
+ OfflineMapStatus.EXCEPTION_SDCARD -> {
408
+ synchronized(lock) {
409
+ downloadingCities.remove(cityCode)
410
+ }
411
+ sendEvent("onDownloadError", Bundle().apply {
412
+ putString("cityCode", cityCode)
413
+ putString("cityName", cityName)
414
+ putString("error", "SD卡读写异常")
415
+ })
416
+ }
417
+
418
+ OfflineMapStatus.PAUSE -> {
419
+ // 检查是否是用户主动暂停
420
+ val isPaused = synchronized(lock) { pausedCities.contains(cityCode) }
421
+ if (isPaused) {
422
+ sendEvent("onDownloadPaused", Bundle().apply {
423
+ putString("cityCode", cityCode)
424
+ putString("cityName", cityName)
425
+ })
426
+ }
427
+ }
428
+ }
429
+ }
430
+
431
+ /**
432
+ * 转换城市对象为 Map
433
+ */
434
+ private fun convertCityToMap(city: OfflineMapCity): Bundle {
435
+ val isPaused = synchronized(lock) { pausedCities.contains(city.code) }
436
+ val isDownloading = synchronized(lock) { downloadingCities.contains(city.code) }
437
+
438
+ val status = when {
439
+ isPaused -> "paused"
440
+ isDownloading -> "downloading"
441
+ else -> getStatusString(city.state)
442
+ }
443
+
444
+ return Bundle().apply {
445
+ putString("cityCode", city.code)
446
+ putString("cityName", city.city)
447
+ putLong("size", city.size)
448
+ putString("status", status)
449
+ putInt("progress", city.getcompleteCode())
450
+ putString("version", city.version)
451
+ putLong("downloadedSize", (city.size * city.getcompleteCode() / 100))
452
+ }
453
+ }
454
+
455
+ /**
456
+ * 转换省份对象为 Map
457
+ */
458
+ private fun convertProvinceToMap(province: OfflineMapProvince): Bundle {
459
+ return Bundle().apply {
460
+ putString("cityCode", province.provinceCode)
461
+ putString("cityName", province.provinceName)
462
+ putLong("size", province.size)
463
+ putString("status", getStatusString(province.state))
464
+ putInt("progress", province.getcompleteCode())
465
+ putString("version", province.version)
466
+ putString("provinceName", province.provinceName)
467
+ putString("provinceCode", province.provinceCode)
468
+ }
469
+ }
470
+
471
+ /**
472
+ * 获取状态字符串
473
+ * 注意:只有 SUCCESS 状态才表示真正下载完成
474
+ */
475
+ private fun getStatusString(state: Int): String {
476
+ return when (state) {
477
+ OfflineMapStatus.SUCCESS -> "downloaded"
478
+ OfflineMapStatus.LOADING -> "downloading"
479
+ OfflineMapStatus.UNZIP -> "unzipping"
480
+ OfflineMapStatus.WAITING -> "downloading"
481
+ OfflineMapStatus.PAUSE -> "paused"
482
+ OfflineMapStatus.STOP -> "paused"
483
+ OfflineMapStatus.ERROR -> "failed"
484
+ OfflineMapStatus.EXCEPTION_NETWORK_LOADING -> "downloading" // 网络问题,可继续
485
+ OfflineMapStatus.EXCEPTION_AMAP -> "failed" // 认证异常
486
+ OfflineMapStatus.EXCEPTION_SDCARD -> "failed" // SD卡异常
487
+ OfflineMapStatus.START_DOWNLOAD_FAILD -> "failed" // 开始下载失败
488
+ OfflineMapStatus.CHECKUPDATES -> "not_downloaded"
489
+ OfflineMapStatus.NEW_VERSION -> "not_downloaded"
490
+ else -> "not_downloaded"
491
+ }
492
+ }
493
+ }