当前位置: 移动技术网 > 移动技术>移动开发>Android > Android6.0 GPS框架分析,如何由APP提供定位信息

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

2020年07月17日  | 移动技术网移动技术  | 我要评论

        一直做车载导航的产品,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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网