转自http://www.ibm.com/developerworks/cn/opensource/os-cn-android-location/
定位服务是移动设备上最常用的功能之一,下文以 Android 源码为基础,详细分析了 Android 系统中定位服务的架构和实现。 定位服务是 Android 系统提供的一项系统服务,在 Android 系统中,所有系统服务的架构都是类似的。只要明白其中一个,然后再去理解其他是很容易的。 对于 Android 的应用开发人员来说,本文可以帮助他们了解他们所使用的 API 背后的实现。 对于 Android 的系统开发人员来说,本文可以帮助他们更好的了解 Android 系统架构。 关于如何获取 Android 源码,请参阅 Android Source 的官方网站:http://source.android.com/source/downloading.html Android 源码中包含了大量的文件,有些源文件甚至是同名的。为了清楚的指明我们所讨论的文件,本文在提到源码文件的时候都会指明其在 Android 源码树中的路径。
定位服务提供给应用层的 API 位于 android.location 包中,它其中包含的类和接口如表 1 所示:
名称 | 类型 | 说明 |
---|---|---|
GpsStatus.Listener | 接口 | 用于接受 GPS 状态改变时的通知。 |
GpsStatus.NmeaListener | 接口 | 用于接受 Nmea(为海用电子设备制定的格式)信息。 |
LocationListener | 接口 | 用于接受位置信息改变时的通知。 |
Address | 类 | 用于描述地址信息。 |
Criteria | 类 | 用于选择 LocationProvider。 |
Geocoder | 类 | 用于处理地理位置的编码。 |
GpsSatellite | 类 | 用于描述 GPS 卫星的状态。 |
GpsStatus | 类 | 用于描述 GPS 设备的状态。 |
Location | 类 | 用于描述地理位置信息,包括经度,纬度,海拔,方向等信息。 |
LocationManager | 类 | 用于获取和调用定位服务。 |
LocationProvider | 类 | 描述 Location Provider 的超类,Location Provider 是真正用来获取位置信息的组件。Location Provider 的实现主要可以分为两类:一种依赖于 GPS 设备,另一种依赖网络状态。 |
在表 1 中,最重要的类是 LocationManager,这是整个定位服务的入口类。 清单 1 是使用定位服务 API 的代码示例:
public class MainActivity extends Activity { // 测试使用的日志 Tag private static final String TAG = "LocationService API Demo"; // 将在 onCreate 中被初始化 private LocationManager locationManager; // 接受位置更新的监听器 protected final LocationListener locationListener = new LocationListener() { // 当位置发生变化时,输出位置信息 public void onLocationChanged(Location location) { Log.d(TAG, "Location changed to: " + getLocationInfo(location)); } public void onProviderDisabled(String provider) { Log.d(TAG, provider + " disabled."); } public void onProviderEnabled(String provider) { Log.d(TAG, provider + " enabled."); } public void onStatusChanged(String provider, int status, Bundle extras){ Log.d(TAG, provider + " status changed."); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取 LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE); } @Override protected void onResume() { super.onResume(); // 指定一个 Provider String currentProvider = LocationManager.NETWORK_PROVIDER; Log.d(TAG, "CurrentProvider: " + currentProvider); // 获取 Provider 最后一个记录的地址信息 Location lastKnownLocation = locationManager .getLastKnownLocation(currentProvider); if (lastKnownLocation != null) { Log.d(TAG, "LastKnownLocation: " + getLocationInfo(lastKnownLocation)); } else { Log.d(TAG, "Last Location Unkown!"); } // 注册监听器接受位置更新 locationManager.requestLocationUpdates(currentProvider, 0, 0, locationListener); } @Override protected void onPause() { super.onPause(); // 移除监听器 locationManager.removeUpdates(locationListener); Log.d(TAG, "LocationListener: " + locationListener + " removed."); } /** * 将 Location 对象转换成字符串形式方便显示 * * @param location * Location 对象 * @return 字符串形式的表示 */ private String getLocationInfo(Location location) { String info = ""; info += "Longitude:" + location.getLongitude(); info += ", Latitude:" + location.getLatitude(); if (location.hasAltitude()) { info += ", Altitude:" + location.getAltitude(); } if (location.hasBearing()) { info += ", Bearing:" + location.getBearing(); } return info; } } |
这段代码的说明如下: 在 Activity 显示的时候首先尝试获取通过网络定位的 Location Provider 记录的最后一次定位信息,然后在系统中注册一个监听器来监听位置信息的变更,这里的 API 都是使用定位服务最常用的。
整个定位服务的架构如图 1 所示。该结构共分为四层:
- 最上面是应用层,即 android.location 包中包含的内容,是以 Java 语言提供的 API。
- 第二层是框架层,这一层包含了系统服务的实现,主要由 Java 语言来实现。
- 第三层是共享库层,本层由 C 以及 C++ 语言实现 , 框架层与共享库层使用 JNI 进行衔接。
- 最下面一层是 Linux 内核层 , 整个 Android 系统都是以 Linux 内核为基础的。
从上至下它们是逐层依赖的关系,每层依赖下面一层完成其所需提供的服务。
以下是定位服务的架构图
系统的服务的启动与注册
从图 1 中可以看出,在框架层,实现位置服务的类是 LocationManagerService,这是一个系统服务。 那么 LocationManager 和 LocationManagerService 两者是什么关系,它们是如何关联起来的呢? 想要理解这一点就要先介绍一下 Android 中的 Binder 机制。 在 Android 系统中,系统服务运行在一个专门的进程中,这个进程名称为 system_server。该进程在系统启动的时候便被加载和启动。系统中有一个专门用来管理系统服务的类,它叫做 ServiceManager。这个类负责注册并管理所有的系统服务。 当应用程序想要使用系统服务时,需要通过服务的代理来调用服务。由于客户应用程序运行在自己的进程中,这和 system_server 是两个独立的进程,因此代理需要通过进程间通讯将请求发送到 system_server 进程,由该进程来响应服务,然后再返回结果。整个这个机制称之为 Binder 机制。Binder 机制在 Android 系统中应用非常之广,几乎所有的进程间通讯都是使用该进制完成的。
图 2 描述了 Binder 机制的请求和响应过程: