在开发android app的时候,我们可以使用android自带的一些系统级的服务,例如:
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
不同于android sdk里面的service,这些服务在android底层framework中实现,随系统启动自动启动,上层app可以使用,与android app运行在不同的进程,有些需要在androidManifest.xml中赋予特定的权限才能调用。
有的时候,我们需要定义与开发出自己的系统级service,随系统一起发布。
1. 有些功能本身就是android底层的功能,需要开机自启动,这些功能模块适合做成一个单独的系统级服务,随系统发布,随系统自启动;
2. android SDK是android framework的一个子集,framework的很多api并没有在SDK中开放给用户使用,要使用这一部分功能,往往需要定义出自己的系统级服务来调用这些api;
3.权限问题,android的权限控制很严格,要获取system权限,必须签名,但要获取system更高的权限,就只能定义出自己的系统服务,系统服务拥有较高的权限。
在项目中,我需要定义自己的系统服务ProfileService
1. 首先定义AIDL接口,在源代码frameworks\base\core\java\android\app目录下面,创建文件IProfile.aidl,定义接口:
package android.app;
/**
* System private API for talking with the profile service.
*
* {@hide}
*/
interface IProfile{
String getProp(String prop);
void setProp(String prop, String value);
String getIPAssignment();
void setIPAssignment(String ipAssign);
String getSN(String fileName);
void setSN(String fileName, String newSN);
void startVNCServer(String file);
void poweroffbox();
void poweronbox();
}
2. 修改frameworks\base目录下的Android.mk,在LOCAL_SRC_FILES添加core/java/android/app/IProfile.aidl
3. 在frameworks\base\services\java\com\android\server目录下,新建ProfileService.java,该文件是IProfile.aidl定义的接口的实现,在这个文件里面要对上面定义的接口进行具体的实现
4.在frameworks\base\core\java\android\app目录,新建ProfileManager.java,这是类似于 WifiManager 的实现,其实对ProfileService的一个封装
package android.app;
import android.os.RemoteException;
public class ProfileManager
{
private final IProfile mService;
/**
* package private on purpose
*/
ProfileManager(IProfile service) {
mService = service;
}
public String getProp(String prop) {
try {
return mService.getProp(prop);
}catch(RemoteException ex){
}
return null;
}
public void setProp(String prop, String value) {
try {
mService.setProp(prop,value);
}catch(RemoteException ex) {
}
}
public String getSN(String fileName) {
try {
return mService.getSN(fileName);
}catch(RemoteException ex) {
}
return null;
}
public void setSN(String fileName, String newSN) {
try {
mService.setSN(fileName,newSN);
}catch(RemoteException ex) {
}
}
public void setIPAssignment(String ipAssign) {
try {
mService.setIPAssignment(ipAssign);
}catch(RemoteException ex) {
}
}
public String getIPAssignment() {
try {
return mService.getIPAssignment();
}catch(RemoteException ex){
}
return null;
}
public void startVNCServer(String file) {
try {
mService.startVNCServer(file);
}catch(RemoteException ex) {
}
}
public void poweroffbox() {
try {
mService.poweroffbox();
}catch(RemoteException ex) {
}
}
public void poweronbox() {
try {
mService.poweronbox();
}catch(RemoteException ex) {
}
}
}
5.修改frameworks\base\core\java\android\content目录下的Context.java,增加定义
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.app.profile} for receiving intents at a
* time of your choosing.
*
* @see #getSystemService
* @see android.app.profile
*/
public static final String PROFILE_SERVICE = "profile";
这样修改的目的是为了以后调用Context.PROFILE_SERVICE及为调用ProfileService,是一个包装类
6.修改frameworks\base\services\java\com\android\server目录下的SystemServer.java,增加
Slog.i(TAG, "Profile Service");
profile = new ProfileService(context);
ServiceManager.addService(Context.PROFILE_SERVICE, profile);
将ProfileService增加到ServiceManager中,注册新的系统服务
7.修改的frameworks\base\core\java\android\app目录下的ContextImpl.java,增加
registerService(PROFILE_SERVICE, new StaticServiceFetcher() {
public Object createStaticService() {
IBinder b = ServiceManager.getService(PROFILE_SERVICE);
IProfile service = IProfile.Stub.asInterface(b);
return new ProfileManager(service);
}});
生成新的ProfileManager以便调用
8.最后编译源代码,一般要执行make update-api,编译生成的jar包在\out\target\common\obj\JAVA_LIBRARIES\framework_intermediates下面,提取class.jar导入到上层app工程中,即可在app中调用
ProfileManager profileManager = (ProfileManager)context.getSystemService(Context.PROFILE_SERVICE);