Android6.0 GPS框架分析,如何由APP提供定位信息
一直做车载导航的产品,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