如何透過華為定位API精準獲取使用者所在地理位置?

華為開發者論壇發表於2021-06-28

我們在外出旅行時,通常需要在酒店 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


原文連結: https://developer.huawei.com/consumer/cn/forum/topic/0202558665631260611?fid=18

原作者:胡椒


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69970551/viewspace-2778568/,如需轉載,請註明出處,否則將追究法律責任。

相關文章