如何添加系统Service

简介

今天来谈谈Android系统service,大家都知道android系统是基于Linux的。只不过是对Linux做了些修改和再封装。在我们android开发当中,各项system service的使用可谓是占了相当大的比例,较为经典的有为4大组件服务的ams、pms、zygote等。了解binder通信以及各种service的功能,对于我们理解android framework有很大帮助。关于binder通信相关的资料,网上可谓是汗牛充栋,大家最好了解下c++,嵌入式编程、linux编程,了解完这个。再去学习会事半功倍,推荐大家看一下韦东山老师的关于Binder通信的视频,讲解的比较详细(非拖)

我们可以在手机shell中,用ps命令查看下运行进程[图片上传中...(image-33c17f-1523686626159-0)]

我这用的是华为荣耀3的机器,看的出来里面的进程比较多,不清楚他们在做系统裁剪的时候做了什么。

在这里我们可以看到zygote进程,这个进程是用来创建android应用进程的,每当我们启动activity和service或者其他组件的时候,一般都会检查这个组件。关于zygote的详细内容可以参考这篇文章以及AMS文章,内容较长但绝对干货。比我写的有价值多了。

我们用命令ps之后,并没有发现与ams、pms的相关进程,这是因为这些服务都是一个叫system_server的进程拉起来的。和它隶属于同一个进程,在我们通过conext.getSystemService()方法拿到这些service的代理类,然后通过Binder与其进行通信。

下面我们说说将服务做成SYSTEM SERVICE的一些好处:

1.因为system_server进程会专门被监控,挂掉的时候会导致zygote自杀,然后系统重启。只要自己添加的service是稳定的,那么这个进程就会一直存在,我们就不用担心服务被干掉之类的。

2.system_server属于system用户,权限略小于root,大于普通用户。这样我们自添加的service拥有较大的权限做一些特殊的事情。

3.android framework启动过程中,service的启动是相当耗时的,因为有扫描应用程序的过程。而有些东西,我们需要在系统启动的时候做,例如启动的时候闪灯。这时候,我们就需要把一些操作放到Linux内核启动的过程中或者android环境启动过程中。Linux内核启动相对较快,综合考虑的话,还是放到android环境启动过程中较好。

坏处就是system service编写和使用都比较麻烦,好在系统为我们提供了利用aidl添加service。下面我们来看看怎么添加service。

一、编写IHelloWorld.aidl,并放到源码frameworks/base/core/java/android/os/ 下面(如果是在ide中写这些代码,注意写完之后编译下项目,否则无法生成相关的stub)

// IHelloWorld.aidl.aidl
package android.os;

// Declare any non-default types here with import statements

interface IHelloWorld {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
     void printSth(String content);
     String getHelloWorld();

}

二、创建Service文件(java),放到源码 frameworks/base/services/core/java/com/android/server/下面

package com.android.server;

import android.os.IHelloWorld;
import android.os.RemoteException;
import android.util.Log;

/**
 * Created by 41264 on 07/10/17.
 */

public class HelloWorldService extends IHelloWorld.Stub {

    private static final String TAG = HelloWorldService.class.getSimpleName();

    @Override
    public void printSth(String content) throws RemoteException {
        Log.i(TAG, content);
    }

    @Override
    public String getHelloWorld() throws RemoteException {
        return "hello world";
    }
}

三、将自定义Service加入到SystemServer启动进程,先在 frameworks/base/core/java/android/content/Context.java 中添加一行

public static final String HELLOWORLD_SERVICE="helloworld ";

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

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

try {

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

    ServiceManager.addService(Context. HELLOWORLD_SERVICE, new HelloWorldService());

} catch (Throwable e) {

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

}

四、创建Manager,即HelloWorldManager,并放到frameworks/base/core/java/android/app/ 下

package android.app;

import android.content.Context;
import android.os.IHelloWorld;
import android.os.RemoteException;

/**
 * Created by 41264 on 07/10/17.
 */

public class HelloWorldManager {
    IHelloWorld mService;
    public HelloWorldManager(Context ctx,IHelloWorld service){
        mService = service;
    }

    public void printSth(String content){
        try {
            mService.printSth(content);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    public String getHelloWorld(){
        try {
            mService.getHelloWorld();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return null;
    }
}

五、注册到SystemService,修改frameworks/base/core/java/android/app/SystemServiceRegistry.java,在静态代码块中增加如下代码

registerService(Context. HELLOWORLD_SERVICE, HelloWorldManager.class,
        new CachedServiceFetcher() {
            @Override
            public HelloWorldManager createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(Context. HELLOWORLD_SERVICE);
                IHelloWorld service = IHelloWorld.Stub.asInterface(b);
                return new HelloWorldManager (ctx, service);
            }});

六、编译

make update-api 后再重新编译烧录系统(也可编译相应模块Push到系统中去)。

七、测试

有两种方式,一种是将编出来的jar包通过lib方式导入工程。jar包位置:out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar。另一种是在自建的app包下创建 HelloWorldManager类,导出Jar包供我们项目依赖。这样开发过程中就不会报错

代码位置

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容