|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
|
import 'package:geolocator/geolocator.dart';
|
|
|
|
import 'package:huixiang/generated/l10n.dart';
|
|
|
|
import 'package:huixiang/retrofit/data/address.dart';
|
|
|
|
import 'package:huixiang/retrofit/retrofit_api.dart';
|
|
|
|
import 'package:huixiang/view_widget/request_permission.dart';
|
|
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:permission_handler/permission_handler.dart' as PH;
|
|
|
|
|
|
|
|
import 'font_weight.dart';
|
|
|
|
|
|
|
|
class LocationInstance {
|
|
|
|
static LocationInstance _instance;
|
|
|
|
|
|
|
|
LocationInstance._internal() {}
|
|
|
|
|
|
|
|
static LocationInstance getInstance() {
|
|
|
|
if (_instance == null) {
|
|
|
|
_instance = LocationInstance._internal();
|
|
|
|
}
|
|
|
|
return _instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<bool> startLocation(
|
|
|
|
context, Function(Position locationData) locationCallback) async {
|
|
|
|
LocationPermission permissionStatus = await Geolocator.checkPermission();
|
|
|
|
if (permissionStatus == LocationPermission.denied) {
|
|
|
|
permissionStatus = await Geolocator.requestPermission();
|
|
|
|
}
|
|
|
|
if (permissionStatus == LocationPermission.denied) {
|
|
|
|
showTipsAlertDialog(context);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (permissionStatus == LocationPermission.deniedForever) {
|
|
|
|
showTipsAlertDialog(context);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (permissionStatus == LocationPermission.whileInUse ||
|
|
|
|
permissionStatus == LocationPermission.always) {
|
|
|
|
bool isNext = true;
|
|
|
|
Future.delayed(Duration(seconds: 5), () {
|
|
|
|
if (isNext) {
|
|
|
|
EasyLoading.dismiss();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Position locationData = await Geolocator.getCurrentPosition();
|
|
|
|
isNext = false;
|
|
|
|
locationCallback.call(locationData);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void 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();
|
|
|
|
Geolocator.openLocationSettings();
|
|
|
|
// startLocation();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
heightRatioWithWidth: 0.82,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
requestDialog(context, Function(Position 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 PH.openAppSettings();
|
|
|
|
if ((await Geolocator.checkPermission()) ==
|
|
|
|
LocationPermission.whileInUse ||
|
|
|
|
(await Geolocator.checkPermission()) ==
|
|
|
|
LocationPermission.always) {
|
|
|
|
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,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
Geolocator.requestPermission();
|
|
|
|
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 PH.openAppSettings();
|
|
|
|
if ((await Geolocator.checkPermission()) ==
|
|
|
|
LocationPermission.whileInUse ||
|
|
|
|
(await Geolocator.checkPermission()) ==
|
|
|
|
LocationPermission.always)
|
|
|
|
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,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
///计算距离(当前位置到店位置直线距离)
|
|
|
|
static Future<String> calculateDistance(
|
|
|
|
Position bmfCoordinate, Position myLatLng,
|
|
|
|
{bool isMi = false}) async {
|
|
|
|
double mi = Geolocator.distanceBetween(
|
|
|
|
bmfCoordinate.latitude,
|
|
|
|
bmfCoordinate.longitude,
|
|
|
|
myLatLng.latitude,
|
|
|
|
myLatLng.longitude,
|
|
|
|
);
|
|
|
|
NumberFormat numberFormat = NumberFormat("#.#");
|
|
|
|
return "${numberFormat.format(mi / (isMi ? 1 : 1000))}";
|
|
|
|
}
|
|
|
|
|
|
|
|
// ///坐标系转换(高德转百度)
|
|
|
|
// static Future<Latlng> coordConvert(Latlng latLng) async {
|
|
|
|
// return BMFCalculateUtils.coordConvert(
|
|
|
|
// coordinate: latLng,
|
|
|
|
// fromType: BMF_COORD_TYPE.COMMON,
|
|
|
|
// toType: BMF_COORD_TYPE.BD09LL);
|
|
|
|
// }
|
|
|
|
|
|
|
|
Future<Address> getAddress(double lat, double lang) async {
|
|
|
|
var result = await ApiService(Dio()).geocodeRegeo("$lat", "$lang");
|
|
|
|
print("address_result: $result");
|
|
|
|
if (result["status"] == 1 &&
|
|
|
|
result["regeocode"] != null &&
|
|
|
|
result["regeocode"]["addressComponent"] != null) {
|
|
|
|
Address address = Address.fromJson({
|
|
|
|
"address": result["regeocode"]["formatted_address"],
|
|
|
|
"area": result['regeocode']["addressComponent"]["district"],
|
|
|
|
"city": result['regeocode']["addressComponent"]["city"],
|
|
|
|
"latitude": lat,
|
|
|
|
"longitude": lang,
|
|
|
|
"province": result['regeocode']["addressComponent"]["province"],
|
|
|
|
});
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|