capacitor-baidu-location 0.0.1
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/CapacitorBaiduLocation.podspec +23 -0
- package/Package.swift +44 -0
- package/README.md +376 -0
- package/android/build.gradle +71 -0
- package/android/src/main/AndroidManifest.xml +32 -0
- package/android/src/main/kotlin/com/hybrid/baidu/location/CPBaiduLocation.kt +246 -0
- package/android/src/main/kotlin/com/hybrid/baidu/location/CPBaiduLocationConfig.kt +22 -0
- package/android/src/main/kotlin/com/hybrid/baidu/location/CPBaiduLocationPlugin.kt +225 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +294 -0
- package/dist/esm/definitions.d.ts +163 -0
- package/dist/esm/definitions.js +24 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +69 -0
- package/dist/esm/web.js +133 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +170 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +173 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CPBaiduLocationPlugin/CPBaiduLocation.swift +646 -0
- package/ios/Sources/CPBaiduLocationPlugin/CPBaiduLocationConfig.swift +38 -0
- package/ios/Sources/CPBaiduLocationPlugin/CPBaiduLocationPlugin.swift +167 -0
- package/package.json +82 -0
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
@_exported import BMKLocationKit
|
|
3
|
+
import CoreLocation
|
|
4
|
+
import Network
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 百度地图定位插件iOS端实现类
|
|
8
|
+
* 负责处理百度地图定位的核心逻辑,包括定位权限管理、AK验证、定位请求等
|
|
9
|
+
*/
|
|
10
|
+
@objc public class CPBaiduLocation: NSObject, BMKLocationAuthDelegate, BMKLocationManagerDelegate, CLLocationManagerDelegate {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 插件配置对象
|
|
14
|
+
*/
|
|
15
|
+
private var config: CPBaiduLocationConfig
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 系统定位管理器(用于权限请求和系统级定位)
|
|
19
|
+
*/
|
|
20
|
+
private var clLocationManager: CLLocationManager = CLLocationManager()
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 定位结果回调(弱引用自身避免循环引用)
|
|
24
|
+
*/
|
|
25
|
+
private var completion: (([String: Any]) -> Void)?
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 标记是否已执行回调(防止重复调用)
|
|
29
|
+
*/
|
|
30
|
+
private var isCallbackInvoked = false
|
|
31
|
+
|
|
32
|
+
// MARK: - 状态管理
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* API Key
|
|
36
|
+
*/
|
|
37
|
+
private var ak: String?
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* AK验证状态
|
|
41
|
+
*/
|
|
42
|
+
private var isAKValidated = false
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 坐标类型
|
|
46
|
+
* 默认值:BMKLocationCoordinateType.BMK09LL(百度经纬度坐标)
|
|
47
|
+
*/
|
|
48
|
+
private var coordinateType: BMKLocationCoordinateType = .BMK09LL
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* AK验证回调队列
|
|
52
|
+
* 存储等待AK验证结果的回调
|
|
53
|
+
*/
|
|
54
|
+
private var akValidationCallbacks: [(Bool, Int?, String?) -> Void] = []
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 定位权限回调队列
|
|
58
|
+
* 存储等待定位权限结果的回调
|
|
59
|
+
*/
|
|
60
|
+
private var locationPermissionCallbacks: [(String) -> Void] = []
|
|
61
|
+
|
|
62
|
+
// MARK: - 网络状态监听
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 网络状态监视器
|
|
66
|
+
*/
|
|
67
|
+
private var networkMonitor: NWPathMonitor?
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 当前网络路径
|
|
71
|
+
*/
|
|
72
|
+
private var networkPath: NWPath?
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 是否已启动网络监听
|
|
76
|
+
*/
|
|
77
|
+
private var isMonitoringNetwork = false
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 百度定位管理器(持强引用避免提前释放)
|
|
81
|
+
* 懒加载,确保在需要时才初始化
|
|
82
|
+
*/
|
|
83
|
+
private lazy var bmkLocationManager: BMKLocationManager = {
|
|
84
|
+
// 初始化并配置定位管理器
|
|
85
|
+
let manager = BMKLocationManager()
|
|
86
|
+
manager.delegate = self
|
|
87
|
+
manager.coordinateType = coordinateType // 坐标类型
|
|
88
|
+
manager.desiredAccuracy = kCLLocationAccuracyBest // 默认定位精度
|
|
89
|
+
manager.activityType = .automotiveNavigation // 默认定位场景
|
|
90
|
+
manager.pausesLocationUpdatesAutomatically = false // 默认不被系统自动暂停定位
|
|
91
|
+
manager.allowsBackgroundLocationUpdates = true // 允许后台定位,需要在xcode开启配置
|
|
92
|
+
manager.locationTimeout = 10 // 定位超时时间,单位:秒
|
|
93
|
+
manager.reGeocodeTimeout = 10 // 逆地理编码超时时间,单位:秒
|
|
94
|
+
return manager
|
|
95
|
+
}()
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 使用配置对象初始化
|
|
99
|
+
* @param config 配置对象
|
|
100
|
+
*/
|
|
101
|
+
public init(config: CPBaiduLocationConfig) {
|
|
102
|
+
self.config = config
|
|
103
|
+
super.init()
|
|
104
|
+
clLocationManager.delegate = self
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 默认初始化
|
|
109
|
+
*/
|
|
110
|
+
override init() {
|
|
111
|
+
self.config = CPBaiduLocationConfig(from: nil)
|
|
112
|
+
super.init()
|
|
113
|
+
clLocationManager.delegate = self
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
// MARK: - AK管理
|
|
119
|
+
/**
|
|
120
|
+
* 设置百度地图API Key
|
|
121
|
+
* @param ak API Key
|
|
122
|
+
* @param completion 验证结果回调
|
|
123
|
+
*/
|
|
124
|
+
@objc public func setAK(_ ak: String, completion: @escaping ([String: Any]) -> Void) {
|
|
125
|
+
if isAKValidated || ak == self.ak {
|
|
126
|
+
completion([
|
|
127
|
+
"success": true,
|
|
128
|
+
])
|
|
129
|
+
}
|
|
130
|
+
// 存储API Key
|
|
131
|
+
self.ak = ak
|
|
132
|
+
|
|
133
|
+
// 重置验证状态
|
|
134
|
+
isAKValidated = false
|
|
135
|
+
|
|
136
|
+
// 自动设置同意隐私协议
|
|
137
|
+
if !BMKLocationAuth.sharedInstance().isAgreePrivacy {
|
|
138
|
+
BMKLocationAuth.sharedInstance().setAgreePrivacy(true)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 添加到回调队列
|
|
142
|
+
akValidationCallbacks.append { success, errorCode, errorMessage in
|
|
143
|
+
var result: [String: Any] = [
|
|
144
|
+
"success": success
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
if let errorCode = errorCode {
|
|
148
|
+
result["errorCode"] = errorCode
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if let errorMessage = errorMessage {
|
|
152
|
+
result["errorMessage"] = errorMessage
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
completion(result)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
startNetworkMonitoring()
|
|
159
|
+
|
|
160
|
+
// 触发AK验证
|
|
161
|
+
BMKLocationAuth.sharedInstance().checkPermision(withKey: ak, authDelegate: self)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// MARK: - 坐标类型管理
|
|
165
|
+
/**
|
|
166
|
+
* 辅助方法:将字符串类型的坐标类型转换为BMKLocationCoordinateType枚举类型
|
|
167
|
+
* @param type 坐标类型字符串
|
|
168
|
+
* @return BMKLocationCoordinateType枚举类型
|
|
169
|
+
*/
|
|
170
|
+
private func coordinateTypeFromString(_ type: String) -> BMKLocationCoordinateType {
|
|
171
|
+
switch type {
|
|
172
|
+
case "BD09LL":
|
|
173
|
+
return .BMK09LL // 百度经纬度坐标
|
|
174
|
+
case "BD09MC":
|
|
175
|
+
return .BMK09MC // 百度墨卡托米制坐标
|
|
176
|
+
case "GCJ02":
|
|
177
|
+
return .GCJ02 // 国测局坐标
|
|
178
|
+
case "WGS84":
|
|
179
|
+
return .WGS84 // WGS84坐标
|
|
180
|
+
default:
|
|
181
|
+
return .BMK09LL // 默认百度经纬度坐标
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 设置坐标类型
|
|
187
|
+
* @param type 坐标类型
|
|
188
|
+
* @param completion 设置结果回调
|
|
189
|
+
*/
|
|
190
|
+
@objc public func setCoordinateType(_ type: String, completion: @escaping () -> Void) {
|
|
191
|
+
// 根据坐标类型设置定位参数
|
|
192
|
+
self.coordinateType = coordinateTypeFromString(type)
|
|
193
|
+
if bmkLocationManager != nil {
|
|
194
|
+
bmkLocationManager.coordinateType = coordinateType
|
|
195
|
+
}
|
|
196
|
+
completion()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取当前坐标类型
|
|
201
|
+
* @return 当前坐标类型
|
|
202
|
+
*/
|
|
203
|
+
@objc public func getCoordinateType() -> String {
|
|
204
|
+
switch coordinateType {
|
|
205
|
+
case .BMK09LL:
|
|
206
|
+
return "BD09LL"
|
|
207
|
+
case .BMK09MC:
|
|
208
|
+
return "BMK09MC"
|
|
209
|
+
case .GCJ02:
|
|
210
|
+
return "GCJ02"
|
|
211
|
+
case .WGS84:
|
|
212
|
+
return "WGS84"
|
|
213
|
+
default:
|
|
214
|
+
return "BD09LL"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// MARK: - 权限管理
|
|
219
|
+
/**
|
|
220
|
+
* 检查定位权限状态
|
|
221
|
+
* @return 权限状态结果
|
|
222
|
+
*/
|
|
223
|
+
@objc public func checkPermission() -> [String: Any] {
|
|
224
|
+
let status = CLLocationManager.authorizationStatus()
|
|
225
|
+
|
|
226
|
+
var statusString: String
|
|
227
|
+
var hasPermission = false
|
|
228
|
+
|
|
229
|
+
switch status {
|
|
230
|
+
case .authorizedWhenInUse, .authorizedAlways:
|
|
231
|
+
statusString = "granted"
|
|
232
|
+
hasPermission = true
|
|
233
|
+
case .denied, .restricted:
|
|
234
|
+
statusString = "denied"
|
|
235
|
+
hasPermission = false
|
|
236
|
+
case .notDetermined:
|
|
237
|
+
statusString = "notDetermined"
|
|
238
|
+
hasPermission = false
|
|
239
|
+
@unknown default:
|
|
240
|
+
statusString = "unknown"
|
|
241
|
+
hasPermission = false
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return [
|
|
245
|
+
"success": true,
|
|
246
|
+
"hasPermission": hasPermission,
|
|
247
|
+
"status": statusString
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* 请求定位权限
|
|
253
|
+
* @param completion 权限请求结果回调
|
|
254
|
+
*/
|
|
255
|
+
@objc public func requestPermission(completion: @escaping ([String: Any]) -> Void) {
|
|
256
|
+
let status = CLLocationManager.authorizationStatus()
|
|
257
|
+
|
|
258
|
+
if status == .notDetermined {
|
|
259
|
+
// 请求权限
|
|
260
|
+
locationPermissionCallbacks.append { statusString in
|
|
261
|
+
let hasPermission = statusString == "granted"
|
|
262
|
+
completion([
|
|
263
|
+
"success": true,
|
|
264
|
+
"granted": hasPermission,
|
|
265
|
+
"status": statusString
|
|
266
|
+
])
|
|
267
|
+
}
|
|
268
|
+
clLocationManager.requestWhenInUseAuthorization()
|
|
269
|
+
} else {
|
|
270
|
+
// 直接返回当前状态
|
|
271
|
+
let checkResult = self.checkPermission()
|
|
272
|
+
completion([
|
|
273
|
+
"success": true,
|
|
274
|
+
"granted": checkResult["hasPermission"] as? Bool ?? false,
|
|
275
|
+
"status": checkResult["status"] as? String ?? "unknown"
|
|
276
|
+
])
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// MARK: - 定位
|
|
281
|
+
/**
|
|
282
|
+
* 获取当前位置信息
|
|
283
|
+
* @param needAddress 是否需要地址信息
|
|
284
|
+
* @param needLocationDescribe 是否需要位置描述
|
|
285
|
+
* @param completion 定位结果回调(主线程执行)
|
|
286
|
+
*/
|
|
287
|
+
@objc public func getCurrentPosition(needAddress: Bool, needLocationDescribe: Bool, completion: @escaping ([String: Any]) -> Void) {
|
|
288
|
+
// 重置状态
|
|
289
|
+
isCallbackInvoked = false
|
|
290
|
+
self.completion = completion
|
|
291
|
+
|
|
292
|
+
// 检查前置条件
|
|
293
|
+
checkPreconditions { [weak self] isReady, errorCode, errorMessage in
|
|
294
|
+
guard let strongSelf = self else { return }
|
|
295
|
+
|
|
296
|
+
if !isReady {
|
|
297
|
+
// 前置条件不满足,返回错误
|
|
298
|
+
let result: [String: Any] = [
|
|
299
|
+
"latitude": 0.0,
|
|
300
|
+
"longitude": 0.0,
|
|
301
|
+
"accuracy": 0.0,
|
|
302
|
+
"errorCode": errorCode ?? -1,
|
|
303
|
+
"errorMessage": errorMessage ?? "定位前置条件不满足"
|
|
304
|
+
]
|
|
305
|
+
strongSelf.invokeCompletion(with: result)
|
|
306
|
+
} else {
|
|
307
|
+
// 前置条件满足,执行定位
|
|
308
|
+
strongSelf.performLocationRequest(needAddress: needAddress, needLocationDescribe: needLocationDescribe)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* 检查定位前置条件
|
|
315
|
+
* @param completion 检查结果回调
|
|
316
|
+
*/
|
|
317
|
+
private func checkPreconditions(completion: @escaping (Bool, Int?, String?) -> Void) {
|
|
318
|
+
// 检查定位权限
|
|
319
|
+
let permissionResult = checkPermission()
|
|
320
|
+
if !(permissionResult["hasPermission"] as? Bool ?? false) {
|
|
321
|
+
completion(false, -3, "定位权限未授权!")
|
|
322
|
+
return
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// 检查系统定位服务是否开启
|
|
326
|
+
if !CLLocationManager.locationServicesEnabled() {
|
|
327
|
+
completion(false, 2, "定位服务未开启!")
|
|
328
|
+
return
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// 检查AK是否已验证
|
|
332
|
+
if isAKValidated {
|
|
333
|
+
completion(true, nil, nil)
|
|
334
|
+
return
|
|
335
|
+
} else {
|
|
336
|
+
completion(false, -1, "未设置AK!")
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* 执行定位请求
|
|
343
|
+
* @param needAddress 是否需要地址信息
|
|
344
|
+
* @param needLocationDescribe 是否需要位置描述
|
|
345
|
+
*/
|
|
346
|
+
private func performLocationRequest(needAddress: Bool, needLocationDescribe: Bool) {
|
|
347
|
+
// 请求单次定位
|
|
348
|
+
bmkLocationManager.requestLocation(withReGeocode: needAddress, withNetworkState: true) { [weak self] (location, state, error) in
|
|
349
|
+
guard let strongSelf = self else { return }
|
|
350
|
+
// 构建定位结果
|
|
351
|
+
let result = strongSelf.buildLocationResult(
|
|
352
|
+
location: location,
|
|
353
|
+
error: error,
|
|
354
|
+
needAddress: needAddress,
|
|
355
|
+
needLocationDescribe: needLocationDescribe
|
|
356
|
+
)
|
|
357
|
+
// 执行回调(确保仅调用一次)
|
|
358
|
+
strongSelf.invokeCompletion(with: result)
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// MARK: - 其他方法
|
|
363
|
+
/**
|
|
364
|
+
* 构建定位结果字典
|
|
365
|
+
* @param location 百度定位信息对象
|
|
366
|
+
* @param error 定位错误(如果有)
|
|
367
|
+
* @param needAddress 是否需要地址信息
|
|
368
|
+
* @param needLocationDescribe 是否需要位置描述
|
|
369
|
+
* @return 定位结果字典,包含经纬度、精度、地址信息等
|
|
370
|
+
*/
|
|
371
|
+
private func buildLocationResult(
|
|
372
|
+
location: BMKLocation?,
|
|
373
|
+
error: Error?,
|
|
374
|
+
needAddress: Bool,
|
|
375
|
+
needLocationDescribe: Bool
|
|
376
|
+
) -> [String: Any] {
|
|
377
|
+
// 初始化默认结果(兜底值)
|
|
378
|
+
var result: [String: Any] = [
|
|
379
|
+
"latitude": 0.0,
|
|
380
|
+
"longitude": 0.0,
|
|
381
|
+
"accuracy": 0.0,
|
|
382
|
+
"errorCode": -1,
|
|
383
|
+
"errorMessage": "定位失败",
|
|
384
|
+
"type": "baidu" // 标记为百度定位结果
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
// 处理错误优先
|
|
388
|
+
if let error = error {
|
|
389
|
+
let nsError = error as NSError
|
|
390
|
+
let errorCode = nsError.code
|
|
391
|
+
result["errorCode"] = errorCode
|
|
392
|
+
result["errorMessage"] = nsError.localizedDescription
|
|
393
|
+
|
|
394
|
+
let bmkError = BMKLocationErrorCode(rawValue: nsError.code)
|
|
395
|
+
if (bmkError != nil) {
|
|
396
|
+
print("定位错误来自百度SDK")
|
|
397
|
+
}
|
|
398
|
+
return result
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// 处理定位成功
|
|
402
|
+
guard let bmkLocation = location, let clLocation = bmkLocation.location else {
|
|
403
|
+
result["errorMessage"] = "未获取到位置信息"
|
|
404
|
+
return result
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// 基础定位信息
|
|
408
|
+
result["latitude"] = clLocation.coordinate.latitude
|
|
409
|
+
result["longitude"] = clLocation.coordinate.longitude
|
|
410
|
+
result["accuracy"] = clLocation.horizontalAccuracy
|
|
411
|
+
result["errorCode"] = 0
|
|
412
|
+
result["errorMessage"] = "定位成功"
|
|
413
|
+
|
|
414
|
+
// 地址信息(按需添加)
|
|
415
|
+
if needAddress, let rgcData = bmkLocation.rgcData {
|
|
416
|
+
result["address"] = rgcData.address ?? ""
|
|
417
|
+
result["country"] = rgcData.country ?? ""
|
|
418
|
+
result["province"] = rgcData.province ?? ""
|
|
419
|
+
result["city"] = rgcData.city ?? ""
|
|
420
|
+
result["district"] = rgcData.district ?? ""
|
|
421
|
+
result["street"] = rgcData.street ?? ""
|
|
422
|
+
result["adcode"] = rgcData.adCode ?? ""
|
|
423
|
+
result["town"] = rgcData.town ?? ""
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// 位置描述(按需添加)
|
|
427
|
+
if needLocationDescribe, let rgcData = bmkLocation.rgcData, let poiRegion = rgcData.poiRegion {
|
|
428
|
+
result["locationDescribe"] = "\(poiRegion.name ?? "") \(poiRegion.directionDesc ?? "")"
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return result
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* 执行回调(确保主线程+仅执行一次)
|
|
436
|
+
* @param result 定位结果字典
|
|
437
|
+
*/
|
|
438
|
+
private func invokeCompletion(with result: [String: Any]) {
|
|
439
|
+
guard !isCallbackInvoked else { return }
|
|
440
|
+
isCallbackInvoked = true
|
|
441
|
+
|
|
442
|
+
// 切主线程执行回调(避免UI操作崩溃)
|
|
443
|
+
DispatchQueue.main.async { [weak self] in
|
|
444
|
+
self?.completion?(result)
|
|
445
|
+
// 清理资源
|
|
446
|
+
self?.cleanup()
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* 清理定位资源
|
|
452
|
+
* 释放回调引用,避免循环引用
|
|
453
|
+
*/
|
|
454
|
+
private func cleanup() {
|
|
455
|
+
completion = nil
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// MARK: - 网络状态监听
|
|
459
|
+
/**
|
|
460
|
+
* 启动网络状态监听
|
|
461
|
+
*/
|
|
462
|
+
private func startNetworkMonitoring() {
|
|
463
|
+
guard !isMonitoringNetwork else { return }
|
|
464
|
+
|
|
465
|
+
networkMonitor = NWPathMonitor()
|
|
466
|
+
networkPath = networkMonitor?.currentPath
|
|
467
|
+
|
|
468
|
+
if networkPath?.status == .satisfied {
|
|
469
|
+
return
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
networkMonitor?.pathUpdateHandler = { [weak self] path in
|
|
473
|
+
guard let strongSelf = self else { return }
|
|
474
|
+
strongSelf.networkPath = path
|
|
475
|
+
|
|
476
|
+
// 当网络从不可用变为可用,且AK未验证成功时,重新触发AK验证
|
|
477
|
+
if path.status == .satisfied && !strongSelf.isAKValidated, let ak = strongSelf.ak {
|
|
478
|
+
print("网络恢复,重新验证AK")
|
|
479
|
+
DispatchQueue.main.async {
|
|
480
|
+
BMKLocationAuth.sharedInstance().checkPermision(withKey: ak, authDelegate: strongSelf)
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// 启动监听
|
|
486
|
+
let queue = DispatchQueue(label: "com.baidu.location.network")
|
|
487
|
+
networkMonitor?.start(queue: queue)
|
|
488
|
+
isMonitoringNetwork = true
|
|
489
|
+
print("网络状态监听已启动")
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* 停止网络状态监听
|
|
494
|
+
*/
|
|
495
|
+
private func stopNetworkMonitoring() {
|
|
496
|
+
guard isMonitoringNetwork else { return }
|
|
497
|
+
|
|
498
|
+
networkMonitor?.cancel()
|
|
499
|
+
networkMonitor = nil
|
|
500
|
+
networkPath = nil
|
|
501
|
+
isMonitoringNetwork = false
|
|
502
|
+
print("网络状态监听已停止")
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// MARK: - CLLocationManagerDelegate
|
|
506
|
+
/**
|
|
507
|
+
* 定位权限状态变化回调 (iOS 14-)
|
|
508
|
+
* @param manager 定位管理器
|
|
509
|
+
* @param status 权限状态
|
|
510
|
+
*/
|
|
511
|
+
@objc public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
|
|
512
|
+
handleLocationManager(manager, didChangeAuthorization: status)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* 定位权限状态变化回调 (iOS 14+ 推荐使用)
|
|
517
|
+
* @param manager 定位管理器
|
|
518
|
+
*/
|
|
519
|
+
@available(iOS 14.0, *)
|
|
520
|
+
@objc public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
|
521
|
+
handleLocationManager(manager, didChangeAuthorization: manager.authorizationStatus)
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// MARK: - 定位权限状态变化处理
|
|
525
|
+
private func handleLocationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
|
|
526
|
+
// 执行所有等待的权限回调
|
|
527
|
+
let callbacks = locationPermissionCallbacks
|
|
528
|
+
locationPermissionCallbacks.removeAll()
|
|
529
|
+
|
|
530
|
+
let statusString: String
|
|
531
|
+
switch status {
|
|
532
|
+
case .authorizedWhenInUse, .authorizedAlways:
|
|
533
|
+
statusString = "granted"
|
|
534
|
+
// 检查精确定位状态(iOS 14+)
|
|
535
|
+
if #available(iOS 14.0, *) {
|
|
536
|
+
let accuracyStatus = manager.accuracyAuthorization
|
|
537
|
+
if accuracyStatus == .reducedAccuracy {
|
|
538
|
+
// 精确定位未开启,引导用户跳转到系统设置
|
|
539
|
+
// showPreciseLocationSettingAlert()
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
case .denied, .restricted:
|
|
543
|
+
statusString = "denied"
|
|
544
|
+
case .notDetermined:
|
|
545
|
+
statusString = "notDetermined"
|
|
546
|
+
@unknown default:
|
|
547
|
+
statusString = "unknown"
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// 执行回调
|
|
551
|
+
callbacks.forEach { $0(statusString) }
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// MARK: - 请求精确定位权限(iOS 14+)
|
|
555
|
+
@available(iOS 14.0, *)
|
|
556
|
+
private func requestPreciseLocationAuthorization() {
|
|
557
|
+
// 检查当前精确定位权限
|
|
558
|
+
let accuracyStatus = clLocationManager.accuracyAuthorization
|
|
559
|
+
switch accuracyStatus {
|
|
560
|
+
case .fullAccuracy:
|
|
561
|
+
// 已授权精确定位:可启动百度定位
|
|
562
|
+
print("accuracyStatus: fullAccuracy")
|
|
563
|
+
case .reducedAccuracy:
|
|
564
|
+
// 仅大致定位:请求临时精确定位(需 Info.plist 配置 PurposeKey)
|
|
565
|
+
clLocationManager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "LocationTempUsage")
|
|
566
|
+
@unknown default:
|
|
567
|
+
print("accuracyStatus: \(accuracyStatus)")
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// MARK: - BMKLocationAuthDelegate
|
|
572
|
+
/**
|
|
573
|
+
* AK验证状态变化回调
|
|
574
|
+
* @param iError 错误号 : 为0时验证通过,具体参加BMKLocationAuthErrorCode
|
|
575
|
+
*/
|
|
576
|
+
public func onCheckPermissionState(_ iError: BMKLocationAuthErrorCode) {
|
|
577
|
+
var success = false
|
|
578
|
+
var errorCode = iError.rawValue
|
|
579
|
+
var errorMessage: String?
|
|
580
|
+
|
|
581
|
+
// 如果网络状态为未确定(用户还未选择网络权限),则不执行回调,等待网络状态变化后重试
|
|
582
|
+
if let networkPath = networkPath, networkPath.status != .satisfied {
|
|
583
|
+
return
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
switch iError {
|
|
587
|
+
case .success:
|
|
588
|
+
success = true
|
|
589
|
+
isAKValidated = true
|
|
590
|
+
errorMessage = "AK验证成功"
|
|
591
|
+
ak = nil
|
|
592
|
+
// 触发懒加载(有个bug,之后再初始化就无法定位成功)
|
|
593
|
+
print("allowsBackgroundLocationUpdates = \(bmkLocationManager.allowsBackgroundLocationUpdates)")
|
|
594
|
+
// 验证成功,停止网络监听
|
|
595
|
+
stopNetworkMonitoring()
|
|
596
|
+
case .networkFailed:
|
|
597
|
+
success = false
|
|
598
|
+
isAKValidated = false
|
|
599
|
+
errorMessage = "网络错误导致AK验证失败"
|
|
600
|
+
case .failed:
|
|
601
|
+
success = false
|
|
602
|
+
isAKValidated = false
|
|
603
|
+
errorMessage = "KEY非法导致AK验证失败"
|
|
604
|
+
default:
|
|
605
|
+
success = false
|
|
606
|
+
isAKValidated = false
|
|
607
|
+
errorMessage = "未知AK验证错误"
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// 执行所有等待的回调
|
|
611
|
+
let callbacks = akValidationCallbacks
|
|
612
|
+
akValidationCallbacks.removeAll()
|
|
613
|
+
callbacks.forEach { $0(success, errorCode, errorMessage) }
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// MARK: - BMKLocationManagerDelegate
|
|
617
|
+
/**
|
|
618
|
+
* 定位失败代理回调(系统级错误触发)
|
|
619
|
+
* @param manager 定位管理器
|
|
620
|
+
* @param error 错误信息
|
|
621
|
+
*/
|
|
622
|
+
public func bmkLocationManager(_ manager: BMKLocationManager, didFailWithError error: Error?) {
|
|
623
|
+
// 使用统一的错误处理逻辑
|
|
624
|
+
let result = buildLocationResult(
|
|
625
|
+
location: nil,
|
|
626
|
+
error: error,
|
|
627
|
+
needAddress: false,
|
|
628
|
+
needLocationDescribe: false
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
// 执行回调(防止重复)
|
|
632
|
+
invokeCompletion(with: result)
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
public func bmkLocationManager(_ manager: BMKLocationManager, didChange status: CLAuthorizationStatus) {
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
public func bmkLocationManagerDidChangeAuthorization(_ manager: BMKLocationManager) {
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
deinit {
|
|
642
|
+
// 确保网络监听已停止
|
|
643
|
+
stopNetworkMonitoring()
|
|
644
|
+
print("CPBaiduLocation实例已销毁")
|
|
645
|
+
}
|
|
646
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 百度地图定位插件配置类
|
|
6
|
+
* 集中管理所有配置项,提供类型安全的访问方式
|
|
7
|
+
*/
|
|
8
|
+
public class CPBaiduLocationConfig {
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* iOS平台百度地图API Key
|
|
12
|
+
*/
|
|
13
|
+
private var _iOSAK: String?
|
|
14
|
+
|
|
15
|
+
// MARK: - Getters and Setters
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* iOS平台百度地图API Key
|
|
19
|
+
*/
|
|
20
|
+
public var iOSAK: String? {
|
|
21
|
+
get {
|
|
22
|
+
return _iOSAK
|
|
23
|
+
}
|
|
24
|
+
set {
|
|
25
|
+
_iOSAK = newValue
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 从Capacitor配置中初始化配置对象
|
|
31
|
+
*/
|
|
32
|
+
convenience public init(from config: PluginConfig?) {
|
|
33
|
+
self.init()
|
|
34
|
+
if let config = config {
|
|
35
|
+
self.iOSAK = config.getString("iOSAK")
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|