连续定位用于持续接收位置变化。
本文档介绍连续定位的接口、生命周期、相关事件流以及前台 / 后台定位的处理方式。
class TencentLocationManager {
Future<void> startContinuousLocation(TencentLocationRequest request);
Future<void> stopContinuousLocation();
Stream<TencentLocation> get onLocationChanged;
Stream<TencentLocationError> get onLocationError;
Stream<TencentDeviceStatus> get onStatusChanged;
}
调用顺序:
创建 TencentLocationManager 实例。
订阅 onLocationChanged / onLocationError 等事件流。
调用 startContinuousLocation(request) 启动连续定位。
在不再需要定位时调用 stopContinuousLocation(),并调用 dispose() 释放管理器。
final manager = TencentLocationManager();
final locationSubscription = manager.onLocationChanged.listen((location) {
print('新位置:${location.latitude}, ${location.longitude}, '
'accuracy=${location.accuracy}, source=${location.source}');
});
final errorSubscription = manager.onLocationError.listen((error) {
print('定位错误:${error.code} ${error.message}');
});
final request = TencentLocationRequest.create()
..setRequestLevel(RequestLevel.adminArea)
..setCoordinateType(CoordinateType.gcj02)
..setInterval(const Duration(seconds: 3));
await manager.startContinuousLocation(request);
setInterval 配置位置回调的最小间隔,建议不小于 1 秒。
注意:在同一个 TencentLocationManager 实例上重复调用 startContinuousLocation 会抛出 TencentLocationError,错误码为 alreadyStarted。如需修改请求参数,请先调用 stopContinuousLocation() 再重新启动。
await locationSubscription.cancel();
await errorSubscription.cancel();
await manager.stopContinuousLocation();
await manager.dispose();
dispose() 是幂等的,可以多次调用。dispose 之后再调用本实例的任何方法都会抛出 StateError。
stopContinuousLocation 在未启动连续定位时调用是安全的,不会抛错。
onLocationChanged每次产生新的定位结果时回调,回调的 TencentLocation 字段含义与 单次定位 章节中说明一致。
onLocationChanged 是一个广播流,可以被多次订阅,所有订阅者都会收到事件。
onLocationError定位过程中产生的错误会通过本流回调,例如网络异常、定位失败等。错误对象同样为 TencentLocationError,错误码列表见 错误码。
onStatusChanged(设备状态)随连续定位一并产生的 GPS / Wi-Fi / 蜂窝网络 / 定位总开关等状态变化事件。
final statusSubscription = manager.onStatusChanged.listen((status) {
print('设备状态变化:kind=${status.kind}, status=${status.status}, '
'description=${status.description}');
});
TencentDeviceStatus 包含三个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
kind |
DeviceStatusKind |
状态类别:gps / wifi / cellular / vpn / locationSwitch |
status |
DeviceStatus |
当前状态:available / enabledButUnavailable / disabled / denied / unknown |
description |
String? |
系统提供的额外描述文本(可能为空) |
平台支持:
Android:完整支持,事件随连续定位回调一并产生
iOS:iOS 系统层面对插件不开放等价的状态回调,订阅本流不会抛异常但也不会收到事件
HarmonyOS:支持,事件类型覆盖蜂窝网络 / Wi-Fi / VPN 网络可用性、定位总开关状态等
如果你的业务对设备状态有跨端一致需求,建议结合 错误码 中的错误回调(例如 permissionDenied / locationSwitchOff)一并处理。
启动连续定位之后,可以使用 changeCallbackInterval 动态修改回调间隔,避免重新启动定位带来的开销:
await manager.changeCallbackInterval(const Duration(seconds: 5));
平台支持:
Android:支持
iOS:不支持,调用会抛出 TencentLocationError,错误码为 unsupportedOnThisPlatform
HarmonyOS:不支持,鸿蒙原生 SDK 需要 stop→改 request→start 才能改回调间隔,调用会抛出 TencentLocationError,错误码为 unsupportedOnThisPlatform
如需在 iOS / HarmonyOS 端调整频率,建议先 stopContinuousLocation(),重新构造请求并 startContinuousLocation。
final last = await manager.getLastLocation();
if (last != null) {
print('最近一次位置:${last.latitude}, ${last.longitude}');
}
平台支持:
Android:支持
iOS:不支持,调用会抛出 TencentLocationError,错误码为 unsupportedOnThisPlatform
HarmonyOS:支持
应用进入后台后,Android 系统可能会收紧后台定位频率甚至完全停止后台定位。如需在后台稳定接收定位回调,可以启用前台服务:
await manager.enableForeground(
notificationId: 1001,
channelId: 'location_channel',
title: '正在为您提供定位服务',
text: '点击返回应用',
smallIconResourceName: 'ic_launcher',
);
参数说明:
notificationId:通知 ID,必须大于 0
channelId:Android 8.0 及以上必填的 NotificationChannel ID
title / text:通知栏展示的标题与正文文案
smallIconResourceName:通知小图标的资源名(位于 mipmap / drawable 目录下,不含扩展名);为空时使用应用默认图标
不再需要前台服务时调用:
await manager.disableForeground();
平台支持:
Android:支持
iOS:不支持,调用会抛出 TencentLocationError,错误码为 unsupportedOnThisPlatform
HarmonyOS:不支持,鸿蒙的后台定位由 后台定位任务 一节的独立接口提供,不共用同一套 API
iOS 端的后台定位通过在 Info.plist 中勾选 UIBackgroundModes 的 location 启用,并在请求权限时申请「始终允许」(requestIosAlwaysAuthorization)。
HarmonyOS 提供独立的后台定位任务接口,用于让应用在进入后台后仍可持续接收位置回调:
await manager.startBackgroundLocationTask();
// 不再需要后台定位时:
await manager.stopBackgroundLocationTask();
startBackgroundLocationTask 接受一个可选参数 wantAgentInfo:需要自定义后台任务通知点击行为时,传入鸿蒙 wantAgent.WantAgentInfo 对应的 map(key 与鸿蒙 API 一致,原样透传);不传时使用系统默认行为。
调用 startBackgroundLocationTask 时,系统会通过通知栏显示一条常驻通知向用户表明后台定位正在进行;点击通知会拉起应用自身的 Ability。
平台支持:
Android:不支持,调用会抛出 TencentLocationError,错误码为 unsupportedOnThisPlatform。Android 端请使用上一节的 前台定位 接口。
iOS:不支持,调用会抛出 TencentLocationError,错误码为 unsupportedOnThisPlatform。iOS 端请在 Info.plist 中勾选 UIBackgroundModes 的 location,并申请「始终允许」授权。
HarmonyOS:支持
调用前请确认已在 entry/src/main/module.json5 中声明 ohos.permission.LOCATION_IN_BACKGROUND 并申请到用户授权。
import 'dart:async';
import 'package:tencent_location_flutter_plugin/tencent_location_flutter_plugin.dart';
class LocationService {
final TencentLocationManager _manager = TencentLocationManager();
StreamSubscription<TencentLocation>? _locationSub;
StreamSubscription<TencentLocationError>? _errorSub;
Future<void> start() async {
_locationSub = _manager.onLocationChanged.listen((location) {
print('位置更新:${location.latitude}, ${location.longitude}');
});
_errorSub = _manager.onLocationError.listen((error) {
print('定位错误:${error.code} ${error.message}');
});
final request = TencentLocationRequest.create()
..setRequestLevel(RequestLevel.adminArea)
..setCoordinateType(CoordinateType.gcj02)
..setInterval(const Duration(seconds: 3));
await _manager.startContinuousLocation(request);
}
Future<void> stop() async {
await _manager.stopContinuousLocation();
await _locationSub?.cancel();
await _errorSub?.cancel();
await _manager.dispose();
}
}
有帮助
没帮助