expo-gaode-map 2.2.26-next.0 → 2.2.26
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 +46 -0
- package/android/build.gradle +25 -1
- package/android/src/main/cpp/CMakeLists.txt +2 -0
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +3 -0
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapOfflineModule.kt +46 -4
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +34 -60
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapViewModule.kt +13 -3
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/utils/GeoUtils.d.ts.map +1 -1
- package/build/utils/GeoUtils.js +10 -3
- package/build/utils/GeoUtils.js.map +1 -1
- package/build/utils/throttle.d.ts +10 -0
- package/build/utils/throttle.d.ts.map +1 -0
- package/build/utils/throttle.js +19 -0
- package/build/utils/throttle.js.map +1 -0
- package/ios/ExpoGaodeMap.podspec +2 -4
- package/ios/ExpoGaodeMapModule.swift +1 -1
- package/ios/ExpoGaodeMapView.swift +6 -35
- package/ios/ExpoGaodeMapViewModule.swift +10 -2
- package/package.json +7 -11
- package/plugin/build/withGaodeMap.d.ts +6 -1
- package/plugin/build/withGaodeMap.js +58 -13
package/README.md
CHANGED
|
@@ -44,6 +44,14 @@
|
|
|
44
44
|
|
|
45
45
|
## 📦 安装
|
|
46
46
|
|
|
47
|
+
> ⚠️ **版本兼容性说明**:
|
|
48
|
+
> - 如果你的项目使用 **Expo SDK 54 及以上**,请安装 默认的 版本。
|
|
49
|
+
> - 如果你的项目使用 **Expo SDK 53 及以下**(如 50, 51, 52, 53),请使用 **V1** 版本(Tag: `v1`)。
|
|
50
|
+
> ```bash
|
|
51
|
+
> npm install expo-gaode-map@v1
|
|
52
|
+
> ```
|
|
53
|
+
> **说明**:V1 版本除了不支持**世界地图**功能外,其余 API 与 V2 (Latest) 版本完全一致。
|
|
54
|
+
|
|
47
55
|
### 方案一:仅使用地图和定位(核心包)
|
|
48
56
|
|
|
49
57
|
```bash
|
|
@@ -162,9 +170,46 @@ try {
|
|
|
162
170
|
}
|
|
163
171
|
}
|
|
164
172
|
```
|
|
173
|
+
### 5. 地图在模拟器上显示异常(可能会出现黑屏或闪退)
|
|
174
|
+
|
|
175
|
+
建议:
|
|
176
|
+
- 确保在真机上测试,模拟器可能不支持地图功能
|
|
177
|
+
- 检查是否正确配置了 API Key
|
|
165
178
|
|
|
166
179
|
**完整错误处理指南**:[ERROR_HANDLING_GUIDE.md](./ERROR_HANDLING_GUIDE.md)
|
|
167
180
|
|
|
181
|
+
### 6. Google Play 版本支持
|
|
182
|
+
|
|
183
|
+
如果你的应用需要上架 Google Play,需要使用高德地图 Google Play 版本的 SDK(通过了 Google Play 的合规审核)。
|
|
184
|
+
|
|
185
|
+
#### 步骤 1:下载 SDK
|
|
186
|
+
前往 [高德开放平台](https://lbs.amap.com/api/android-sdk/download) 下载包含 Google Play 版本的 SDK(通常是合包,包含地图、搜索、定位功能)。
|
|
187
|
+
|
|
188
|
+
#### 步骤 2:放入项目
|
|
189
|
+
将下载的 `.aar` 或 `.jar` 文件放入你的 Expo 项目根目录下的 `libs` 文件夹中(如果没有则创建),例如 `libs/AMap_3DMap_GooglePlay.aar`。
|
|
190
|
+
|
|
191
|
+
#### 步骤 3:配置插件
|
|
192
|
+
在 `app.json` 中配置 `customMapSdkPath`:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"expo": {
|
|
197
|
+
"plugins": [
|
|
198
|
+
[
|
|
199
|
+
"expo-gaode-map",
|
|
200
|
+
{
|
|
201
|
+
"androidKey": "your-android-key",
|
|
202
|
+
"iosKey": "your-ios-key",
|
|
203
|
+
"customMapSdkPath": "./libs/AMap_3DMap_GooglePlay.aar"
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
> **注意**:Google Play 版本的 SDK 通常是合包(包含地图+搜索+定位)。如果你的项目中引入了其他高德相关依赖(如 `expo-gaode-map-search`),可能会导致类冲突。插件会自动处理大部分冲突,但如果依然遇到 `Duplicate class` 错误,请检查是否引入了多余的依赖。
|
|
212
|
+
|
|
168
213
|
支持的错误类型:
|
|
169
214
|
- `SDK_NOT_INITIALIZED` - SDK 未初始化
|
|
170
215
|
- `INVALID_API_KEY` - API Key 配置错误
|
|
@@ -185,6 +230,7 @@ MIT
|
|
|
185
230
|
|
|
186
231
|
- [在线文档](https://TomWq.github.io/expo-gaode-map/)
|
|
187
232
|
- [错误处理指南](./ERROR_HANDLING_GUIDE.md) 🆕
|
|
233
|
+
- [性能优化指南](./PERFORMANCE_GUIDE.md) 🆕
|
|
188
234
|
- [GitHub 仓库](https://github.com/TomWq/expo-gaode-map)
|
|
189
235
|
- [示例项目(地图)](https://github.com/TomWq/expo-gaode-map-example)
|
|
190
236
|
- [示例项目(导航)](https://github.com/TomWq/expo-gaode-map-navigation-example)
|
package/android/build.gradle
CHANGED
|
@@ -54,5 +54,29 @@ android {
|
|
|
54
54
|
|
|
55
55
|
dependencies {
|
|
56
56
|
// 高德地图 3D SDK
|
|
57
|
-
|
|
57
|
+
def customSdkPath = null
|
|
58
|
+
println "ExpoGaodeMap: Checking for custom SDK property in rootProject: ${rootProject.name}"
|
|
59
|
+
if (rootProject.hasProperty("EXPO_GAODE_MAP_CUSTOM_SDK_PATH")) {
|
|
60
|
+
customSdkPath = rootProject.property("EXPO_GAODE_MAP_CUSTOM_SDK_PATH")
|
|
61
|
+
println "ExpoGaodeMap: Found custom SDK path property: ${customSdkPath}"
|
|
62
|
+
} else {
|
|
63
|
+
println "ExpoGaodeMap: No custom SDK path property found."
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (customSdkPath) {
|
|
67
|
+
def sdkFile = rootProject.file(customSdkPath)
|
|
68
|
+
if (!sdkFile.exists()) {
|
|
69
|
+
// Try to find the file relative to the project root (parent of android folder)
|
|
70
|
+
sdkFile = new File(rootProject.projectDir.parentFile, customSdkPath)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (sdkFile.exists()) {
|
|
74
|
+
println "ExpoGaodeMap: Using custom Map SDK from ${sdkFile.absolutePath}"
|
|
75
|
+
implementation files(sdkFile)
|
|
76
|
+
} else {
|
|
77
|
+
throw new FileNotFoundException("ExpoGaodeMap: Could not find custom SDK at ${customSdkPath}. Please check your customMapSdkPath configuration.")
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
implementation ('com.amap.api:3dmap:latest.integration')
|
|
81
|
+
}
|
|
58
82
|
}
|
|
@@ -79,6 +79,9 @@ class ExpoGaodeMapModule : Module() {
|
|
|
79
79
|
SDKInitializer.initSDK(appContext.reactContext!!, androidKey)
|
|
80
80
|
getLocationManager() // 初始化定位管理器
|
|
81
81
|
|
|
82
|
+
// 打印当前 SDK 版本信息,便于验证依赖来源
|
|
83
|
+
android.util.Log.i("ExpoGaodeMap", "✅ SDK 初始化完成 - Version: ${MapsInitializer.getVersion()}")
|
|
84
|
+
|
|
82
85
|
// 初始化成功后自动触发一次预加载
|
|
83
86
|
MapPreloadManager.startPreload(appContext.reactContext!!, poolSize = 1)
|
|
84
87
|
} catch (e: SecurityException) {
|
|
@@ -446,9 +446,9 @@ class ExpoGaodeMapOfflineModule : Module() {
|
|
|
446
446
|
putString("cityName", city.city)
|
|
447
447
|
putLong("size", city.size)
|
|
448
448
|
putString("status", status)
|
|
449
|
-
putInt("progress", city
|
|
449
|
+
putInt("progress", getDownloadProgress(city))
|
|
450
450
|
putString("version", city.version)
|
|
451
|
-
putLong("downloadedSize", (city.size * city
|
|
451
|
+
putLong("downloadedSize", (city.size * getDownloadProgress(city) / 100))
|
|
452
452
|
}
|
|
453
453
|
}
|
|
454
454
|
|
|
@@ -461,12 +461,54 @@ class ExpoGaodeMapOfflineModule : Module() {
|
|
|
461
461
|
putString("cityName", province.provinceName)
|
|
462
462
|
putLong("size", province.size)
|
|
463
463
|
putString("status", getStatusString(province.state))
|
|
464
|
-
putInt("progress", province
|
|
464
|
+
putInt("progress", getDownloadProgress(province))
|
|
465
465
|
putString("version", province.version)
|
|
466
466
|
putString("provinceName", province.provinceName)
|
|
467
467
|
putString("provinceCode", province.provinceCode)
|
|
468
468
|
}
|
|
469
469
|
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* 兼容获取 START_DOWNLOAD_FAILED 状态码
|
|
473
|
+
* 国内版拼写为 START_DOWNLOAD_FAILD,Google Play 版修正为 START_DOWNLOAD_FAILED
|
|
474
|
+
*/
|
|
475
|
+
private val startDownloadFailedCode: Int by lazy {
|
|
476
|
+
try {
|
|
477
|
+
OfflineMapStatus::class.java.getField("START_DOWNLOAD_FAILED").getInt(null)
|
|
478
|
+
} catch (e: Exception) {
|
|
479
|
+
try {
|
|
480
|
+
OfflineMapStatus::class.java.getField("START_DOWNLOAD_FAILD").getInt(null)
|
|
481
|
+
} catch (e2: Exception) {
|
|
482
|
+
-1
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* 兼容获取下载进度
|
|
489
|
+
* Google Play 版本 SDK 可能修复了 getcompleteCode 的命名或使用了不同的 API
|
|
490
|
+
*/
|
|
491
|
+
private fun getDownloadProgress(obj: Any): Int {
|
|
492
|
+
try {
|
|
493
|
+
// 尝试标准版的命名 (getcompleteCode)
|
|
494
|
+
val method = obj.javaClass.getMethod("getcompleteCode")
|
|
495
|
+
return method.invoke(obj) as Int
|
|
496
|
+
} catch (e: Exception) {
|
|
497
|
+
try {
|
|
498
|
+
// 尝试修正后的命名 (getCompleteCode) - Google Play 版本可能使用此命名
|
|
499
|
+
val method = obj.javaClass.getMethod("getCompleteCode")
|
|
500
|
+
return method.invoke(obj) as Int
|
|
501
|
+
} catch (e2: Exception) {
|
|
502
|
+
// 如果都失败了,尝试直接访问 completeCode 字段
|
|
503
|
+
try {
|
|
504
|
+
val field = obj.javaClass.getField("completeCode")
|
|
505
|
+
return field.getInt(obj)
|
|
506
|
+
} catch (e3: Exception) {
|
|
507
|
+
return 0
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
470
512
|
|
|
471
513
|
/**
|
|
472
514
|
* 获取状态字符串
|
|
@@ -484,7 +526,7 @@ class ExpoGaodeMapOfflineModule : Module() {
|
|
|
484
526
|
OfflineMapStatus.EXCEPTION_NETWORK_LOADING -> "downloading" // 网络问题,可继续
|
|
485
527
|
OfflineMapStatus.EXCEPTION_AMAP -> "failed" // 认证异常
|
|
486
528
|
OfflineMapStatus.EXCEPTION_SDCARD -> "failed" // SD卡异常
|
|
487
|
-
|
|
529
|
+
startDownloadFailedCode -> "failed" // 兼容两种拼写的开始下载失败
|
|
488
530
|
OfflineMapStatus.CHECKUPDATES -> "not_downloaded"
|
|
489
531
|
OfflineMapStatus.NEW_VERSION -> "not_downloaded"
|
|
490
532
|
else -> "not_downloaded"
|
|
@@ -5,7 +5,7 @@ import android.content.Context
|
|
|
5
5
|
import android.view.View
|
|
6
6
|
import android.view.ViewGroup
|
|
7
7
|
import com.amap.api.maps.AMap
|
|
8
|
-
import com.amap.api.maps.
|
|
8
|
+
import com.amap.api.maps.TextureMapView
|
|
9
9
|
import com.amap.api.maps.MapsInitializer
|
|
10
10
|
import com.amap.api.maps.model.LatLng
|
|
11
11
|
import expo.modules.kotlin.AppContext
|
|
@@ -64,23 +64,11 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
64
64
|
private val onCameraMove by EventDispatcher()
|
|
65
65
|
private val onCameraIdle by EventDispatcher()
|
|
66
66
|
|
|
67
|
-
//
|
|
68
|
-
/** 相机移动事件节流间隔(毫秒) */
|
|
69
|
-
private val CAMERA_MOVE_THROTTLE_MS = 100L
|
|
70
|
-
/** 上次触发相机移动事件的时间戳 */
|
|
71
|
-
private var lastCameraMoveTime = 0L
|
|
72
|
-
/** 缓存的相机移动事件数据 */
|
|
67
|
+
// 缓存的相机移动事件数据
|
|
73
68
|
private var pendingCameraMoveData: Map<String, Any>? = null
|
|
74
|
-
/** 节流定时器 Runnable */
|
|
75
|
-
private val throttleRunnable = Runnable {
|
|
76
|
-
pendingCameraMoveData?.let { data ->
|
|
77
|
-
onCameraMove(data)
|
|
78
|
-
pendingCameraMoveData = null
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
69
|
|
|
82
70
|
// 高德地图视图
|
|
83
|
-
private lateinit var mapView:
|
|
71
|
+
private lateinit var mapView: TextureMapView
|
|
84
72
|
private lateinit var aMap: AMap
|
|
85
73
|
|
|
86
74
|
// 管理器
|
|
@@ -97,18 +85,9 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
97
85
|
MapsInitializer.updatePrivacyShow(context, true, true)
|
|
98
86
|
MapsInitializer.updatePrivacyAgree(context, true)
|
|
99
87
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (preloadedMapView != null) {
|
|
104
|
-
mapView = preloadedMapView
|
|
105
|
-
android.util.Log.i("ExpoGaodeMapView", "🚀 使用预加载的 MapView 实例")
|
|
106
|
-
} else {
|
|
107
|
-
// 创建地图视图
|
|
108
|
-
mapView = MapView(context)
|
|
109
|
-
mapView.onCreate(null)
|
|
110
|
-
android.util.Log.i("ExpoGaodeMapView", "⚠️ 创建新的 MapView 实例 (未命中预加载池)")
|
|
111
|
-
}
|
|
88
|
+
// 创建地图视图 - 使用 TextureMapView 以支持截图
|
|
89
|
+
mapView = TextureMapView(context)
|
|
90
|
+
mapView.onCreate(null)
|
|
112
91
|
|
|
113
92
|
aMap = mapView.map
|
|
114
93
|
|
|
@@ -184,7 +163,6 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
184
163
|
|
|
185
164
|
// 相机移动中 - 应用节流优化
|
|
186
165
|
cameraPosition?.let {
|
|
187
|
-
val currentTime = System.currentTimeMillis()
|
|
188
166
|
val visibleRegion = aMap.projection.visibleRegion
|
|
189
167
|
val eventData = mapOf(
|
|
190
168
|
"cameraPosition" to mapOf(
|
|
@@ -208,23 +186,16 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
208
186
|
)
|
|
209
187
|
)
|
|
210
188
|
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
pendingCameraMoveData = eventData
|
|
222
|
-
mainHandler.removeCallbacks(throttleRunnable)
|
|
223
|
-
mainHandler.postDelayed(
|
|
224
|
-
throttleRunnable,
|
|
225
|
-
CAMERA_MOVE_THROTTLE_MS - (currentTime - lastCameraMoveTime)
|
|
226
|
-
)
|
|
227
|
-
}
|
|
189
|
+
// 使用 onCameraMove 自身的节流机制(如果在 Module 定义中配置了 Coalescing)
|
|
190
|
+
// 或者在这里简单发送,让 JS 端处理节流,或者依赖 Expo 的事件批处理
|
|
191
|
+
// 这里我们移除自定义的 Handler 实现,直接发送事件,简化代码逻辑
|
|
192
|
+
// 注意:高德地图的 onCameraChange 调用频率非常高,
|
|
193
|
+
// 建议在 Module 定义中使用 Events("onCameraMove") 时考虑是否需要原生侧节流
|
|
194
|
+
// 目前 Expo Modules 默认没有自动节流,但为了代码简洁和避免 Handler 泄漏风险,
|
|
195
|
+
// 我们可以依赖 JS 端的 debounce/throttle,或者如果性能是瓶颈,再加回轻量级的节流。
|
|
196
|
+
// 鉴于之前的 Handler 实现比较复杂且容易出错,我们先简化。
|
|
197
|
+
|
|
198
|
+
onCameraMove(eventData)
|
|
228
199
|
}
|
|
229
200
|
}
|
|
230
201
|
|
|
@@ -493,27 +464,34 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
493
464
|
|
|
494
465
|
aMap.getMapScreenShot(object : AMap.OnMapScreenShotListener {
|
|
495
466
|
override fun onMapScreenShot(bitmap: android.graphics.Bitmap?) {
|
|
496
|
-
//
|
|
467
|
+
// 这个回调通常在旧版 SDK 或部分机型触发
|
|
468
|
+
// 如果已经处理过(通过带 status 的回调),则忽略
|
|
497
469
|
if (isSettled.getAndSet(true)) return
|
|
498
470
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
471
|
+
if (bitmap == null) {
|
|
472
|
+
promise.reject("SNAPSHOT_FAILED", "Bitmap is null", null)
|
|
473
|
+
return
|
|
502
474
|
}
|
|
475
|
+
handleSnapshot(bitmap, promise)
|
|
503
476
|
}
|
|
504
477
|
|
|
505
478
|
override fun onMapScreenShot(bitmap: android.graphics.Bitmap?, status: Int) {
|
|
506
479
|
// 如果已经处理过,直接返回
|
|
507
480
|
if (isSettled.getAndSet(true)) return
|
|
508
481
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
promise.reject("SNAPSHOT_FAILED", "Failed to take snapshot, status code: $status", null)
|
|
482
|
+
if (bitmap == null) {
|
|
483
|
+
promise.reject("SNAPSHOT_FAILED", "Bitmap is null", null)
|
|
512
484
|
return
|
|
513
485
|
}
|
|
514
|
-
|
|
515
|
-
|
|
486
|
+
|
|
487
|
+
// 根据高德文档:
|
|
488
|
+
// status != 0 地图渲染完成,截屏无网格
|
|
489
|
+
// status == 0 地图未渲染完成,截屏有网格
|
|
490
|
+
if (status == 0) {
|
|
491
|
+
android.util.Log.w("ExpoGaodeMapView", "Warning: Map snapshot taken before rendering completed (grid may be visible)")
|
|
516
492
|
}
|
|
493
|
+
|
|
494
|
+
handleSnapshot(bitmap, promise)
|
|
517
495
|
}
|
|
518
496
|
})
|
|
519
497
|
}
|
|
@@ -601,10 +579,6 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
601
579
|
@Suppress("unused")
|
|
602
580
|
fun onDestroy() {
|
|
603
581
|
try {
|
|
604
|
-
// 清理节流定时器
|
|
605
|
-
mainHandler.removeCallbacks(throttleRunnable)
|
|
606
|
-
pendingCameraMoveData = null
|
|
607
|
-
|
|
608
582
|
// 清理 Handler 回调,防止内存泄露
|
|
609
583
|
mainHandler.removeCallbacksAndMessages(null)
|
|
610
584
|
|
|
@@ -654,7 +628,7 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
654
628
|
return
|
|
655
629
|
}
|
|
656
630
|
|
|
657
|
-
if (child is
|
|
631
|
+
if (child is TextureMapView) {
|
|
658
632
|
super.addView(child, index)
|
|
659
633
|
return
|
|
660
634
|
}
|
|
@@ -702,7 +676,7 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
702
676
|
try {
|
|
703
677
|
val child = super.getChildAt(index)
|
|
704
678
|
|
|
705
|
-
if (child is
|
|
679
|
+
if (child is TextureMapView) {
|
|
706
680
|
return
|
|
707
681
|
}
|
|
708
682
|
|
|
@@ -3,6 +3,16 @@ package expo.modules.gaodemap
|
|
|
3
3
|
import expo.modules.kotlin.modules.Module
|
|
4
4
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
5
5
|
|
|
6
|
+
import expo.modules.kotlin.types.Enumerable
|
|
7
|
+
|
|
8
|
+
enum class MapType(val value: Int) : Enumerable {
|
|
9
|
+
STANDARD(1),
|
|
10
|
+
SATELLITE(2),
|
|
11
|
+
NIGHT(3),
|
|
12
|
+
NAVI(4),
|
|
13
|
+
BUS(5)
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
/**
|
|
7
17
|
* 高德地图视图 Module
|
|
8
18
|
*/
|
|
@@ -24,9 +34,9 @@ class ExpoGaodeMapViewModule : Module() {
|
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
|
|
27
|
-
Prop<
|
|
28
|
-
view.mapType = type
|
|
29
|
-
view.setMapType(type)
|
|
37
|
+
Prop<MapType>("mapType") { view, type ->
|
|
38
|
+
view.mapType = type.value
|
|
39
|
+
view.setMapType(type.value)
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
Prop<Map<String, Any?>?>("initialCameraPosition") { view, position ->
|
package/build/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { PlatformDetector, DeviceType, FoldState, isAndroid14Plus, isiOS17Plus,
|
|
|
10
10
|
export type { DeviceInfo, SystemVersion } from './utils/PlatformDetector';
|
|
11
11
|
export { PermissionUtils, PermissionManager, // 向后兼容的别名
|
|
12
12
|
LocationPermissionType, } from './utils/PermissionUtils';
|
|
13
|
+
export { throttle } from './utils/throttle';
|
|
13
14
|
export { FoldableMapView, useFoldableMap, } from './components/FoldableMapView';
|
|
14
15
|
export type { FoldableMapViewProps, FoldableConfig, } from './components/FoldableMapView';
|
|
15
16
|
export { default as ExpoGaodeMapOfflineModule } from './utils/OfflineMapManager';
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAC;AAExB,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,OAAO,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,GACR,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GACP,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG1E,OAAO,EACL,eAAe,EACf,iBAAiB,EAAE,UAAU;AAC7B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,eAAe,EACf,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,oBAAoB,EACpB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEjF,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAM/B;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,wOAGjC,CAAA;AAGF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAC;AAExB,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,OAAO,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,GACR,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GACP,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG1E,OAAO,EACL,eAAe,EACf,iBAAiB,EAAE,UAAU;AAC7B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EACL,eAAe,EACf,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,oBAAoB,EACpB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEjF,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAM/B;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,wOAGjC,CAAA;AAGF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -17,6 +17,8 @@ export { PlatformDetector, DeviceType, FoldState, isAndroid14Plus, isiOS17Plus,
|
|
|
17
17
|
// 导出权限工具类(仅提供文案和诊断,实际权限请求使用 ExpoGaodeMapModule)
|
|
18
18
|
export { PermissionUtils, PermissionManager, // 向后兼容的别名
|
|
19
19
|
LocationPermissionType, } from './utils/PermissionUtils';
|
|
20
|
+
// 导出节流工具函数
|
|
21
|
+
export { throttle } from './utils/throttle';
|
|
20
22
|
// 导出折叠屏适配组件
|
|
21
23
|
export { FoldableMapView, useFoldableMap, } from './components/FoldableMapView';
|
|
22
24
|
// 导出离线地图 API
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,6BAA6B,MAAM,sBAAsB,CAAC;AAEjE,mBAAmB;AACnB,cAAc,SAAS,CAAC;AACxB,SAAS;AACT,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAErE,WAAW;AACX,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,UAAU;AACV,OAAO,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,GACR,MAAM,uBAAuB,CAAC;AAE/B,WAAW;AACX,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,sBAAsB,CAAC;AAG9B,WAAW;AACX,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GACP,MAAM,0BAA0B,CAAC;AAGlC,gDAAgD;AAChD,OAAO,EACL,eAAe,EACf,iBAAiB,EAAE,UAAU;AAC7B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,YAAY;AACZ,OAAO,EACL,eAAe,EACf,cAAc,GACf,MAAM,8BAA8B,CAAC;AAMtC,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAejF,MAAM,uBAAuB,GAAG,6BAA6B,CAAC,yBAAyB,CAAA;AACvF,MAAM,mBAAmB,GAAG,6BAA6B,CAAC,uBAAuB,CAAA;AAGjF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;IACzD,SAAS,EAAE,mBAAmB;IAC9B,aAAa,EAAE,uBAAuB;CACvC,CAAC,CAAA;AAEF,yBAAyB;AACzB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D,WAAW;AACX,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["\nimport { createPermissionHook } from 'expo-modules-core';\nimport ExpoGaodeMapModuleWithHelpers from './ExpoGaodeMapModule';\n\n// 导出类型定义(包含所有通用类型)\nexport * from './types';\n// 导出原生模块\nexport { default as ExpoGaodeMapModule } from './ExpoGaodeMapModule';\n\n// 导出地图视图组件\nexport { default as MapView } from './ExpoGaodeMapView';\nexport { useMap } from './components/MapContext';\nexport { MapUI } from './components/MapUI';\n\n// 导出覆盖物组件\nexport {\n Marker,\n Polyline,\n Polygon,\n Circle,\n HeatMap,\n MultiPoint,\n Cluster,\n} from './components/overlays';\n\n// 导出错误处理工具\nexport {\n ErrorHandler,\n ErrorLogger,\n GaodeMapError,\n ErrorType,\n} from './utils/ErrorHandler';\nexport type { ErrorDetails } from './utils/ErrorHandler';\n\n// 导出平台检测工具\nexport {\n PlatformDetector,\n DeviceType,\n FoldState,\n isAndroid14Plus,\n isiOS17Plus,\n isTablet,\n isFoldable,\n isIPad,\n} from './utils/PlatformDetector';\nexport type { DeviceInfo, SystemVersion } from './utils/PlatformDetector';\n\n// 导出权限工具类(仅提供文案和诊断,实际权限请求使用 ExpoGaodeMapModule)\nexport {\n PermissionUtils,\n PermissionManager, // 向后兼容的别名\n LocationPermissionType,\n} from './utils/PermissionUtils';\n\n// 导出折叠屏适配组件\nexport {\n FoldableMapView,\n useFoldableMap,\n} from './components/FoldableMapView';\nexport type {\n FoldableMapViewProps,\n FoldableConfig,\n} from './components/FoldableMapView';\n\n// 导出离线地图 API\nexport { default as ExpoGaodeMapOfflineModule } from './utils/OfflineMapManager';\n\nexport type {\n OfflineMapInfo,\n OfflineMapStatus,\n OfflineMapDownloadConfig,\n OfflineMapDownloadEvent,\n OfflineMapCompleteEvent,\n OfflineMapErrorEvent,\n OfflineMapPausedEvent,\n OfflineMapCancelledEvent,\n OfflineMapStorageInfo,\n OfflineMapEvents,\n} from './types/offline.types';\n\nconst requestPermissionsAsync = ExpoGaodeMapModuleWithHelpers.requestLocationPermission\nconst getPermissionsAsync = ExpoGaodeMapModuleWithHelpers.checkLocationPermission\n\n\n/**\n * Check or request permissions to access the location.\n * This uses both `requestPermissionsAsync` and `getPermissionsAsync` to interact with the permissions.\n *\n * @example\n * ```ts\n * const [status, requestPermission] = useLocationPermissions();\n * ```\n */\nexport const useLocationPermissions = createPermissionHook({\n getMethod: getPermissionsAsync,\n requestMethod: requestPermissionsAsync,\n})\n\n// 导出便捷读取的 SDK 配置与 webKey\nexport { getSDKConfig, getWebKey } from './ExpoGaodeMapModule';\n\n// 默认导出原生模块\nexport { default } from './ExpoGaodeMapModule';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,6BAA6B,MAAM,sBAAsB,CAAC;AAEjE,mBAAmB;AACnB,cAAc,SAAS,CAAC;AACxB,SAAS;AACT,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAErE,WAAW;AACX,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,UAAU;AACV,OAAO,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,OAAO,GACR,MAAM,uBAAuB,CAAC;AAE/B,WAAW;AACX,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,GACV,MAAM,sBAAsB,CAAC;AAG9B,WAAW;AACX,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,eAAe,EACf,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GACP,MAAM,0BAA0B,CAAC;AAGlC,gDAAgD;AAChD,OAAO,EACL,eAAe,EACf,iBAAiB,EAAE,UAAU;AAC7B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,WAAW;AACX,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,YAAY;AACZ,OAAO,EACL,eAAe,EACf,cAAc,GACf,MAAM,8BAA8B,CAAC;AAMtC,aAAa;AACb,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAejF,MAAM,uBAAuB,GAAG,6BAA6B,CAAC,yBAAyB,CAAA;AACvF,MAAM,mBAAmB,GAAG,6BAA6B,CAAC,uBAAuB,CAAA;AAGjF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;IACzD,SAAS,EAAE,mBAAmB;IAC9B,aAAa,EAAE,uBAAuB;CACvC,CAAC,CAAA;AAEF,yBAAyB;AACzB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE/D,WAAW;AACX,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC","sourcesContent":["\nimport { createPermissionHook } from 'expo-modules-core';\nimport ExpoGaodeMapModuleWithHelpers from './ExpoGaodeMapModule';\n\n// 导出类型定义(包含所有通用类型)\nexport * from './types';\n// 导出原生模块\nexport { default as ExpoGaodeMapModule } from './ExpoGaodeMapModule';\n\n// 导出地图视图组件\nexport { default as MapView } from './ExpoGaodeMapView';\nexport { useMap } from './components/MapContext';\nexport { MapUI } from './components/MapUI';\n\n// 导出覆盖物组件\nexport {\n Marker,\n Polyline,\n Polygon,\n Circle,\n HeatMap,\n MultiPoint,\n Cluster,\n} from './components/overlays';\n\n// 导出错误处理工具\nexport {\n ErrorHandler,\n ErrorLogger,\n GaodeMapError,\n ErrorType,\n} from './utils/ErrorHandler';\nexport type { ErrorDetails } from './utils/ErrorHandler';\n\n// 导出平台检测工具\nexport {\n PlatformDetector,\n DeviceType,\n FoldState,\n isAndroid14Plus,\n isiOS17Plus,\n isTablet,\n isFoldable,\n isIPad,\n} from './utils/PlatformDetector';\nexport type { DeviceInfo, SystemVersion } from './utils/PlatformDetector';\n\n// 导出权限工具类(仅提供文案和诊断,实际权限请求使用 ExpoGaodeMapModule)\nexport {\n PermissionUtils,\n PermissionManager, // 向后兼容的别名\n LocationPermissionType,\n} from './utils/PermissionUtils';\n\n// 导出节流工具函数\nexport { throttle } from './utils/throttle';\n\n// 导出折叠屏适配组件\nexport {\n FoldableMapView,\n useFoldableMap,\n} from './components/FoldableMapView';\nexport type {\n FoldableMapViewProps,\n FoldableConfig,\n} from './components/FoldableMapView';\n\n// 导出离线地图 API\nexport { default as ExpoGaodeMapOfflineModule } from './utils/OfflineMapManager';\n\nexport type {\n OfflineMapInfo,\n OfflineMapStatus,\n OfflineMapDownloadConfig,\n OfflineMapDownloadEvent,\n OfflineMapCompleteEvent,\n OfflineMapErrorEvent,\n OfflineMapPausedEvent,\n OfflineMapCancelledEvent,\n OfflineMapStorageInfo,\n OfflineMapEvents,\n} from './types/offline.types';\n\nconst requestPermissionsAsync = ExpoGaodeMapModuleWithHelpers.requestLocationPermission\nconst getPermissionsAsync = ExpoGaodeMapModuleWithHelpers.checkLocationPermission\n\n\n/**\n * Check or request permissions to access the location.\n * This uses both `requestPermissionsAsync` and `getPermissionsAsync` to interact with the permissions.\n *\n * @example\n * ```ts\n * const [status, requestPermission] = useLocationPermissions();\n * ```\n */\nexport const useLocationPermissions = createPermissionHook({\n getMethod: getPermissionsAsync,\n requestMethod: requestPermissionsAsync,\n})\n\n// 导出便捷读取的 SDK 配置与 webKey\nexport { getSDKConfig, getWebKey } from './ExpoGaodeMapModule';\n\n// 默认导出原生模块\nexport { default } from './ExpoGaodeMapModule';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeoUtils.d.ts","sourceRoot":"","sources":["../../src/utils/GeoUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"GeoUtils.d.ts","sourceRoot":"","sources":["../../src/utils/GeoUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA+B1D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC;AACrE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;AACzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC"}
|
package/build/utils/GeoUtils.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export function normalizeLatLng(point) {
|
|
10
10
|
if (Array.isArray(point)) {
|
|
11
|
-
let longitude = point[0];
|
|
12
|
-
let latitude = point[1];
|
|
11
|
+
let longitude = Number(point[0]);
|
|
12
|
+
let latitude = Number(point[1]);
|
|
13
13
|
// 智能纠错:如果纬度超出范围 [-90, 90] 且交换后在范围内,则认为是用户传反了
|
|
14
14
|
if (Math.abs(latitude) > 90 && Math.abs(longitude) <= 90) {
|
|
15
15
|
console.warn(`[expo-gaode-map] 检测到坐标数组格式可能为 [latitude, longitude] (${point}),已自动纠正为 [longitude, latitude]。建议显式使用 [经度, 纬度] 格式以遵循 GeoJSON 标准。`);
|
|
@@ -23,7 +23,14 @@ export function normalizeLatLng(point) {
|
|
|
23
23
|
latitude,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
-
//
|
|
26
|
+
// 对象格式:强制转换为数字,防止传入 string 类型导致原生层 Crash
|
|
27
|
+
if (point && typeof point === 'object') {
|
|
28
|
+
const p = point;
|
|
29
|
+
return {
|
|
30
|
+
latitude: Number(p.latitude),
|
|
31
|
+
longitude: Number(p.longitude),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
27
34
|
return point;
|
|
28
35
|
}
|
|
29
36
|
export function normalizeLatLngList(points) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeoUtils.js","sourceRoot":"","sources":["../../src/utils/GeoUtils.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"GeoUtils.js","sourceRoot":"","sources":["../../src/utils/GeoUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import { LatLng, LatLngPoint } from '../types/common.types';\n\n/**\n * 将坐标点归一化为对象格式\n * 支持 [longitude, latitude] 数组或 { latitude, longitude } 对象\n * 注意:数组格式遵循 GeoJSON 标准,即 [经度, 纬度]\n * \n * @param point 坐标点\n * @returns { latitude, longitude } 对象\n */\nexport function normalizeLatLng(point: LatLngPoint): LatLng {\n if (Array.isArray(point)) {\n let longitude = Number(point[0]);\n let latitude = Number(point[1]);\n\n // 智能纠错:如果纬度超出范围 [-90, 90] 且交换后在范围内,则认为是用户传反了\n if (Math.abs(latitude) > 90 && Math.abs(longitude) <= 90) {\n console.warn(\n `[expo-gaode-map] 检测到坐标数组格式可能为 [latitude, longitude] (${point}),已自动纠正为 [longitude, latitude]。建议显式使用 [经度, 纬度] 格式以遵循 GeoJSON 标准。`\n );\n return {\n latitude: longitude,\n longitude: latitude\n };\n }\n\n return {\n longitude,\n latitude,\n };\n }\n // 对象格式:强制转换为数字,防止传入 string 类型导致原生层 Crash\n if (point && typeof point === 'object') {\n const p = point as any;\n return {\n latitude: Number(p.latitude),\n longitude: Number(p.longitude),\n };\n }\n \n return point as LatLng;\n}\n\n/**\n * 将坐标点数组归一化为对象数组\n * 支持一维数组 [p1, p2, ...] 或二维嵌套数组 [[p1, p2, ...], [p3, p4, ...]]\n * \n * @param points 坐标点数组或嵌套数组\n * @returns 归一化后的坐标数组\n */\nexport function normalizeLatLngList(points: LatLngPoint[]): LatLng[];\nexport function normalizeLatLngList(points: LatLngPoint[][]): LatLng[][];\nexport function normalizeLatLngList(points: LatLngPoint[] | LatLngPoint[][]): LatLng[] | LatLng[][];\nexport function normalizeLatLngList(points: any): any {\n if (!points || points.length === 0) return [];\n\n // 检查是否为嵌套数组 (检查第一项是否也是数组或对象,且不符合 LatLngPoint 的基本判断)\n // 如果第一项是数组且长度 > 2,或者第一项的第一个元素也是数组/对象,则认为是嵌套数组\n const firstItem = points[0];\n \n if (Array.isArray(firstItem)) {\n // 如果第一项是 [number, number],则这可能是一个一维坐标点数组 (LatLngPoint[])\n // 除非所有元素都是数组且至少有一个子数组长度不等于2,或者我们明确知道这是嵌套的\n // 为了支持 Polygon 的嵌套格式,我们需要递归处理\n \n // 启发式判断:如果第一项是数组且它的第一个元素也是数组或对象,那么它一定是嵌套的\n if (Array.isArray(firstItem[0]) || (typeof firstItem[0] === 'object' && firstItem[0] !== null && 'latitude' in firstItem[0])) {\n return (points as LatLngPoint[][]).map(ring => ring.map(normalizeLatLng));\n }\n \n // 另一种情况:用户传入的是 [[lng, lat], [lng, lat]],这既可以看作 LatLngPoint[],\n // 也可以看作 LatLngPoint[][] (只有一个外轮廓)。\n // 在 Polygon 组件中,我们希望统一处理。\n // 如果是 Polygon 传入的,我们希望保留嵌套结构。\n // 但 normalizeLatLngList 是通用的。\n \n // 改进逻辑:如果 data[0] 是一个点,我们把它当作一维数组处理。\n // 如果 data[0] 不是一个点(即它是点的集合),我们当作二维处理。\n if (isPoint(firstItem)) {\n return (points as LatLngPoint[]).map(normalizeLatLng);\n } else {\n return (points as LatLngPoint[][]).map(ring => ring.map(normalizeLatLng));\n }\n }\n\n return (points as LatLngPoint[]).map(normalizeLatLng);\n}\n\n/**\n * 判断一个对象是否为坐标点 (LatLngPoint)\n */\nfunction isPoint(item: unknown): item is LatLngPoint {\n if (!item || typeof item !== 'object') return false;\n // { latitude, longitude } 格式\n if ('latitude' in item && 'longitude' in (item as Record<string, unknown>)) return true;\n // [longitude, latitude] 格式\n if (Array.isArray(item) && item.length >= 2 && typeof item[0] === 'number' && typeof item[1] === 'number') return true;\n return false;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一个轻量级的节流函数,用于限制函数调用的频率。
|
|
3
|
+
* 特别适用于处理高频事件,如地图移动、滚动等。
|
|
4
|
+
*
|
|
5
|
+
* @param func 需要节流的函数
|
|
6
|
+
* @param limit 时间间隔(毫秒)
|
|
7
|
+
* @returns 节流后的函数
|
|
8
|
+
*/
|
|
9
|
+
export declare function throttle<T extends (...args: any[]) => void>(func: T, limit: number): T;
|
|
10
|
+
//# sourceMappingURL=throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/utils/throttle.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAStF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一个轻量级的节流函数,用于限制函数调用的频率。
|
|
3
|
+
* 特别适用于处理高频事件,如地图移动、滚动等。
|
|
4
|
+
*
|
|
5
|
+
* @param func 需要节流的函数
|
|
6
|
+
* @param limit 时间间隔(毫秒)
|
|
7
|
+
* @returns 节流后的函数
|
|
8
|
+
*/
|
|
9
|
+
export function throttle(func, limit) {
|
|
10
|
+
let inThrottle;
|
|
11
|
+
return function (...args) {
|
|
12
|
+
if (!inThrottle) {
|
|
13
|
+
func.apply(this, args);
|
|
14
|
+
inThrottle = true;
|
|
15
|
+
setTimeout(() => (inThrottle = false), limit);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=throttle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../src/utils/throttle.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAqC,IAAO,EAAE,KAAa;IACjF,IAAI,UAAmB,CAAC;IACxB,OAAO,UAAoB,GAAG,IAAW;QACvC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvB,UAAU,GAAG,IAAI,CAAC;YAClB,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;IACH,CAAM,CAAC;AACT,CAAC","sourcesContent":["\n/**\n * 一个轻量级的节流函数,用于限制函数调用的频率。\n * 特别适用于处理高频事件,如地图移动、滚动等。\n *\n * @param func 需要节流的函数\n * @param limit 时间间隔(毫秒)\n * @returns 节流后的函数\n */\nexport function throttle<T extends (...args: any[]) => void>(func: T, limit: number): T {\n let inThrottle: boolean;\n return function(this: any, ...args: any[]) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n } as T;\n}\n"]}
|
package/ios/ExpoGaodeMap.podspec
CHANGED
|
@@ -19,11 +19,9 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
s.static_framework = true
|
|
20
20
|
|
|
21
21
|
s.dependency 'ExpoModulesCore'
|
|
22
|
-
s.dependency 'AMapFoundation'
|
|
23
|
-
s.dependency 'AMapLocation'
|
|
24
22
|
s.dependency 'AMap3DMap'
|
|
25
|
-
|
|
26
|
-
s.
|
|
23
|
+
s.dependency "AMapLocation"
|
|
24
|
+
s.dependency "AMapLocation"
|
|
27
25
|
|
|
28
26
|
# Swift/Objective-C compatibility
|
|
29
27
|
s.pod_target_xcconfig = {
|
|
@@ -92,14 +92,8 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
92
92
|
|
|
93
93
|
// MARK: - 事件节流控制
|
|
94
94
|
|
|
95
|
-
/// 相机移动事件节流间隔(秒)
|
|
96
|
-
private let cameraMoveThrottleInterval: TimeInterval = 0.1
|
|
97
|
-
/// 上次触发相机移动事件的时间戳
|
|
98
|
-
private var lastCameraMoveTime: TimeInterval = 0
|
|
99
95
|
/// 缓存的相机移动事件数据
|
|
100
96
|
private var pendingCameraMoveData: [String: Any]?
|
|
101
|
-
/// 节流定时器
|
|
102
|
-
private var throttleTimer: Timer?
|
|
103
97
|
|
|
104
98
|
/// 缩放手势识别器(用于模拟惯性)
|
|
105
99
|
private var pinchGesture: UIPinchGestureRecognizer!
|
|
@@ -856,9 +850,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
856
850
|
* 当视图从层级中移除并释放时自动调用
|
|
857
851
|
*/
|
|
858
852
|
deinit {
|
|
859
|
-
//
|
|
860
|
-
throttleTimer?.invalidate()
|
|
861
|
-
throttleTimer = nil
|
|
853
|
+
// 清理资源
|
|
862
854
|
pendingCameraMoveData = nil
|
|
863
855
|
|
|
864
856
|
// 清理代理,停止接收回调
|
|
@@ -935,11 +927,10 @@ extension ExpoGaodeMapView {
|
|
|
935
927
|
}
|
|
936
928
|
|
|
937
929
|
/**
|
|
938
|
-
* 地图区域即将改变时触发
|
|
930
|
+
* 地图区域即将改变时触发
|
|
939
931
|
*/
|
|
940
932
|
public func mapView(_ mapView: MAMapView, regionWillChangeAnimated animated: Bool) {
|
|
941
|
-
// 相机开始移动
|
|
942
|
-
let currentTime = Date().timeIntervalSince1970
|
|
933
|
+
// 相机开始移动
|
|
943
934
|
let cameraPosition = cameraManager.getCameraPosition()
|
|
944
935
|
let visibleRegion = mapView.region
|
|
945
936
|
|
|
@@ -957,29 +948,9 @@ extension ExpoGaodeMapView {
|
|
|
957
948
|
]
|
|
958
949
|
]
|
|
959
950
|
|
|
960
|
-
//
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
lastCameraMoveTime = currentTime
|
|
964
|
-
onCameraMove(eventData)
|
|
965
|
-
// 清除待处理的事件和定时器
|
|
966
|
-
throttleTimer?.invalidate()
|
|
967
|
-
throttleTimer = nil
|
|
968
|
-
pendingCameraMoveData = nil
|
|
969
|
-
} else {
|
|
970
|
-
// 在节流时间内,缓存事件数据,使用定时器延迟触发
|
|
971
|
-
pendingCameraMoveData = eventData
|
|
972
|
-
throttleTimer?.invalidate()
|
|
973
|
-
|
|
974
|
-
let delay = cameraMoveThrottleInterval - (currentTime - lastCameraMoveTime)
|
|
975
|
-
throttleTimer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { [weak self] _ in
|
|
976
|
-
guard let self = self, let data = self.pendingCameraMoveData else { return }
|
|
977
|
-
self.lastCameraMoveTime = Date().timeIntervalSince1970
|
|
978
|
-
self.onCameraMove(data)
|
|
979
|
-
self.pendingCameraMoveData = nil
|
|
980
|
-
self.throttleTimer = nil
|
|
981
|
-
}
|
|
982
|
-
}
|
|
951
|
+
// 直接触发事件,移除手动节流
|
|
952
|
+
// 建议在 JS 端进行 debounce/throttle 处理
|
|
953
|
+
onCameraMove(eventData)
|
|
983
954
|
}
|
|
984
955
|
|
|
985
956
|
/**
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
2
|
import MAMapKit
|
|
3
3
|
|
|
4
|
+
enum MapType: Int, Enumerable {
|
|
5
|
+
case standard = 0
|
|
6
|
+
case satellite = 1
|
|
7
|
+
case night = 2
|
|
8
|
+
case navi = 3
|
|
9
|
+
case bus = 4
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
/**
|
|
5
13
|
* 高德地图视图 Module
|
|
6
14
|
*/
|
|
@@ -11,8 +19,8 @@ public class ExpoGaodeMapViewModule: Module {
|
|
|
11
19
|
View(ExpoGaodeMapView.self) {
|
|
12
20
|
Events("onMapPress", "onMapLongPress", "onLoad", "onLocation", "onCameraMove", "onCameraIdle")
|
|
13
21
|
|
|
14
|
-
Prop("mapType") { (view: ExpoGaodeMapView, type:
|
|
15
|
-
view.mapType = type
|
|
22
|
+
Prop("mapType") { (view: ExpoGaodeMapView, type: MapType) in
|
|
23
|
+
view.mapType = type.rawValue
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
Prop("initialCameraPosition") { (view: ExpoGaodeMapView, position: [String: Any]?) in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-gaode-map",
|
|
3
|
-
"version": "2.2.26
|
|
3
|
+
"version": "2.2.26",
|
|
4
4
|
"description": "A full-featured AMap (Gaode Map) React Native component library built with Expo Modules, providing map display, location services, overlays, and more.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -14,18 +14,18 @@
|
|
|
14
14
|
"plugin/build"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "expo-module build &&
|
|
17
|
+
"build": "expo-module build && yarn build:plugin",
|
|
18
18
|
"build:plugin": "tsc --project plugin/tsconfig.json",
|
|
19
19
|
"clean": "expo-module clean && rm -rf plugin/build",
|
|
20
20
|
"lint": "expo-module lint",
|
|
21
21
|
"test": "expo-module test",
|
|
22
|
-
"prepare": "expo-module prepare &&
|
|
22
|
+
"prepare": "expo-module prepare && yarn build:plugin",
|
|
23
23
|
"prepublishOnly": "echo 'Skipping proofread check' && exit 0",
|
|
24
24
|
"expo-module": "expo-module",
|
|
25
25
|
"open:ios": "xed example/ios",
|
|
26
26
|
"open:android": "open -a \"Android Studio\" example/android",
|
|
27
|
-
"publish:next": "
|
|
28
|
-
"publish:latest": "
|
|
27
|
+
"publish:next": "npm publish --tag next",
|
|
28
|
+
"publish:latest": "npm publish --tag latest"
|
|
29
29
|
},
|
|
30
30
|
"keywords": [
|
|
31
31
|
"react-native",
|
|
@@ -50,19 +50,15 @@
|
|
|
50
50
|
"registry": "https://registry.npmjs.org/"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@expo/config-plugins": "~54.0.4",
|
|
54
|
-
"@testing-library/react-native": "^13.3.3",
|
|
55
53
|
"@babel/runtime": "^7.25.7",
|
|
54
|
+
"@testing-library/react-native": "^13.3.3",
|
|
56
55
|
"@types/jest": "^29.5.14",
|
|
57
56
|
"@types/react": "~19.1.0",
|
|
58
|
-
"
|
|
59
|
-
"babel-preset-expo": "^54.0.8",
|
|
60
|
-
"expo": "^54.0.31",
|
|
57
|
+
"expo": "^54.0.27",
|
|
61
58
|
"expo-module-scripts": "^5.0.8",
|
|
62
59
|
"jest": "~29.7.0",
|
|
63
60
|
"jest-expo": "^54.0.16",
|
|
64
61
|
"react-native": "0.81.5",
|
|
65
|
-
"react-test-renderer": "19.1.0",
|
|
66
62
|
"typescript": "^5.9.3"
|
|
67
63
|
},
|
|
68
64
|
"peerDependencies": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigPlugin } from '
|
|
1
|
+
import { ConfigPlugin } from 'expo/config-plugins';
|
|
2
2
|
/**
|
|
3
3
|
* 高德地图插件配置类型
|
|
4
4
|
*/
|
|
@@ -13,6 +13,11 @@ export type GaodeMapPluginProps = {
|
|
|
13
13
|
locationDescription?: string;
|
|
14
14
|
/** 是否启用后台定位(Android & iOS) */
|
|
15
15
|
enableBackgroundLocation?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* 自定义高德地图 SDK 路径(例如 Google Play 版本)
|
|
18
|
+
* 相对于项目根目录的路径,例如 "./libs/AMap_3DMap_V9.0.0_GooglePlay.aar"
|
|
19
|
+
*/
|
|
20
|
+
customMapSdkPath?: string;
|
|
16
21
|
};
|
|
17
22
|
/**
|
|
18
23
|
* 导出为可运行一次的插件
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const config_plugins_1 = require("
|
|
3
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
4
4
|
const pkg = require('../../package.json');
|
|
5
5
|
/** 默认定位权限描述 */
|
|
6
6
|
const DEFAULT_LOCATION_USAGE = '需要访问您的位置信息以提供地图服务';
|
|
@@ -11,22 +11,24 @@ const withGaodeMapIOSPermissions = (config, props) => {
|
|
|
11
11
|
if (props.enableLocation === false) {
|
|
12
12
|
return config;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
// 使用 IOSConfig.Permissions 简化权限配置
|
|
15
|
+
// 注意:locationDescription 的检查已移至 withGaodeMapInfoPlist 中以避免重复打印
|
|
16
|
+
const description = props.locationDescription;
|
|
17
|
+
const finalDescription = description || DEFAULT_LOCATION_USAGE;
|
|
15
18
|
// 构建权限配置对象
|
|
16
19
|
const permissionDefaults = {
|
|
17
20
|
NSLocationWhenInUseUsageDescription: DEFAULT_LOCATION_USAGE,
|
|
18
21
|
};
|
|
19
22
|
const permissionValues = {
|
|
20
|
-
NSLocationWhenInUseUsageDescription:
|
|
23
|
+
NSLocationWhenInUseUsageDescription: finalDescription,
|
|
21
24
|
};
|
|
22
25
|
// 如果启用后台定位,添加额外权限
|
|
23
26
|
if (props.enableBackgroundLocation) {
|
|
24
27
|
permissionDefaults.NSLocationAlwaysUsageDescription = DEFAULT_LOCATION_USAGE;
|
|
25
28
|
permissionDefaults.NSLocationAlwaysAndWhenInUseUsageDescription = DEFAULT_LOCATION_USAGE;
|
|
26
|
-
permissionValues.NSLocationAlwaysUsageDescription =
|
|
27
|
-
permissionValues.NSLocationAlwaysAndWhenInUseUsageDescription =
|
|
29
|
+
permissionValues.NSLocationAlwaysUsageDescription = finalDescription;
|
|
30
|
+
permissionValues.NSLocationAlwaysAndWhenInUseUsageDescription = finalDescription;
|
|
28
31
|
}
|
|
29
|
-
// 使用 IOSConfig.Permissions 简化权限配置
|
|
30
32
|
return config_plugins_1.IOSConfig.Permissions.createPermissionsPlugin(permissionDefaults)(config, permissionValues);
|
|
31
33
|
};
|
|
32
34
|
/**
|
|
@@ -34,6 +36,16 @@ const withGaodeMapIOSPermissions = (config, props) => {
|
|
|
34
36
|
*/
|
|
35
37
|
const withGaodeMapInfoPlist = (config, props) => {
|
|
36
38
|
return (0, config_plugins_1.withInfoPlist)(config, (config) => {
|
|
39
|
+
// 检查 iOS API Key
|
|
40
|
+
if (!props.iosKey && !props.androidKey) {
|
|
41
|
+
// 仅当两个平台都未配置时提示 Notice,避免打扰单平台开发者
|
|
42
|
+
// 这里使用 console.log 而不是 WarningAggregator,因为这只是一个提示
|
|
43
|
+
console.log('\u001b[33m[expo-gaode-map] Notice: 未在 app.json 中配置 API Key。请确保在应用启动时通过代码配置 Key,否则地图将无法加载。建议在 app.json 中配置 API Key 以避免运行时错误。\u001b[0m');
|
|
44
|
+
}
|
|
45
|
+
// 检查 locationDescription
|
|
46
|
+
if (props.enableLocation !== false && !props.locationDescription) {
|
|
47
|
+
config_plugins_1.WarningAggregator.addWarningIOS('expo-gaode-map', `未配置 iOS 定位权限描述 (locationDescription)。将使用默认描述: "${DEFAULT_LOCATION_USAGE}"。建议在 app.json 中配置以满足 App Store 审核要求。`);
|
|
48
|
+
}
|
|
37
49
|
// 添加高德地图 API Key
|
|
38
50
|
if (props.iosKey) {
|
|
39
51
|
config.modResults.AMapApiKey = props.iosKey;
|
|
@@ -146,12 +158,48 @@ const withGaodeMapAndroidManifest = (config, props) => {
|
|
|
146
158
|
});
|
|
147
159
|
};
|
|
148
160
|
/**
|
|
149
|
-
* Android: 修改 app/build.gradle
|
|
161
|
+
* Android: 修改 app/build.gradle
|
|
162
|
+
* 当使用自定义 SDK 路径时,自动注入 exclude 规则以解决 duplicate class 冲突
|
|
150
163
|
*/
|
|
151
164
|
const withGaodeMapAppBuildGradle = (config, props) => {
|
|
152
165
|
return (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
if (props.customMapSdkPath) {
|
|
167
|
+
// 只有在配置了 customMapSdkPath 时才注入
|
|
168
|
+
const buildGradle = config.modResults.contents;
|
|
169
|
+
// 检查是否已经注入过
|
|
170
|
+
if (!buildGradle.includes('configurations.all { exclude group: "com.amap.api", module: "search" }')) {
|
|
171
|
+
const injection = `
|
|
172
|
+
// [expo-gaode-map] Auto-generated to fix duplicate class issues with custom SDK
|
|
173
|
+
configurations.all {
|
|
174
|
+
exclude group: "com.amap.api", module: "search"
|
|
175
|
+
exclude group: "com.amap.api", module: "location"
|
|
176
|
+
}
|
|
177
|
+
`;
|
|
178
|
+
config.modResults.contents = buildGradle + injection;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return config;
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Android: 修改 gradle.properties 注入自定义 SDK 路径
|
|
186
|
+
*/
|
|
187
|
+
const withGaodeMapAndroidSdk = (config, props) => {
|
|
188
|
+
return (0, config_plugins_1.withGradleProperties)(config, (config) => {
|
|
189
|
+
if (props.customMapSdkPath) {
|
|
190
|
+
const key = 'EXPO_GAODE_MAP_CUSTOM_SDK_PATH';
|
|
191
|
+
const existing = config.modResults.find((item) => item.type === 'property' && item.key === key);
|
|
192
|
+
if (existing && existing.type === 'property') {
|
|
193
|
+
existing.value = props.customMapSdkPath;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
config.modResults.push({
|
|
197
|
+
type: 'property',
|
|
198
|
+
key: key,
|
|
199
|
+
value: props.customMapSdkPath,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
155
203
|
return config;
|
|
156
204
|
});
|
|
157
205
|
};
|
|
@@ -159,10 +207,6 @@ const withGaodeMapAppBuildGradle = (config, props) => {
|
|
|
159
207
|
* 主插件函数 - 组合所有修改器
|
|
160
208
|
*/
|
|
161
209
|
const withGaodeMap = (config, props = {}) => {
|
|
162
|
-
// 验证配置
|
|
163
|
-
if (!props.iosKey && !props.androidKey) {
|
|
164
|
-
config_plugins_1.WarningAggregator.addWarningIOS('expo-gaode-map', '未配置 API Key。请在 app.json 的 plugins 中配置 iosKey 和 androidKey');
|
|
165
|
-
}
|
|
166
210
|
// 应用 iOS 配置
|
|
167
211
|
config = withGaodeMapIOSPermissions(config, props); // 使用 IOSConfig 添加权限
|
|
168
212
|
config = withGaodeMapInfoPlist(config, props); // 添加 API Key 和后台模式
|
|
@@ -170,6 +214,7 @@ const withGaodeMap = (config, props = {}) => {
|
|
|
170
214
|
config = withGaodeMapAndroidPermissions(config, props); // 使用 AndroidConfig 添加权限
|
|
171
215
|
config = withGaodeMapAndroidManifest(config, props); // 添加服务和 API Key
|
|
172
216
|
config = withGaodeMapAppBuildGradle(config, props);
|
|
217
|
+
config = withGaodeMapAndroidSdk(config, props); // 注入自定义 SDK 路径
|
|
173
218
|
return config;
|
|
174
219
|
};
|
|
175
220
|
/**
|