如何使用 Flutter 中的 Geolocator 插件获取用户的位置

介绍

地理定位是在用户与您的应用程序交互时识别用户当前物理位置的过程。

有一个geolocator和一个Fluttergeocoding可用于地理定位。

在本文中,您将创建一个示例 Flutter 应用程序,该应用程序使用geolocatorgeocoding包来确定用户的位置。

先决条件

要完成本教程,您需要:

本教程通过 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在您的代码编辑器中打开并添加以下插件:

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你的代码编辑器,并添加NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription以及NSLocationAlwaysAndWhenInUseUsageDescription

从 iOS 和 开始Info.plist,添加以下键/值对并根据您的喜好自定义它们:

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 应用程序,并且您不想在应用程序未使用时获取用户位置,则可以放弃添加NSLocationAlwaysUsageDescriptionNSLocationAlwaysAndWhenInUseUsageDescription

安卓权限

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并将homefrom更改MyHomePageHomePage

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);
      });
  }
}

编译你的代码并让它在模拟器中运行:

在模拟器中运行的应用程序的两个屏幕截图。 第一个屏幕截图描述了允许应用程序访问位置的提示。 第二个屏幕截图描绘了用户位置的纬度和经度。

当您与“获取位置”按钮交互时,您最初可能会看到请求访问您的应用程序的提示。一旦您允许访问您的位置,您当前位置latitudelongitude将出现在屏幕上。

第 4 步 – 将纬度和经度转换为人类可读的地址

下一步是转换坐标以显示地址。

传递latitudelongitude坐标到placemarkFromCoordinates将返回一个Placemark. Placemark包含像信息localitypostalCode以及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);
    }
  }
}

编译你的代码并让它在模拟器中运行:

显示在地址为 San Francisco, 94108, United States 的模拟器中运行的应用程序的屏幕截图。

当您与“获取位置”按钮交互时,您最初可能会看到请求访问您的应用程序的提示。一旦你允许进入你的位置,你localitypostalCodecounty将被显示在屏幕上。

结论

在本教程中,您在 Flutter 应用程序中使用了geolocatorgeocoding包。

如果您想了解有关 Flutter 的更多信息,请查看我们的 Flutter 主题页面以获取练习和编程项目。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁