公司项目需要,自定义了一套服务以供多个配置软件的适配需求,这篇文章记录当初学习自定义服务时的代码和理解。
Aidl接口文件
位置:frameworks/base/core/java/android/os/IFeiService.aidl
package android.os;
// create by weiyuanfei
interface IFeiService {
void setVal (String key , String val);
String getVal (String val);
}
接口很简单,定义了2个方法供后续使用,。
另外,需要在frameworks/base/Android.mk里加入IFeiService.aidl
LOCAL_SRC_FILES += \
core/java/android/os/IFeiService.aidl \
使用过aidl的都知道,编译后aidl文件会生成一个同名的java文件,这是aidl技术的核心代码,是binder技术java层的实现。
Aidl生成的java文件
位置:/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IFeiService.java
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/IFeiService.aidl
*/
package android.os;
// create by weiyuanfei
public interface IFeiService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements android.os.IFeiService {
private static final java.lang.String DESCRIPTOR = "android.os.IFeiService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.os.IFeiService interface,
* generating a proxy if needed.
*/
public static android.os.IFeiService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof android.os.IFeiService))) {
return ((android.os.IFeiService) iin);
}
return new android.os.IFeiService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_setVal: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _arg1;
_arg1 = data.readString();
this.setVal(_arg0, _arg1);
reply.writeNoException();
return true;
}
case TRANSACTION_getVal: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.getVal(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements android.os.IFeiService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void setVal(java.lang.String key, java.lang.String val) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(key);
_data.writeString(val);
mRemote.transact(Stub.TRANSACTION_setVal, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.lang.String getVal(java.lang.String val) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(val);
mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void setVal(java.lang.String key, java.lang.String val) throws android.os.RemoteException;
public java.lang.String getVal(java.lang.String val) throws android.os.RemoteException;
}
服务的定义
位置:frameworks/base/services/core/java/com/android/server/FeiService.java
package com.android.server;
import android.content.Context;
import android.os.IFeiService;
import android.os.RemoteException;
import java.util.HashMap;
/**
* Created by weiyuanfei on 17-5-27.
*/
public class FeiService extends IFeiService.Stub {
private static HashMap<String, String> map = new HashMap<String, String>();
public FeiService(Context context) {
}
@Override
public void setVal(String key, String value) throws RemoteException {
map.put(key, value);
}
@Override
public String getVal(String key) throws RemoteException {
return map.get(key);
}
}
FeiService实现之前定义的两个方法,我们需要看到的是FeiService继承了IFeiService.Stub。
定义Service的封装接口Manager
package android.app;
import android.content.Context;
import android.os.IFeiService;
import android.util.Log;
/**
* Created by weiyuanfei on 17-5-27.
*/
public class FeiManager {
IFeiService mService;
public FeiManager(Context ctx, IFeiService service){
mService=service;
}
public void setVal(String key,String value){
try{
mService.setVal(key,value);
}catch(Exception e){
Log.e("FeiManager",e.toString());
e.printStackTrace();
}
}
public String getVal(String key){
try{
return mService.getVal(key);
}catch(Exception e){
Log.e("FeiManager",e.toString());
e.printStackTrace();
}
return null;
}
}
封装了之前在服务端实现的两个方法,注意到方法的调用者是IFeiService,实际上在后续注册服务的时候,我们可以看到并把它理解为服务的本地代理prox。
服务的注册
代码位置:/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
. .....
FeiService mFeiService = null;
.....
traceBeginAndSlog("StartFeiService");
mFeiService = new FeiService(context);
ServiceManager.addService("fei",mFeiService);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
systemserver是启动各个系统服务的地方,系统服务会add到servicemanager,由其管理。
代码位置:frameworks/base/core/java/android/app/SystemServiceRegistry.java
registerService(Context.Fei_Service, FeiManager.class,
new CachedServiceFetcher<FeiManager>() {
@Override
public FeiManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.Fei_Service);
IFeiService service = IFeiService.Stub.asInterface(b);
return new FeiManager(ctx, service);
}});
定义了getsystemservice获得manager的位置
服务名字的定义
frameworks/base/core/java/android/content/Context.java
public static final String Fei_Service = "fei";
SELINUX权限添加
system/sepolicy/service.te
type fei_service, system_api_service, system_server_service, service_manager_type;
system/sepolicy/service_contexts
fei u:object_r:fei_service:s0
需要添加的代码到这里就结束了,编译前需要先 make update-api,然后正常编译即可.
Case验证
FeiManager feimanager;
private static String TAG = "feifei";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
feimanager = (FeiManager) getSystemService("fei");
feimanager.setVal("fan1","lizhi");
feimanager.setVal("fan2","eason");
String test = feimanager.getVal("fan2");
Log.d(TAG, "test = " + test);
}
简单定义了一个activity,调用系统服务FeiManager的setVal和getVal方法,成功的话可以看到打印正常的log.
参考链接:http://gityuan.com/2016/10/01/system_service_common/(两种系统服务的注册方式)
网友评论