下面这个程序在会监听GPS 开启,关闭,位置改变,
- public class MainActivity extends Activity implements LocationListener {
- /** Called when the activity is first created. */
- private final static String TAG = "LocationTest";
- TextView tv;
- Button btn;
- private LocationManager lm;
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- // 与Location_service建立连接
- lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- // 注册activity到监听队列中
- lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1l, 1l, this);
- }
- // Location发生变化时会调用这个
- public void onLocationChanged(Location location) {
- Log.d(TAG, "location: " + location);
- }
- // 关闭GPS卫星会调用这个
- public void onProviderDisabled(String provider) {
- Log.d(TAG, "provider disable" + provider);
- }
- // 启用GPS卫星会调用这个
- public void onProviderEnabled(String provider) {
- Log.d(TAG, "provider enable");
- }
- public void onStatusChanged(String provider, int status, Bundle extras) {
- Log.d(TAG, "status changed status = " + status);
- }
- }
使用GPS 需要这个权限:
< uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" >
</ uses-permission >
使用GPS 相关的资源,需要先用getSystemService 获得一个LOCATION_SERVICE 的实例,获得这个实例之后就可以进行相关操作了。
@frameworks/base/services/java/com/android/server/SystemServer.java
LOCATION_SERVICE 是在SystemServer.java 中启动的,也就是系统启动之后,这个服务就已经启动了:
ServiceManager.addService(Context.LOCATION_SERVICE, new LocationManagerService(context));
源码结构
主要分为四部分,client ,service ,jni ,hardware
frameworks/base/location/* (client 部分)
frameworks/base/services/java/com/android/serverLocationManagerService.java (server 部分)
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp (JNI 部分)
hardware/libhardware_legacy/gps/* (hardware 接口部分)
1. frameworks/base/location/java (Client 部分)
.
├── android
│ └── location
│ ├── Address.aidl
│ ├── Address.java 描述地理位置信息
│ ├── Criteria.aidl
│ ├── Criteria.java 定位提供商的应用标准
│ ├── Geocoder.java 地理编码,好像是定位信息转换用的
│ ├── GpsSatellite.java 描述当前GPS satellite 信息
│ ├── GpsStatus.java 描述当前GPS engine 信息
│ ├── IGeocodeProvider.aidl
│ ├── IGpsStatusListener.aidl
│ ├── IGpsStatusProvider.aidl
│ ├── ILocationListener.aidl
│ ├── ILocationManager.aidl
│ ├── ILocationProvider.aidl
│ ├── INetInitiatedListener.aidl
│ ├── Location.aidl
│ ├── Location.java 描述定位的详细信息经度,纬度等等
│ ├── LocationListener.java 监听定位服务
│ ├── LocationManager.java 用来访问定位服务AIDL
│ ├── LocationProvider.java 定位提供者信息
│ └── package.html
└── com
└── android
└── internal
└── location
├── DummyLocationProvider.java
├── GpsLocationProvider.java
├── GpsNetInitiatedHandler.java
├── GpsXtraDownloader.java
├── LocationProviderProxy.java
├── MockProvider.java
└── NmeaParser.java
2. frameworks/base/services/java/com/android/server/ LocationManagerService.java (server 部分)
3. frameworks/base/core/jni/android_location_GpsLocationProvider.cpp (JNI 部分)
4. (hardware 接口部分)
hardware/libhardware_legacy/gps.h
hardware/libhardware_legacy/gps_ni.h
hardware/libhardware_legacy/gps/*
.
├── Android.mk
├── gps.cpp
└── gps_qemu.c
代码分析
1. 控制通道,也就是由app 层发起的比如enable 或disable 的控制命令,这个在”设置/ 位置和安全设置/ 使用GPS 卫星”里面设置。
LocationManager.java 主要负责通信。具体的实现在LocationManagerService.java 中,通过AIDL 实现通信,接口文件是ILocationManager.aidl 。在LocationManagerService 在初始化的时候,会判断是否有GPS 设备,如果存在则创建了一个GpsLocationProvider.java ,并通过JNI 调 android_location_GpsLocationProvider.cpp ,该文件再通过GPSInterface 来调用硬件的具体实现代码。
2. enable 后的Location 数据和状态上报。对于数据的上报过程,主要就是关注几个callback 函数。主要代码分析如下:
在 GpsLocationProvider.java 文件中enable() 一个GpsLocationProvider 时,会启动一个 GpsEventThread, 该线程主要就是调用了native_wait_for_event(); 通过JNI 调用到了android_location_GpsLocationProvider_wait_for_event()@ anroid_location_GpsLocationProvider.cpp ,而该event的触发是由来自硬件驱动 Location 数据包的上报,底层的硬件驱动程序会把raw gps data 通过串口或其他的方式送出来,这个要看gps 驱动的实现了,我们通过自己实现的GpsInterface 来解析raw gps data 并调用loaction_callback() 来触发event 并copy Location 数据,等待到event 后再调用GpsLocationProvider.java 中的reportLocation() 上报Location.
另外一部分就是hardware/libhardware_legacy/gps 部分的实现,这个主要就是实现gps.h 里面的几个数据结构:
- const void* (*get_extension)(const char* name);
- } GpsInterface;
- typedef struct {
- uint16_t flags;
- double latitude;
- double longitude;
- double altitude;
- float speed;
- float bearing;
- float accuracy;
- GpsUtcTime timestamp;
- } GpsLocation;
在GpsInterface->init() 的时候要把上层的GpsCallbacks 传进来,然后start 后,从驱动那里poll 获得gps raw data ,并对raw data 进行解析并填充GpsLocation 数据结构,然后调用location_cb 上报location 数据。
- //初始化的时候,得到GpsInterface,调用init,并且设置callback函数:
- static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
- {
- if (!sGpsInterface)