关于flutter-geolocator库使用问题,解决android使用LocationManager定位问题


有需要直接定位到最下面。

最新改动

2022年7月7日更新,如果getCurrentPosition获取不到数据,可以尝试先调用getLastKnownPosition。
2022年1月28日更新,geolocator官方库在v8+的版本中适配了android12,并且执行方法有变动, 基于源码v8.0.3修改 ,分支geolocator_v8.0.3_20220121,引入和修改源码位置可以参考以下内容。

相关知识

  • geolocator flutter一个比较好用的定位库
  • android原生提供的LocationManager,常用的定位库
  • 谷歌定位服务Google Location Service,需要引入google服务
    已经具备定位权限,并用户同意授权。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

问题

import 'package:geolocator/geolocator.dart';

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

在使用flutter-geolocator遇到的问题。有的手机获取定位很快,有的手机半天没有定位结果,定位很慢。

现象

查看flutter-geolocator源码,发现内部使用了两种定位方式。一种是android原生提供的LocationManager,另一种是谷歌定位服务Google Location Service,需要引入google服务。
1.在使用Google Location Service的方式获取定位,没有翻墙,没有回调。
2.在使用原生LocationManager的方式获取定位,有两种情况,一种是网络定位、一种是GPS定位。使用网络定位,但没有连接网络,没回调。使用PGS定位,在室内测试没回调。

分析问题

在Flutter调用Geolocator.getCurrentPosition方法

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

会进入到原生,具体使用哪个方式来获取定位,从这里可以知道

  1. 设置属性forceAndroidLocationManager为true,则会使用android原生的LocationManager获取定位信息。
    forceAndroidLocationManager为false,则会判断google服务是否可用
  2. google服务可用,则会使用Google Location Service的方式,这里就是FusedLocationClient封装了方法。
  3. google服务不可用,也会使用android原生的LocationManager获取定位信息。
public LocationClient createLocationClient(
      Context context,
      boolean forceAndroidLocationManager,
      @Nullable LocationOptions locationOptions) {
    if (forceAndroidLocationManager) {
      return new LocationManagerClient(context, locationOptions);
    }

    return isGooglePlayServicesAvailable(context)
        ? new FusedLocationClient(context, locationOptions)
        : new LocationManagerClient(context, locationOptions);
  }

解决问题

为了在国内外都能正常使用,就不能依赖google服务,所以这里我们打将forceAndroidLocationManager属性设置为true。

Geolocator.getCurrentPosition(forceAndroidLocationManager: true)

这样就会使用Android原生的LocationManager定位,但又有新的问题,上面说了,LocationManager有两种情况,一种是网络定位、一种是GPS定位。使用GPS的话,在室内会非常慢,这肯定是不太想要的,所以我们只要使用网络定位的方式就可以很好的解决问题。

定位到LocationManagerClient类,getBestProvider方法。发现代码的实现方式,先通过locationManager.getProviders获取支持的定位方式。

if (Strings.isEmptyOrWhitespace(provider)) {
    List<String> providers = locationManager.getProviders(true);
    if (providers.size() > 0) provider = providers.get(0);
}

官方提供了几种Provider:

  1. LocationManager.NETWORK_PROVIDER,网络定位,网络定位则更具有实时性,在精度要求不高以及室内
  2. LocationManager.GPS_PROVIDER,GPS定位,首次采集数据较慢,定位精度高
  3. LocationManager.PASSIVE_PROVIDER,被动定位,被动定位并不会做任何获取位置信息的尝试,它只是被动的接收位置信息的更新,只有其他应用使用了网络定位或GPS定位获取到了新的位置信息后,被动定位的监听者才能获取当前位置。

修改源码

官方实现方式是直接获取第一个定位方式,如果这个方式刚好是GPS定位,那在室内调试的时候,半天获取不到数据。只要改成,都使用网络定位的方式就好了。

      Location currentLocation = locationManager.getLastKnownLocation(provider);
      List<String> providers = locationManager.getProviders(true);
    
      if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
          provider = LocationManager.NETWORK_PROVIDER;
      } else if (providers.contains(LocationManager.GPS_PROVIDER)) {
          provider = LocationManager.GPS_PROVIDER;
      }

如果存在NETWORK_PROVIDER,就使用网络定位的方式。这样就解决问题了。

再进行一些其他优化,源码中onLocationChanged回调函数,是获取定位的回调,里面还进行了一些误差范围的限制,由于使用网络定位,误差可能会比原本的限制值偏大,所以也进行了一点微调。
在精确度中,加入一个lowest:1000的值。

private static float accuracyToFloat(LocationAccuracy accuracy) {
    switch (accuracy) {
      case lowest:
          return 1000;
      case low:
        return 500;
      case medium:
        return 250;
      case best:
      case bestForNavigation:
        return 50;
      default:
        return 100;
    }
  }

使用方式

pubspec.yaml

dependencies:
  flutter-geolocator:
    git:
      url: "https://github.com/Super-Bin/flutter-geolocator"
	  ref: geolocator_v7.0.3_zzb_0421

使用兼容android12的版本- 基于源码v8.0.3修改 分支geolocator_v8.0.3_20220121
pubspec.yaml

dependencies:
  flutter-geolocator:
    git:
      url: "https://github.com/Super-Bin/flutter-geolocator"
	  ref: geolocator_v8.0.3_20220121

flutter调用

Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.lowest,
                      forceAndroidLocationManager: true)

最好先把代码拉下来,在demo运行验证通过了再集成到项目中。

2022.5.5更新

最近在一个新项目中按照以上方式引入,发现修改的代码没有生效,我明明改了android源码。原因是在v8.0库开始,插件分类管理,分类引入,在引入库的配置上有问题。
在这里插入图片描述

在这里插入图片描述

主入口geolocator中的pubspec.yaml文件可以看到,统一接口引入了geolocator_platform_interface库,android相关功能使用geolocator_android库,ios相关功能使用geolocator_apple库。
但是文章介绍修改源码的地方都是在geolocator_android中完成,然而在主入口geolocator中的pubspec.yaml,依旧引入geolocator_android: ^3.0.2,这个表示从pub仓库下载geolocator_android库,所以引用的依然是pub仓库中原来的代码,我修改的源码没有生效。

// geolocator中的pubspec.yaml
geolocator_android: ^3.0.2

解决方案1:本地引入

既然修改的是geolocator_android源码,那就整个geolocator都使用本地引入的方式,将geolocator移到项目根目录中,然后引入。

// 根目录中的pubspec.yaml,我在根目录下面创建了plugins文件夹用来存放本地引入的库。
dependencies:
  flutter-geolocator:
    path: ./plugins/flutter-geolocator/

// geolocator中的pubspec.yaml,这里需要修改引入本地的geolocator_android库
dependencies:
  geolocator_android: 
    path: ../geolocator_android

解决方案2:远程依赖

远程依赖需要分2种方式,第1是自己搭建的pub,这种方便。第2是使用github类比pub仓库的方式。
这里就用github来举例,思路是一样。
我们在本地修改了geolocator_android,然后geolocator又需要引用这个修改过的geolocator_android库,那就把geolocator_android推送到github上,修改中geolocator中的pubspec.yaml,引入GitHub上的geolocator_android库。

// 根目录中的pubspec.yaml,引入github上的flutter-geolocator。
dependencies:
  flutter-geolocator:
    git:
      url: "https://github.com/Super-Bin/flutter-geolocator"
	  ref: geolocator_v8.0.3_20220121

// geolocator中的pubspec.yaml,这里需要修改引入github的geolocator_android库,下面只是演示,可以上传到自己的github库上,目前没有在我的GitHub上创建flutter-geolocator-android
dependencies:
  geolocator_android: 
    git:
      url: "https://github.com/Super-Bin/flutter-geolocator-android"
	  ref: xxx

2022.7.6更新

最近测试,发现在某些机型上通过Geolocator.getCurrentPosition方法获取不到定位,暂不清楚原因。
可以尝试先获取getLastKnownPosition,没有数据的话再去请求getCurrentPosition方法。

try{
      Position? lastKnownPosition = await Geolocator.getLastKnownPosition(
        forceAndroidLocationManager: true,);

      Position position2 = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.lowest,
          forceAndroidLocationManager: true,
          timeLimit: const Duration(seconds: 4));

      print("结果lastKnownPosition $lastKnownPosition");
      print("结果position2 $position2");

}catch (e){
	print("_getCurrentPosition error $e");
}
  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
### 回答1: Flutter是Google开源的一款跨平台的UI开发框架,可以快速地构建高质量的移动、Web和桌面应用程序。而Embedded Linux是指Linux操作系统在嵌入式设备中的应用。通过将Flutter与Embedded Linux结合起来,可以让开发者在嵌入式设备上创建漂亮且功能强大的应用程序。 Flutter的跨平台特性使得开发者可以使用相同的代码在多个平台上运行应用程序,包括嵌入式设备。嵌入式设备通常资源有限,但Flutter的轻量级和高性能使得它非常适合在此类设备上运行。Flutter的热重载功能可以让开发者快速迭代和测试应用程序,提高开发效率。 使用Flutter-Embedded Linux,开发者可以利用Flutter的丰富的UI组件和强大的渲染引擎来创建嵌入式设备上的用户界面。Flutter提供了丰富的UI控件和动画效果,可以实现各种视觉效果和交互体验。Flutter还具备良好的跨平台兼容性和高度定制性,可以适应不同嵌入式设备的各种需求。 除此之外,Flutter-Embedded Linux还提供了与Linux操作系统的良好集成,可以调用底层系统资源和API,如文件系统、网络接口等。这使得开发者可以通过Flutter在嵌入式设备上实现更强大的功能,例如与传感器的交互、与云服务的连接等。 总而言之,Flutter-Embedded Linux是一个强大的开发工具,可以帮助开发者在嵌入式设备中创建高质量的应用程序。它结合了Flutter的跨平台特性和Embedded Linux的优势,为开发者提供了更灵活、高效的开发环境。无论是工业控制、智能家居还是其他嵌入式应用,Flutter-Embedded Linux都能提供良好的开发体验和用户体验。 ### 回答2: Flutter-embedded-linux是指在嵌入式Linux平台上使用Flutter框架进行应用开发的一种技术方案。嵌入式Linux是指在资源有限的嵌入式设备上运行Linux操作系统的系统;而Flutter是一种跨平台的移动应用开发框架,可以同时在Android和iOS上运行。 使用Flutter-embedded-linux可以让开发者在嵌入式Linux平台上开发出跨平台的应用。这样一来,开发者不再需要针对不同的平台编写不同的代码,大大提高了开发效率。同时,Flutter的高性能和优秀的用户体验也被保留在嵌入式设备上。 在使用Flutter-embedded-linux时,开发者需要在嵌入式Linux平台上搭建Flutter的开发环境,包括安装Flutter SDK、配置相关的依赖等。然后,可以使用Flutter提供的开发工具和API进行应用的开发和调试。 Flutter-embedded-linux可以应用于很多领域,例如智能家居、智能工业设备、嵌入式系统等。开发者可以利用Flutter-embedded-linux开发各种类型的应用,如物联网设备控制应用、工业监控系统、嵌入式音视频播放器等。 需要注意的是,由于嵌入式Linux平台的资源限制,开发者在使用Flutter-embedded-linux时需要特别关注应用的性能和资源消耗情况,避免出现过多的资源占用或性能瓶颈。 总之,Flutter-embedded-linux为开发者在嵌入式Linux平台上开发跨平台应用提供了一种方便、高效、高性能的技术方案,有望在嵌入式设备领域得到广泛应用。 ### 回答3: Flutter-Embedded-Linux是一种使用Flutter框架进行嵌入式开发的技术方案。Flutter是一种跨平台的开源UI框架,可以快速构建高性能、精美的应用程序。而Embedded-Linux则是嵌入式设备常用的操作系统。 通过将Flutter应用程序集成到Linux嵌入式系统中,可以在嵌入式设备上实现高效、流畅和美观的用户界面。Flutter的特点是能够在不同平台上保持一致的用户体验,因此在嵌入式系统上也能够实现类似于移动设备和桌面系统上的应用程序。 使用Flutter-Embedded-Linux进行嵌入式开发有一些优势。首先,Flutter具有快速构建UI界面的能力,可以节省开发时间。其次,Flutter对于动画和渲染效果的支持非常好,可以在嵌入式设备上实现更加流畅和绚丽的动画效果。此外,Flutter还支持热重载功能,可以实时更新应用程序而无需重新启动,极大地提高了开发效率。 然而,使用Flutter-Embedded-Linux也存在一些挑战。嵌入式设备通常资源有限,对占用内存和CPU的要求较高,需要对Flutter应用程序进行优化以提高性能。另外,由于Flutter是基于Dart语言开发的,需要事先熟悉Dart开发语言和Flutter框架的使用。 总之,Flutter-Embedded-Linux是一种用于嵌入式开发的技术方案,可以帮助开发者快速构建高品质的应用程序界面。它在嵌入式设备上的应用可以提供与移动设备和桌面系统相媲美的用户体验。但是,开发者需要注意对资源的合理利用和性能的优化,以确保应用程序在嵌入式设备上能够运行流畅。
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值