古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。这篇文章主要讲述Android系统服务(SystemService)简介相关的知识,希望能为你提供帮助。
什么是SystemService我们在android开发过程中经常会用到各种各样的系统管理服务,如进行窗口相关的操作会用到窗口管理服务WindowManager,进行电源相关的操作会用到电源管理服务PowerManager,还有很多其他的系统管理服务,如通知管理服务NotifacationManager、振动管理服务Vibrator、电池管理服务BatteryManager…… 这些Manager提供了很多对系统层的控制接口。对于App开发者,只需要了解这些接口的使用方式就可以方便的进行系统控制,获得系统各个服务的信息,而不需要了解这些接口的具体实现方式。而对于Framework开发者,则需要了解这些Manager服务的常用实现模式,维护这些Manager的接口,扩展这些接口,或者实现新的Manager。
文章图片
一个简单的SystemService我们从一个简单的系统服务Vibrator服务来看一下一个系统服务是怎样建立的。
Vibrator服务提供的控制手机振动的接口,应用可以调用Vibrator的接口来让手机产生振动,达到提醒用户的目的。
从Android的官方文档中可以看到Vibrator只是一个抽象类,只有4个抽象接口:
- bstract void cancel() 取消振动
- abstract boolean hasVibrator() 是否有振动功能
- abstract void vibrate(long[] pattern, int repeat) 按节奏重复振动
- abstract void vibrate(long milliseconds) 持续振动
Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);
Vibrator使用起来很简单,我们再来看一下实现起来是不是也简单。
从文档中可以看到Vibrator只是定义在android.os 包里的一个抽象类,在源码里的位置即frameworks/base/core/java/android/os/Vibrator.java,那么应用中实际使用的是哪个实例呢?应用中使用的Vibrator实例是通过Context的一个方法getSystemService(Context.VIBRATOR_SERVICE)获得的,而Context的实现一般都在ContextImpl中,那我们就看一下ContextImpl是怎么实现getSystemService的:
frameworks/base/core/java/android/app/ContextImpl.java
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
frameworks/base/core/java/android/app/SystemServiceRegistry.java
(SystemServiceRegistry是 Android 6.0之后才有的,Android 6.0 之前的代码没有该类,下面的代码是直接写在ContextImpl里的)
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<
?>
fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
SYSTEM_SERVICE_MAP是一个HashMap,通过我们服务的名字name字符串,从这个HashMap里取出一个ServiceFetcher,再return这个ServiceFetcher的getService()。ServiceFetcher是什么?它的getService()又是什么?既然他是从SYSTEM_SERVICE_MAP这个HashMap里get出来的,那就找一找这个HashMap都put了什么。
通过搜索SystemServiceRegistry可以找到如下代码:
private static <
T>
void registerService(String serviceName, Class<
T>
serviceClass,
ServiceFetcher<
T>
serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
这里往SYSTEM_SERVICE_MAP里put了一对String与ServiceFetcher组成的key/value对,registerService()又是从哪里调用的?继续搜索可以发现很多类似下面的代码:
public class SystemVibrator extends Vibrator {
...
}
我们再从SystemVibrator看一下系统的振动控制是怎么实现的。以hasVibrator()为例,这个是查询当前系统是否能够振动,在SystemVibrator中它的实现如下:
public boolean hasVibrator() {
...
try {
return mService.hasVibrator();
} catch (RemoteException e) {
}
...
}
这里直接调用了一个mService.hasVibrator()。mService是什么?哪来的?搜索一下可以发现:
private final IVibratorService mService;
public SystemVibrator() {
...
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("
vibrator"
));
}
mService 是一个IVibratorService,我们先不去管IVibratorService.Stub.asInterface是怎么回事,先看一下IVibratorService是什么。搜索一下代码发现这并不是一个java文件,而是一个aidl文件:
frameworks/base/core/java/android/os/IVibratorService.aidl
AIDL (Android Interface Definition Language) 是Android中的接口定义文件,为系统提供了一种简单跨进程通信方法。
IVibratorService 中定义了几个接口,SystemVibrator中使用的也是这几个接口,包括我们刚才使用的hasVibrator()
interface IVibratorService
{
boolean hasVibrator();
void vibrate(...);
void vibratePattern(...);
void cancelVibrate(IBinder token);
}
这里又只是接口定义,接口实现在哪呢?通过在frameworks/base目录下进行grep搜索,或者在AndroidXRef搜索,可以发现IVibratorService接口的实现在frameworks/base/services/java/com/android/server/VibratorService.java
public class VibratorService extends IVibratorService.Stub
可以看到 VibratorService实现了IVibratorService定义的所有接口,并通过JNI调用到native层,进行更底层的实现。更底层的实现不是这篇文档讨论的内容,我们需要分析的是VibratorService怎么成为系统服务的。那么VibratorService是怎么注册为系统服务的呢?在SystemServer里面:
VibratorService vibrator = null;
...
//实例化VibratorService并添加到ServiceManager
traceBeginAndSlog("
StartVibratorService"
);
vibrator = new VibratorService(context);
ServiceManager.addService("
vibrator"
, vibrator);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
...
//通知服务系统启动完成
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "
MakeVibratorServiceReady"
);
try {
vibrator.systemReady();
} catch (Throwable e) {
reportWtf("
making Vibrator Service ready"
, e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
这样在SystemVibrator里就可以通过下面的代码连接到VibratorService,与底层的系统服务进行通信了:
IVibratorService.Stub.asInterface(ServiceManager.getService("
vibrator"
));
mService相当于IVibratorService在应用层的一个代理,所有的实现还是在SystemServer的VibratorService里。
看代码时可以发现registerService是在static代码块里静态调用的,所以getSystemServcr获得的各个Manager也都是单例的。
System Service实现流程从上面的分析,我们可以总结出Vibrator服务的整个实现流程:
- 定义一个抽象类Vibrator,定义了应用中可以访问的一些抽象方法
frameworks/base/core/java/android/os/Vibrator.java
- 定义具体的类SystemVibrator继承Vibrator,实现抽象方法
frameworks/base/core/java/android/os/SystemVibrator.java
- 定义一个AIDL接口文件IVibratorService,定义系统服务接口
frameworks/base/core/java/android/os/IVibratorService.aidl
- 定义服务VibratorService,实现IVibratorService定义的接口
frameworks/base/services/java/com/android/server/VibratorService.java
- 将VibratorServicey添加到系统服务
frameworks/base/services/java/com/android/server/SystemServer.java
VibratorService vibrator = null;
...
//实例化VibratorService并添加到ServiceManager
Slog.i(TAG, "
Vibrator Service"
);
vibrator = new VibratorService(context);
ServiceManager.addService("
vibrator"
, vibrator);
...
//通知服务系统启动完成
try {
vibrator.systemReady();
} catch (Throwable e) {
reportWtf("
making Vibrator Service ready"
, e);
}
- 在SystemVibrator中通过IVibratorService的代理连接到VibratorService,这样SystemVibrator的接口实现里就可以调用IVibratorService的接口:
frameworks/base/core/java/android/os/SystemVibrator.java
private final IVibratorService mService;
...
public SystemVibrator() {
...
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("
vibrator"
));
...
public boolean hasVibrator() {
...
try {
return mService.hasVibrator();
} catch (RemoteException e) {
}
...
}
}
- 在Context里定义一个代表Vibrator服务的字符串
frameworks/base/core/java/android/content/Context.java
public static final String VIBRATOR_SERVICE = "
vibrator"
;
- 在ContextImpl里添加SystemVibrator的实例化过程
frameworks/base/core/java/android/app/ContextImpl.java
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new SystemVibrator(ctx);
}});
- 在应用中使用Vibrator的接口
Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);
- 为保证编译正常,还需要将AIDL文件添加到编译配置里
frameworks/base/Android.mk
LOCAL_SRC_FILES += ...
core/java/android/os/IVibratorService.aidl
System Service 新加接口
如果我们需要实现一个新的系统服务,就可以按照上面的步骤在系统中扩展出一个新的服务,并给应用层提供出使用接口。如果想在Vibrator里添加一个新的接口,需要下面3步:
- 在IVibratorService添加接口;
- 在VibratorService添加接口的实现;
- 在Vibrator及SystemVibrator里扩展新的接口;
应用层与 System Service 通信上面的实现我们看到的只是从应用层通过服务代理,调用系统服务的接口,如果我们想反过来,将系统服务的状态通知给应用层,该怎么做呢?
- 方法一:使用Broadcast
- 方法二:使用AIDL
//获得定位服务
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
//定义定位监听器
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
//监听到位置信息
}
...
};
//注册监听器
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
0, 0, locationListener);
从上面的代码可以看到,我们创建了一个位置监听器LocationListener,并将这个监听器在LocationManager里进行了注册。当系统定位到系统的位置后,就会回调监听器的onLocationChanged(),将位置信息通知给监听器。LocationListener就是一个系统服务调用应用层接口的例子,我们就研究一下LocationListener的实现方式。
我们先从LocationManager怎么注册LocationListener开始研究:
frameworks/base/location/java/android/location/LocationManager.java
private final ILocationManager mService;
...
private void requestLocationUpdates(LocationRequest request,
LocationListener listener, Looper looper, PendingIntent intent) {
...
// wrap the listener class
ListenerTransport transport = wrapListener(listener, looper);
try {
mService.requestLocationUpdates(request, transport,
intent, packageName);
} catch (RemoteException e) {
Log.e(TAG, "
RemoteException"
, e);
}
}
可以看到LocationListener被重新封装成了一个ListenerTransport,然后传递给了ILocationManager ,从前面的分析可以猜测到这个ILocationManager应该就是LocationManagerService的一个代理。那么ListenerTransport又是什么呢?搜索LocationManager.java可以找到:
private class ListenerTransport extends ILocationListener.Stub {
...
@Override
public void onLocationChanged(Location location) {
...
}
}
原来是ILocationListener.Stub的一个继承实现,那么ILocationListener应该就是一个AIDL接口定义:
frameworks/base/location/java/android/location/ILocationListener.aidl
oneway interface ILocationListener
{
void onLocationChanged(in Location location);
...
}
而在LocationManagerService里只要调用ILocationListener的方法就可以将消息传递给应用层的监听:
mListener.onLocationChanged(new Location(location));
实现 System Service 的注意事项
- 注意防止阻塞
应用层访问系统服务提供的接口时会有两种情况:
【Android系统服务(SystemService)简介】另一种是调用端不需要等待服务端返回结果,调用完成后直接返回void,这样服务端发生阻塞不会影响到应用端,这样的单向的接口在AIDL里定义时需要添加oneway关键字,如:
oneway void statusBarVisibilityChanged(int visibility);
对于需要在服务端调用,在应用端实现的接口,考虑到系统的稳定性以及安全性,一般都会设计成上面的第二种,即AIDL里所有的接口都是单向的,如上面的ILocationListener
oneway interface ILocationListener
- 注意多线程访问
一种是通过同步锁机制,锁住一个对象实例(一般是这个服务对象本身),这样这个服务同一时间只能响应一个访问请求,如LocationManagerService里:
public boolean callStatusChangedLocked(...) {
...
synchronized (this) {
...
}
}
另一种方法就是使用Handler机制,这种服务一般会创建一个单独的线程,当有应用端访问请求到来时会向服务线程的Handler里发送一个Message,利用单线程顺序执行的特性,保证所有的访问都按顺序进行处理,但这种方法只适合单向的访问,不适合需要返回的双向访问。
推荐阅读
- Spring Data JPA中的mappedBy
- android获取数据库查询的结果
- Android按钮单击事件的五种实现方式
- 增强现实(AR)(趋势,框架和工具)
- 9个最佳工具,可从iPhone和iPad恢复数据
- 10部让你安心的最佳室内家用安全摄像机
- 9种加密货币钱包可安全存储你的加密货币
- 如何为移动用户优化你的网站()
- 如何不管理你的远程开发人员团队