• 添加系统服务需要添加aidl,service,manager文件,需要修改SystemServer,Context,ContextImpl
  • 下面举例进行说明,主要添加一个服务,用于获取系统时间和版本号

1.在frameworks/base/core/java/android/app/下添加aidl文件

frameworks/base/core/java/android/app/ISystemStatusManager.aidl
package android.app;  

interface ISystemStatusManager
{
String[] getSystemStatus();
}

2.修改frameworks/base/Android.mk文件,将aidl加到该文件中,这样才可以被编译到,否则编译不过

将core/java/android/app/ISystemStatusManager.aidl \加到LOCAL_SRC_FILES后面

3.在frameworks/base/services/core/java/com/android/server/下添加service文件

frameworks/base/services/core/java/com/android/server/SystemStatusManagerService.java
package com.android.server;  

import android.app.ISystemStatusManager;
import android.content.Context;
import android.os.Build;
import android.util.Slog; import java.text.SimpleDateFormat;
import java.util.Date; public class SystemStatusManagerService extends ISystemStatusManager.Stub {
private Context mContext; public SystemStatusManagerService(Context context) {
mContext = context; Slog.d("SystemStatus", "Date:" + getDateTime() + "\nVersion:" + getVersion());
} @Override
public String[] getSystemStatus() {
String[] infos = new String[]; infos[] = "Date:" + getDateTime();
infos[] = "Version:" + getVersion(); return infos;
} private String getDateTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-DD-mm HH:mm:s");
Date date = new Date(System.currentTimeMillis()); return format.format(date);
} private String getVersion() {
return Build.DISPLAY;
}
}

4.在frameworks/base/core/java/android/app/下添加manager

frameworks/base/core/java/android/app/SystemStatusManager.java
package android.app;  

import android.content.Context;
import android.os.RemoteException;
import android.util.Slog; public class SystemStatusManager {
Context mContext;
ISystemStatusManager mService; public SystemStatusManager(Context context, ISystemStatusManager service) {
mContext = context;
mService = service;
} public String[] getSystemStatus() {
if (mService != null) {
try {
return mService.getSystemStatus();
} catch (RemoteException e) {
Slog.e("SystemStatus", "RemoteException " + e);
return null;
}
} return null;
}
}

5.在frameworks/base/core/java/android/content/Context.java中添加service名称定义

public static final String SYSTEM_STATUS_SERVICE = "system_status_service";

6.在frameworks/base/services/java/com/android/server/SystemServer.java中添加服务

  • 在startOtherServices()方法中添加如下代码

    try {
    ServiceManager.addService(Context.SYSTEM_STATUS_SERVICE, new SystemStatusManagerService(context));
    } catch (Throwable e) {
    Slog.e(TAG, "Failure starting System Status Service ", e);
    }

7.在frameworks/base/core/java/android/app/ContextImpl.java中注册服务

  • 在static {}中添加如下代码

    registerService(SYSTEM_STATUS_SERVICE, new ServiceFetcher() {
    public Object createService(ContextImpl ctx) {
    IBinder b = ServiceManager.getService(SYSTEM_STATUS_SERVICE);
    return new SystemStatusManager(ctx, ISystemStatusManager.Stub.asInterface(b));
    }
    });

8.编译framework.jar和services.jar,push到手机,重启手机

  编译前需要更新API,执行:

make update-api
  • 重启手机后就会输出如下log:

    D/SystemStatus(  ): Date:-- ::
    D/SystemStatus( ): Version:xxx

9.如果系统app需要使用该service,可以通过如下方式调用

SystemStatusManager mManager = (SystemStatusManager) getSystemService(Context.SYSTEM_STATUS_SERVICE);
try {
String[] infos = mManager.getSystemStatus();
Log.i("SystemStatus", "SystemStatus Date:" + infos[] + "\nVersion:" + infos[]);
} catch (Exception e) {
e.printStackTrace();
}

本文以一个简单的例子详细介绍如何为Android 6.0 系统新增一个系统服务,以及如何使用自定义系统服务。

目标:1.创建一个自定义服务CCCService

2.APP 开发过程中可以使用 getSystemService("ccc") 获取 CCCManager 并且调用里面的函数。

 step1 创建aidl文件

在源码frameworks/base/core/java/android/os/ 下面新增 一个 ICCCService.aidl

假设我们定义了5个函数,这些函数将会在SystemServer进程执行。

内容如下

// ICCCService.aidl
package android.os; // Declare any non-default types here with import statements interface ICCCService {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void setVal(String key,String value);
String getVal(String key);
void appendLog(String log);
void clearLog();
String readLog();
}

step2 创建Service文件 (CCCService)

在 frameworks/base/services/core/java/com/android/server/ 下面新增一个 CCCService.java 用来实现aidl文件定义的接口。

内容如下

package com.android.server;

import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.*;
import java.util.HashMap;
import android.os.RemoteException;
import android.os.ICCCService; /**
*
* Created by zhuangqianliu on 2016/9/21.
*/ public class CCCService extends ICCCService.Stub {
private static HashMap<String,String> map=new HashMap<>();
private static String inner_log=""; public CCCService() { } @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);
} @Override
public void appendLog(String log) throws RemoteException {
inner_log+=log+"\n";
} @Override
public void clearLog() throws RemoteException {
inner_log="";
} @Override
public String readLog() throws RemoteException {
return inner_log;
} }

step3 将自定义Service 加入到SystemServer 启动进程

先在 frameworks/base/core/java/android/content/Context.java 中添加一行 

public static final String CCC_SERVICE="ccc";

修改 frameworks/base/services/java/com/android/server/SystemServer.java

在  startOtherServices() 函数 的try模块中增加以下代码

 try {

                Slog.i(TAG, "CCC Service");

                ServiceManager.addService(Context.CCC_SERVICE, new CCCService());

            } catch (Throwable e) {

                Slog.e(TAG, "Failure starting CCC Service", e);

            }

最终效果如图

step4 创建Manager,即CCCManager

在frameworks/base/core/java/android/app/ 下创建CCCManager.java 文件 内容如下

package android.app;

/**
* Created by liam on 16/10/2.
*/
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ICCCService;
import android.util.Log; public class CCCManager {
ICCCService mService;
public CCCManager(Context ctx,ICCCService service){
mService=service;
}
public void setVal(String key,String value){
try{
mService.setVal(key,value);
}catch(Exception e){
Log.e("CCCManager",e.toString());
e.printStackTrace();
} }
public String getVal(String key){
try{
return mService.getVal(key);
}catch(Exception e){
Log.e("CCCManager",e.toString());
e.printStackTrace();
}
return null;
}
public void appendLog(String log){
try{
mService.appendLog(log);
}catch(Exception e){
Log.e("CCCManager",e.toString());
e.printStackTrace();
}
}
public void clearLog(){
try{
mService.clearLog();
}catch(Exception e){
Log.e("CCCManager",e.toString());
e.printStackTrace();
}
}
public String readLog(){
try{
return mService.readLog();
}catch(Exception e){
Log.e("CCCManager",e.toString());
e.printStackTrace();
}
return null;
}
}

step5 注册到SystemService

修改frameworks/base/core/java/android/app/SystemServiceRegistry.java

在静态代码块中增加

 registerService(Context.CCC_SERVICE, CCCManager.class,
new CachedServiceFetcher<CCCManager>() {
@Override
public CCCManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.CCC_SERVICE);
ICCCService service = ICCCService.Stub.asInterface(b);
return new CCCManager(ctx, service);
}});

step6 修改SePolicy的编译验证

修改 /external/sepolicy/service.te

在最后一行添加

type ccc_service, system_api_service, system_server_service, service_manager_type;

然后修改同目录下 /external/sepolicy/service_contexts 文件

中间插入一行

ccc u:object_r:ccc_service:s0

如图所示

step7 重新编译源码

别忘了先 make update-api。

Step8 测试 

tip:

可以先创建一个java工程简单写一个CCCManager类,导出jar 在ide中使用provided 依赖。这样开发过程中就不会报错。

java临时工程如下使用 IDEA创建的java项目

Android studio 项目配置

 

最新文章

  1. HTML5 Canvas玩转酷炫大波浪进度图
  2. EJB之Timer
  3. Inversion_树状数组***
  4. Linux(CentOS)中安装MongoDB
  5. 3分钟4个步骤超级简单入门配置lamp
  6. navicat----------局域网数据库:如何让navicat链接局域网其他的数据库。
  7. Corel Painter 15在Surface Pro 4下开启笔触压力感应
  8. Fedora和Ubuntu下安装OpenGL开发环境配置
  9. python 代码片段14
  10. 【Pro ASP.NET MVC 3 Framework】.学习笔记.11.ASP.NET MVC3的细节:概览MVC项目
  11. 10大html5前端框架
  12. 谈谈map中的count方法
  13. Altium Designer 里面怎么画等长线
  14. Swift--基础(一)基本类型 符号 字符串(不熟的地方)
  15. 基于python机器学习人脸自动补全
  16. xtrabackup单表备份与恢复
  17. 进程,线程,协程,io多路复用 总结
  18. 强大的矩阵奇异值分解(SVD)
  19. ubuntu16.04搭建geodjango+postgresql+postgis的WebGIS框架(三)加载空间数据
  20. mysql 表锁进程非常多的情况

热门文章

  1. Objective-C学习笔记(三)——用Objective-C编写第一个程序:Hello,World!
  2. ASP.NET Web API中通过URI显示实体中的部分字段
  3. 利用Delphi编写IE扩展
  4. Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题
  5. Install windows server 2008 on ESXi 5.1, add to domain and config for remote desktop
  6. centos清除dns cache.
  7. 服务器能远程连接,网络连接正常,但是外网域名Ping不通,浏览器中打不开网站
  8. ubuntu16 64位 编译64位程序和32位程序
  9. Oracle 12c: RMAN restore/recover pluggable database
  10. 迁移ORACLE_HOME引发的登录sqlplus无法加载类库错误