介绍
地理定位是在用户与您的应用程序交互时识别用户当前物理位置的过程。
有一个geolocator包和一个Fluttergeocoding包可用于地理定位。
在本文中,您将创建一个示例 Flutter 应用程序,该应用程序使用geolocator和geocoding包来确定用户的位置。
先决条件
要完成本教程,您需要:
- 下载并安装Flutter。
- 下载并安装Android Studio 或 Visual Studio Code。
- 建议为您的代码编辑器安装插件:
本教程通过 Flutter v1.22.2、Android SDK v30.0.2、Android Studio v4.1 验证。本教程中的代码已更新为支持geolocator6+ 和geocoding1+。
步骤 1 — 设置项目
为 Flutter 设置环境后,您可以运行以下命令来创建新应用程序:
- flutter create flutter_geolocator_example
导航到新的项目目录:
- cd flutter_geolocator_example
使用flutter create将生成一个演示应用程序,该应用程序将显示单击按钮的次数。
pubspec.yaml在您的代码编辑器中打开并添加以下插件:
dependencies:
flutter:
sdk: flutter
geocoding: ^1.0.5
geolocator: ^6.1.1
注意:您需要确保您的 Android 项目为此使用 AndroidX。如果你在 1.7 版本之后创建了 Flutter 应用程序,这是默认的。如果没有,请遵循本指南:AndroidX 迁移。
然后,您需要通过编辑ios/Runner/Info.plist和为 Android 和 iOS 添加权限android/app/src/main/AndroidManifest.xml。
iOS 权限
打开Info.plist你的代码编辑器,并添加NSLocationWhenInUseUsageDescription,NSLocationAlwaysUsageDescription以及NSLocationAlwaysAndWhenInUseUsageDescription:
从 iOS 和 开始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:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
或者ACCESS_COARSE_LOCATION:
<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并将homefrom更改MyHomePage为HomePage:
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文件并添加以下代码:
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():
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);
});
}
}
编译你的代码并让它在模拟器中运行:

当您与“获取位置”按钮交互时,您最初可能会看到请求访问您的应用程序的提示。一旦您允许访问您的位置,您当前位置的latitude和longitude将出现在屏幕上。
第 4 步 – 将纬度和经度转换为人类可读的地址
下一步是转换坐标以显示地址。
传递latitude和longitude坐标到placemarkFromCoordinates将返回一个Placemark. Placemark包含像信息locality,postalCode以及country。
重新访问home_page.dart并添加_getAddressFromLatLng_():
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);
}
}
}
编译你的代码并让它在模拟器中运行:

当您与“获取位置”按钮交互时,您最初可能会看到请求访问您的应用程序的提示。一旦你允许进入你的位置,你locality,postalCode和county将被显示在屏幕上。
结论
在本教程中,您在 Flutter 应用程序中使用了geolocator和geocoding包。
如果您想了解有关 Flutter 的更多信息,请查看我们的 Flutter 主题页面以获取练习和编程项目。