flutter获取地理定位:geolocator依赖详细用法

 本文使用geolocator插件实现app物理定位功能。

该插件的主要功能有:

  • 获取最后已知位置;
  • 获取设备当前位置;
  • 获取连续的位置更新;
  • 检查设备是否启用了定位服务;
  • 计算两个地理坐标之间的距离(米);
  • 计算两个地理坐标之间的方位;

如何安装:

 方法一:在pubspec.yaml文件中添加它,10.1.0是当前最新版本号,也可指定特定版本号。

然后在终端运行以下命令:

flutter packages get

方法二:直接在终端运行以下命令获取最新版本geolocator插件

flutter pub add geolocator

配置app环境 :

Android系统

1.在 "android\gradle.properties" 文件中添加以下内容:

android.useAndroidX=true
android.enableJetifier=true

2.确保将 "android/app/build.gradle "文件中的 compileSdkVersion 设置为 33(10.1.0版本时要求,不同版本可能要求不一样,具体看原依赖文档):

android {
  compileSdkVersion 33

  ...
}

3.确保将所有 android. 依赖项替换为 AndroidX 对应项(完整列表可在此处找到:迁移到 AndroidX)。

4.打开 "android\app\src\main\AndroidManifest.xml" 文件,将以下两行中的一行添加为<manifest> 标签的直接子代(当这两种权限都配置时,geolocator将使用 ACCESS_FINE_LOCATION):

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

如果你目标用户用的是Android10或者以上的系统,就需要再添加ACCESS_BACKGROUND_LOCATION这条权限

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

IOS系统

打开 "ios\Runner\Info.plist" 文件,添加以下内容。string标签内为描述,可更改以贴合上下文。

<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>

如果你想在应用程序处于后台时也能接收位置更新,你还需要在 XCode 项目中添加后台模式功能(项目 > 签名和功能 > "+ 功能 "按钮)并选择位置更新。(但要注意,在向 AppStore 提交应用程序时,你需要向苹果公司详细解释为什么您的应用程序需要这样做。如果苹果不满意您的解释,您的应用程序将被拒绝。)

使用 requestTemporaryFullAccuracy({purposeKey: "YourPurposeKey"}) 方法时,应在 Info.plist 文件中添加一个字典。第二个键(本例中称为 YourPurposeKey)应与 requestTemporaryFullAccuracy() 方法中传递的 purposeKey 相匹配

<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
  <key>YourPurposeKey</key>
  <string>The example App requires temporary access to the device&apos;s precise location.</string>
</dict>

简单使用举例:

权限配置完成后我们就可以开始使用地理定位依赖了,下面的代码举例说明了如何获取设备的当前位置,包括检查定位服务是否启用,以及检查/请求访问设备位置的权限:

/// 位置服务
  Future _determinePosition() async {
    bool serviceEnabled;
    LocationPermission permission;
    double longitude=0;
    double latitude=0;
    try {
      /// 手机GPS服务是否已启用。
      serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        //定位服务未启用,要求用户启用定位服务
        var res = await Geolocator.openLocationSettings();
        if (!res) {
          /// 被拒绝
          return;
        }
      }
      /// 是否允许app访问地理位置
      permission = await Geolocator.checkPermission();

      if (permission == LocationPermission.denied) {
        /// 之前访问设备位置的权限被拒绝,重新申请权限
        permission = await Geolocator.requestPermission();
        if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
          /// 再次被拒绝。根据Android指南,你的应用现在应该显示一个解释性UI。
          return;
        }
      } else if (permission == LocationPermission.deniedForever) {
        /// 之前权限被永久拒绝,打开app权限设置页面
        await Geolocator.openAppSettings();
        return;
      }
      /// 允许访问地理位置,获取地理位置
      Position position = await Geolocator.getCurrentPosition();
      longitude = position.longitude;
      latitude = position.latitude;
    } catch (e) {
      print(e);
    }
  }
   

geolocator依赖的完整API:

 检查GPS是否启用:isLocationServiceEnabled

可用该方法检查手机GPS(全球定位系统)是否打开,以此进行不同操作

import 'package:geolocator/geolocator.dart';

bool isLocationServiceEnabled  = await Geolocator.isLocationServiceEnabled();

然后可以调用 getServiceStatusStream监听服务状态变化。这将返回一个可以监听的 Stream<ServiceStatus>,以接收位置服务状态更新。

import 'package:geolocator/geolocator.dart';

StreamSubscription<ServiceStatus> serviceStatusStream = Geolocator.getServiceStatusStream().listen(
    (ServiceStatus status) {
        print(status);
    });

 检查是否允许APP获取位置权限:checkPermission

import 'package:geolocator/geolocator.dart';

LocationPermission permission = await Geolocator.checkPermission();

 APP请求获取位置权限:requestPermission

import 'package:geolocator/geolocator.dart';

LocationPermission permission = await Geolocator.requestPermission();

checkPermission 和 requestPermission 方法返回值说明

  • denied:用户拒绝了访问设备位置的权限。您可以再次申请权限(这也是初始权限状态)。
  • deniedForever:永久拒绝访问设备位置的权限。请求权限时,权限对话框将不会显示,直到用户在应用程序设置中更新权限。
  • whileInUse:仅当应用程序正在使用时才允许访问设备位置。
  • always:即使应用程序在后台运行,也允许访问设备位置。

打开相关设置页面:

在某些情况下,有必要询问用户并更新其设备设置。例如,用户最初永久拒绝了APP访问设备位置的权限,或者位置服务未启用(在 Android 上,自动解析不起作用)。在这种情况下,你可以使用 openAppSettingsopenLocationSettings 方法立即将用户重定向到设备的设置页面。 

安卓系统中,openAppSettings 方法将把用户重定向到应用程序特定设置,用户可以在此重新设置APP相关权限。

openLocationSettings 方法将弹窗询问或把用户重定向到设备位置设置,用户可在此启用/禁用位置服务。


iOS 系统中,我们不允许打开特定的设置页面,因此这两种方法都会将用户重定向到 "设置应用",用户可以从该应用导航到正确的设置类别,以更新权限或启用/禁用位置服务。

import 'package:geolocator/geolocator.dart';

await Geolocator.openAppSettings();
await Geolocator.openLocationSettings();

获取当前位置:getCurrentPosition

  • desiredAccuracy:app希望接收的位置数据的精度(可选值在文章结尾有说明);
  • timeLimit:获取当前位置所允许的最长时间。超过时间限制后,将抛出 TimeOutException 异常,并取消调用。默认情况下未配置任何限制,即永不超时。
import 'package:geolocator/geolocator.dart';

Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);

获取最后已知位置:getLastKnownPosition

import 'package:geolocator/geolocator.dart';

Position? position = await Geolocator.getLastKnownPosition();

监听持续性的位置变化:getPositionStream

  • accuracy:应用程序希望接收的位置数据的精确度;
  • distanceFilter:在生成更新事件之前,设备水平移动的最小距离(以米为单位);
  • timeLimit:位置更新之间允许的最长间隔时间。超过时限后,将抛出 TimeOutException 异常,并取消数据流。默认情况下未配置任何限制,即永不超时。
import 'package:geolocator/geolocator.dart';

final LocationSettings locationSettings = LocationSettings(
  accuracy: LocationAccuracy.high,
  distanceFilter: 100,
);
StreamSubscription<Position> positionStream = Geolocator.getPositionStream(locationSettings: locationSettings).listen(
    (Position? position) {
        print(position == null ? 'Unknown' : '${position.latitude.toString()}, ${position.longitude.toString()}');
    });

在某些情况下,有必要指定一些平台特定的设置。这可以通过使用特定平台的 AndroidSettings 或 AppleSettings 类来实现。使用特定平台类时,还必须导入特定平台包。示例:

import 'package:geolocator/geolocator.dart';
import 'package:geolocator_apple/geolocator_apple.dart';
import 'package:geolocator_android/geolocator_android.dart';

late LocationSettings locationSettings;

if (defaultTargetPlatform == TargetPlatform.android) {
  locationSettings = AndroidSettings(
    accuracy: LocationAccuracy.high,
    distanceFilter: 100,
    forceLocationManager: true,
    intervalDuration: const Duration(seconds: 10),
    //(可选)设置前台通知配置,使应用程序在进入后台时保持活跃
    foregroundNotificationConfig: const ForegroundNotificationConfig(
        notificationText:
        "Example app will continue to receive your location even when you aren't using it",
        notificationTitle: "Running in Background",
        enableWakeLock: true,
    )
  );
} else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) {
  locationSettings = AppleSettings(
    accuracy: LocationAccuracy.high,
    activityType: ActivityType.fitness,
    distanceFilter: 100,
    pauseLocationUpdatesAutomatically: true,
    // 只有当我们的APP在后台启动时才设置为true
    showBackgroundLocationIndicator: false,
  );
} else {
    locationSettings = LocationSettings(
    accuracy: LocationAccuracy.high,
    distanceFilter: 100,
  );
}

StreamSubscription<Position> positionStream = Geolocator.getPositionStream(locationSettings: locationSettings).listen(
    (Position? position) {
        print(position == null ? 'Unknown' : '${position.latitude.toString()}, ${position.longitude.toString()}');
    });

 计算两个坐标间的距离:distanceBetween

  • startLatitude:起始位置的经度。
  • startLongitude:起始位置的纬度。
  • endLatitude:终点位置的经度。
  • endLongitude:终点位置的维度。
import 'package:geolocator/geolocator.dart';

double distanceInMeters = Geolocator.distanceBetween(52.2165157, 6.9437819, 52.3546274, 4.8285838);

 计算两个坐标间的方位:bearingBetween

同样需要上述四个参数。

import 'package:geolocator/geolocator.dart';

double bearing = Geolocator.bearingBetween(52.2165157, 6.9437819, 52.3546274, 4.8285838);

定位精度枚举值

Android

  • lowest:确保不会使用额外的功率来计算位置。这意味着该请求将充当被动监听器,只接收代表其他客户端计算的 "空闲 "位置,而不会只代表该请求计算位置。(可能不会返回任何位置信息)
  • low:以可能牺牲定位精度为代价,对低功耗进行权衡。
  • medium:要求在定位精度和耗电量之间进行权衡。
  • high:要求权衡高精度定位和可能的额外耗电量。

IOS  请求的数据越详细,对电池消耗的影响就越大。

  • lowest:精确到最近的三公里。
  • low:精确到最近的一公里。
  • medium:精度精确到一百米以内。
  • high:精确到距离所需目标十米以内。
  • best:可用的最佳精度级别。
  • bestForNavigation:使用附加传感器数据以方便导航应用程序的最高精度。

好了,去玩吧 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/335878.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——排序

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;也是顺利的考完试迎来了寒假。众所周知&#xff0c;不怕同学是学霸&#xff0c;就怕学霸放寒假&#xff0c;假期身为弯道超车的最佳时间&#xff0c;我们定然是不能懒散的度过。 今天我们就一起来学习数据结构初阶的终章——…

眼镜用超声波清洗机好不好?洗眼镜比较好用的超声波清洗机推荐

眼镜是我们日常生活中必不可少的用品&#xff0c;它不仅能帮助我们矫正视力&#xff0c;更是我们与外界进行交流的重要工具。然而&#xff0c;随着眼镜的长时间佩戴&#xff0c;眼镜表面容易积累灰尘、污垢和细菌&#xff0c;这不仅影响了我们的视野&#xff0c;也可能对眼睛健…

Docker(一)简介和基本概念:什么是 Docker?用它会带来什么样的好处?

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 一、简介 本章将带领你进入 Docker 的世界。 什么是 Docker&#xff1f; 用它会带来什么样的好处&#xff1f; 好吧&#xff0c;让我们带…

Python连接数据库的梳理

我们通常用的数据库类型主要有关系型数据库&#xff0c;非关系型数据库等&#xff0c;其中关系型数据库主要有Microsoft SQL Server ,MySQL,Oracle&#xff0c;SQLite等&#xff0c;常用的非关系型数据库包括Redis、DynamoDB&#xff0c;MongoDB等 ​​​​​​​ 一 关系型…

hdu 3709 Balanced Number

Balanced Number 题意 定义一个非负整数在第 p p p 位为 p i v o t pivot pivot 的权重为&#xff1a;这个数位的值 \times 这个数位到 p i v o t pivot pivot 的距离 之和。如果在 p i v o t pivot pivot 左边的权重等于在 p i v o t pivot pivot 右边的权重&#xf…

uni-app小程序:文件下载打开文件方法苹果安卓都适用

api: const filetype e.substr(e.lastIndexOf(.)1)//获取文件地址的类型 console.log(文档,filetype) uni.downloadFile({url: e,//e是图片地址success(res) {console.log(res)if (res.statusCode 200) {console.log(下载成功,);var filePath encodeURI(res.tempFilePath);…

python开发之远程开发工具对比

前言 除了本地开发外&#xff0c;还有一种常见的开发方式就是远程开发&#xff0c;一般情况是一台Windows或mac笔记本作为日常使用的电脑&#xff0c;另有一台linux服务器作为开发服务器。开发服务器的性能往往较强&#xff0c;这样远程开发的方式一方面可以让我们在习惯的系统…

Python网络爬虫步骤是什么?新手小白必看 !

python网络爬虫步骤&#xff1a;首先准备所需库&#xff0c;编写爬虫调度程序&#xff1b;然后编写url管理器&#xff0c;并编写网页下载器&#xff1b;接着编写网页解析器&#xff1b;最后编写网页输出器即可。 本教程操作环境&#xff1a;windows7系统、python3.9版&#xff…

Spring | Spring中的Bean--下

Spring中的Bean: 4.Bean的生命周期5.Bean的配装配式 ( 添加Bean到IOC容器的方式 依赖注入的方式 )5.1 基于XML的配置5.2 基于Annotation (注解) 的装配 (更常用&#xff09;5.3 自动装配 4.Bean的生命周期 Spring容器可以管理 singleton作用域的Bean的生命周期&#xff0c;在此…

【Github搭建网站】零基础零成本搭建个人Web网站~

Github网站&#xff1a;https://github.com/ 这是我个人搭建的网站&#xff1a;https://xf2001.github.io/xf/ 大家可以搭建完后发评论区看看&#xff01;&#xff01;&#xff01; 搭建教程&#xff1a;https://www.bilibili.com/video/BV1xc41147Vb/?spm_id_from333.999.0.0…

sql570 | 至少有5名下属的经理 | join on | group by | having

讲给一张表&#xff0c;表字段分别为 id 、姓名、部分、经理id&#xff0c;可能存在张三既是下属也是经理 现在找出下属起码有5名员工的经理 CREATE TABLE Employee (id INT,name VARCHAR(255),department VARCHAR(255),managerId INT );INSERT INTO Employee (id, name, depar…

HarmonyOS 页面跳转控制整个界面的转场动画

好 本文 我们来说 页面间的转场动画 就是 第一个界面到另一个界面 第一个界面的退场和第二个界面的进场效果 首先 我这里 创建了两个页面文件 Index.ets和AppView.ets index组件 编写代码如下 import router from "ohos.router" Entry Component struct Index {b…

架构的演进

1.1单体架构 单体架构也称之为单体系统或者是单体应用。就是一种把系统中所有的功能、模块耦合在一个应用中的架构方式。 存在的问题&#xff1a; 代码耦合&#xff1a;模块的边界模糊、依赖关系不清晰&#xff0c;整个项目非常复杂&#xff0c;每次修改代码都心惊胆战迭代困…

LeetCode.2788. 按分隔符拆分字符串

题目 题目链接 分析 题目的意思是给我们一个字符串数组和一个分隔符&#xff0c;让我们按照分隔符把字符串数组分割成新的字符串数组。 看到这个描述&#xff0c;这不就是直接就是利用 按照分隔符分割字符串的系统库函数split()&#xff0c;这个函数的意思就是 把一个字符串…

SpringBoot解决Slow HTTP慢速攻击漏洞

项目场景&#xff1a; 扫描到的漏洞截图&#xff1a; 攻击原理&#xff1a; Web应用在处理HTTP请求之前都要先接收完所有的HTTP头部&#xff0c;因为HTTP头部中包含了一些Web应用可能用到的重要的信息。攻击者利用这点&#xff0c;发起一个HTTP请求&#xff0c;一直不停的发送…

H3C交换机S6850配置M-LAG三层转发

正文共&#xff1a;1999 字 30 图&#xff0c;预估阅读时间&#xff1a;3 分钟 前面提到M-LAG是一种跨设备链路聚合技术&#xff0c;将两台物理设备在聚合层面虚拟成一台设备来实现跨设备链路聚合&#xff0c;从而提供设备级冗余保护和流量负载分担。 之前已经做了DRNI的三层转…

MySQL之外键约束和表关系

前言 一个项目中如果将所有的数据都存放在一张表中是不合理的&#xff0c;比如一个员工信息&#xff0c;公司只有2个部门&#xff0c;但是员工有1亿人&#xff0c;就意味着员工信息这张表中的部门字段的值需要重复存储&#xff0c;极大的浪费资源&#xff0c;因此可以定义一个…

突破性概念“整车智能”背后,比亚迪又在蓄力何方?

比亚迪再以“整车智能”的颠覆性创意惊艳我们&#xff0c;他们这次又在酝酿哪些革命性技术&#xff0c;引领行业&#xff1f; 2024年的比亚迪梦想日&#xff0c;为汽车行业带来了一次全新的飞跃。这家传统但很有实力&#xff0c;却又颇有野心的自主品牌车企&#xff0c;再次以开…

使用Python在本地生成助记词

新建并打开一个空文件夹 逐行 执行命令 python3 -m pip install --upgrade pippip3 install eth_accountpip3 install web3touch acco.py然后看到文件夹下面会有个acco.py文件 将把下面的代码粘贴到acco.py中保存。 import os from eth_account import Accountif __name__ …

AI视频智能识别技术在智慧农业大棚升级改造管理场景中的应用方案

一、需求分析 随着科技的进步和农业现代化的推进&#xff0c;智能化技术逐渐成为现代农业发展的重要支撑。农业大棚作为现代农业的重要组成部分&#xff0c;其智能化改造对于提高农业生产效率、降低成本、增加收益具有重要意义。利用先进的信息化手段来对农业大棚进行管理&…