欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android6.0 GPS框架分析,如何由APP提供定位信息

程序员文章站 2022-07-01 16:18:30
一直做车载导航的产品,GPS是都有用的,不过基本都是串口的GPS模组,所以也没有怎么去关心过GPS的框架,最近一个客户提出安卓要共享车上已有设备的GPS信息,通过网络连接发送坐标信息过来,所以就对GPS框架大概看了下,简单梳理如下(基于全志T3平台):1、HAL层:android\device\softwinner\t3-common\hardware\gps\gps.c android\hardware\libhardware\include\h......

        一直做车载导航的产品,GPS是都有用的,不过基本都是串口的GPS模组,所以也没有怎么去关心过GPS的框架,最近一个客户提出安卓要共享车上已有设备的GPS信息,通过网络连接发送坐标信息过来,所以就对GPS框架大概看了下,简单梳理如下(基于全志T3平台):

1、HAL层:android\device\softwinner\t3-common\hardware\gps\gps.c

                   android\hardware\libhardware\include\hardware\gps.h

2、JNI: android\frameworks\base\services\core\jni\com_android_server_location_GpsLocationProvider.cpp

               gps.c与GpsLocationProvider.java 沟通的桥梁

3、Framework层及本次实例要关注的文件:

1)、android\frameworks\base\services\core\java\com\android\server\location

         Framework对Location服务的内部实现

        GpsLocationProvider.java

 

 

2)、android\frameworks\base\location\java\android\location\

                这里主要是提供一些供APP调用的功能

                LocationManager.java

                ILocationManager.aidl

 

 

3)、android\frameworks\base\services\core\java\com\android\server\LocationManagerService.java

        这个文件主要是封装了一些Location服务,是对应用的接口

好像应该说GPS框架了,不过这种东西网上太多了,还是自己度吧,人家都写的都比我写的好,所以我这里就偷懒了,我这里直接说一下我用APP接收NMEA数据给系统提供定位信息的过程:

上面提到的gps.c就是GPS模块的HAL层实现,没有几行代码,实现也比较简单,就是实现一个GpsInterface接口,其他的我们基本不用去管,只要实现这个接口的几个函数,把不管任何方式获取的NMEA数据解析后报给系统就可以了,所以我就直接修改这里增加了一个APP给GPS模块写NMEA数据的接口,协议解析还是用他自己的,并且调用这个接口后就把NMEA的获取从串口转过来,忽略串口数据(备注:以下修改红色为新增加的内容

static const GpsInterface  athrGpsInterface = {

       .size =sizeof(GpsInterface),

       .init = athr_gps_init,

       .start = athr_gps_start,

       .stop = athr_gps_stop,

       .cleanup = athr_gps_cleanup,

       .inject_time = athr_gps_inject_time,

       .inject_location = athr_gps_inject_location,

       .delete_aiding_data = athr_gps_delete_aiding_data,

       .set_position_mode = athr_gps_set_position_mode,

       .get_extension = athr_gps_get_extension,

       .nmea_from_app = athr_gps_nmea_from_app, //sunlei

};

 

对应上面gps.c的修改,gps.h对这个结构定义也做对应修改,如下:

/** Represents the standard GPS interface. */

typedef struct {

        /** set to sizeof(GpsInterface) */

        size_t          size;

        ……………………

        /** Get a pointer to extension information. */

        const void* (*get_extension)(const char* name);

      

         /** App write Nmea data to hal, instead of nmea form uart GPS module. */

         const void* (*nmea_from_app)(const char* nmeaStr);//sunlei

} GpsInterface;

修改com_android_server_location_GpsLocationProvider.cpp,增加如下:

//sunlei start

static void android_location_GpsLocationProvider_app_send_nmeaStr(JNIEnv* env, jobject obj,

        jstring nmeaStr)

{

    if (sGpsInterface) { 

           const char *c_nmeaStr = env->GetStringUTFChars(nmeaStr, NULL);

           sGpsInterface->nmea_from_app(c_nmeaStr);

           ALOGD("JNI app_send_nmeaStr:%s", nmeaStr);

           env->ReleaseStringUTFChars(nmeaStr, c_nmeaStr);            

    }   

}

//sunlei end

static JNINativeMethod sMethods[] = {

        /* name, signature, funcPtr */

        {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},

           ……………………

         {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},

         //sunlei note A:@20200715 for app send nmea Str to hal gps module

         {"native_app_send_nmeaStr", "(Ljava/lang/String;)V",(void*)android_location_GpsLocationProvider_app_send_nmeaStr},

           ……………………

};

 

修改GpsLocationProvider.java

//sunlei start

public static void sendNmeaStrToHAL(String nmeaStr) {

        Log.d(TAG, "GpsLocationProvider.java sendNmeaStrToHAL: " + nmeaStr);

        if (nmeaStr != null) {

            native_app_send_nmeaStr(nmeaStr);

        }

 }

 //sunlei end

 

修改LocationManagerService.java在LocationManagerService类中增加以下代码,为应用提供调用接口

//sunlei start

       public void appSendNmeaStr(String nmeaStr) {

              GpsLocationProvider.sendNmeaStrToHAL(nmeaStr);

       }

       //sunlei end

 

修改LocationManager.java,增加如下代码:

//sunlei start

       public void appSendNmeaStr(String nmeaStr) {

              try {

                      mService.appSendNmeaStr(nmeaStr);

              } catch (RemoteException e) {

                     Log.e(TAG, "RemoteException", e);

              }

       }

       //sunlei end

修改ILocationManager.aidl增加如下代码:

void appSendNmeaStr(String nmeaStr);//sunlei

 

以上代码因修改因为我们增加了一个新的系统API,所以要先如下编译:

$: make update-api

$: make –j32; pack

使用我们新译出来的IMG文件烧录后,系统就增加了APP向HAL写入NMEA数据的API,下面就是APP从网络接收数据并下发了

 

应用调用:

    import android.location.LocationManager;

       ……………………

    LocationManager locationManager = (LocationManager)                                                                                                                                                    getApplicationContext().getSystemService(Context.LOCATION_SERVICE);

然后在合适的位置获取NMEA数据并做如下调用:

locationManager.appSendNmeaStr(nmeaStr);

 

如果使用AndroidStudio的话,那么我们新增加的这个API他使用默认的SDK是不能被识别的,解决的方式就是把LocationManager.java编译出来的LocationManager.class替换掉Android\Sdk\platforms\android-26\android.jar里面对应的文件即可,我是直接用WinRAR打开找到对应位置粘贴,自动重新压缩就可以了,LocationManager.clas的位置在:

android/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes/android/location/LocationManager.class

 

没事我也弄了个公众号,目前没有内容啊,后面会陆续放些实用的东西上去,如果有兴趣可以微信搜索  “雷影知识库” 关注,

欢迎技术交流,尤其是搞软件的跟我交流硬件,或者搞硬件的跟我交流软件 ,^_^

本文地址:https://blog.csdn.net/YanLai20/article/details/107387215