tencent_location_flutter 0.1.0
tencent_location_flutter: ^0.1.0 copied to clipboard
Unofficial Flutter Tencent location plugin with federated Android and iOS implementations.
tencent_location_flutter #
tencent_location_flutter 是面向业务应用的 Flutter 腾讯定位主包。
非官方声明:本包不是腾讯官方包,也不代表腾讯地图或腾讯位置服务官方 SDK。 本包只是面向 Flutter 的第三方封装;腾讯、腾讯地图、Tencent Location SDK 等名称、商标、原生 SDK 与官方接口语义归其权利方所有。
它提供:
- 初始化、隐私同意、SDK 信息、授权状态、单次定位、连续定位
- 统一入口:朝向、距离计算、圆形范围判断、坐标转换、取消单次定位、回调频率调整、设备 ID、自定义 SDK 数据、DR 惯导
- 统一入口:圆形/多边形/行政区划围栏、围栏事件流
- Android 命名空间:场景化定位、前台服务通知、最近一次定位、GPS 支持判断、OAID、系统缓存开关、原生库加载开关
- iOS 命名空间:权限申请、临时完整精度授权、原生朝向校准界面控制
- 强类型模型、事件流,以及统一的跨平台调用入口
当前固定原生版本:
- Android:
7.6.1.8 - iOS:
4.3.1
Android 8.7.5.1 已做过编译验证,但该版本线缺少围栏、场景化定位、DR、系统缓存等当前需要开放的公开 SDK API;默认版本固定在仍覆盖这些能力的 7.x 版本线最新版本。iOS 4.3.1 随包 xcf 已公开 geofence 头文件,插件通过 SwiftPM 开放统一地理围栏能力。
安装 #
当前仓库地址:
- 浏览地址:
https://cnb.cool/nazo/tencent_location_flutter - Git 地址:
https://cnb.cool/nazo/tencent_location_flutter.git
业务应用只依赖这一个包:
dependencies:
tencent_location_flutter:
git:
url: https://cnb.cool/nazo/tencent_location_flutter.git
path: packages/flutter_tencent_location
说明:
- 宿主不需要额外修改
build.gradle - 宿主不需要创建或修改
Podfile;Flutter 3.44+ 按 SwiftPM 解析 iOS 插件 - 宿主不需要手工下载腾讯 Android/iOS SDK
宿主配置 #
Android #
至少声明这些权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
如果要做后台定位或前台服务,再补充:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
iOS #
至少声明:
NSLocationWhenInUseUsageDescriptionNSLocationAlwaysAndWhenInUseUsageDescription
如果要临时完整精度定位,再补:
NSLocationTemporaryUsageDescriptionDictionary
如果要后台定位,再打开:
Background Modes > Location updates
说明:
- iOS Simulator 不支持腾讯定位 SDK,请直接用真机验证
- 即使插件已经内置 iOS SDK,权限声明依然必须由宿主自己完成
快速开始 #
final TencentLocation location = TencentLocation.instance;
await location.setUserAgreePrivacy(true);
await location.initialize(
const InitializeOptions(
key: 'YOUR_TENCENT_LOCATION_KEY',
coordinateType: TencentLocationCoordinateType.gcj02,
requestLevel: TencentLocationRequestLevel.adminName,
android: AndroidInitOptions(
locationMode: TencentAndroidLocationMode.highAccuracy,
allowGps: true,
),
ios: IosManagerOptions(
allowsBackgroundLocationUpdates: true,
pausesLocationUpdatesAutomatically: false,
),
),
);
final TencentLocationData data = await location.getLocationOnce(
options: const SingleLocationOptions(),
);
print(data.latitude);
print(data.longitude);
print(data.address);
print(data.addressDescription);
关于地址描述 #
如果你的业务目标是“拿一个可直接展示给用户的位置描述”,优先使用:
TencentLocationRequestLevel.formattedAddress
对应行为:
- Android:如果原生 SDK 提供
REQUEST_LEVEL_FORMATTED_ADDRESS就使用该级别;当前实现会在缺少该常量时回退到REQUEST_LEVEL_ADMIN_AREA - iOS:因为原生 SDK 没有完全等价级别,插件会退化到可返回地址字符串的级别
单次定位在 Android 上还会额外做两件事:
- 请求级别不是
geo时,要求首个结果就带地址信息 - 关闭缓存,并把
SingleLocationOptions.timeoutMillis映射到原生首个结果超时
字段语义:
address原生 SDK 自己的地址字段addressDescription插件整理后的“描述地址”,更适合直接展示
如果你主要想拿 POI,请用 TencentLocationRequestLevel.poi,但它不保证一定有 address / addressDescription。
连续 geo 定位运行中可以再发起一次单次定位,插件不会主动停止当前连续定位监听。
但 Android 腾讯 SDK 的 requestSingleFreshLocation(...) 在周期性定位已启动时,
返回结果会跟随当前连续请求级别;因此连续 geo 会话中单次 poi 请求通常仍只返回坐标,
不能稳定拿到省市区、街道或 POI。需要这些详情时,应让连续请求级别本身使用 adminName/poi,
或停止连续 geo 会话后再执行单次详情定位。
2026-05-24 的 Android 全功能真机测试已覆盖连续定位、单次地址、heading、围栏、DR
等主能力;连续 geo 中单次 poi 的专项测试在本轮真机环境中连续首包超时,
未取得有效结论。该专项仍保留为设备侧复测入口,用于确认具体机型和网络环境下的真实表现。
连续定位示例 #
final LocationUpdateSession session = await location.startLocationUpdates(
const LocationUpdateOptions(
intervalMillis: 15000,
requestLevel: TencentLocationRequestLevel.adminName,
backgroundLocation: true,
androidRequest: AndroidLocationRequestOptions(
intervalMillis: 15000,
locationMode: TencentAndroidLocationMode.highAccuracy,
),
androidForegroundNotification: AndroidForegroundNotificationOptions(
id: 1001,
channelId: 'location_foreground',
channelName: 'Tencent Location',
title: 'Tencent Location',
text: 'Continuous location is running',
),
),
);
session.updates.listen(print);
session.errors.listen(print);
设备朝向 #
设备朝向通过独立系统传感器链路提供;插件不暴露腾讯定位请求里的
allowDirection,定位结果也不再包含设备朝向字段。GPS bearing 只表示移动方向,
不能作为设备机身朝向使用。
Android 原生层使用 SensorManager,优先监听 TYPE_ROTATION_VECTOR,
其次回退到 TYPE_GEOMAGNETIC_ROTATION_VECTOR,设备不支持旋转向量时才使用
TYPE_ACCELEROMETER + TYPE_MAGNETIC_FIELD 合成朝向。
iOS 原生层使用系统 CLLocationManager.startUpdatingHeading() 获取罗盘 heading,
不走 TencentLBSLocationManager.startUpdatingHeading(),也不使用定位点 course。
采集开启后,插件会以约 500ms 间隔持续推送最后已知朝向;即使设备静止、
系统传感器没有新的角度变化,上层也不需要回退到定位 bearing 来维持方向显示。
await location.startHeadingUpdates();
location.headingUpdates.listen((HeadingData data) {
print(data.magneticHeading);
});
await location.stopHeadingUpdates();
跨平台官方能力 #
Android / iOS 语义一致的 SDK 能力会通过 TencentLocation 统一入口暴露,
业务代码不需要感知平台命名空间:
final double distance = await location.distanceBetween(
startLatitude: 22.5,
startLongitude: 113.9,
endLatitude: 22.6,
endLongitude: 114.0,
);
final bool inside = await location.containsCoordinate(
centerLatitude: 22.5,
centerLongitude: 113.9,
radiusMeters: 100,
latitude: 22.5001,
longitude: 113.9001,
);
await location.changeCallbackInterval(3000);
await location.cancelLocationRequest();
await location.setDeviceId('user-or-device-id');
await location.setSdkData('ReGeoCodingnKey', 'YOUR_WEB_SERVICE_KEY');
final bool drSupported = await location.isDrSupported();
if (drSupported) {
final TencentDrStartCode code = await location.startDrEngine(
const TencentDrOptions(motionType: TencentDrMotionType.walk),
);
final DrPosition? position = await location.getDrPosition();
await location.stopDrEngine();
}
如果你还需要访问平台专属能力,location.android / location.ios
命名空间只保留无法可靠抽象为跨平台语义的能力,例如场景化定位、OAID 和 iOS 权限等。
中国区域离线判断 #
final bool inChina = isCoordinateInChina(
latitude: 22.543096,
longitude: 114.057865,
);
final bool sameResult = location.isCoordinateInChina(
latitude: 22.543096,
longitude: 114.057865,
);
isCoordinateInChina(...) 是纯 Dart 离线函数,覆盖中国大陆、香港、澳门、台湾以及数据源多边形中包含的岛屿。实现使用边界盒、经纬度网格索引和多边形精确包含判断;索引只减少候选多边形与边数量,不用粗略矩形、圆形或坐标偏移规则替代边界判断。
坐标转换使用独立的 isCoordinateInGcj02TransformRegion(...) 作为偏移适用区判断。该函数不是领土判断;香港、澳门、台湾仍会被 isCoordinateInChina(...) 判定为中国区域,但默认不会被套用 GCJ-02 近似偏移。
坐标转换 #
final TencentCoordinate wgs84 = gcj02ToWgs84(
latitude: 22.587286,
longitude: 113.948066,
);
final TencentCoordinate gcj02 = location.convertWgs84ToGcj02(
latitude: wgs84.latitude,
longitude: wgs84.longitude,
);
gcj02ToWgs84(...)、wgs84ToGcj02(...) 以及 TencentLocation.instance
上的同名语义方法都在 Dart 层离线执行;GCJ-02 偏移适用区域外坐标会原样返回。
正向 WGS84 -> GCJ-02 公式与公开开源 coordtransform 等常见实现同族,是移动互联网地图业务里常见的非官方近似公式;逆向 GCJ-02 -> WGS84 由本插件基于同一正向公式做迭代反解。该能力不依赖 Android/iOS 原生 SDK,也不会发起网络请求。它不是腾讯定位 SDK 的官方双向转换接口,也不是国家公开标准算法。腾讯 iOS SDK 公开了 TencentLBSLocationUtils.WGS84TOGCJ02,但没有对等的 GCJ02TOWGS84;Android 定位 SDK 文档主要提供定位结果坐标系配置,未提供双端对等的独立双向转换工具。
gcj02ToWgs84(...) 通过迭代反解本插件的 wgs84ToGcj02(...),误差边界只表示相对同一近似公式的数值反解误差,不代表相对腾讯 SDK 内部实现或测绘级算法的官方精度保证。该能力适合普通移动定位业务中的坐标系归一、地图展示和轨迹存储前处理,不适用于测绘、法律边界、审计、资产确权或其他要求官方转换参数的场景。
平台专属官方能力 #
Android:
final String? oaid = await location.android.getOaid();
final bool gpsSupported = await location.android.isGpsSupported();
final LocationUpdateSession sceneSession =
await location.android.startLocationWithScene(
TencentAndroidLocationScene.sport,
);
AndroidLocationRequestOptions.smallAppKey 会映射到 Android 原生
TencentLocationRequest.setSmallAppKey(...),用于官方文档中的分渠道或业务场景标识。
iOS:
await location.ios.requestWhenInUseAuthorization();
await location.ios.dismissHeadingCalibrationDisplay();
说明:
- 原生 SDK 文档中标记为测试、调试或内部使用的接口不作为业务 API 暴露。
- Android SDK 日志监听、
setDebuggable等诊断入口不进入主包公开接口。 - 地理围栏只通过统一入口暴露:
location.addGeofence(...)、location.getValidGeofences()、location.removeGeofence(...)与location.removeAllGeofences()。
进一步阅读 #
- 详细使用说明:USAGE.md
- 仓库维护说明:../../DEPLOYMENT.md
- 许可与第三方说明:../../LICENSE