Android GNSS 模块分析(一)整体介绍 - App

这篇具有很好参考价值的文章主要介绍了Android GNSS 模块分析(一)整体介绍 - App。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、前言

2、Android GNSS 介绍

3、Android GNSS 各层级流程分析

        3.1 API 接口层

        3.2 Framework 服务层

        3.3 JNI 层级调用

        3.4 Native 层 / Hal 层

4、GNSS NMEA 数据概述

正文

1 前言

        大家好,本章节是介绍 Android GNSS 整体框架服务。此篇为学习记录随笔,文中若有错误,还请大家不吝告知,指正修改,小弟先行告谢!!!

        文章代码基于Android Q 版本代码分析。文章按照 Android 的层次架构来系统整理 Android GNSS 模块的流程及功能。

2 Android GNSS 介绍

        GNSS为Global Navigation Satellite System的缩写,即全球导航卫星系统。当前应用较广泛的主要有美国的GPS、俄罗斯的GLONASS、欧盟的GALILEO和中国北斗卫星导航系统等。

Android GNSS 框架图

Android GNSS 模块分析(一)整体介绍 - App

(Android GNSS 架构图)

        首先先来介绍一下 Android GNSS 模块的整体架构。从图中可以看到,GNSS 架构是从 应用层 ---> 通过原生 jar 包 ---> 调用 AIDL 接口 ---> 连接到 Android Framework 层 ---> 通过 JNI ---> 调用 HIDL 接口 ---> 连接到 Hal 层。AIDL 和 HIDL 跨进程通信用橙色标注,表明调用进程切换。

Android GNSS 应用接口 -> Framework 类图

Android GNSS 模块分析(一)整体介绍 - App

(引用图,版本应该比较老了)

         上图基本包含接口包(android.location 包)中比较重要的类以及 Framework 层 GNSS 服务端比较重要的类。

3 Android GNSS 各层级流程分析

3.1 API 接口层

3.1.1 Location 权限

        Location 权限类型:类别(前台信息/后台信息)、精确度(确切位置/大致位置)。

类别

        前台位置信息:如果应用仅需要接收一次位置信息或者只在特定一段时间内接收位置信息,则申请前台位置权限。android:foregroundServiceType="location"

        后台位置信息:如果应用需要不断获取位置信息,那么需要申请后台位置权限。在 Q 版本及以后,必须在 Manifest 中声明  ACCESS_BACKGROUND_LOCATION 权限。在较低的 Android 版本中,当应用获得前台位置信息访问权限时,也会自动获得后台位置信息访问权限。

精确度

        大致位置:提供设备位置的估算值。如果位置值来自 LocationManagerService 或 FusedLocationProvider,该估算值的精确度大约在 3 平方公里内。对应权限为 ACCESS_COARSE_LOCATION 权限。

        精确位置:提供尽可能准确的设备位置估算值。如果位置值来自 LocationManagerService 或 FusedLocationProvider,则此估算值的精确度在 50 米内,有时甚至可以精确到几米内。对应权限为 ACCESS_FINE_LOCATION 权限。

3.1.2 代码路径

        Android GNSS接口位置代码目录在 frameworks/base/location 下,有三个目录:java、lib、tests。

Android GNSS 模块分析(一)整体介绍 - App

        java目录下的代码被封装到 framework.jar 中为应用提供接口服务;lib目录下的代码被封装为 com.android.location.provider.jar 包;tests目录中是测试相关代码。

3.1.3 重要接口/方法

        在原生接口中,比较重要的有 LocationManager、LocationProvider、LocationListener、Location等,具体可以参考 Google官方文档(地址:android.location  |  Android Developers)。

Android GNSS 模块分析(一)整体介绍 - App

Android GNSS 模块分析(一)整体介绍 - App

​        这些都是 Google 官方提供的 location 包的功能类。其中最重要的类是 LocationManager,这是整个定位服务的入口类。LocationListener 接口是接收 GNSS 信息的回调接口。

        下面介绍以下 LocationManager 中一些比较重要的方法

        * 获取 LocationManager 对象 —— Context.getSystemService(Context.LOCATION_SERVICE)

        * 获取 LocationProvider —— getBestProvider(Criteria criteria, boolean enabledOnly)

        * 获取位置信息 —— requestLocationUpdates(String provider, long minTimeMs, float minDistanceM, LocationListener listener)

        requestLocationUpdates() 方法的功能是通过给定的参数注册给 Location 服务端,请求位置信息,并且能够持续收到信息回调。

        系统通过这一个函数封装整个注册的过程,下面我们以上述接口参数为例,跟踪接口是如何进行封装的。

        应用调用 requestLocationUpdates() 请求的语句一般如下

requestLocationUpdates(@NonNull String provider, long minTime, float minDistance,
        @NonNull LocationListener listener)
参数解析:
    provider:位置提供者的名称
    minTime:按配置的时间间隔提供位置数据,单位是 毫秒
    minDistance:按移动的距离提供位置数据,单位是 米
    listener:回调接口,位置更新是被调用
requestLocationUpdates(@NonNull String provider, long minTime, float minDistance,
            @NonNull PendingIntent intent)
参数解析:
	provider:位置提供者的名称
	minTime:按配置的时间间隔提供位置数据,单位是 毫秒
	minDistance:按移动的距离提供位置数据,单位是 米
	intent:Framework通过此PendingIntent返回携带location的位置数据,通过send()触发

(frameworks/base/location/java/android/location/LocationManager.java)

        总体来说有这两种,区别在于监听位置的回调对象一个是 LocationListener,另一个是 PendingIntent。当然, Framework 在 reportLocation 通知应用的时候,也会在这里判断,是通过哪种方式通知上层。

        在 LocationManager 中有很多 requestLocationUpdates() 请求方法的重载,重载之间有嵌套调用,那么在最后还是有一个重载去调用到 Framework 服务中去。如下:

private void requestLocationUpdates(LocationRequest request, LocationListener listener,
            Looper looper, PendingIntent intent) {

        String packageName = mContext.getPackageName();

        // wrap the listener class
        // ListenerTransport 是内部类,继承自 ILocationListener.Stub,是 ILocationListener.aidl 的实现,内部封装了对外提供的接口 LocationListener;Framework 层的回调会先调用到 ListenerTransport,再通过 ListenerTransport 内部保存的应用实现的 LocationListener 对象通知到应用端。
        ListenerTransport transport = wrapListener(listener, looper);

        try {
            mService.requestLocationUpdates(request, transport, intent, packageName);
       } catch (RemoteException e) {
           throw e.rethrowFromSystemServer();
       }
    }

(frameworks/base/services/core/java/com/android/server/LocationManagerService.java)

        我们主要来看下调用到服务端的参数构成,有哪些比较重要的结构组成。

参数一 LocationRequest

        LocationRequest 是一个数据对象,表明你所要请求位置服务的要求,例如精确度、按时间回调、按距离回调等。基本是通过其 静态方法 createFromDeprecatedProvider() 去创建对象,传入对象包括:provider、minTime、minDistance、singleShot(在 requestLocationUpdates 的调用中传入的均是 false)。

参数二 ListenerTransport

        ListenerTransport 是 LocationManager 的内部类,继承自 ILocationListener.Stub,是 ILocationListener.aidl 的实现,内部封装了对外提供的接口 LocationListener;Framework 层的回调会先调用到 ListenerTransport,再通过 ListenerTransport 内部保存的应用实现的 LocationListener 对象通知到应用端。

参数三 PendingIntent

        PendingIntent 是应用端调用 requestLocationUpdates 函数传过来的,如果有 PendingIntent 的话,代表应用通过 PendingIntent 接收回调

参数四 PackageName

        PackageName 表示函数调用方的包名

3.1.4 API 使用简单示例

        * 在应用的 AndroidManifest.xml 中添加权限

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

        * 设置位置监听

private LocationListener locationListener = new LocationListener() {
        // 位置变化时触发
        public void onLocationChanged(Location location) {
            mLocation = location;
            Log.i(TAG, "时间" + location.getTime());
            Log.i(TAG, "经度" + location.getLongitude());
            Log.i(TAG, "纬度" + location.getLatitude());
            Log.i(TAG, "海拔" + location.getAltitude());
        }

        // GPS 状态变化时触发
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
                case LocationProvider.AVAILABLE: {
                    Log.i(TAG, "当前 GPS 状态为 可见");
                    break;
                }
                case LocationProvider.OUT_OF_SERVICE: {
                    Log.i(TAG, "当前 GPS 状态为 超出服务区");
                    break;
                }
                case LocationProvider.TEMPORARILY_UNAVAILABLE: {
                    Log.i(TAG, "当前 GPS 状态为 暂停服务");
                    break;
                }
            }
        }

        // GPS 开启时触发
        public void onProviderEnable(String provider) {
            if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                mContext.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1000);
            }

            if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                mContext.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1001);
            }
            Location location = mLocationManager.getLastKnownLocation(provider);
            mLocation = location;

        }

        // GPS 禁用时触发
        public void onPorviderDisabled(String provider) {
            mLocation = null;
        }
    };

        * 配置定位请求 getCriteria()

private static Criteria getCriteria() {
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE); // 设置定位精确度,ACCURACY_COARSE比较粗略;ACCURACY_FINE比较精确
        criteria.setSpeedAccuracy(0); // 设置是否要求速度
        criteria.setCostAllowed(false); // 设置是否允许运行商收费
        criteria.setBearingAccuracy(0); // 设置是否需要方位信息
        criteria.setAltitudeRequired(false); // 设置是否需要海拔信息
        criteria.setPowerRequirement(Criteria.POWER_LOW); // 设置对电源的需求
        return criteria;
    }

        * 获取 LocationManager 位置信息

LocationManager mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

// 为获取地理位置信息时设置查询条件
String bestProvider = mLocationManager.getBestProvider(getCriteria(), true);
Log.e(TAG,"bestProvider = " + bestProvider);

// 获取当前位置
Location location = mLocationManager.getLastKnownLocation(bestProvider);
Log.e(TAG,"getLastKnownLocation = " + location);

// 调用位置请求函数,持续请求位置信息
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,1,locationListener);

        以上步骤是应用触发位置请求流程的基本步骤。

下一篇:Android GNSS 模块分析(二)Framework 层

如果文中有错,烦请告知作者,必当有则改之,无则加勉。在此,小弟先行告谢!

 联系作者:文章来源地址https://www.toymoban.com/news/detail-408642.html

到了这里,关于Android GNSS 模块分析(一)整体介绍 - App的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android T 远程动画显示流程其一——整体流程以及堆栈介绍

    本地动画和远程动画区别是什么? 本地动画:自给自足。对自身SurfaceControl矢量动画进行控制。 远程动画:拿来吧你!一个app A对另一个app B通过binder跨进程通信,控制app B的SurfaceControl矢量动画。 无论是本地动画还是远程动画,都仅仅只是对SurfaceControl动画图层控制,而无法控

    2024年04月11日
    浏览(80)
  • 《Git入门实践教程》前言+目录

    版本控制系统(VCS)在项目开发中异常重要,但和在校大学生的交流中知道,这个重要方向并未受到重视。具备这一技能,既是项目开发能力的体现,也可为各种面试加码。在学习体验后知道,Git多样化平台、多种操作方式、丰富的资源为业内人士提供了方便的同时,也造成

    2024年02月10日
    浏览(56)
  • FPGA学习实践之旅——前言及目录

    很早就有在博客中记录技术细节,分享一些自己体会的想法,拖着拖着也就到了现在。毕业至今已经半年有余,随着项目越来越深入,感觉可以慢慢进行总结工作了。趁着2024伊始,就先开个头吧,这篇博客暂时作为汇总篇,记录在这几个月以及之后从FPGA初学者到也算有一定

    2024年02月03日
    浏览(44)
  • GNSS定位模块串口配置说明,亲测(使用ATGM332D模块,通用)

    CAS00-设置保存配置指令 拓展指令只有当前上电有效,重启后恢复默认。如果想要配置一次永久生效,可使用该指令。 例:$PCAS00*01 0x24,0x50,0x43,0x41,0x53,0x30,0x30,0x2A,0x30,0x31, 0x0D,0x0A CAS01-设置串口波特率 两种方案: 1、先用9600波特率配置波特率,然后重新初始化串口即可; 2、生

    2023年04月11日
    浏览(46)
  • 【PCL自学:目录】PCL简介及主要功能模块介绍 (持续更新)

    当你知道一切都不重要时,世界就是你的了。 ——《瑞克和莫蒂》S3E8   对于从事计算机视觉、机器视觉领域的从业者来说,OpenCV库并不陌生,甚至是我们入门这个领域时的学习的第一个开源库,如果说OpenCV是二维信息处理方面的工兵铲,那PCL(Point Cloud Library)就是在三维

    2024年02月06日
    浏览(37)
  • 【Nuxt3】modules目录和nuxt3模块的简单介绍

    记录下nuxt3项目中module的用法 使用 modules/ 目录在应用程序中自动注册本地模块。 这是一个很好的地方,可以放置您在构建应用程序时开发的任何本地nuxt模块。 nuxt模块相当于npm包,可以发布到npm社区中 在modules/ 目录下的本地模块,会自动注册模块,无需在 nuxt.config.ts文件中

    2024年04月27日
    浏览(31)
  • GNSS基本概念(7):Android 手机GNSS参数意义(上)

    train/[drive_id]/[phone_name]/ground_truth.csv  - Reference locations at expected timestamps. MessageType  - \\\"Fix\\\", the prefix of sentence. Provider  - \\\"GT\\\", short for ground truth. [Latitude/Longitude]Degrees  - The WGS84 latitude, longitude (in decimal degrees) estimated by the reference GNSS receiver (NovAtel SPAN). When extracting from the NMEA file

    2024年02月10日
    浏览(33)
  • 关于GNSS技术介绍(一)

    GNSS的全称是全球导航卫星系统(Global Navigation Satellite System),它是泛指所有的卫星导航系统,包括全球的、区域的和增强的。GNSS是覆盖全球的自主地利空间定位的卫星系统,用于导航与定位测量,简单来讲,GNSS系统就是利用卫星信号传输实时位置与时间信息,并从而计算得

    2024年02月14日
    浏览(37)
  • Android手机GNSS原始观测量

    随着谷歌开放了Android手机GNSS原始观测值数据获取接口,使得测绘领域中高精数据处理手段如(RTD/RTK/PPP)在智能手机的应用成为了可能,有望进一步提高智能手机的定位性能,使得基于位置服务的体验更好。这篇文章主要对Android手机提供的原始观测值进行简要的介绍,并对它们

    2024年02月09日
    浏览(36)
  • 【物联网】BDS/GNSS 全星座定位导航模块——ATGM332D-5N

    随着科技的不断进步,导航系统已经成为我们日常生活中不可或缺的一部分。传统的导航系统往往只提供基本的地图和路线规划,对于一些特殊需求或个性化定位并不够满足。 全星座定位导航模块 的出现,为我们带来了全新的导航体验。通过结合星座学说和个人特质,这一

    2024年02月05日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包