Android GPS模块学习心得



 

应用程序不能直接创建

LocationManager

实例对象,必须通过调用

Context

getSystemService

法获取,例如:

 

mLocationManager = 

            (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE); 

往下跟踪,如何通过

Context

getSystemService

获取实例的:

 

    private 

LocationManager getLocationManager() { 

        synchronized 

(sSync) 

            if 

(sLocationManager 

== 

null) 

                IBinder 

b

 = ServiceManager.getService(LOCATION_SERVICE); 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ILocationManager 

service

 = ILocationManager.Stub.asInterface(

b

); 

                sLocationManager 

new 

LocationManager(

service

); 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

        return 

sLocationManager; 

 

 

 

 

从这里可以看到,

会创建一个

LocationManager

实例并返回,

并且

LocationManager

通过

IBinder

AIDL

接口

ILocationManager

LocationManagerService

通信。

 

获得

LocationManager

服务实例后,就可以通过调用它的

API

了,

LocationManager

一些

API

说明:

 

public boolean addGpsStatusListener(GpsStatus.Listener listener)

:添加一个监听

GPS

状态的监听器。

 

public void addProximityAlert(double latitude, double longitude, 

        float 

radius, 

long 

expiration, 

PendingIntent 

intent)

:添加一个临近警告。

 

public Location getLastKnownLocation(String provider)

:根据

LocationProvider

获取最近一次已知的

location

信息

 

public void requestLocationUpdates(String provider, 

        long 

minTime, 

float 

minDistance, 

LocationListener 

listener)

通过制定的

LocationProvider

周期性

地获取定位信息,并处罚

listener

对应的触发器。

 

还有其他的一些接口,就不一一介绍了。

 

 

4

JNI

 

JNI

层只有一个文件,起到承上启下的作用。上层承接

Framework

,下层调用

HAL

层具体硬件抽象

实现。

com_android_server_location_GpsLocationProvider

.cpp

 

JNI

重要的回调函数:

 

GpsCallbacks sGpsCallbacks = { 

    sizeof(GpsCallbacks), 

    location_callback, 

    status_callback, 

    sv_status_callback, 

    nmea_callback, 

    set_capabilities_callback, 

    acquire_wakelock_callback, 

    release_wakelock_callback, 

    create_thread_callback, 

}; 

这组回调函数,在初始化的时候,会通过

GpsInterface

接口函数注册到

HAL

层,在

HAL

层中。这组回

 

 

调函数,

通过

JNI

机制,

Framework

层进行通信,

所以在

HAL

层中,

通过调用注册的回调函数,

GPS

数据上报。

 

static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) { 

 

 

 

 

// this must be set before calling into the HAL library 

    if 

(!mCallbacksObj) 

        mCallbacksObj = env->NewGlobalRef(obj); 

 

    if 

(!sGpsInterface) 

        sGpsInterface 

get_gps_interface();         

 

 

 

 

    if 

(!sGpsInterface 

|| 

sGpsInterface->init(&

sGpsCallbacks

) != 0) { 

 

 

 

 

 

 

 

 

 

 

 

 

sGpsInterface = NULL; 

 

 

 

 

 

 

 

 

 

 

 

 

return NULL; 

 

 

 

 

 

 

 

 

    return 

sGpsInterface; 

其中

sGpsInterface->init(&

sGpsCallbacks

)

sGpsCallbacks

回调函数注册到

HAL

层去。

 

 

5

HAL

 

GpsInterface

接口是

gps

模块中最重要的数据结构,它是底层驱动实现的接口,定义在

gps.h

中定义,

然后根据具体的硬件,实现这组接口。在

12007

项目中,这组接口定义如下:

 

static const GpsInterface sLocEngInterface = 

    sizeof(GpsInterface), 

    loc_eng_init, 

    loc_eng_start, 

    loc_eng_stop, 

    loc_eng_cleanup, 

    loc_eng_inject_time, 

    loc_eng_inject_location, 

    loc_eng_delete_aiding_data, 

    loc_eng_set_position_mode, 

    loc_eng_get_extension, 

}; 

JNI

层,

利用

static const GpsInterface* get_gps_interface()

函数获取这组

GpsInterface

接口。

上述的

JNI

层中,

通过

sGpsInterface->init(

&sGpsCallbacks)

来注册

JNI

层的回调函数,

即通过

loc_eng_init

来注册

JNI

层的回调函数。

 

loc_eng_init

是一个非常重要的函数,在该函数中,主要作用如下:

 

a

、注册

sGpsCallbacks

回调函数

 

    loc_eng_data.location_cb    = 

callbacks->location_cb; 

    loc_eng_data.sv_status_cb   = 

callbacks->sv_status_cb; 

    loc_eng_data.status_cb      = 

callbacks->status_cb; 

    loc_eng_data.nmea_cb        = 

callbacks->nmea_cb; 

    loc_eng_data.acquire_wakelock_cb = callbacks->acquire_wakelock_cb; 

 

loc_eng_data.release_wakelock_cb = callbacks->release_wakelock_cb; 

b

、在

loc_api_glue_init

中创建一个

RPC client

通讯,获取底层

GPS

数据

 

c

、创建处理

GPS

数据的线程

 

loc_eng_data.deferred_action_thread = callbacks->create_thread_cb("loc_api", 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

loc_eng_process_deferred_action

, NULL); 

loc_eng_process_deferred_action

专门用来处理

GPS

数据。

 

进入

loc_eng_process_deferred_action

中的

loc_eng_process_loc_event

处理函数,分析一下

position

数据上报的流程:

 

 

static void loc_eng_process_loc_event (rpc_loc_event_mask_type loc_event, 

        rpc_loc_event_payload_u_type* 

loc_event_payload) 

if (loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT) 

loc_eng_report_position

 

(&(loc_event_payload->rpc_loc_event_payload_u_type_u.parsed_location_report)); 

继续往下跟踪

 

static void loc_eng_report_position (const rpc_loc_parsed_position_s_type *location_report_ptr) 

    loc_eng_data.

location_cb 

(&location); 

loc_eng_data.location_cb

调用这个函数的时候相当于真正调的是

JNI

注册到

hal

的函数,通过这种方式就

实现了

jni

hal

的数据传递。

loc_eng_data.location_cb

就是

JNI

层的回调函数

location_callback

 

 

6

GPS

数据上传流程

 

应用通过

GPS

服务的

getLastKnownLocation

方法获得最近一次已知的

Location

信息,这

Location

信息是如何从底层往上传递而来的呢?下面以

Location

为例,分析从底层数据往上传递,一直到应用通过

getLastKnownLocation

获得最近信息的整个流程。

 

从上述

HAL

层的分析,数据通过

loc_eng_data.location_cb (&location)

,也就是通过

JNI

层的回调函

location_callback

将数据上报到

JNI

层,看一下

JNI

location_callback

具体代码:

 

static void location_callback(GpsLocation* location) 

    JNIEnv* 

env 

AndroidRuntime::getJNIEnv(); 

    env->CallV

oidMethod(mCallbacksObj, 

method_reportLocation

, location->flags, 

            (jdouble)location->latitude, (jdouble)location->longitude, 

            (jdouble)location->altitude, 

            (jfloat)location->speed, 

(jfloat)location->bearing, 

            (jfloat)location->accuracy, (jlong)location->timestamp); 

    checkAndClearExceptionFromCallback(env, 

__FUNCTION__); 

再看一下

JNI

初始化语句:

 

static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz){ 

method_reportLocation

 = env->GetMethodID(clazz, "

reportLocation

", "(IDDDFFFJ)V"); 

 

从中可以看出,通过

JNI

方法,将数据上报到

GpsLocationProvider. reportLocation

,完成了数据从

C/C++

上报到

Java

层的过程。

 

分析

GpsLocationProvider. reportLocation

函数:

 

private void reportLocation(int flags, double latitude, double longitude, double altitude, 

 

 

 

 

 

 

 

 

 

 

 

 

float speed, float bearing, float accuracy, long timestamp){ 

 try 

mLocationManager. reportLocation

(mLocation, false); 

catch (RemoteException e) { 

Log.e(TAG

, "RemoteException calling reportLocation"); 

 

 

 

 

 

GpsLocationProvider. reportLocation

中,调用了成员变量

mLocationManager

reportLocation

方法。

 

mLocationManager

是什么呢?我们来看

GpsLocationProvider

的构造函数

 

public GpsLocationProvider(Context context, ILocationManager locationManager) { 

mContext = context; 

mLocationManager

 = locationManager; 

… 

再看

GpsLocationProvider

创建实例的地方,

LocationManagerService

类中创建实例

GpsLocationProvider

 

 private void _loadProvidersLocked() { 

 

    if 

(GpsLocationProvider.isSupported()) 

 

GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext,

this

); 

addProvider(gpsProvider); 

updateProvidersLocked(); 

}  

可以看出,

GpsLocationProvider

中的

mLocationManager

LocationManagerService

的引用,所以

 

mLocationManager

reportLocation

方法是

LocationManagerService

reportLocation

方法,

具体定义如下:

 

public void reportLocation(Location location, boolean passive) { 

mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location); 

Message m = Message.obtain(mLocationHandler, 

MESSAGE_LOCATION_CHANGED

, location); 

m.arg1 = (passive ? 1 : 0); 

mLocationHandler.sendMessageAtFrontOfQueue(m); 

mLocationHandler

发了一条消息

MESSAGE_LOCATION_CHANGED

mLocationHandler

处理消息如下:

 

 

private class LocationWorkerHandler extends Handler { 

  @Override 

 

 

public void handleMessage(Message msg) { 

 

 

 

try { 

    if 

(msg.what 

== 

MESSAGE_LOCATION_CHANGED) 

 

 

 

 

… 

 

 

 

 

 

handleLocationChangedLocked

(location, passive); 

 

 

 

 

 

  

 

… 

调用了

handleLocationChangedLocked

方法如下:

 

private void handleLocationChangedLocked(Location location, boolean passive) { 

 Location 

lastLocation

 = mLastKnownLocation.get(provider); 

 

if (lastLocation == null) { 

 

 

mLastKnownLocation

.put(provider, new Location(location)); 

 

} else { 

 

 

lastLocation

.set(location); 

 } 

最终将

Location

信息添加到

mLastKnownLocation

中,到这里

Location

信息上报流程基本结束了,再从应用层

看,

LocationManager.getLastKnownLocation

是如何获得

Location

信息的。

 

public Location getLastKnownLocation(String provider) { 

 

 

 

 

… 

return 

mService.getLastKnownLocation

(provider); 

… 

getLastKnownLocation

调用

LocationManager

的成员变量

mService

getLastKnownLocation

方法,

Context

的方法

getSystemService

获取

LocationManager

实例可知,

mService

LocationManagerService

的引用,所以通过

LocationManagerService

getLastKnownLocation

方法获得

Location

信息:

 

public Location getLastKnownLocation(String provider) { 

Location loc = 

_getLastKnownLocationLocked

(provider); 

return loc 

private Location _getLastKnownLocationLocked(String provider) { 

Location loc = 

mLastKnownLocation.get

(provider); 

return loc 

Location

信息最终是从

mLastKnownLocation

中获得,而通过上面数据上报的分析可知,

Location

信息最终也

是上报到

mLastKnownLocation

表中,到此,

Location

信息从底层上报,一直到应用层获得

Location

信息的流

程分析完毕。

 

其流程图如下:

 

应用程序不能直接创建

LocationManager

实例对象,必须通过调用

Context

getSystemService

法获取,例如:

 

mLocationManager = 

            (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE); 

往下跟踪,如何通过

Context

getSystemService

获取实例的:

 

    private 

LocationManager getLocationManager() { 

        synchronized 

(sSync) 

            if 

(sLocationManager 

== 

null) 

                IBinder 

b

 = ServiceManager.getService(LOCATION_SERVICE); 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ILocationManager 

service

 = ILocationManager.Stub.asInterface(

b

); 

                sLocationManager 

new 

LocationManager(

service

); 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

        return 

sLocationManager; 

 

 

 

 

从这里可以看到,

会创建一个

LocationManager

实例并返回,

并且

LocationManager

通过

IBinder

AIDL

接口

ILocationManager

LocationManagerService

通信。

 

获得

LocationManager

服务实例后,就可以通过调用它的

API

了,

LocationManager

一些

API

说明:

 

public boolean addGpsStatusListener(GpsStatus.Listener listener)

:添加一个监听

GPS

状态的监听器。

 

public void addProximityAlert(double latitude, double longitude, 

        float 

radius, 

long 

expiration, 

PendingIntent 

intent)

:添加一个临近警告。

 

public Location getLastKnownLocation(String provider)

:根据

LocationProvider

获取最近一次已知的

location

信息

 

public void requestLocationUpdates(String provider, 

        long 

minTime, 

float 

minDistance, 

LocationListener 

listener)

通过制定的

LocationProvider

周期性

地获取定位信息,并处罚

listener

对应的触发器。

 

还有其他的一些接口,就不一一介绍了。

 

 

4

JNI

 

JNI

层只有一个文件,起到承上启下的作用。上层承接

Framework

,下层调用

HAL

层具体硬件抽象

实现。

com_android_server_location_GpsLocationProvider

.cpp

 

JNI

重要的回调函数:

 

GpsCallbacks sGpsCallbacks = { 

    sizeof(GpsCallbacks), 

    location_callback, 

    status_callback, 

    sv_status_callback, 

    nmea_callback, 

    set_capabilities_callback, 

    acquire_wakelock_callback, 

    release_wakelock_callback, 

    create_thread_callback, 

}; 

这组回调函数,在初始化的时候,会通过

GpsInterface

接口函数注册到

HAL

层,在

HAL

层中。这组回

 

 

调函数,

通过

JNI

机制,

Framework

层进行通信,

所以在

HAL

层中,

通过调用注册的回调函数,

GPS

数据上报。

 

static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) { 

 

 

 

 

// this must be set before calling into the HAL library 

    if 

(!mCallbacksObj) 

        mCallbacksObj = env->NewGlobalRef(obj); 

 

    if 

(!sGpsInterface) 

        sGpsInterface 

get_gps_interface();         

 

 

 

 

    if 

(!sGpsInterface 

|| 

sGpsInterface->init(&

sGpsCallbacks

) != 0) { 

 

 

 

 

 

 

 

 

 

 

 

 

sGpsInterface = NULL; 

 

 

 

 

 

 

 

 

 

 

 

 

return NULL; 

 

 

 

 

 

 

 

 

    return 

sGpsInterface; 

其中

sGpsInterface->init(&

sGpsCallbacks

)

sGpsCallbacks

回调函数注册到

HAL

层去。

 

 

5

HAL

 

GpsInterface

接口是

gps

模块中最重要的数据结构,它是底层驱动实现的接口,定义在

gps.h

中定义,

然后根据具体的硬件,实现这组接口。在

12007

项目中,这组接口定义如下:

 

static const GpsInterface sLocEngInterface = 

    sizeof(GpsInterface), 

    loc_eng_init, 

    loc_eng_start, 

    loc_eng_stop, 

    loc_eng_cleanup, 

    loc_eng_inject_time, 

    loc_eng_inject_location, 

    loc_eng_delete_aiding_data, 

    loc_eng_set_position_mode, 

    loc_eng_get_extension, 

}; 

JNI

层,

利用

static const GpsInterface* get_gps_interface()

函数获取这组

GpsInterface

接口。

上述的

JNI

层中,

通过

sGpsInterface->init(

&sGpsCallbacks)

来注册

JNI

层的回调函数,

即通过

loc_eng_init

来注册

JNI

层的回调函数。

 

loc_eng_init

是一个非常重要的函数,在该函数中,主要作用如下:

 

a

、注册

sGpsCallbacks

回调函数

 

    loc_eng_data.location_cb    = 

callbacks->location_cb; 

    loc_eng_data.sv_status_cb   = 

callbacks->sv_status_cb; 

    loc_eng_data.status_cb      = 

callbacks->status_cb; 

    loc_eng_data.nmea_cb        = 

callbacks->nmea_cb; 

    loc_eng_data.acquire_wakelock_cb = callbacks->acquire_wakelock_cb; 

 

loc_eng_data.release_wakelock_cb = callbacks->release_wakelock_cb; 

b

、在

loc_api_glue_init

中创建一个

RPC client

通讯,获取底层

GPS

数据

 

c

、创建处理

GPS

数据的线程

 

loc_eng_data.deferred_action_thread = callbacks->create_thread_cb("loc_api", 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

loc_eng_process_deferred_action

, NULL); 

loc_eng_process_deferred_action

专门用来处理

GPS

数据。

 

进入

loc_eng_process_deferred_action

中的

loc_eng_process_loc_event

处理函数,分析一下

position

数据上报的流程:

 

 

static void loc_eng_process_loc_event (rpc_loc_event_mask_type loc_event, 

        rpc_loc_event_payload_u_type* 

loc_event_payload) 

if (loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT) 

loc_eng_report_position

 

(&(loc_event_payload->rpc_loc_event_payload_u_type_u.parsed_location_report)); 

继续往下跟踪

 

static void loc_eng_report_position (const rpc_loc_parsed_position_s_type *location_report_ptr) 

    loc_eng_data.

location_cb 

(&location); 

loc_eng_data.location_cb

调用这个函数的时候相当于真正调的是

JNI

注册到

hal

的函数,通过这种方式就

实现了

jni

hal

的数据传递。

loc_eng_data.location_cb

就是

JNI

层的回调函数

location_callback

 

 

6

GPS

数据上传流程

 

应用通过

GPS

服务的

getLastKnownLocation

方法获得最近一次已知的

Location

信息,这

Location

信息是如何从底层往上传递而来的呢?下面以

Location

为例,分析从底层数据往上传递,一直到应用通过

getLastKnownLocation

获得最近信息的整个流程。

 

从上述

HAL

层的分析,数据通过

loc_eng_data.location_cb (&location)

,也就是通过

JNI

层的回调函

location_callback

将数据上报到

JNI

层,看一下

JNI

location_callback

具体代码:

 

static void location_callback(GpsLocation* location) 

    JNIEnv* 

env 

AndroidRuntime::getJNIEnv(); 

    env->CallV

oidMethod(mCallbacksObj, 

method_reportLocation

, location->flags, 

            (jdouble)location->latitude, (jdouble)location->longitude, 

            (jdouble)location->altitude, 

            (jfloat)location->speed, 

(jfloat)location->bearing, 

            (jfloat)location->accuracy, (jlong)location->timestamp); 

    checkAndClearExceptionFromCallback(env, 

__FUNCTION__); 

再看一下

JNI

初始化语句:

 

static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz){ 

method_reportLocation

 = env->GetMethodID(clazz, "

reportLocation

", "(IDDDFFFJ)V"); 

 

从中可以看出,通过

JNI

方法,将数据上报到

GpsLocationProvider. reportLocation

,完成了数据从

C/C++

上报到

Java

层的过程。

 

分析

GpsLocationProvider. reportLocation

函数:

 

private void reportLocation(int flags, double latitude, double longitude, double altitude, 

 

 

 

 

 

 

 

 

 

 

 

 

float speed, float bearing, float accuracy, long timestamp){ 

 try 

mLocationManager. reportLocation

(mLocation, false); 

catch (RemoteException e) { 

Log.e(TAG

, "RemoteException calling reportLocation"); 

 

 

 

 

 

GpsLocationProvider. reportLocation

中,调用了成员变量

mLocationManager

reportLocation

方法。

 

mLocationManager

是什么呢?我们来看

GpsLocationProvider

的构造函数

 

public GpsLocationProvider(Context context, ILocationManager locationManager) { 

mContext = context; 

mLocationManager

 = locationManager; 

… 

再看

GpsLocationProvider

创建实例的地方,

LocationManagerService

类中创建实例

GpsLocationProvider

 

 private void _loadProvidersLocked() { 

 

    if 

(GpsLocationProvider.isSupported()) 

 

GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext,

this

); 

addProvider(gpsProvider); 

updateProvidersLocked(); 

}  

可以看出,

GpsLocationProvider

中的

mLocationManager

LocationManagerService

的引用,所以

 

mLocationManager

reportLocation

方法是

LocationManagerService

reportLocation

方法,

具体定义如下:

 

public void reportLocation(Location location, boolean passive) { 

mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location); 

Message m = Message.obtain(mLocationHandler, 

MESSAGE_LOCATION_CHANGED

, location); 

m.arg1 = (passive ? 1 : 0); 

mLocationHandler.sendMessageAtFrontOfQueue(m); 

mLocationHandler

发了一条消息

MESSAGE_LOCATION_CHANGED

mLocationHandler

处理消息如下:

 

 

private class LocationWorkerHandler extends Handler { 

  @Override 

 

 

public void handleMessage(Message msg) { 

 

 

 

try { 

    if 

(msg.what 

== 

MESSAGE_LOCATION_CHANGED) 

 

 

 

 

… 

 

 

 

 

 

handleLocationChangedLocked

(location, passive); 

 

 

 

 

 

  

 

… 

调用了

handleLocationChangedLocked

方法如下:

 

private void handleLocationChangedLocked(Location location, boolean passive) { 

 Location 

lastLocation

 = mLastKnownLocation.get(provider); 

 

if (lastLocation == null) { 

 

 

mLastKnownLocation

.put(provider, new Location(location)); 

 

} else { 

 

 

lastLocation

.set(location); 

 } 

最终将

Location

信息添加到

mLastKnownLocation

中,到这里

Location

信息上报流程基本结束了,再从应用层

看,

LocationManager.getLastKnownLocation

是如何获得

Location

信息的。

 

public Location getLastKnownLocation(String provider) { 

 

 

 

 

… 

return 

mService.getLastKnownLocation

(provider); 

… 

getLastKnownLocation

调用

LocationManager

的成员变量

mService

getLastKnownLocation

方法,

Context

的方法

getSystemService

获取

LocationManager

实例可知,

mService

LocationManagerService

的引用,所以通过

LocationManagerService

getLastKnownLocation

方法获得

Location

信息:

 

public Location getLastKnownLocation(String provider) { 

Location loc = 

_getLastKnownLocationLocked

(provider); 

return loc 

private Location _getLastKnownLocationLocked(String provider) { 

Location loc = 

mLastKnownLocation.get

(provider); 

return loc 

Location

信息最终是从

mLastKnownLocation

中获得,而通过上面数据上报的分析可知,

Location

信息最终也

是上报到

mLastKnownLocation

表中,到此,

Location

信息从底层上报,一直到应用层获得

Location

信息的流

程分析完毕。

 

其流程图如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值