前言
定位、地图也算是广大应用平台基本上都会用到的功能,flutter 中自然也出现了对应的相关组件,即:amap_flutter 系列,下面介绍下配置,以及简单使用
高德api平台可以在里面注册认证申请相关id,其中 android 端会用到 SHA 码,具体的可以参考 android 签名文件配置
amap_flutter搜索页面 、amap_flutter_map 、amap_flutter_location
环境配置
key 配置
进入 高德api平台 可以在里面注册认证申请相关id,其中 android 端会用到 SHA 码,具体的可以参考 android 签名文件配置,具体配置就不多介绍了
flutter 端配置
通过 flutter pub add 库名导入相关三方库,使用的库如下所示
//使用定位和地图是要引入这四个库的,第四个权限的不多说
//amap_flutter_base为基础库,无论是定位还是地图都要引入
amap_flutter_map
amap_flutter_location
amap_flutter_base
permission_handler
ios端配置
ios 端的定位可以进入 permission_handler 文档查看 podfile文件要修改的(前面文章有介绍过),另外 m1 的芯片记得不要再 android studio 中执行 pod install 要在自己配置好的终端执行
下面几个定位前面是新版本的定位权限,后面是老的定位权限都加入即可,ios11增加的权限,根据兼容情况选择即可,如果老的没用 xcode 也不会显示出来让咱们选是吧
<key>NSLocationDefaultAccuracyReduced</key>
<string>$(PRODUCT_BUNDLE_NAME)精准定位</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>$(PRODUCT_BUNDLE_NAME)持续定位</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_BUNDLE_NAME)使用期间获取定位</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>$(PRODUCT_BUNDLE_NAME)持续定位</string>
<key>NSLocationUsageDescription</key>
<string>$(PRODUCT_BUNDLE_NAME)使用期间获取定位</string>
//这个不太一样,根据需要加入一般app会有但是用户会关闭,有的话最好加入
<key>NSUserTrackingUsageDescription</key>
<string>$(PRODUCT_BUNDLE_NAME)将会获取 idfa 广告标识符信息</string>
android 端配置
manifest文件设置
不多说,一个是定位权限,一个是 service,定位权限在 manifest下即可, service 在 application下
<manifest>
///
<application>
...
<!-- 添加service -->
<service android:name="com.amap.api.location.APSService"/>
<!-- 这个key不多说了吧-->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="f6c46787c43cb7df5510d9f4c530fd1e"/>
</application>
<!--添加一系列权限-->
<!--访问网络-->
<uses-permission android:name="android.permission.INTERNET" />
<!--粗略定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--精确定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!--用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--用于写入缓存数据到扩展存储卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 配置定位Service -->
</manifest>
然后是app/build.gradle配置,里面加入下面依赖,根据自己是否需要定位或者地图选择即可
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.amap.api:location:5.2.0'
implementation 'com.amap.api:3dmap:5.0.0'
}
然后需要同步内容,点击右上角,进入 android 的编译环境,进行同步依赖
选择 build.gradle,右上角点击 sync 即可(这里已经同步过了,所以显示的不一样)
flutter 使用
map 使用
const String amapAndroidKey = "a551cc8a227032924733d16cbb59f683";
const String amapIosKey = "f3d258b85086e98d66100f5a9a396970";
AMapController? _controller;
//平台key,使用上面的key即可(这里的key是我随机输入的😂,因此不要抱有侥幸心理)
static const AMapApiKey amapApiKeys = AMapApiKey(iosKey: amapIosKey, androidKey: amapAndroidKey,);
//高德地图隐私政策连接,使用前请先确定用于已经同意了隐私政策,https://lbs.amap.com/pages/privacy/
//一般是在启动页加入隐私政策,用户点击之后,里面参数设置为true即可,其中隐私协议最好带有跳转高德隐私协议功能
//毕竟隐私协议是国家要求,因此必须加入的,测试时直接设置为
static const AMapPrivacyStatement amapPrivacyStatement = AMapPrivacyStatement(hasContains: true, hasShow: true, hasAgree: true);
//地图组件
AMapWidget(
//位置改变回调
onLocationChanged: (argument) {
print(argument);
},
//可以设置初始定位
initialCameraPosition: CameraPosition(
target: LatLng(lat, lon),
),
//显示我的定位信息,可以设置个人位置图标
myLocationStyleOptions: MyLocationStyleOptions(true),
//上面隐私协议相关设置的 true 的那个
privacyStatement: amapPrivacyStatement,
apiKey: amapApiKeys,
//创建完成后返回的 controller,可以保存用于调用方法更新视角等
onMapCreated: (AMapController controller) {
_controller = controller;
},
markers: const <Marker>{}, //markers
),
location使用
使用也相对简单,只不过没有传统的单次定位方法了,他们走的都是一个方法,通过添加监听的方式获取定位后的回调,只不过可以通过参数控制是单次还是持续定位
Map<String, Object>? _locationResult; //用于更新位置的参数
final AMapFlutterLocation _locationPlugin = AMapFlutterLocation(); //用于保存定位
StreamSubscription<Map<String, Object>>? _locationListener;//监听定位
double lon = 117;
double lat = 39;
@override
void initState() {
super.initState();
initLocation();
}
initLocation() async{
//启动一下
AMapFlutterLocation.updatePrivacyShow(true, true);
AMapFlutterLocation.updatePrivacyAgree(true);
AMapFlutterLocation.setApiKey(amapAndroidKey, amapIosKey);
//动态申请权限,前面 Permission_handler 有介绍到
requestPermission();
if (Platform.isIOS) {
//精确定位权限,和上面一样
requestAccuracyAuthorization();
}
///注册持续定位结果监听
_locationListener = _locationPlugin.onLocationChanged().listen((Map<String, Object> result) {
//_locationResult可以保存定位的结果,也可以直接使用
});
}
///设置定位参数
void setLocationOption() {
AMapLocationOption locationOption = AMapLocationOption();
///是否单次定位,设置了之后会定位一次,比较精确,但是仍受ios端精确权限限制
locationOption.onceLocation = false;
///是否需要返回逆地理信息
locationOption.needAddress = true;
///逆地理信息的语言类型
locationOption.geoLanguage = GeoLanguage.DEFAULT;
locationOption.desiredLocationAccuracyAuthorizationMode = AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
///设置Android端连续定位的定位间隔
locationOption.locationInterval = 2000;
///设置Android端的定位模式<br>
///可选值:<br>
///<li>[AMapLocationMode.Battery_Saving]</li>
///<li>[AMapLocationMode.Device_Sensors]</li>
///<li>[AMapLocationMode.Hight_Accuracy]</li>
locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
///设置iOS端的定位最小更新距离<br>
locationOption.distanceFilter = -1;
///设置iOS端期望的定位精度
/// 可选值:<br>
/// <li>[DesiredAccuracy.Best] 最高精度</li>
/// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
/// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
/// <li>[DesiredAccuracy.Kilometer] 1000米</li>
/// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
locationOption.desiredAccuracy = DesiredAccuracy.Best;
///设置iOS端是否允许系统暂停定位
locationOption.pausesLocationUpdatesAutomatically = false;
///将定位参数设置给定位插件
_locationPlugin.setLocationOption(locationOption);
}
///开始定位
void startLocation() {
///开始定位之前设置定位参数
setLocationOption();
_locationPlugin.startLocation();
}
///停止持续定位
void stopLocation() {
_locationPlugin.stopLocation();
}
///获取iOS native的accuracyAuthorization类型
void requestAccuracyAuthorization() async {
AMapAccuracyAuthorization currentAccuracyAuthorization = await _locationPlugin.getSystemAccuracyAuthorization();
if (currentAccuracyAuthorization == AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
print("精确定位类型");
} else if (currentAccuracyAuthorization == AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
print("模糊定位类型");
} else {
print("未知定位类型");
}
}
/// 动态申请定位权限
void requestPermission() async {
// 申请权限
bool hasLocationPermission = await requestLocationPermission();
if (hasLocationPermission) {
print("定位权限申请通过");
} else {
print("定位权限申请不通过");
}
}
/// 申请定位权限
/// 授予定位权限返回true, 否则返回false
Future<bool> requestLocationPermission() async {
//获取当前的权限
var status = await Permission.location.status;
if (status == PermissionStatus.granted) {
//已经授权
return true;
} else {
//未授权则发起一次申请
status = await Permission.location.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
在 ios 端模拟器的效果如下
最后
到这里你可能觉得,我都点进去看了一些,竟然没有发现定位转换的,这个确实我也没找到,现在对安全要求比较严格,今天服务器也保存高德的火星定位,如果涉及到硬件位置转化的,可以走服务器的转化逻辑,还省钱了不是😂
另外可以尝试一下是否成功,其中可能 m1 电脑没用习惯的,会碰到不少问题,配置好了后,能使用自己的终端尽量使用自己的哈