Commit 5fe1bdef authored by 汪林玲's avatar 汪林玲

高德地图定位插件null-safety

parent c89b9f4b
......@@ -5,7 +5,6 @@ buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
......@@ -17,7 +16,6 @@ rootProject.allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
......@@ -35,5 +33,5 @@ android {
}
dependencies {
implementation 'com.amap.api:location:latest.integration'
compile fileTree(include: ['*.jar'], dir: 'libs')
}
\ No newline at end of file
......@@ -7,49 +7,49 @@ packages:
path: ".."
relative: true
source: path
version: "1.0.0"
version: "2.1.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.0-nullsafety.1"
version: "2.8.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.1"
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.3"
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.1"
version: "1.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.15.0-nullsafety.3"
version: "1.15.0"
cupertino_icons:
dependency: "direct main"
description:
......@@ -63,7 +63,7 @@ packages:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
......@@ -80,21 +80,21 @@ packages:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.10-nullsafety.1"
version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0-nullsafety.3"
version: "1.7.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0-nullsafety.1"
version: "1.8.0"
sky_engine:
dependency: transitive
description: flutter
......@@ -106,56 +106,56 @@ packages:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0-nullsafety.2"
version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.0-nullsafety.1"
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.1"
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.1"
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.19-nullsafety.2"
version: "0.4.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0-nullsafety.3"
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.3"
version: "2.1.0"
sdks:
dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.20.0"
dart: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
......@@ -4,6 +4,8 @@
@interface AmapsLocationPlugin()<AMapLocationManagerDelegate>
@property (nonatomic, copy) AMapLocatingCompletionBlock completionBlock;
@property(nonatomic, retain) AMapLocationManager *locationManager;
@property(nonatomic) FlutterResult locationResult;
......@@ -40,6 +42,12 @@
[[AMapServices sharedServices] setEnableHTTPS:YES];
[[AMapServices sharedServices] setApiKey:apiKey];
self.locationManager = [[AMapLocationManager alloc] init];
// 带逆地理信息的一次定位(返回坐标和地址信息)
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyHundredMeters];
// 定位超时时间,最低2s,此处设置为10s
self.locationManager.locationTimeout =10;
// 逆地理请求超时时间,最低2s,此处设置为10s
self.locationManager.reGeocodeTimeout = 10;
}
self.locationManager.delegate = self;
CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus];
......@@ -50,27 +58,89 @@
NSLog(@"======> 缺少定位权限。。。。。拒绝了定位权限");
self.locationResult(@{@"errorCode":@12,@"errorInfo":@"请在设备的设置中开启app的定位权限。"});
}else if(authorizationStatus == kCLAuthorizationStatusAuthorized){
[self.locationManager setLocatingWithReGeocode:YES];
[self.locationManager startUpdatingLocation];
[self getLocation:YES result:result];
}else{
self.locationResult(@{@"errorCode":@21,@"errorInfo":@"没有权限的其他状态。"});
[self getLocation:YES result:result];
}
} else {
result(FlutterMethodNotImplemented);
}
}
-(void)getLocation:(BOOL)withReGeocode result:(FlutterResult)result{
self.completionBlock = ^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error){
if (regeocode){
NSLog(@"reGeocode:%@", regeocode);
}else{
NSLog(@"=======> 无");
}
if (error != nil && error.code == AMapLocationErrorLocateFailed){
//定位错误:此时location和regeocode没有返回值,不进行annotation的添加
NSLog(@"定位错误:{%ld - %@};", (long)error.code, error.localizedDescription);
result(@{ @"code":@(error.code),@"description":error.localizedDescription, @"success":@NO });
return;
}else if (error != nil && (error.code == AMapLocationErrorReGeocodeFailed
|| error.code == AMapLocationErrorTimeOut
|| error.code == AMapLocationErrorCannotFindHost
|| error.code == AMapLocationErrorBadURL
|| error.code == AMapLocationErrorNotConnectedToInternet
|| error.code == AMapLocationErrorCannotConnectToHost)){
//逆地理错误:在带逆地理的单次定位中,逆地理过程可能发生错误,此时location有返回值,regeocode无返回值,进行annotation的添加
NSLog(@"逆地理错误:{%ld - %@};", (long)error.code, error.localizedDescription);
}else if (error != nil && error.code == AMapLocationErrorRiskOfFakeLocation){
//存在虚拟定位的风险:此时location和regeocode没有返回值,不进行annotation的添加
NSLog(@"存在虚拟定位的风险:{%ld - %@};", (long)error.code, error.localizedDescription);
result(@{ @"code":@(error.code),@"description":error.localizedDescription, @"success":@NO });
return;
}else{
//没有错误:location有返回值,regeocode是否有返回值取决于是否进行逆地理操作,进行annotation的添加
}
NSMutableDictionary* md = [[NSMutableDictionary alloc]initWithDictionary: [AmapsLocationPlugin location2map:location]];
if(regeocode){
[md addEntriesFromDictionary:[ AmapsLocationPlugin regeocode2map:regeocode ]];
}
md[@"success"]=@YES;
result(md);
};
[self.locationManager requestLocationWithReGeocode:withReGeocode completionBlock:self.completionBlock];
}
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location reGeocode:(AMapLocationReGeocode *)reGeocode{
if(self.locationManager){
[self.locationManager stopUpdatingLocation];
}
NSLog(@"location:{lat:%f; lon:%f; accuracy:%f}", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy);
if (reGeocode){
NSLog(@"=======> %@",reGeocode);
}
if(self.locationResult){
self.locationResult(@{@"errorCode":@0});
}
}
+(NSDictionary*)regeocode2map:(AMapLocationReGeocode *)regeocode{
return @{@"address":regeocode.formattedAddress,
@"country":regeocode.country,
@"province":regeocode.province,
@"city":regeocode.city,
@"district":regeocode.district,
@"citycode":regeocode.citycode,
@"adcode":regeocode.adcode,
@"street":regeocode.street,
@"number":regeocode.number,
@"poiName":[self checkNull : regeocode.POIName],
@"aoiName":[self checkNull :regeocode.AOIName],
};
}
+(NSDictionary*)location2map:(CLLocation *)location{
return @{@"latitude": @(location.coordinate.latitude),
@"longitude": @(location.coordinate.longitude),
@"accuracy": @((location.horizontalAccuracy + location.verticalAccuracy)/2),
@"altitude": @(location.altitude),
@"speed": @(location.speed),
@"timestamp": @(location.timestamp.timeIntervalSince1970),};
}
+(id)checkNull:(NSObject*)value{
return value == nil ? [NSNull null] : value;
}
@end
......@@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'amaps_location'
s.version = '0.0.1'
s.version = '1.0.0'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
......@@ -17,8 +17,8 @@ A new flutter plugin project.
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'AMapLocation-NO-IDFA'
s.static_framework = true
s.platform = :ios, '9.0'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
end
......@@ -2,3 +2,4 @@ library location;
export 'src/amaps_location.dart';
export 'src/location_option.dart';
export 'src/location_entity.dart';
import 'dart:async';
import 'package:amaps_location/src/plugin_controller.dart';
import 'location_entity.dart';
import 'plugin_controller.dart';
abstract class AmapsLocation {
///
/// 获取一个单例
///
static AmapsLocation create() {
static AmapsLocation? create() {
return AmapsLocationImpl.getInstance();
}
......@@ -15,17 +14,17 @@ abstract class AmapsLocation {
/// 获取GPS定位
/// [apiKey] 高德地图官方apiKey
///
Future<LocationEntity> getLocation({String apiKey});
Future<LocationEntity> getLocation({String? apiKey});
///
/// 是否打开GPS
///
Future<bool> isOpenGPS();
Future<bool?> isOpenGPS();
///
/// 启用手机GPS
///
Future<bool> enableGPS();
Future<bool?> enableGPS();
}
class AmapsLocationImpl extends AmapsLocation {
......@@ -33,9 +32,9 @@ class AmapsLocationImpl extends AmapsLocation {
AmapsLocationImpl._() : _amapsController = PluginControllerFactory().create();
static AmapsLocationImpl _instance;
static AmapsLocationImpl? _instance;
static AmapsLocationImpl getInstance() {
static AmapsLocationImpl? getInstance() {
if (_instance == null) {
_instance = AmapsLocationImpl._();
}
......@@ -43,17 +42,17 @@ class AmapsLocationImpl extends AmapsLocation {
}
@override
Future<bool> enableGPS() async {
Future<bool?> enableGPS() async {
return _amapsController.enableGPS();
}
@override
Future<bool> isOpenGPS() async {
Future<bool?> isOpenGPS() async {
return _amapsController.isOpenGPS();
}
@override
Future<LocationEntity> getLocation({String apiKey}) {
Future<LocationEntity> getLocation({String? apiKey}) {
return _amapsController.getLocation(apiKey: apiKey);
}
}
class LocationEntity {
//获取纬度
double latitude;
double? latitude;
//获取经度
double longitude;
double? longitude;
//获取定位精度 单位:米
double accuracy;
double? accuracy;
//获取海拔高度信息
double altitude;
double? altitude;
//速度 单位:米/秒
double speed;
double? speed;
//获取方向角信息
double bearing;
double? bearing;
//室内定位建筑物Id
String buildingId;
String? buildingId;
//室内定位楼层
String floor;
String? floor;
//地址描述
String address;
String? address;
//获取国家名称
String country;
String? country;
//获取省名称
String province;
String? province;
//获取城市名称
String city;
String? city;
//获取城区名称
String district;
String? district;
//获取街道名称
String street;
String? street;
//获取街道门牌号信息
String streetNum;
String? streetNum;
//获取城市编码信息
String cityCode;
String? cityCode;
//获取区域编码信息
String adCode;
String? adCode;
//获取当前位置的POI名称
String poiName;
String? poiName;
//获取当前位置所处AOI名称
String aoiName;
String? aoiName;
//获取GPS当前状态,返回值可参考AMapLocation类提供的常量
int gpsAccuracyStatus;
int? gpsAccuracyStatus;
//获取定位结果来源
int locationType;
int? locationType;
//定位信息描述
String locationDetail;
String? locationDetail;
//定位出现异常的描述
String errorInfo;
String? errorInfo;
//定位出现异常时的编码
int errorCode;
int? errorCode;
LocationEntity({
this.latitude,
......@@ -99,40 +99,39 @@ class LocationEntity {
});
static LocationEntity fromJson(dynamic data) {
print('===> fromJson $data');
return LocationEntity(
latitude: data['latitude'] == null ? 0 : (data['latitude'] as double),
longitude: data['longitude'] == null ? 0 : (data['longitude'] as double),
accuracy: data['accuracy'] == null ? 0 : (data['accuracy'] as double),
altitude: data['altitude'] == null ? 0 : (data['altitude'] as double),
speed: data['speed'] == null ? 0 : (data['speed'] as double),
bearing: data['bearing'] == null ? 0 : (data['bearing'] as double),
latitude: data['latitude'] == null ? 0 : (data['latitude'] as double?),
longitude: data['longitude'] == null ? 0 : (data['longitude'] as double?),
accuracy: data['accuracy'] == null ? 0 : (data['accuracy'] as double?),
altitude: data['altitude'] == null ? 0 : (data['altitude'] as double?),
speed: data['speed'] == null ? 0 : (data['speed'] as double?),
bearing: data['bearing'] == null ? 0 : (data['bearing'] as double?),
buildingId:
data['buildingId'] == null ? null : (data['buildingId'] as String),
floor: data['floor'] == null ? null : (data['floor'] as String),
address: data['address'] == null ? null : (data['address'] as String),
country: data['country'] == null ? null : (data['country'] as String),
province: data['province'] == null ? null : (data['province'] as String),
city: data['city'] == null ? null : (data['city'] as String),
district: data['district'] == null ? null : (data['district'] as String),
street: data['street'] == null ? null : (data['street'] as String),
data['buildingId'] == null ? null : (data['buildingId'] as String?),
floor: data['floor'] == null ? null : (data['floor'] as String?),
address: data['address'] == null ? null : (data['address'] as String?),
country: data['country'] == null ? null : (data['country'] as String?),
province: data['province'] == null ? null : (data['province'] as String?),
city: data['city'] == null ? null : (data['city'] as String?),
district: data['district'] == null ? null : (data['district'] as String?),
street: data['street'] == null ? null : (data['street'] as String?),
streetNum:
data['streetNum'] == null ? null : (data['streetNum'] as String),
cityCode: data['cityCode'] == null ? null : (data['cityCode'] as String),
adCode: data['adCode'] == null ? null : (data['adCode'] as String),
poiName: data['poiName'] == null ? null : (data['poiName'] as String),
aoiName: data['aoiName'] == null ? null : (data['aoiName'] as String),
data['streetNum'] == null ? null : (data['streetNum'] as String?),
cityCode: data['cityCode'] == null ? null : (data['cityCode'] as String?),
adCode: data['adCode'] == null ? null : (data['adCode'] as String?),
poiName: data['poiName'] == null ? null : (data['poiName'] as String?),
aoiName: data['aoiName'] == null ? null : (data['aoiName'] as String?),
gpsAccuracyStatus: data['gpsAccuracyStatus'] == null
? null
: (data['gpsAccuracyStatus'] as int),
: (data['gpsAccuracyStatus'] as int?),
locationType:
data['locationType'] == null ? null : (data['locationType'] as int),
data['locationType'] == null ? null : (data['locationType'] as int?),
locationDetail: data['locationDetail'] == null
? null
: (data['locationDetail'] as String),
: (data['locationDetail'] as String?),
errorInfo:
data['errorInfo'] == null ? null : (data['errorInfo'] as String),
errorCode: data['errorCode'] as int,
data['errorInfo'] == null ? null : (data['errorInfo'] as String?),
errorCode: data['errorCode'] as int?,
);
}
}
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'location_entity.dart';
......@@ -8,35 +7,39 @@ abstract class AmapsController {
/// 获取GPS定位
/// [apiKey] 高德地图官方apiKey
///
Future<LocationEntity> getLocation({String apiKey});
Future<LocationEntity> getLocation({String? apiKey});
///
/// 是否打开GPS
///
Future<bool> isOpenGPS();
Future<bool?> isOpenGPS();
///
/// 启用手机GPS
///
Future<bool> enableGPS();
Future<bool?> enableGPS();
}
class PluginController implements AmapsController {
final MethodChannel _amapsChannel;
PluginController({
@required MethodChannel amapsChannel,
required MethodChannel amapsChannel,
}) : _amapsChannel = amapsChannel;
@override
Future<bool> enableGPS() async {
Future<bool?> enableGPS() async {
return await _amapsChannel.invokeMethod('enableGPS');
}
@override
Future<LocationEntity> getLocation({String apiKey}) async {
Future<LocationEntity> getLocation({String? apiKey}) async {
LocationEntity entity = await _amapsChannel
.invokeMethod('getLocation', {'apiKey': apiKey})
.then((value) {
print(value);
return value;
})
.asStream()
.map(LocationEntity.fromJson)
.first;
......@@ -44,7 +47,7 @@ class PluginController implements AmapsController {
}
@override
Future<bool> isOpenGPS() async {
Future<bool?> isOpenGPS() async {
return await _amapsChannel.invokeMethod('isOpenGPS');
}
}
......
......@@ -7,49 +7,49 @@ packages:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.0-nullsafety.1"
version: "2.8.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.1"
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.3"
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.1"
version: "1.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.15.0-nullsafety.3"
version: "1.15.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
version: "1.2.0"
flutter:
dependency: "direct main"
description: flutter
......@@ -66,21 +66,21 @@ packages:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.10-nullsafety.1"
version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0-nullsafety.3"
version: "1.7.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0-nullsafety.1"
version: "1.8.0"
sky_engine:
dependency: transitive
description: flutter
......@@ -92,56 +92,56 @@ packages:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0-nullsafety.2"
version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.0-nullsafety.1"
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.1"
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.1"
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.19-nullsafety.2"
version: "0.4.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0-nullsafety.3"
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.3"
version: "2.1.0"
sdks:
dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.20.0"
dart: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
name: amaps_location
description: 高德地图定位插件.
version: 1.0.0
author:
version: 2.1.0
homepage:
environment:
sdk: ">=2.7.0 <3.0.0"
flutter: ">=1.20.0"
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
dependencies:
flutter:
......@@ -17,10 +16,6 @@ dev_dependencies:
sdk: flutter
flutter:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
......
......@@ -18,6 +18,6 @@ void main() {
});
test('getPlatformVersion', () async {
expect(await AmapsLocation.create().isOpenGPS(), '42');
expect(await AmapsLocation.create()!.isOpenGPS(), '42');
});
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment