| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | // lib/utils/location_helper.dart
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import 'dart:async'; | 
					
						
							|  |  |  |  | import 'dart:math'; | 
					
						
							|  |  |  |  | import 'package:flutter/material.dart'; | 
					
						
							|  |  |  |  | import 'package:geolocator/geolocator.dart'; | 
					
						
							|  |  |  |  | import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; | 
					
						
							|  |  |  |  | import 'package:qhd_prevention/customWidget/toast_util.dart'; | 
					
						
							|  |  |  |  | import 'package:shared_preferences/shared_preferences.dart'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// ============ 常量与坐标转换相关(WGS84/GCJ02/BD09) ============
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const double _pi = 3.1415926535897932384626; | 
					
						
							|  |  |  |  | const double _xPi = _pi * 3000.0 / 180.0; | 
					
						
							|  |  |  |  | const double _a = 6378245.0; | 
					
						
							|  |  |  |  | const double _ee = 0.006693421622965943; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// 判断是否在中国境内(仅中国境内需要偏移处理)
 | 
					
						
							|  |  |  |  | bool _outOfChina(double lat, double lon) { | 
					
						
							|  |  |  |  |   if (lon < 72.004 || lon > 137.8347) return true; | 
					
						
							|  |  |  |  |   if (lat < 0.8293 || lat > 55.8271) return true; | 
					
						
							|  |  |  |  |   return false; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | double _transformLat(double x, double y) { | 
					
						
							|  |  |  |  |   double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(x.abs()); | 
					
						
							|  |  |  |  |   ret += (20.0 * sin(6.0 * x * _pi) + 20.0 * sin(2.0 * x * _pi)) * 2.0 / 3.0; | 
					
						
							|  |  |  |  |   ret += (20.0 * sin(y * _pi) + 40.0 * sin(y / 3.0 * _pi)) * 2.0 / 3.0; | 
					
						
							|  |  |  |  |   ret += (160.0 * sin(y / 12.0 * _pi) + 320.0 * sin(y * _pi / 30.0)) * 2.0 / 3.0; | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | double _transformLon(double x, double y) { | 
					
						
							|  |  |  |  |   double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(x.abs()); | 
					
						
							|  |  |  |  |   ret += (20.0 * sin(6.0 * x * _pi) + 20.0 * sin(2.0 * x * _pi)) * 2.0 / 3.0; | 
					
						
							|  |  |  |  |   ret += (20.0 * sin(x * _pi) + 40.0 * sin(x / 3.0 * _pi)) * 2.0 / 3.0; | 
					
						
							|  |  |  |  |   ret += (150.0 * sin(x / 12.0 * _pi) + 300.0 * sin(x / 30.0 * _pi)) * 2.0 / 3.0; | 
					
						
							|  |  |  |  |   return ret; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// WGS84 -> GCJ02
 | 
					
						
							|  |  |  |  | List<double> wgs84ToGcj02(double lat, double lon) { | 
					
						
							|  |  |  |  |   if (_outOfChina(lat, lon)) return [lat, lon]; | 
					
						
							|  |  |  |  |   double dLat = _transformLat(lon - 105.0, lat - 35.0); | 
					
						
							|  |  |  |  |   double dLon = _transformLon(lon - 105.0, lat - 35.0); | 
					
						
							|  |  |  |  |   double radLat = lat / 180.0 * _pi; | 
					
						
							|  |  |  |  |   double magic = sin(radLat); | 
					
						
							|  |  |  |  |   magic = 1 - _ee * magic * magic; | 
					
						
							|  |  |  |  |   double sqrtMagic = sqrt(magic); | 
					
						
							|  |  |  |  |   dLat = (dLat * 180.0) / ((_a * (1 - _ee)) / (magic * sqrtMagic) * _pi); | 
					
						
							|  |  |  |  |   dLon = (dLon * 180.0) / ((_a / sqrtMagic) * cos(radLat) * _pi); | 
					
						
							|  |  |  |  |   double mgLat = lat + dLat; | 
					
						
							|  |  |  |  |   double mgLon = lon + dLon; | 
					
						
							|  |  |  |  |   return [mgLat, mgLon]; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// GCJ02 -> BD09
 | 
					
						
							|  |  |  |  | List<double> gcj02ToBd09(double lat, double lon) { | 
					
						
							|  |  |  |  |   double x = lon; | 
					
						
							|  |  |  |  |   double y = lat; | 
					
						
							|  |  |  |  |   double z = sqrt(x * x + y * y) + 0.00002 * sin(y * _xPi); | 
					
						
							|  |  |  |  |   double theta = atan2(y, x) + 0.000003 * cos(x * _xPi); | 
					
						
							|  |  |  |  |   double bdLon = z * cos(theta) + 0.0065; | 
					
						
							|  |  |  |  |   double bdLat = z * sin(theta) + 0.006; | 
					
						
							|  |  |  |  |   return [bdLat, bdLon]; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// 直接 WGS84 -> BD09(先 WGS84->GCJ02,再 GCJ02->BD09)
 | 
					
						
							|  |  |  |  | List<double> wgs84ToBd09(double lat, double lon) { | 
					
						
							|  |  |  |  |   final gcj = wgs84ToGcj02(lat, lon); | 
					
						
							|  |  |  |  |   return gcj02ToBd09(gcj[0], gcj[1]); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// ============ 定位相关设置 ============
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// 定位请求超时时间(可根据需要调整)
 | 
					
						
							|  |  |  |  | const Duration _locationTimeout = Duration(seconds: 10); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  | /// ============ 新增:获取 Position(带权限/超时/后备策略) ============
 | 
					
						
							|  |  |  |  | /// 返回 Position(WGS84)
 | 
					
						
							|  |  |  |  | Future<Position> getPositionFromGeolocator({ | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  |   LocationAccuracy accuracy = LocationAccuracy.high, | 
					
						
							|  |  |  |  | }) async { | 
					
						
							|  |  |  |  |   // 1. 权限检查与请求(先请求权限)
 | 
					
						
							|  |  |  |  |   LocationPermission permission = await Geolocator.checkPermission(); | 
					
						
							|  |  |  |  |   if (permission == LocationPermission.denied) { | 
					
						
							|  |  |  |  |     permission = await Geolocator.requestPermission(); | 
					
						
							|  |  |  |  |     if (permission == LocationPermission.denied) { | 
					
						
							|  |  |  |  |       // 用户拒绝(不是永久拒绝)
 | 
					
						
							|  |  |  |  |       throw Exception('定位权限被用户拒绝'); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   if (permission == LocationPermission.deniedForever) { | 
					
						
							|  |  |  |  |     // 永久拒绝(需要用户手动到设置开启)
 | 
					
						
							|  |  |  |  |     throw Exception('定位权限被永久拒绝'); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // 2. 检查定位服务是否开启(GPS/定位开关)
 | 
					
						
							|  |  |  |  |   bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); | 
					
						
							|  |  |  |  |   if (!serviceEnabled) { | 
					
						
							|  |  |  |  |     throw Exception('定位服务未开启'); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // 3. 尝试获取当前位置(主方案:getCurrentPosition,带超时)
 | 
					
						
							|  |  |  |  |   Position? position; | 
					
						
							|  |  |  |  |   try { | 
					
						
							|  |  |  |  |     position = await Geolocator.getCurrentPosition(desiredAccuracy: accuracy) | 
					
						
							|  |  |  |  |         .timeout(_locationTimeout); | 
					
						
							|  |  |  |  |   } on TimeoutException catch (_) { | 
					
						
							|  |  |  |  |     position = null; | 
					
						
							|  |  |  |  |   } catch (_) { | 
					
						
							|  |  |  |  |     position = null; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // 4. 后备:尝试 getLastKnownPosition(可能是旧位置)
 | 
					
						
							|  |  |  |  |   if (position == null) { | 
					
						
							|  |  |  |  |     try { | 
					
						
							|  |  |  |  |       position = await Geolocator.getLastKnownPosition(); | 
					
						
							|  |  |  |  |     } catch (_) { | 
					
						
							|  |  |  |  |       position = null; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   // 5. 后备:在 Android 上尝试 forceAndroidLocationManager(某些设备/厂商兼容性问题)
 | 
					
						
							|  |  |  |  |   if (position == null) { | 
					
						
							|  |  |  |  |     try { | 
					
						
							|  |  |  |  |       position = await Geolocator.getCurrentPosition( | 
					
						
							|  |  |  |  |         desiredAccuracy: accuracy, | 
					
						
							|  |  |  |  |         forceAndroidLocationManager: true, | 
					
						
							|  |  |  |  |       ).timeout(_locationTimeout); | 
					
						
							|  |  |  |  |     } catch (_) { | 
					
						
							|  |  |  |  |       position = null; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // 6. 最终仍无位置 -> 抛异常
 | 
					
						
							|  |  |  |  |   if (position == null) { | 
					
						
							|  |  |  |  |     throw Exception('无法获取位置信息,请检查设备定位设置或权限'); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |   return position; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// 获取 BD09 坐标(保持向后兼容:仍然返回 [bdLat, bdLon])
 | 
					
						
							|  |  |  |  | /// 内部改为调用 getPositionFromGeolocator 并转换
 | 
					
						
							|  |  |  |  | Future<List<double>> getBd09FromGeolocator({ | 
					
						
							|  |  |  |  |   LocationAccuracy accuracy = LocationAccuracy.high, | 
					
						
							|  |  |  |  | }) async { | 
					
						
							|  |  |  |  |   final pos = await getPositionFromGeolocator(accuracy: accuracy); | 
					
						
							|  |  |  |  |   return wgs84ToBd09(pos.latitude, pos.longitude); | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /// ============ 错误提示(中文映射) ============
 | 
					
						
							|  |  |  |  | String _mapExceptionToChineseMessage(Object e) { | 
					
						
							|  |  |  |  |   final msg = e?.toString() ?? ''; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (msg.contains('定位权限被用户拒绝') || msg.contains('Location permissions are denied') || msg.contains('denied')) { | 
					
						
							|  |  |  |  |     return '定位权限被拒绝,请允许应用获取定位权限。'; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   if (msg.contains('定位权限被永久拒绝') || msg.contains('deniedForever') || msg.contains('permanently denied')) { | 
					
						
							|  |  |  |  |     return '定位权限被永久拒绝,请到系统设置手动开启定位权限。'; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   if (msg.contains('定位服务未开启') || msg.contains('Location services are disabled')) { | 
					
						
							|  |  |  |  |     return '设备定位功能未开启,请打开系统定位后重试。'; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   if (msg.contains('无法获取位置信息') || msg.contains('无法获取位置信息')) { | 
					
						
							|  |  |  |  |     return '无法获取有效定位,请检查网络/GPS并重试(可尝试切换到高精度模式)。'; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  |   // 默认返回空字符串,调用方根据空串决定是否显示
 | 
					
						
							|  |  |  |  |   return '定位失败:${msg.replaceAll('Exception: ', '')}'; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  | /// 点位数组计算中心点
 | 
					
						
							|  |  |  |  | Map<String, double> geographicCentroid(List<dynamic> points) { | 
					
						
							|  |  |  |  |   if (points.isEmpty) { | 
					
						
							|  |  |  |  |     throw ArgumentError('points 不能为空'); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   double x = 0.0, y = 0.0, z = 0.0; | 
					
						
							|  |  |  |  |   double altSum = 0.0; | 
					
						
							|  |  |  |  |   int altCount = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (var p in points) { | 
					
						
							|  |  |  |  |     final lon = p[0]; | 
					
						
							|  |  |  |  |     final lat = p[1]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     final latR = lat * pi / 180.0; | 
					
						
							|  |  |  |  |     final lonR = lon * pi / 180.0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     final cx = cos(latR) * cos(lonR); | 
					
						
							|  |  |  |  |     final cy = cos(latR) * sin(lonR); | 
					
						
							|  |  |  |  |     final cz = sin(latR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     x += cx; | 
					
						
							|  |  |  |  |     y += cy; | 
					
						
							|  |  |  |  |     z += cz; | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     if (p.length > 2 && p[2] != null) { | 
					
						
							|  |  |  |  |       altSum += p[2]; | 
					
						
							|  |  |  |  |       altCount++; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   final cnt = points.length.toDouble(); | 
					
						
							|  |  |  |  |   x /= cnt; | 
					
						
							|  |  |  |  |   y /= cnt; | 
					
						
							|  |  |  |  |   z /= cnt; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   final hyp = sqrt(x * x + y * y); | 
					
						
							|  |  |  |  |   final centroidLat = atan2(z, hyp) * 180.0 / pi; | 
					
						
							|  |  |  |  |   final centroidLon = atan2(y, x) * 180.0 / pi; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   final result = <String, double>{ | 
					
						
							|  |  |  |  |     'lon': centroidLon, | 
					
						
							|  |  |  |  |     'lat': centroidLat, | 
					
						
							|  |  |  |  |   }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (altCount > 0) { | 
					
						
							|  |  |  |  |     result['alt'] = altSum / altCount; | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return result; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | /// ============ 主业务方法:获取并保存 BD09(同时处理 UI 提示/引导) ============
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  | /// 现在会同时保存:WGS84(原始) / GCJ02 / BD09,以及保存时间戳(bd_saved_at)
 | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | Future<void> fetchAndSaveBd09(BuildContext context) async { | 
					
						
							|  |  |  |  |   try { | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     // 获取原始位置(WGS84)
 | 
					
						
							|  |  |  |  |     final Position position = await getPositionFromGeolocator(); | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     final double wgsLat = position.latitude; | 
					
						
							|  |  |  |  |     final double wgsLon = position.longitude; | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     // 计算 GCJ02(在中国境内会偏移,否则返回原始)
 | 
					
						
							|  |  |  |  |     final gcj = wgs84ToGcj02(wgsLat, wgsLon); | 
					
						
							|  |  |  |  |     final double gcjLat = gcj[0]; | 
					
						
							|  |  |  |  |     final double gcjLon = gcj[1]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 计算 BD09
 | 
					
						
							|  |  |  |  |     final bd = gcj02ToBd09(gcjLat, gcjLon); | 
					
						
							|  |  |  |  |     final double bdLat = bd[0]; | 
					
						
							|  |  |  |  |     final double bdLon = bd[1]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 保存到 SharedPreferences(同时保存原始 WGS84、GCJ02、BD09,以及保存时间)
 | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  |     final prefs = await SharedPreferences.getInstance(); | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     await prefs.setString('wgs84_lat', wgsLat.toString()); | 
					
						
							|  |  |  |  |     await prefs.setString('wgs84_lon', wgsLon.toString()); | 
					
						
							|  |  |  |  |     await prefs.setString('gcj02_lat', gcjLat.toString()); | 
					
						
							|  |  |  |  |     await prefs.setString('gcj02_lon', gcjLon.toString()); | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  |     await prefs.setString('bd_lat', bdLat.toString()); | 
					
						
							|  |  |  |  |     await prefs.setString('bd_lon', bdLon.toString()); | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     await prefs.setInt('bd_saved_at', DateTime.now().millisecondsSinceEpoch); | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     // 成功提示(按需开启)
 | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  |     // ToastUtil.showNormal(context, '定位成功:$bdLat, $bdLon');
 | 
					
						
							|  |  |  |  |   } on Exception catch (e) { | 
					
						
							|  |  |  |  |     final msg = e.toString(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 定位权限被永久拒绝 -> 引导用户打开应用设置
 | 
					
						
							|  |  |  |  |     if (msg.contains('定位权限被永久拒绝') || msg.contains('deniedForever') || msg.contains('permanently denied')) { | 
					
						
							|  |  |  |  |       final open = await CustomAlertDialog.showConfirm( | 
					
						
							|  |  |  |  |         context, | 
					
						
							|  |  |  |  |         title: '定位权限', | 
					
						
							|  |  |  |  |         content: '定位权限被永久拒绝,需要手动到应用设置开启定位权限,是否现在打开设置?', | 
					
						
							|  |  |  |  |         cancelText: '取消', | 
					
						
							|  |  |  |  |         confirmText: '去设置', | 
					
						
							|  |  |  |  |       ); | 
					
						
							|  |  |  |  |       if (open == true) { | 
					
						
							|  |  |  |  |         await Geolocator.openAppSettings(); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |     // 定位服务未开启 -> 引导用户打开系统定位设置
 | 
					
						
							|  |  |  |  |     else if (msg.contains('定位服务未开启') || msg.contains('Location services are disabled')) { | 
					
						
							|  |  |  |  |       final open = await CustomAlertDialog.showConfirm( | 
					
						
							|  |  |  |  |         context, | 
					
						
							|  |  |  |  |         title: '打开定位', | 
					
						
							|  |  |  |  |         content: '检测到设备定位服务未开启,是否打开系统定位设置?', | 
					
						
							|  |  |  |  |         cancelText: '取消', | 
					
						
							|  |  |  |  |         confirmText: '去打开', | 
					
						
							|  |  |  |  |       ); | 
					
						
							|  |  |  |  |       if (open == true) { | 
					
						
							|  |  |  |  |         await Geolocator.openLocationSettings(); | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |     // 其它错误 -> 以 toast 显示中文提示(如果映射为空则显示原错误)
 | 
					
						
							|  |  |  |  |     else { | 
					
						
							|  |  |  |  |       final userMsg = _mapExceptionToChineseMessage(e); | 
					
						
							|  |  |  |  |       if (userMsg.isNotEmpty) { | 
					
						
							|  |  |  |  |         // ToastUtil.showError(context, userMsg);
 | 
					
						
							|  |  |  |  |       } else { | 
					
						
							|  |  |  |  |         // ToastUtil.showError(context, '定位失败:${e.toString()}');
 | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   } catch (e) { | 
					
						
							|  |  |  |  |     // 捕获任何未预期异常
 | 
					
						
							|  |  |  |  |     // ToastUtil.showError(context, '发生未知错误:${e.toString()}');
 | 
					
						
							|  |  |  |  |   } finally { | 
					
						
							| 
									
										
										
										
											2025-09-05 09:16:54 +08:00
										 |  |  |  |     // 如需隐藏 loading 可在此处处理
 | 
					
						
							| 
									
										
										
										
											2025-09-02 16:22:17 +08:00
										 |  |  |  |   } | 
					
						
							|  |  |  |  | } |