Files
ln-ios/ln_jq_app/lib/pages/c_page/map/controller.dart
2025-11-27 15:25:58 +08:00

137 lines
4.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Position>? 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})",
);
}
}