|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:android_intent_plus/android_intent.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_bmflocation/flutter_bmflocation.dart';
|
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
|
import 'package:huixiang/generated/l10n.dart';
|
|
|
|
import 'package:huixiang/view_widget/request_permission.dart';
|
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
|
|
|
|
import 'font_weight.dart';
|
|
|
|
|
|
|
|
BaiduLocationAndroidOption initAndroidOptions() {
|
|
|
|
BaiduLocationAndroidOption options = BaiduLocationAndroidOption(
|
|
|
|
// 定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
|
|
|
|
locationMode: BMFLocationMode.hightAccuracy,
|
|
|
|
// 是否需要返回地址信息
|
|
|
|
isNeedAddress: true,
|
|
|
|
// 是否需要返回海拔高度信息
|
|
|
|
isNeedAltitude: false,
|
|
|
|
// 是否需要返回周边poi信息
|
|
|
|
isNeedLocationPoiList: false,
|
|
|
|
// 是否需要返回新版本rgc信息
|
|
|
|
isNeedNewVersionRgc: false,
|
|
|
|
// 是否需要返回位置描述信息
|
|
|
|
isNeedLocationDescribe: true,
|
|
|
|
// 是否使用gps
|
|
|
|
openGps: true,
|
|
|
|
// 可选,设置场景定位参数,包括签到场景、运动场景、出行场景
|
|
|
|
locationPurpose: BMFLocationPurpose.signIn,
|
|
|
|
// 坐标系
|
|
|
|
coordType: BMFLocationCoordType.bd09ll,
|
|
|
|
// 设置发起定位请求的间隔,int类型,单位ms
|
|
|
|
// 如果设置为0,则代表单次定位,即仅定位一次,默认为0
|
|
|
|
scanspan: 0);
|
|
|
|
return options;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaiduLocationIOSOption initIOSOptions() {
|
|
|
|
BaiduLocationIOSOption options = BaiduLocationIOSOption(
|
|
|
|
// 坐标系
|
|
|
|
coordType: BMFLocationCoordType.bd09ll,
|
|
|
|
// 位置获取超时时间
|
|
|
|
locationTimeout: 10,
|
|
|
|
// 获取地址信息超时时间
|
|
|
|
reGeocodeTimeout: 10,
|
|
|
|
// 应用位置类型 默认为automotiveNavigation
|
|
|
|
activityType: BMFActivityType.automotiveNavigation,
|
|
|
|
// 设置预期精度参数 默认为best
|
|
|
|
desiredAccuracy: BMFDesiredAccuracy.best,
|
|
|
|
// 是否需要最新版本rgc数据
|
|
|
|
isNeedNewVersionRgc: false,
|
|
|
|
// 指定定位是否会被系统自动暂停
|
|
|
|
pausesLocationUpdatesAutomatically: false,
|
|
|
|
// 指定是否允许后台定位,
|
|
|
|
// 允许的话是可以进行后台定位的,但需要项目配置允许后台定位,否则会报错,具体参考开发文档
|
|
|
|
allowsBackgroundLocationUpdates: false,
|
|
|
|
// 设定定位的最小更新距离
|
|
|
|
distanceFilter: 10,
|
|
|
|
);
|
|
|
|
return options;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Location {
|
|
|
|
static Location _instance;
|
|
|
|
|
|
|
|
Location._internal() {
|
|
|
|
aMapFlutterLocation = LocationFlutterPlugin();
|
|
|
|
}
|
|
|
|
|
|
|
|
static Location getInstance() {
|
|
|
|
if (_instance == null) {
|
|
|
|
_instance = Location._internal();
|
|
|
|
}
|
|
|
|
return _instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
LocationFlutterPlugin aMapFlutterLocation;
|
|
|
|
|
|
|
|
Future<bool> startLocation(
|
|
|
|
context, Function(BaiduLocation result) locationCallback) async {
|
|
|
|
aMapFlutterLocation.prepareLoc(
|
|
|
|
initAndroidOptions().getMap(), initIOSOptions().getMap());
|
|
|
|
var permissionStatus = await Permission.location.status;
|
|
|
|
if (!permissionStatus.isGranted) {
|
|
|
|
if (permissionStatus.isUndetermined)
|
|
|
|
showTipsAlertDialog(context);
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
aMapFlutterLocation.singleLocationCallback(
|
|
|
|
callback: (BaiduLocation result) {
|
|
|
|
locationCallback.call(result);
|
|
|
|
});
|
|
|
|
if (Platform.isIOS) {
|
|
|
|
await aMapFlutterLocation.singleLocation({
|
|
|
|
'isReGeocode': true,
|
|
|
|
'isNetworkState': true,
|
|
|
|
});
|
|
|
|
} else if (Platform.isAndroid) {
|
|
|
|
await aMapFlutterLocation.startLocation();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void stopLocation() {
|
|
|
|
if (aMapFlutterLocation != null) aMapFlutterLocation.stopLocation();
|
|
|
|
}
|
|
|
|
|
|
|
|
enableLocation(context) {
|
|
|
|
showCupertinoDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) {
|
|
|
|
return RequestPermission(
|
|
|
|
"assets/image/icon_permission_location_bg.webp",
|
|
|
|
S.of(context).nindingweigongnengweikaiqi,
|
|
|
|
S.of(context).weilexiangnintuijianfujindemendianxinxi,
|
|
|
|
S.of(context).dakaidingwei,
|
|
|
|
(result) async {
|
|
|
|
if (result) {
|
|
|
|
final AndroidIntent intent = AndroidIntent(
|
|
|
|
action: 'action_location_source_settings',
|
|
|
|
package: "com.zsw.huixiang");
|
|
|
|
await intent.launch();
|
|
|
|
// startLocation();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
heightRatioWithWidth: 0.82,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
requestDialog(context, Function(BaiduLocation result) locationCallback) {
|
|
|
|
showCupertinoDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) {
|
|
|
|
return RequestPermission(
|
|
|
|
"assets/image/icon_permission_location_bg.webp",
|
|
|
|
S.of(context).nindingweiquanxianweiyunxu,
|
|
|
|
S.of(context).weilexiangnintuijianfujindemendianxinxi,
|
|
|
|
S.of(context).kaiqiquanxian,
|
|
|
|
(result) async {
|
|
|
|
if (result) {
|
|
|
|
await openAppSettings();
|
|
|
|
if (await Permission.location.isGranted) {
|
|
|
|
startLocation(context, locationCallback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
heightRatioWithWidth: 0.82,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///定位权限说明弹窗
|
|
|
|
showTipsAlertDialog(context) async {
|
|
|
|
//显示对话框
|
|
|
|
showDialog(
|
|
|
|
context: context,
|
|
|
|
barrierDismissible: false,
|
|
|
|
barrierColor: null,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
return Column(
|
|
|
|
children: [
|
|
|
|
Container(
|
|
|
|
width: double.infinity,
|
|
|
|
padding: EdgeInsets.all(15),
|
|
|
|
margin: EdgeInsets.all(15),
|
|
|
|
decoration: new BoxDecoration(
|
|
|
|
color: Colors.white,
|
|
|
|
borderRadius: BorderRadius.circular(10),
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
Icon(
|
|
|
|
Icons.location_on_outlined,
|
|
|
|
color: Colors.black,
|
|
|
|
size: 22,
|
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
// "访问精确地理位置信息权限说明",
|
|
|
|
"位置权限使用说明",
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 18.sp,
|
|
|
|
fontWeight: MyFontWeight.regular,
|
|
|
|
color: Colors.black,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
SizedBox(
|
|
|
|
height: 3.h,
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
// "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。",
|
|
|
|
"为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息",
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 13.sp,
|
|
|
|
fontWeight: MyFontWeight.regular,
|
|
|
|
color: Colors.black,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
await Permission.location.request();
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
///定位权限说明和申请弹窗
|
|
|
|
showAlertDialog(context) {
|
|
|
|
//显示对话框
|
|
|
|
showDialog(
|
|
|
|
context: context,
|
|
|
|
barrierDismissible: true,
|
|
|
|
barrierColor: null,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
return Column(
|
|
|
|
children: [
|
|
|
|
Container(
|
|
|
|
width: double.infinity,
|
|
|
|
padding: EdgeInsets.all(15),
|
|
|
|
margin: EdgeInsets.all(15),
|
|
|
|
decoration: new BoxDecoration(
|
|
|
|
color: Colors.black.withOpacity(0.6),
|
|
|
|
borderRadius: BorderRadius.circular(10),
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
// "访问精确地理位置信息权限说明",
|
|
|
|
"定位服务未开启",
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 18.sp,
|
|
|
|
fontWeight: MyFontWeight.regular,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
SizedBox(
|
|
|
|
height: 3.h,
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
// "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。",
|
|
|
|
"开启后才能提供更详细的定位服务哦!",
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 13.sp,
|
|
|
|
fontWeight: MyFontWeight.regular,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
GestureDetector(
|
|
|
|
child: Container(
|
|
|
|
child: Text(
|
|
|
|
"去开启",
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 15.sp,
|
|
|
|
fontWeight: MyFontWeight.regular,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
margin: EdgeInsets.symmetric(
|
|
|
|
horizontal: 15.w, vertical: 25.h),
|
|
|
|
padding:
|
|
|
|
EdgeInsets.symmetric(vertical: 2.h, horizontal: 10.w),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: Colors.green,
|
|
|
|
borderRadius: BorderRadius.circular(100),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
onTap: () async {
|
|
|
|
await openAppSettings();
|
|
|
|
if (await Permission.location.isGranted)
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
),
|
|
|
|
GestureDetector(
|
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
child: Container(
|
|
|
|
child: Icon(
|
|
|
|
Icons.close,
|
|
|
|
color: Colors.white.withOpacity(0.8),
|
|
|
|
size: 12,
|
|
|
|
),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: Colors.black.withOpacity(0.8),
|
|
|
|
borderRadius: BorderRadius.circular(100),
|
|
|
|
),
|
|
|
|
padding: EdgeInsets.all(5),
|
|
|
|
),
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|