137 lines
4.3 KiB
Dart
137 lines
4.3 KiB
Dart
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})",
|
||
);
|
||
}
|
||
}
|