import 'dart:async'; import 'dart:convert'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:geolocator/geolocator.dart'; import 'package:getx_scaffold/getx_scaffold.dart'; import 'package:permission_handler/permission_handler.dart'; class MapController extends GetxController with BaseControllerMixin ,WidgetsBindingObserver{ @override String get builderId => 'map'; InAppWebViewController? webViewController; StreamSubscription? positionStream; // --- 状态标志 --- final RxBool isLocationPermissionGranted = false.obs; final RxBool isMapReady = false.obs; // 跟踪地图是否加载完成 Position? _lastKnownPosition; @override void onInit() { super.onInit(); WidgetsBinding.instance.addObserver(this); // 注册监听 requestLocationPermission(); } @override void onClose() { WidgetsBinding.instance.removeObserver(this); // 移除监听 positionStream?.cancel(); super.onClose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // 回到前台,如果之前有权限且开启过,恢复定位 if(isLocationPermissionGranted.value) _startLocationTracking(); } else if (state == AppLifecycleState.paused) { // 切到后台,取消定位流 positionStream?.cancel(); } } /// WebView 创建完成时调用 void onWebViewCreated(InAppWebViewController controller) { webViewController = controller; // 添加 JS Handler 来监听来自网页的 'mapReady' 事件 controller.addJavaScriptHandler( handlerName: 'mapReady', callback: (args) { print("Flutter<-JS: Map is ready, starting location tracking."); isMapReady.value = true; // 地图就绪后,如果已有权限和缓存的定位,则开始定位 if (isLocationPermissionGranted.value) { _startLocationTracking(); } }, ); } /// 优化后的权限请求函数 void requestLocationPermission() async { bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { showErrorToast('请开启手机的定位服务'); return; } var status = await Permission.locationWhenInUse.request(); switch (status) { case PermissionStatus.granted: isLocationPermissionGranted.value = true; // 权限已获取,如果地图也已就绪,则开始定位 if (isMapReady.value) { _startLocationTracking(); } break; case PermissionStatus.denied: showErrorToast('需要定位权限才能显示您的位置'); break; case PermissionStatus.permanentlyDenied: showErrorToast('定位权限已被永久拒绝,请到设置中手动开启'); openAppSettings(); break; default: showErrorToast('获取定位权限时发生未知错误'); break; } } /// 开始定位监听 (不再需要 delay) void _startLocationTracking() async { if (!isLocationPermissionGranted.value || !await Geolocator.isLocationServiceEnabled()) { return; } const LocationSettings locationSettings = LocationSettings( accuracy: LocationAccuracy.high, distanceFilter: 10, ); // 立即获取一次当前位置,用于快速初始化 try { Position position = await Geolocator.getCurrentPosition(); _lastKnownPosition = position; _syncLocationToMap(position); } catch (e) { print("Error getting initial position: $e"); } // 持续监听位置变化 positionStream?.cancel(); // 先取消旧的监听 positionStream = Geolocator.getPositionStream(locationSettings: locationSettings) .listen((Position position) { _lastKnownPosition = position; _syncLocationToMap(position); }); } // 将 Flutter 的定位数据同步给 JS void _syncLocationToMap(Position position) { if (webViewController == null || !isMapReady.value) return; // 只有当 heading 有效且大于 0 时才传给 JS,否则传 null,让 JS 保持上一次的角度 String headingVal = (position.heading > 0) ? "${position.heading}" : "null"; webViewController!.evaluateJavascript( source: "updateMyLocation(${position.latitude}, ${position.longitude}, ${position.heading})", ); } }