在这篇博文中,我将一步一步建立一个SystemService。
这个系统服务是用于控制收音机的,名字就叫做RadioManagerService。
新建IRadioManager.aidl;
在framework/base/core/java/amdroid/os/中新建IRadioManager.aidl文件。文件的内容如下:
package android.os;
interface IRadioManager{
void test();
}
aidl文件的语法规则可以网上查一下,这里就不做解释了。
将.adil文件名添加到Android.mk脚本中;
上面虽然新建了aidl文件,但是在编译的过程中并不会编译,只有在Android.mk中添加相关说明之后才会编译。
这个Android.mk文件的位置是:frameworks/base/Android.mk
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
#…… 此处省略很多行
com/java/android/os/IRadioManager.aidl
编写Service,实现xxx.stub;
在frameworks/base/services/java/com/android/server/目录下新建RadioManagerService.java。其内容如下:
public class RadioManagerService extends IRadioManager.Stub implements IOnUartMsgListener {
private static final String TAG = "TimothyRadioManagerService";
private Context mContext;
public RadioManagerService(Context context) {
this.mContext = context;
}
@Override
public void test() throws RemoteException {
Log.d(TAG, "test() is called");
}
}
实现Manager,调用Service;
在framework/base/core/java/android/os/目录下新建RadioManager.java,内容如下:
public class RadioManager {
private static final String TAG = "TimothyRadioManager";
private Context mContext;
private IRadioManager mService; // 要调用服务器的接口,首先就要保存服务器的对象。就好比只有知道了找人办事,首先得知道要找的人叫什么。
public RadioManager(Context context, IRadioManager service) {
mContext = context;
mService = service;
}
public void test() {
Log.d(TAG, "test() is called");
mService.test(); // 调用客户端的test()函数,实际上调用的是服务器的test()函数。
}
}
将自定义的服务注册到SystemServer;
在framework/base/services/java/com/android/server/SystemServer.java的initAndLoop()函数里增加声明,并注册Service。
public void initAndLoop() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
SystemClock.uptimeMillis());
Looper.prepareMainLooper();
// 此处省略很多行
Installer installer = null;
AccountManagerService accountManager = null;
ContentService contentService = null;
LightsService lights = null;
PowerManagerService power = null;
// 此处省略很多行
com.android.server.RadioManagerService audioManagerService = null;
// 此处省略很多行
// 找个系统添加其他Service的地方加上下面这些
try {
Slog.i(TAG, "radio service");
radioManagerService = new com.android.server.RadioManagerService(context);
ServiceManager.addService(Context.RADIO_MANAGER_SERVICE, radioManagerService);
} catch (Throwable e) {
reportWtf("starting iflytek radio service", e);
}
}
千万别忘了,在Context中增加RADIO_MANAGER_SERVICE这个常量的定义。
在ContextImpl.java中注册服务;
在framework/base/core/java/android/app/ContextImpl.java中注册其他服务的地方加上下面的代码:
registerService(RADIO_MANAGER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(RADIO_MANAGER_SERVICE);
return new android.os.iflytek.RadioManager(ctx, IRadioManager.Stub.asInterface(b));
}});
当你在使用Context.getSystemService()的时候,代码会走到这里。
结论
到这里,在Android APP中就能通过使用下面的代码调用系统服务:
RadioManager mRadioManager = (RadioManager)getSystemService(Context.RADIO_MANAGER_SERVICE);
mRadioManager.test();
因为改了framework中的代码,增加了接口,在编译的时候,需要先执行
make update-api
之后再make。