【Android架构GPS篇】之定位数据如何从GPS芯片到应用层

本文介绍了Android系统中GPS定位数据从芯片到应用层的传递过程,涉及应用层的onNmeaReceived()方法、Framework层的GpsStatus.NmeaListener接口、Lib层的JNI交互以及HAL层的串口通信和数据解析。通过分析源码,揭示了NMEA信息如何通过串口和JNI在不同层次间传递。
摘要由CSDN通过智能技术生成

Android:V4.2.2
Source Insight

写在前面

在漫长的Android源码编译等待过程中,想起之前写过一部分的Android定位实现的探究小品,于是继续探究。

:代码都是片段化的代码,用来提纲挈领的说明问题。

定位的基础知识
1、定位芯片和CPU之间通过串口进行通信
2、串口和CPU之间传输的是ASCII格式的NMEA(National Marine Electronics Association)信息,如:

$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F
$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D
$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70
$GPRMC,092204.999,A,4250.5589,S,14718.5084,E,0.00,89.68,211200,,*25

基于以上两点,要探知定位数据从GPS芯片到应用层的流程,最好的途径就是从应用层输出NEMA信息的地方开始。

NMEA资料参见:卫星定位数据NMEA介绍

一、GPS定位的应用层实现

Luckily,在应用层我们可以通过onNmeaReceived()方法获取到NMEA信息,如下Code Fragment:

public class GpsTestActivity extends ActionBarActivity {
	/* Other Codes */
	
	/** 获取系统的定位服务,记得在AndroidManifest中赋予定位方面的权限:
     * <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     * <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
     * <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
	 */
	LocationManager mLocationService = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
	mLocationService.addNmeaListener(mNmeaListener);
	
	private GpsStatus.NmeaListener mNmeaListener = new NmeaListener() {
		@Override
		public void onNmeaReceived(long timestamp, String nmea) {
			System.out.println(nmea + "\n");
		}
	};
} 

二、GPS定位的Framework层实现

GpsStatus.NmeaListener是一个接口类,来自GpsStatus.java文件:

frameworks\base\location\java\android\location\GpsStatus.java
/**
 * Used for receiving NMEA sentences from the GPS.
 * NMEA 0183 is a standard for communicating with marine electronic devices
 * and is a common method for receiving data from a GPS, typically over a serial port.
 * See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
 * You can implement this interface and call {@link LocationManager#addNmeaListener}
 * to receive NMEA data from the GPS engine.
 */
public interface NmeaListener {
	void onNmeaReceived(long timestamp, String nmea);
}
在上述App中,我们的应用程序实现了该方法,一旦NMEA数据到来,onNmeaReceived()方法就被调用一次,我们在Console上可以看到原始的NEMA信息。
那么接下来,就要寻找nmea数据的来源了。

mNmeaListener通过LocationManager类的addNmeaListener()方法进行注册(register):

frameworks\base\location\java\android\location\LocationManager.java
/**
 * Adds an NMEA listener.
 *
 * @param listener a {@link GpsStatus.NmeaListener} object to register
 *
 * @return true if the listener was successfully added
 *
 * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
 */
public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
	boolean result;

	/* mNmeaListeners是LocationManager类的成员变量:
	 * private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
     *      new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>();
	 */
	if (mNmeaListeners.get(listener) != null) {
		// listener is already registered
		return true;
	}
	try {
		GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
		result = mService.addGpsStatusListener(transport);
		if (result) {
			mNmeaListeners.put(listener, transport);
		}
	} catch (RemoteException e) {
		Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
		result = false;
	}

	return result;
}
这里,先检测定义的NmeaListener有没有被注册过,若果没有,注册之。
注册到哪里去了呢?
由mNmeaListeners成员的定义可知,和GpsStatus.NmeaListener进行关联的是GpsStatusListenerTransport,而它是LocationManager类的一个内部类。
只看相关的部分:

// This class is used to send GPS status events to the client's main thread.
private class GpsStatusListenerTransport extends IGpsStatusListener.Stub
  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值