如何通过华为定位API精准获取用户所在地理位置?
我们在外出旅行时,通常需要在酒店App中预订酒店。那么,在酒店App中是如何获取用户地理位置信息从而实现 “附近的酒店”的功能查找?为此,我开发了一款名为Hotel Booking的应用。
本文中,我将集成定位服务,并介绍如何使用getLastlocation和getLocationWithAddress方法、如何使用回调方法,以及如何在Flutter中将数据存储到应用中的Shared Preferences。
-
定位服务
定位服务帮助开发者的应用快速准确地获取用户的位置,并通过GPS、Wi-Fi以及基站定位能力来扩展其全球定位能力。
融合定位:提供一套简单易用的API,以便您基于GPS、Wi-Fi以及基站位置数据来快速获取用户设备位置。
活动识别:通过加速度传感器、蜂窝网络信息以及磁力仪等识别用户的活动状态,帮助您根据用户行为调整应用。
地理围栏:您可以通过API来设置一个感兴趣的区域,以便在特定的动作(例如离开、进入或者逗留在该区域)发生时,您的应用可以接收到通知。
软件要求
1. Android Studio 3.X
2. JDK 1.8及以上
3. SDK Platform 19及以上
4. Gradle 4.6及以上
集成步骤
1. 在AppGallery Connect中注册华为开发者账号。
2. 参考“创建您的AGC项目”和“在项目下添加应用”章节创建应用。
3. 根据当前位置来设置数据处理位置。
4. 开通所需服务:华为定位服务。
5. 生成签名证书指纹。
6. 配置签名证书指纹。
7. 将您的agconnect-services.json文件拷贝到您的应用级根目录下。
重要:添加应用时,输入的应用包名应与您的Flutter项目包名一致。
注意:下载agconnect-services.json文件前,确保已开启所需的HMS服务。
开发流程
在Android Studio中创建应用。
1. 创建Flutter项目。
2. 添加编译依赖。
a) 应用级Gradle依赖:
在项目中选择“Android > app > build.gradle”。 apply plugin: ‘com.android.application‘ apply plugin: ‘com.huawei.agconnect‘
b) 项目级Gradle依赖:
maven {url ‘https://developer.huawei.com/repo/‘} classpath ‘com.huawei.agconnect:agcp:1.4.1.300‘
在AndroidManifest.xml文件中添加如下权限:
<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" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION" />
3. 参考链接下载所需的跨平台插件。
4. 完成上述所有步骤后,在pubspec.yaml文件中添加对所需的HMS服务对应的Flutter插件的依赖。您可在pub.dev中找到最新版本的插件。
dependencies: flutter: sdk: flutter shared_preferences: ^0.5.12+4 bottom_navy_bar: ^5.6.0 cupertino_icons: ^1.0.0 provider: ^4.3.3 huawei_location: path: ../huawei_location/ flutter: uses-material-design: true assets: - assets/images/
5. 添加后,执行flutter pub get命令。至此,所有的插件已准备就绪。
6. 打开main.dart文件来创建UI和业务逻辑。
集成定位服务
权限
首先,应用需要有访问位置数据和物理数据的权限。
创建PermissionHandler实例,并调用initState()方法来初始化实例。
final PermissionHandler permissionHandler; @override void initState() { permissionHandler = PermissionHandler(); super.initState(); }
检查权限
调用hasLocationPermission()方法来检查设备是否有所需的权限。
void hasPermission() async { try { final bool status = await permissionHandler.hasLocationPermission(); if(status == true){ showToast("Has permission: $status"); }else{ requestPermission(); } } on PlatformException catch (e) { showToast(e.toString()); } }
如果设备没有所需权限,调用requestLocationPermission()方法来申请相关权限。
void requestPermission() async { try { final bool status = await permissionHandler.requestLocationPermission(); showToast("Is permission granted"); } on PlatformException catch (e) { showToast(e.toString()); } }
-
融合定位
使用init()方法创建FusedLocationPrvoiderClient实例,然后使用该实例调用定位API。
final FusedLocationProviderClient locationService @override void initState() { locationService = FusedLocationProviderClient(); super.initState(); }
位置更新事件
调用onLocationData()方法来侦听位置更新事件。
StreamSubscription<Location> streamSubscription @override void initState() { streamSubscription = locationService.onLocationData.listen((location) {});super.initState(); }
getLastLocation()
void getLastLocation() async { try { Location location = await locationService.getLastLocation(); setState(() { lastlocation = location.toString(); print("print: " + lastlocation); }); } catch (e) { setState(() { print("error: " + e.toString()); }); } }
getLastLocationWithAddress()
创建LocationRequest实例,并设置相关参数。
final LocationRequest locationRequest; locationRequest = LocationRequest() ..needAddress = true ..interval = 5000; void _getLastLocationWithAddress() async { try { HWLocation location = await locationService.getLastLocationWithAddress(locationRequest); setState(() { String street = location.street; String city = location.city; String countryname = location.countryName; currentAddress = ‘$street‘ + ‘,‘ + ‘$city‘ + ‘ , ‘ + ‘$countryname‘; print("res: $location"); }); showToast(currentAddress); } on PlatformException catch (e) { showToast(e.toString()); } }
通过Callback进行位置更新
创建LocationCallback实例,并在initstate()中创建回调函数。
LocationCallback locationCallback; @override void initState() { locationCallback = LocationCallback( onLocationResult: _onCallbackResult, onLocationAvailability: _onCallbackResult, ); super.initState(); } void requestLocationUpdatesCallback() async { if (_callbackId == null) { try { final int callbackId = await locationService.requestLocationUpdatesExCb( locationRequest, locationCallback); _callbackId = callbackId; } on PlatformException catch (e) { showToast(e.toString()); } } else { showToast("Already requested location updates."); } } void onCallbackResult(result) { print(result.toString()); showToast(result.toString()); }
我创建了一个Helper类,用于通过Shared Preferences在本地存储用户登录信息。
class StorageUtil { static StorageUtil _storageUtil; static SharedPreferences _preferences; static Future<StorageUtil> getInstance() async { if (_storageUtil == null) { var secureStorage = StorageUtil._(); await secureStorage._init(); _storageUtil = secureStorage; } return _storageUtil; } StorageUtil._(); Future _init() async { _preferences = await SharedPreferences.getInstance(); } // get string static String getString(String key) { if (_preferences == null) return null; String result = _preferences.getString(key) ?? null; print(‘result,$result‘); return result; } // put string static Future<void> putString(String key, String value) { if (_preferences == null) return null; print(‘result $value‘); return _preferences.setString(key, value); } }
结果
温馨提示
1. 请下载最新版本的HMS服务Flutter插件。
2. 如需使用模拟位置功能,需要在AndroidManifest.xml文件中添加相关权限。
3. 如需更新插件,可点击pug get按钮。
欲了解HMS Core更多详情,请参阅:
>>华为开发者联盟官网
>>获取开发指导文档
>>参与开发者讨论请到CSDN社区或者Reddit社区
>>下载demo和示例代码请到Github或者Gitee
>>解决集成问题请到Stack Overflow
原文链接:developer.huawei.com/consumer/cn…
原作者:胡椒