定位方案-融合定位
· 阅读需 4 分钟
Flutter应用在没有GPS的情况下,可以通过Wi-Fi定位和IP定位两种方案获取位置信息。
一、Wi-Fi定位(推荐)
原理
Wi-Fi定位通过扫描周围Wi-Fi热点的MAC地址和信号强度,与服务器数据库匹配来计算位置,精度可达20-50米。
实现方式
1. 使用高德/百度地图SDK(推荐)
国内地图SDK内置Wi-Fi定位功能,自动融合GPS、Wi-Fi、基站数据。
// 使用 flutter_amap_location 插件
import 'package:flutter_amap_location/flutter_amap_location.dart';
// 初始化定位
await AMapLocationClient.startup(new AMapLocationOption(
desiredAccuracy: CLLocationAccuracy.kCLLocationAccuracyHundredMeters,
locationMode: AMapLocationMode.Hight_Accuracy, // 高精度模式会启用Wi-Fi定位
));
// 获取定位
var location = await AMapLocationClient.getLocation(true);
print('纬度: ${location.latitude}, 经度: ${location.longitude}');
2. 使用 geolocator 插件
import 'package:geolocator/geolocator.dart';
// 检查定位服务是否启用
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
// 获取位置(自动使用最佳可用方案:GPS > Wi-Fi > 基站)
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high, // high会自动启用Wi-Fi定位
);
print('位置: ${position.latitude}, ${position.longitude}');
必需权限(Android)
在 android/app/src/main/AndroidManifest.xml 中声明:
<!-- 网络定位(无GPS情况下的定位)必选 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- Wi-Fi定位必需 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 设备和运营商信息(基站定位辅助) -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
关键点:ACCESS_COARSE_LOCATION 权限允许使用Wi-Fi和基站进行粗略定位。
二、IP定位(备用方案)
原理
通过设备的公网IP地址查询地理位置,精度较低(通常只能定位到城市级别),但无需任何特殊权限。
实现方式
1. 使用 ip_geolocation_io 插件
import 'package:ip_geolocation_io/ip_geolocation_io.dart';
// 获取IP定位信息
final ipGeo = IpGeolocationIo();
final geoData = await ipGeo.getGeoData();
print('国家: ${geoData.country}');
print('省份: ${geoData.state}');
print('城市: ${geoData.city}');
print('纬度: ${geoData.latitude}'); // 城市中心坐标
print('经度: ${geoData.longitude}');
2. 使用 HTTP 请求
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> getLocationByIP() async {
final response = await http.get(Uri.parse('http://ip-api.com/json/'));
if (response.statusCode == 200) {
final data = json.decode(response.body);
print('城市: ${data['city']}');
print('坐标: ${data['lat']}, ${data['lon']}');
}
}
三、两种方案对比
| 特性 | Wi-Fi定位 | IP定位 |
|---|---|---|
| 精度 | 高(20-50米) | 低(城市级,误差几公里) |
| 依赖 | 需开启Wi-Fi,无需连接 | 仅需网络连接 |
| 权限 | 需要定位权限 | 无需权限 |
| 速度 | 快(1-3秒) | 极快(毫秒级) |
| 耗电 | 中等 | 极低 |
| 室内支持 | ✅ 优秀 | ❌ 不支持 |
四、最佳实践建议
1. 自动降级策略
Future<Position?> getLocation() async {
try {
// 优先使用高精度定位(GPS+Wi-Fi)
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
);
} catch (e) {
// GPS/Wi-Fi都失败,降级到IP定位
final ipData = await getLocationByIP();
return Position(
latitude: ipData.latitude,
longitude: ipData.longitude,
timestamp: DateTime.now(),
accuracy: 5000, // 标记低精度
);
}
}
2. Android 10+ 注意事项
- 需要动态申请
ACCESS_BACKGROUND_LOCATION权限才能在后台定位 - 建议引导用户开启Wi-Fi扫描功能以提升定位精度
3. iOS 配置
在 ios/Runner/Info.plist 中添加:
<key>NSLocationWhenInUseUsageDescription</key>
<string>App需要您的同意才能访问位置</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>App需要您的同意才能在后台访问位置</string>
五、总结
推荐使用 Wi-Fi定位 作为GPS的替代方案,精度足以满足大多数场景需求。IP定位仅作为最后备用手段。主流地图SDK已内置完善的多源融合定位能力,开发者无需关心底层实现细节。
实现路径:配置权限 → 选择插件 → 调用统一API → 自动处理GPS/Wi-Fi/基站切换。
微信公众号

