介绍
地理位置是在用户与您的应用程序交互时识别用户当前物理位置的过程。
Flutter 有一个 地理定位器包 和一个 地理编码包,可用于地理定位。
在本文中,您将创建一个示例 Flutter 应用程序,该应用程序使用 geolocator 和 geocoding 包来确定用户的位置。
先决条件
要完成本教程,您需要:
- 下载并安装 Flutter。
- 下载并安装Android Studio 或 Visual Studio Code。
- 建议为您的代码编辑器安装插件: 为 Android Studio 安装了 Flutter 和 Dart 插件。 为 Visual Studio Code 安装了 Flutter 扩展。
本教程已使用 Flutter v1.22.2、Android SDK v30.0.2 和 Android Studio v4.1 进行了验证。 本教程中的代码已更新为支持 geolocator 6+ 和 geocoding 1+。
第 1 步 — 设置项目
为 Flutter 设置好环境后,您可以运行以下命令来创建新应用程序:
flutter create flutter_geolocator_example
导航到新的项目目录:
cd flutter_geolocator_example
使用 flutter create 将生成一个演示应用程序,该应用程序将显示按钮被单击的次数。
在代码编辑器中打开 pubspec.yaml 并添加以下插件:
发布规范.yaml
dependencies:
flutter:
sdk: flutter
geocoding: ^1.0.5
geolocator: ^6.1.1
注意: 为此,您需要确保您的 Android 项目使用 AndroidX。 如果您在 1.7 版本之后创建了 Flutter 应用程序,则默认情况下会出现这种情况。 如果没有,请遵循本指南:AndroidX 迁移。
然后,您需要通过编辑 ios/Runner/Info.plist 和 android/app/src/main/AndroidManifest.xml 来为 Android 和 iOS 添加权限。
iOS 权限
在代码编辑器中打开 Info.plist 并添加 NSLocationWhenInUseUsageDescription、NSLocationAlwaysUsageDescription 和 NSLocationAlwaysAndWhenInUseUsageDescription:
从 iOS 和 Info.plist 开始,添加以下键/值对并根据自己的喜好自定义它们:
ios/Runner/Info.plist
<key>NSLocationWhenInUseUsageDescription</key> <string>This app needs access to location when open.</string> <key>NSLocationAlwaysUsageDescription</key> <string>This app needs access to location when in the background.</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>This app needs access to location when open and in the background.</string>
如果您不打算支持 iOS 10 之前的 iOS 应用程序,并且不想在应用程序不使用时获取用户位置,则可以放弃添加 NSLocationAlwaysUsageDescription 和 NSLocationAlwaysAndWhenInUseUsageDescription。
安卓权限
在代码编辑器中打开 AndroidManifest.xml 并添加以下内容之一。
ACCESS_FINE_LOCATION:
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
或 ACCESS_COARSE_LOCATION:
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
ACCESS_FINE_LOCATION 是最精确的,而 ACCESS_COARSE_LOCATION 给出的结果等于大约一个城市街区。
完成此设置后,您可以创建将触发并显示用户当前位置的小部件。
第 2 步——搭建项目的脚手架
接下来,您需要更新 main.dart 文件并创建一个新的 home_page.dart 文件。
在代码编辑器中打开 main.dart 并导入 home_page.dart 并将 home 从 MyHomePage 更改为 HomePage:
lib/main.dart
import 'package:flutter/material.dart';
import 'home_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
);
}
}
然后,创建一个新的 home_page.dart 文件并添加以下代码:
lib/home_page.dart
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Location"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
child: Text("Get location"),
onPressed: () {
// Get location here
},
),
],
),
),
);
}
}
这将创建一个带有消息 "Get location" 的按钮。
第 3 步 — 获取纬度和经度
下一步是添加地理定位功能。
您可以通过创建 Geolocator 的实例并调用 getCurrentPosition 来实现。 这应该询问用户他们是否有兴趣使用位置功能,如果有兴趣,则将当前位置作为 Position 获取。
重新访问 home_page.dart 并添加 _getCurrentLocation():
lib/home_page.dart
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Position _currentPosition;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Location"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (_currentPosition != null) Text(
"LAT: ${_currentPosition.latitude}, LNG: ${_currentPosition.longitude}"
),
FlatButton(
child: Text("Get location"),
onPressed: () {
_getCurrentLocation();
},
),
],
),
),
);
}
_getCurrentLocation() {
Geolocator
.getCurrentPosition(desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true)
.then((Position position) {
setState(() {
_currentPosition = position;
});
}).catchError((e) {
print(e);
});
}
}
编译你的代码并让它在模拟器中运行:
当您与 Get location 按钮交互时,您最初可能会看到请求访问您的应用程序的提示。 一旦您允许访问您的位置,您当前位置的 latitude 和 longitude 将出现在屏幕上。
第 4 步 — 将纬度和经度转换为人类可读的地址
下一步是转换坐标以显示地址。
将 latitude 和 longitude 坐标传递给 placemarkFromCoordinates 将返回 Placemark。 Placemark 包含 locality、postalCode 和 country 等信息。
重新访问 home_page.dart 并添加 _getAddressFromLatLng_():
lib/home_page.dart
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Position _currentPosition;
String _currentAddress;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Location"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (_currentAddress != null) Text(
_currentAddress
),
FlatButton(
child: Text("Get location"),
onPressed: () {
_getCurrentLocation();
},
),
],
),
),
);
}
_getCurrentLocation() {
Geolocator
.getCurrentPosition(desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true)
.then((Position position) {
setState(() {
_currentPosition = position;
_getAddressFromLatLng();
});
}).catchError((e) {
print(e);
});
}
_getAddressFromLatLng() async {
try {
List<Placemark> placemarks = await placemarkFromCoordinates(
_currentPosition.latitude,
_currentPosition.longitude
);
Placemark place = placemarks[0];
setState(() {
_currentAddress = "${place.locality}, ${place.postalCode}, ${place.country}";
});
} catch (e) {
print(e);
}
}
}
编译你的代码并让它在模拟器中运行:
当您与 Get location 按钮交互时,您最初可能会看到请求访问您的应用程序的提示。 一旦您允许访问您的位置,您的 locality、postalCode 和 county 将显示在屏幕上。
结论
在本教程中,您在 Flutter 应用程序中使用了 geolocator 和 geocoding 包。
如果您想了解有关 Flutter 的更多信息,请查看 我们的 Flutter 主题页面 以获取练习和编程项目。