Flutter 中获取地理位置[Flutter专题61]
大家好,我是堅果,公眾號“堅果前端”
Flutter 中獲取地理位置
如今,發現用戶位置是移動應用程序非常常見且功能強大的用例。如果您曾經嘗試過在 Android 中實現位置,您就會知道樣例代碼會變得多么復雜和混亂。
但這與 Flutter 不同——它有很多令人驚嘆的包,可以為您抽象出樣板代碼,并使實現地理定位成為夢想。另一個好的方面是您可以在 Android 和 iOS 上獲得這些功能。
讓我們快速瀏覽一下我們今天正在構建的用于收集位置數據的內容:
本文將帶您了解兩個最流行且易于使用的 Flutter 地理定位包。
讓我們從location開始,這是Flutter 最喜歡的包。這很簡單。只需三個簡單的步驟,您就可以獲取當前用戶位置以及處理位置權限。
先決條件
在繼續前進之前,讓我們快速檢查一下我們需要的東西:
- 該FlutterSDK
- 編輯器;您可以使用 Visual Code 或 Android Studio
- 至少對 Flutter 有初級的了解
差不多就是這樣!
使用 Flutter 定位包
設置
將依賴項添加到您的文件中:pubspec.yaml
location: ^4.3.0由于 Android 和 iOS 處理權限的方式不同,因此我們必須在每個平臺上分別添加它們。
安卓版
將以下位置權限添加到:AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />如果您還想在后臺訪問用戶的位置,請在訪問后臺位置之前使用該API,并在清單文件中添加后臺權限:enableBackgroundMode({bool enable})
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>對于 iOS
將以下位置權限添加到:Info.plist
<key>NSLocationWhenInUseUsageDescription</key> <string>此應用需要訪問您的位置</string>NSLocationWhenInUseUsageDescription是您需要的唯一許可。這也允許您訪問后臺位置,唯一需要注意的是,當應用程序在后臺訪問位置時,狀態欄中會顯示藍色徽章。與 Android 不同,我們在其中添加了單獨的權限以在后臺訪問用戶的位置。
位置權限
我們需要在請求用戶位置之前檢查位置服務狀態和權限狀態,這可以使用以下幾行代碼輕松完成:
Location location = new Location();bool _serviceEnabled; PermissionStatus _permissionGranted;_serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) {_serviceEnabled = await location.requestService();if (!_serviceEnabled) {return null;} }_permissionGranted = await location.hasPermission(); if (_permissionGranted == PermissionStatus.denied) {_permissionGranted = await location.requestPermission();if (_permissionGranted != PermissionStatus.granted) {return null;} }首先,我們創建一個由Location()包提供的對象,location反過來為我們提供了兩個有用的方法。檢查設備位置是否已啟用或用戶是否已手動禁用它。``serviceEnabled()
對于后者,我們顯示了一個原生提示,允許用戶通過調用快速啟用位置,然后我們再檢查一次,如果他們從提示中啟用了它。requestService()
一旦我們確定啟用了位置服務,下一步就是通過調用它來檢查我們的應用程序是否具有使用它的必要權限,這將返回.hasPermission()``PermissionStatus
PermissionStatus是可以具有以下三個值之一的枚舉:
- PermissionStatus.granted: 定位服務權限已被授予
- PermissionStatus.denied: 定位服務權限被拒絕
- PermissionStatus.deniedForever: 位置服務權限被用戶永久拒絕。這僅適用于 iOS。在這種情況下不會顯示對話框requestPermission()
如果狀態為 ,我們可以通過調用顯示請求位置權限的系統提示。對于 status ,我們可以立即訪問 location ,因此我們返回一個.denied,``requestPermission()``granted``null
如果您還想在后臺訪問用戶位置,請使用。location.enableBackgroundMode(enable: **true**)
獲取當前位置
如果位置服務可用并且用戶已授予位置權限,那么我們只需兩行代碼即可獲取用戶位置 - 不,我不是在開玩笑:
LocationData _locationData; _locationData = await location.getLocation();LocationData類提供以下位置信息:
class LocationData {final double latitude; // Latitude, in degreesfinal double longitude; // Longitude, in degreesfinal double accuracy; // Estimated horizontal accuracy of this location, radial, in metersfinal double altitude; // In meters above the WGS 84 reference ellipsoidfinal double speed; // In meters/secondfinal double speedAccuracy; // In meters/second, always 0 on iOSfinal double heading; // Heading is the horizontal direction of travel of this device, in degreesfinal double time; // timestamp of the LocationDatafinal bool isMock; // Is the location currently mocked }您還可以通過添加onLocationChanged偵聽器在用戶位置發生變化時監聽位置更新來獲得連續回調,這是出租車應用程序、司機/騎手應用程序等的一個很好的用例:
location.onLocationChanged.listen((LocationData currentLocation) {// current user location });注意,一旦您想停止收聽更新,請不要忘記取消流訂閱。
瞧!現在我們有了用戶位置的當前緯度和經度值。
讓我們利用這些緯度和經度值來獲取用戶的完整地址或反向地理編碼。
為此,我們將使用另一個驚人的 Flutter 包:geocode。
使用 Flutter 地理編碼包
設置
將依賴項添加到您的文件中:pubspec.yaml
dependencies:geocode: 1.0.1獲取地址
獲取地址再簡單不過了。就打電話吧。就是這樣!帶有空檢查的完整函數如下所示:reverseGeocoding(latitude: lat, longitude: lang)
Future<String> _getAddress(double? lat, double? lang) async {if (lat == null || lang == null) return "";GeoCode geoCode = GeoCode();Address address =await geoCode.reverseGeocoding(latitude: lat, longitude: lang);return "${address.streetAddress}, ${address.city}, ${address.countryName}, ${address.postal}"; }沒那么簡單!
完整的代碼如下所示:
class GetUserLocation extends StatefulWidget {GetUserLocation({Key? key, required this.title}) : super(key: key);final String title;@override_GetUserLocationState createState() => _GetUserLocationState(); }class _GetUserLocationState extends State<GetUserLocation> {LocationData? currentLocation;String address = "";@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(),body: Center(child: Padding(padding: EdgeInsets.all(16.0),child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[if (currentLocation != null)Text("Location: ${currentLocation?.latitude}, ${currentLocation?.longitude}"),if (currentLocation != null) Text("Address: $address"),MaterialButton(onPressed: () {_getLocation().then((value) {LocationData? location = value;_getAddress(location?.latitude, location?.longitude).then((value) {setState(() {currentLocation = location;address = value;});});});},color: Colors.purple,child: Text("Get Location",style: TextStyle(color: Colors.white),),),],),),),);}Future<LocationData?> _getLocation() async {Location location = new Location();LocationData _locationData;bool _serviceEnabled;PermissionStatus _permissionGranted;_serviceEnabled = await location.serviceEnabled();if (!_serviceEnabled) {_serviceEnabled = await location.requestService();if (!_serviceEnabled) {return null;}}_permissionGranted = await location.hasPermission();if (_permissionGranted == PermissionStatus.denied) {_permissionGranted = await location.requestPermission();if (_permissionGranted != PermissionStatus.granted) {return null;}}_locationData = await location.getLocation();return _locationData;}Future<String> _getAddress(double? lat, double? lang) async {if (lat == null || lang == null) return "";GeoCode geoCode = GeoCode();Address address =await geoCode.reverseGeocoding(latitude: lat, longitude: lang);return "${address.streetAddress}, ${address.city}, ${address.countryName}, ${address.postal}";} }常見的陷阱
盡管這些軟件包讓我們的生活變得更輕松,而且我們不必處理在 Android 和 iOS 中本地訪問位置的復雜過程,但您可能會面臨很多問題。讓我們來看看它們以及可以幫助您修復這些問題的步驟:
- 應用內存泄漏:如果您一直在收聽位置更新,請確保取消流訂閱,一旦您想停止收聽更新
- 用戶必須接受位置權限才能始終允許使用后臺位置。位置權限對話框提示中未顯示始終允許的 Android 11 選項。用戶必須從應用程序設置中手動啟用它
- 用戶可能在 iOS 上永遠拒絕定位,因此不會顯示要求定位權限的本機提示。確保處理這種邊緣情況requestPermisssions()
- 用戶可能隨時從應用程序設置中撤銷位置權限,因此在訪問位置數據之前,請確保在應用程序恢復時檢查它們
結論
由于 Flutter 簡化了訪問位置,因此我們作為開發人員可能會立即將其添加到我們的應用程序中。但同時,我們需要確保我們的應用程序真正適合請求用戶位置并利用它為用戶增加一些價值的用例,而不是僅僅將位置數據發送到服務器。
隨著即將推出的 Android 和 iOS 操作系統版本中安全性和隱私性的提高,訪問位置數據而不向用戶提供價值可能會導致您的應用程序被商店拒絕。有很多很好的用例,您可以使用用戶位置,例如,根據用戶位置為食品/外賣應用程序個性化主屏幕,該應用程序顯示按用戶當前位置的接近程度訂購的餐廳。取件/送貨應用程序是最常見的用例。
您還可以在您實際想要使用的特定屏幕上詢問用戶位置,而不是立即在主屏幕上詢問。這使用戶更清楚,并且他們不太可能拒絕位置權限。
感謝您的陪伴,堅果前端的粉絲們!您可以在GitHub 上訪問本文中使用的示例應用程序。
總結
以上是生活随笔為你收集整理的Flutter 中获取地理位置[Flutter专题61]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flutter 中 stateless
- 下一篇: Flutter 如何禁止手机横屏[Flu