我們在外出旅行時,通常需要在酒店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…
原作者:胡椒
