location_utils.dart 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import 'dart:async';
  2. import 'package:amap_flutter_location/amap_flutter_location.dart';
  3. import 'package:amap_flutter_location/amap_location_option.dart';
  4. import 'package:app_settings/app_settings.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:permission_handler/permission_handler.dart';
  7. import '../router/my_navigator.dart';
  8. import '../widget/button.dart';
  9. class LocationUtils {
  10. LocationUtils._();
  11. ///设置Android和iOS的apikey,建议在weigdet初始化时设置<br>
  12. ///apiKey的申请请参考高德开放平台官网<br>
  13. ///Android端: https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key<br>
  14. ///iOS端: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key<br>
  15. ///[androidKey] Android平台的key<br>
  16. ///[iosKey] ios平台的key<br>
  17. static void setApiKey(String androidKey, String iosKey) {
  18. AMapFlutterLocation.setApiKey(androidKey, iosKey);
  19. }
  20. /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作<br>
  21. /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy<br>
  22. /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b><br>
  23. /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
  24. /// [hasContains] 隐私声明中是否包含高德隐私政策说明<br>
  25. /// [hasShow] 隐私权政策是否弹窗展示告知用户<br>
  26. static void updatePrivacyShow(bool hasContains, bool hasShow) {
  27. AMapFlutterLocation.updatePrivacyShow(hasContains, hasShow);
  28. }
  29. /// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作<br>
  30. /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy<br>
  31. /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b><br>
  32. /// [hasAgree] 隐私权政策是否已经取得用户同意<br>
  33. static void updatePrivacyAgree(bool hasAgree) {
  34. AMapFlutterLocation.updatePrivacyAgree(hasAgree);
  35. }
  36. static AMapFlutterLocation? _location;
  37. static AMapFlutterLocation get location => _location ??= AMapFlutterLocation();
  38. /// 设置定位参数
  39. static AMapFlutterLocation setLocationOption(AMapLocationOption option) {
  40. location.setLocationOption(option);
  41. return location;
  42. }
  43. ///开始定位
  44. static AMapFlutterLocation startLocation() {
  45. location.startLocation();
  46. return location;
  47. }
  48. ///停止定位
  49. static AMapFlutterLocation stopLocation() {
  50. location.stopLocation();
  51. return location;
  52. }
  53. ///销毁定位
  54. static void destroy() {
  55. location.destroy();
  56. cancelLocationListener();
  57. _location = null;
  58. }
  59. ///定位结果回调
  60. ///
  61. ///定位结果以map的形式透出,其中包含的key已经含义如下:
  62. ///
  63. /// `callbackTime`:回调时间,格式为"yyyy-MM-dd HH:mm:ss"
  64. ///
  65. /// `locationTime`:定位时间, 格式为"yyyy-MM-dd HH:mm:ss"
  66. ///
  67. /// `locationType`: 定位类型, 具体类型可以参考https://lbs.amap.com/api/android-location-sdk/guide/utilities/location-type
  68. ///
  69. /// `latitude`:纬度
  70. ///
  71. /// `longitude`:精度
  72. ///
  73. /// `accuracy`:精确度
  74. ///
  75. /// `altitude`:海拔, android上只有locationType==1时才会有值
  76. ///
  77. /// `bearing`: 角度,android上只有locationType==1时才会有值
  78. ///
  79. /// `speed`:速度, android上只有locationType==1时才会有值
  80. ///
  81. /// `country`: 国家,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  82. ///
  83. /// `province`: 省,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  84. ///
  85. /// `city`: 城市,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  86. ///
  87. /// `district`: 城镇(区),android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  88. ///
  89. /// `street`: 街道,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  90. ///
  91. /// `streetNumber`: 门牌号,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  92. ///
  93. /// `cityCode`: 城市编码,android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  94. ///
  95. /// `adCode`: 区域编码, android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  96. ///
  97. /// `address`: 地址信息, android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  98. ///
  99. /// `description`: 位置语义, android上只有通过[AMapLocationOption.needAddress]为true时才有可能返回值
  100. ///
  101. /// `errorCode`: 错误码,当定位失败时才会返回对应的错误码, 具体错误请参考:https://lbs.amap.com/api/android-location-sdk/guide/utilities/errorcode
  102. ///
  103. /// `errorInfo`: 错误信息, 当定位失败时才会返回
  104. // static Stream<Map<String, Object>> onLocationChanged() {
  105. // return location.onLocationChanged().asBroadcastStream();
  106. // }
  107. static Stream<Map<String, Object>> onLocationChanged() {
  108. if (_locationChange == null) {
  109. _locationChange = StreamController.broadcast();
  110. _locationListener = location.onLocationChanged().listen((event) => _locationChange?.add(event));
  111. }
  112. return _locationChange!.stream;
  113. }
  114. static StreamController<Map<String, Object>>? _locationChange;
  115. static StreamSubscription<Map<String, Object>>? _locationListener;
  116. static void cancelLocationListener() {
  117. _locationListener?.cancel();
  118. _locationListener = null;
  119. _locationChange?.close();
  120. _locationChange = null;
  121. }
  122. /// 检查定位是否可用
  123. /// 1.app定位权限
  124. /// 2.系统定位开关
  125. static Future<bool> checkLocationAvailable() async {
  126. // 检查定位权限
  127. var status = await Permission.location.status;
  128. if (status != PermissionStatus.granted) {
  129. //未授权 申请定位权限
  130. status = await Permission.location.request();
  131. if (status != PermissionStatus.granted) {
  132. // 未授权 提示用户去设置
  133. MyNavigator.showToast('请打开APP的定位权限');
  134. showSettingDialog(
  135. title: '定位权限',
  136. content: '为了APP能使用位置功能,您在系统设置中授权APP的定位权限。',
  137. onTap: openAppSettings,
  138. );
  139. return false;
  140. }
  141. }
  142. // 检查系统定位开关
  143. bool locationEnable = await Permission.location.serviceStatus.isEnabled;
  144. if (!locationEnable) {
  145. showSettingDialog(
  146. title: '定位功能',
  147. content: '为了APP能使用位置功能,您在系统设置中打开定位开关。',
  148. onTap: () => AppSettings.openAppSettings(type: AppSettingsType.location),
  149. );
  150. return false;
  151. }
  152. return true;
  153. }
  154. static void showSettingDialog({String? title, String? content, VoidCallback? onTap}) {
  155. MyNavigator.showDialog(
  156. tag: 'setting',
  157. builder: (_) => AlertDialog(
  158. title: title != null ? Text(title) : null,
  159. content: content != null ? Text(content) : null,
  160. actions: [
  161. MyButton(
  162. '去设置',
  163. alignment: null,
  164. backgroundColor: const Color(0xFFCE615A),
  165. onTap: () {
  166. onTap?.call();
  167. MyNavigator.dismiss(tag: 'setting');
  168. },
  169. ),
  170. MyButton('取消', alignment: null, onTap: () => MyNavigator.dismiss(tag: 'setting')),
  171. ],
  172. ),
  173. );
  174. }
  175. }