Android 搭建系统服务
2015-10-29 15:32
1101 查看
本文以系统中已经有的LightsService为例,逐步讲解在系统中搭建系统服务的过程。有几个前提需要说明:
1.由于系统内部就有LightsService这个类(在原生的代码中,它并不是一个真正的服务,只是一个普通类),所以我们无需再建立此类,并且可以根据此类的内容确定需要提供的服务内容。
2. 此处LightsService中需要提供的服务主要是将Light(内部类)的一些操作提供出去
编写aidl
所有远程服务的开始都是从编写aidl开始,新建一个aidl的了文件LightsManager.aidl,放在framework/base/core/java/android/app目录下。文件里的内容主要如下:
文件里的内容根据LightsService需要提供的服务内容确定。
如果在一般的程序中编写自己的aidl文件后,你需要使用google提供的aidl工具编译生成对应的java文件,然后将java文件加入到项目中。
但是现在我们只需要添加aidl文件,而不用手动生成,因为在系统编译的过程中会自动根据aidl生成对应的java文件。不过这样的前提是,我们需要告诉编译器我们添加了这个文件。我们找到framework/base下的Android.mk文件,并向里面加入下面这行:
生成以后的java文件为ILightsManager.java。因为新添的文件会生成新的api,所以需要更新frameworks/base/api/current.txt。否则在编译的时候会中断,并提示更新。
也可以直接运行:
自动更新此文件,检查确认正确后,跟代码一起提交即可。
关于ILightsManager有几个重要的描述:
ILightsManager是一个接口类,并且继承语android.os.Interface
ILightsManager里面会有一个名叫Stub的内部实现类,该类继承android.os.Binder,后面LightsService将继承于这个类
同时里面还会有一个私有内部实现类Proxy,这个类将作为LightsService的代理在Stub类的asInterface中返回给远程客户端
改写LightsService(服务端)
首先我们要让LightsService继承于ILightsManager.Stub,作为远程服务端。其次我们需要添加一个Light的内部变量,方便直接操作。其次需要将对应的方法都实现一遍:
LightsService实现好以后,还需要将其注册到ServiceManager中,客户端才可以获取到该服务。在SystemServer文件中LightsService初始化后面添加一行。
添加LightsManager(客户端/服务端代理)
在远程服务段搭建好了以后,我们需要搭建客户端LightsManager,在core/java/android/app建立该文件。内容如下:
建立连接
我们常见的获取系统的方法是通过上下文调用getSystemService()获取相应的服务。该方法的实现在ContextImpl中,我们需要将一下代码加入静态块中。
这里将已经与远程服务端建立好连接的客户端的实例注册在ContextImpl的一个HashMap中,后面getSystemService中将从该HashMap取出客户端的实例返回。 到这里为止,我们的服务就搭建好了。
其它注意事项
普通列表项目如果我们的服务需要在其他某些项目启动好以后再执行一些操作,可以在LightService中添加systemReady()方法,让后在所有其他项目都准备好以后在调用该服务的systemReady方法。
新添加的服务的初始化尽量放在别的服务的启动后面
1.由于系统内部就有LightsService这个类(在原生的代码中,它并不是一个真正的服务,只是一个普通类),所以我们无需再建立此类,并且可以根据此类的内容确定需要提供的服务内容。
2. 此处LightsService中需要提供的服务主要是将Light(内部类)的一些操作提供出去
编写aidl
所有远程服务的开始都是从编写aidl开始,新建一个aidl的了文件LightsManager.aidl,放在framework/base/core/java/android/app目录下。文件里的内容主要如下:
interface ILightsManager { void setLight(int light); void setColor(int color); void setFlashing(int color, int mode, int onMS, int offMS); void turnOff(); void stopFlashing(); } }
文件里的内容根据LightsService需要提供的服务内容确定。
如果在一般的程序中编写自己的aidl文件后,你需要使用google提供的aidl工具编译生成对应的java文件,然后将java文件加入到项目中。
但是现在我们只需要添加aidl文件,而不用手动生成,因为在系统编译的过程中会自动根据aidl生成对应的java文件。不过这样的前提是,我们需要告诉编译器我们添加了这个文件。我们找到framework/base下的Android.mk文件,并向里面加入下面这行:
core/java/android/app/ILightsManager.aidl \
生成以后的java文件为ILightsManager.java。因为新添的文件会生成新的api,所以需要更新frameworks/base/api/current.txt。否则在编译的时候会中断,并提示更新。
也可以直接运行:
make update-api
自动更新此文件,检查确认正确后,跟代码一起提交即可。
关于ILightsManager有几个重要的描述:
ILightsManager是一个接口类,并且继承语android.os.Interface
ILightsManager里面会有一个名叫Stub的内部实现类,该类继承android.os.Binder,后面LightsService将继承于这个类
同时里面还会有一个私有内部实现类Proxy,这个类将作为LightsService的代理在Stub类的asInterface中返回给远程客户端
改写LightsService(服务端)
首先我们要让LightsService继承于ILightsManager.Stub,作为远程服务端。其次我们需要添加一个Light的内部变量,方便直接操作。其次需要将对应的方法都实现一遍:
public void setColor(int color) throws RemoteException { if (mLight != null) { mLight.setColor(color); } } public void setFlashing(int color, int mode, int on, int off) throws RemoteException { if (mLight != null) { mLight.setFlashing(color, mode, on, off); } } public void setLight(int light) throws RemoteException { mLight = getLight(light); } public void stopFlashing() throws RemoteException { if (mLight != null) { mLight.stopFlashing(); } } public void turnOff() throws RemoteException { if (mLight != null) { mLight.turnOff(); } }
LightsService实现好以后,还需要将其注册到ServiceManager中,客户端才可以获取到该服务。在SystemServer文件中LightsService初始化后面添加一行。
ServiceManager.addService(Context.LIGHTS_SERVICE, lights);
添加LightsManager(客户端/服务端代理)
在远程服务段搭建好了以后,我们需要搭建客户端LightsManager,在core/java/android/app建立该文件。内容如下:
package android.app; import android.content.Intent; import android.os.RemoteException; import android.util.Log; public class LightsManager { private static final String TAG = "LightsManager"; public static final int LIGHT_ID_BACKLIGHT = 0; public static final int LIGHT_ID_KEYBOARD = 1; public static final int LIGHT_ID_BUTTONS = 2; public static final int LIGHT_ID_BATTERY = 3; public static final int LIGHT_ID_NOTIFICATIONS = 4; public static final int LIGHT_ID_ATTENTION = 5; public static final int LIGHT_ID_BLUETOOTH = 6; public static final int LIGHT_ID_WIFI = 7; public static final int LIGHT_ID_COUNT = 8; public static final int LIGHT_FLASH_NONE = 0; public static final int LIGHT_FLASH_TIMED = 1; public static final int LIGHT_FLASH_HARDWARE = 2; private final ILightsManager mService; /*package private on purpose */ public LightsManager(ILightsManager service) { mService = service; } /* Set the light by light id * eg:LIGHT_ID_BATTERY/LIGHT_ID_NOTIFICATIONS is leds light @param light */ public void setLight(int light) { try { mService.setLight(light); } catch (RemoteException ex) { } } /* Set the light color. The Color is GRB by 16 digits. * * eg: 0xFF0000 is red. @param color */ public void setColor(int color){ try { mService.setColor(color); } catch (RemoteException ex) { } } /* @param color The light color same as setColor @param mode The flash mode. LIGHT_FLASH_NONE,LIGHT_FLASH_TIMED or LIGHT_FLASH_HARDWARE @param onMS The flash time. It's millisecond. eg: 200 @param offMS The flash time interval. It's millisecond. eg: 200 */ public void setFlashing(int color, int mode, int onMS, int offMS){ try { mService.setFlashing(color, mode, onMS, offMS); } catch (RemoteException ex) { } } /* Turn off the light */ public void turnOff(){ try { mService.turnOff(); } catch (RemoteException ex) { } } /* Stop the playing flashing */ public void stopFlashing(){ try { mService.stopFlashing(); } catch (RemoteException ex) { } } }
建立连接
我们常见的获取系统的方法是通过上下文调用getSystemService()获取相应的服务。该方法的实现在ContextImpl中,我们需要将一下代码加入静态块中。
registerService(LIGHTS_SERVICE, new StaticServiceFetcher() { public Object createStaticService() { IBinder b = ServiceManager.getService(LIGHTS_SERVICE); ILightsManager service = ILightsManager.Stub.asInterface(b); return new LightsManager(service); } });
这里将已经与远程服务端建立好连接的客户端的实例注册在ContextImpl的一个HashMap中,后面getSystemService中将从该HashMap取出客户端的实例返回。 到这里为止,我们的服务就搭建好了。
其它注意事项
普通列表项目如果我们的服务需要在其他某些项目启动好以后再执行一些操作,可以在LightService中添加systemReady()方法,让后在所有其他项目都准备好以后在调用该服务的systemReady方法。
新添加的服务的初始化尽量放在别的服务的启动后面
相关文章推荐
- Android padding和margin的区别
- Android源码下载遇到的问题
- Android 数据解析格式和JSON对象
- android音乐播放器监听电话状态,解决通话中的音乐的播放
- Android Studio 如何设置编码方式
- Android ViewDragHelper实现QQ侧滑边栏
- Android 静态加载第三发jar
- android SurfaceView中播放视频 按视频的原始比例播放
- Android开发,系统通讯录功能开发扩展资料汇总
- android:scaleType属性
- 【Proguard】Proguard混淆时保留行号信息
- Android开发的七大环节
- Android编程之SurfaceView学习示例详解
- android找不到.xml和资源文件
- Android手机在获取root权限下的抓包过程
- Android 如何解决dialog弹出时无法捕捉Activity的back事件
- Android中自定义属性的使用
- Android DiskLruCache 完全解析,硬盘缓存的最佳方案
- Android开发学习:使用已有的sql数据库
- Android Studio系列教程二--基本设置与运行