文档章节

在ServiceManager中加入自定义的服务

cwr
 cwr
发布于 2015/02/23 14:02
字数 953
阅读 7171
收藏 13
点赞 0
评论 4

    当我们要使用android的系统服务时,一般都是使用Context.getSystemService方法。例如我们要获取AudioManager,我们可以:

AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

    获取的服务,其实是在ServiceManager中注册的Binder服务,然后进行封装后,提供给用户。

    可以看ContextImpl.java中的实现:

   static {
        ......
        // 将AudioManager加入SYSTEM_SERVICE_MAP中,调用getSystemService时,
        // 就会从SYSTEM_SERVICE_MAP得到AudioManager
        registerService(AUDIO_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    return new AudioManager(ctx);
                }});
        ......
    }

    AudioManager是对IAudioService的封装,实际操作都是使用IAudioService进行的,看AudioManager中的代码:

  private static IAudioService getService()
    {
        if (sService != null) {
            return sService;
        }
        // 从ServiceManager中获取Binder
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
        // 将Binder转化成IAudioService,方便调用
        sService = IAudioService.Stub.asInterface(b);
        return sService;
    }

    上面是android系统的使用方式。如果我们添加自己的服务,要如何做呢?

    

    我们在eclipse中建3个测试工程:

    1)MyServiceLib:这是个lib工程,需要在eclipse中勾选Is Library。后面的两个工程,都需要将MyServiceLib添加到Library中。

    2) MyService: 用于在android开机时注册自定义服务进ServiceManager。因为ServiceManager被@hide隐藏了,所以要使用它需要自己手动添加sdk包,添加方式可参考http://my.oschina.net/u/262208/blog/379548。另外,添加服务,需要System用户,所以manifest文件中需要加上android:sharedUserId="android.uid.system", 并且要使用platform签名签名apk。

    3)MyServiceTest:用于测试上面两个工程。



下面我们就来编码。


  1. 先在MyServiceLib工程中创建一个aidl文件,android编译工具会帮我们生成相应的java类,aidl文件如下

package com.test.lib;
interface IMyService {
    void setValue(int val);
    int getValue();
}

定义了两个接口用于测试,setValue和getValue。

android编译工具会帮我们在gen目录下生成一个IMyService的java类。

    2. 在MyService工程中创建MyService类, 这个类继承自IMyService.Stub,实现了setValue和getValue接口,这就是一个Service。

package com.test.myservice;
 
import android.os.RemoteException;
import com.test.lib.IMyService;
 
public class MyService extends IMyService.Stub {
 
    private int value;
     
    @Override
    public void setValue(int val) throws RemoteException {
        this.value = val;
    }
 
    @Override
    public int getValue() throws RemoteException {
        return value;
    }
 
}

下面我们将把它加入至ServiceManager中。

3. 在MyService工程中创建MyServiceApplication类

package com.test.myservice;
 
import android.app.Application;
import android.os.ServiceManager;
 
public class MyServiceApplication extends Application{
 
    @Override
    public void onCreate() {
        super.onCreate();
        ServiceManager.addService("MYSERVICE", new MyService());
    }
     
}

这是一个Application,我们希望android系统启动时,就创建这个Application,在onCreate方法中,创建MyService类,并加入到ServiceManager中。因此,我需要修改下manifest文件

 

  <application
        android:name=".MyServiceApplication"   //指定Application为我们创建的MyServiceApplication
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:persistent="true"             // 加上persistent=ture,ActivityManager创建的时候,就会创建该应用的进程,并调用MyServiceApplication的onCreate方法
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

注意,这个应用需要system用户,并签名才可运行。

这样,服务端就好了,并且开机时,我们的服务就已经在ServiceManager中了。

4. 下面我们提供一个Manager类方便客户端使用。在MyServiceLib中创建MyManager类:

package com.test.lib;
 
import android.os.RemoteException;
import android.os.ServiceManager;
 
public class MyManager {
 
    private static MyManager instance;
    private IMyService myservice;
 
    public static MyManager getInstance() {
        if (instance == null) {
            instance = new MyManager();
        }
        return instance;
    }
 
    private MyManager() {
        // 从ServiceManager中获取服务
        myservice = IMyService.Stub.asInterface(ServiceManager.getService("MYSERVICE"));
    }
 
    public void setValue(int value) throws RemoteException {
        myservice.setValue(value);
    }
 
    public int getValue() throws RemoteException {
        return myservice.getValue();
    }
 
}


5. 在MyServiceTest工程中进行测试

    通过MyManager.getInstance()可以很方便的获取服务的Manager,对远程服务进行调用。我们创建一个Activity来使用MyManager

package com.test.client;
 
import java.util.Random;
 
import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
 
import com.test.binder.client.R;
import com.test.lib.MyManager;
 
public class MainActivity extends Activity implements OnClickListener {
 
    MyManager myManager;
     
    Button btnSetValue;
    Button btnGetValue;
    TextView tvValue;
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        setContentView(R.layout.activity_main);
        btnSetValue = (Button) findViewById(R.id.btn_set_value);
        btnGetValue = (Button) findViewById(R.id.btn_get_value);
        tvValue = (TextView) findViewById(R.id.tv_value);
         
        // 获取MyManager
        myManager = MyManager.getInstance();
    }
 
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.btn_set_value:
            int value = new Random().nextInt();
            try {
                myManager.setValue(value);
                Toast.makeText(this, "set value to "+value+ " success!", 0).show();
            } catch (RemoteException e) {
                e.printStackTrace();
                Toast.makeText(this, "set value fail!", 0).show();
            }
            break;
        case R.id.btn_get_value:
            try {
                tvValue.setText("value:"+myManager.getValue());
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        default:
            break;
        }
    }
     
}







© 著作权归作者所有

共有 人打赏支持
cwr

cwr

粉丝 1
博文 8
码字总数 5030
作品 0
扬州
加载中

评论(4)

x
xieyuan1046

引用来自“李伟平”的评论

找到原因了,Android5.0开始,出于安全考虑,加到ServerManager中的服务必须在device/qcom/sepolicy/common/system_app.te中声明…
请问怎么添加的,有什么资料可以研究?谢谢咯
李伟平
李伟平
找到原因了,Android5.0开始,出于安全考虑,加到ServerManager中的服务必须在device/qcom/sepolicy/common/system_app.te中声明…
李伟平
李伟平
请问你是在Android5.0以上版本源码中试的这个吗?我加的时候抛出安全异常…
noprom
noprom
很不错的文章
Android 之 ServiceManager与服务管理

ServiceMananger是android中比较重要的一个进程,它是在init进程启动之后启动,从名字上就可以看出来它是用来管理系统中的service。比如:InputMethodService、ActivityManagerService等。在...

taoanran ⋅ 2012/08/11 ⋅ 0

Android AudioManager控制系统声音的流程

首先上层java调用 XXXPlayer AudioManager audiomanage = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audiomanager就是我们定义的控制系统声音的对象,(如果context......

雨焰 ⋅ 2012/11/09 ⋅ 0

[实践] Android5.1.1源码 - 在Framework中添加自定义系统服务

前言 本文的方法要修改Android源码。但只要将系统服务写出来,也可以注入systemserver进程将系统服务加载到systemserver中。 步骤1. 添加一个aidl文件,我将aidl文件添加到这个路径下: fram...

阿里聚安全 ⋅ 2016/05/30 ⋅ 0

Zend Framework 2.0的Mvc结构及启动流程分析

原文链接: Zend Framework 2.0的Mvc结构及启动流程分析。 概要 首先需要明确的是,Zend2.0的启动以及MVC构架是完全基于事件驱动的。如果对事件驱动还不太了解的话,应该先弄清楚什么是ZF2的...

AlloVince ⋅ 2012/06/06 ⋅ 1

Android5.1.1源码 - 分析Android系统服务何时被添加到ServiceManager

Android5.1.1源码 - 分析Android系统服务何时被添加到ServiceManager @(Android研究)[ServiceManager PackageManagerService ActivityManagerService] ----------[TOC] 前言 本文公开首发于阿......

i不歪 ⋅ 2015/11/11 ⋅ 0

Android系统的Binder机制之三——服务代理对象(2)

文《Android系统的Binder机制之二——服务代理对象(1)》我们学习了进程的C/C++层面的服务代理对象BpBinder,和Binder底层处理方式。本文我们将深入分析一下在进程的Java层面服务代理对象的...

垂盆草 ⋅ 2012/08/04 ⋅ 0

andriod binder-ServiceManager守护进程

ServiceManager是一个守护进程。它的main()函数源码如下: frameworks/native/cmds/servicemanager/service_manager.c int main(int argc, char **argv){ } /frameworks/native/cmds/service......

android开发 ⋅ 2017/12/08 ⋅ 0

C#控制远程计算机的服务

在.net中提供了一些类来显示和控制Windows系统上的服务,并可以实现对远程计算机服务服务的访问,如System.ServiceProcess命名空间下面的ServiceController 类,System.Management下面的一些...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

WebSphere ESB入门:创建POJO并发布(二)

图 5. 将接口与生成的服务组件相关联   现在接口已与组件关联。我们可以通过使用“Generate Implementation”选项生成实现的框架。   图 6. 为新服务组件生成实现   图 7. 将实现添加到...

fiercelf ⋅ 2011/03/19 ⋅ 0

android系统启动过程

Android的启动过程可以分为两个阶段,第一阶段是Linux的启动,第二阶段才是Android的启动,下面我们分别来了解一下具体的过程。 首先是Linux启动,这一部分我想就可以略过了,无非是Linux的B...

垂盆草 ⋅ 2012/07/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CENTOS7防火墙命令记录

安装Firewall命令: yum install firewalld firewalld-config Firewall开启常见端口命令: firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --zone=public --add-po......

cavion ⋅ 59分钟前 ⋅ 0

【C++】【STL】利用chromo来测量程序运行时间与日志时间打印精确到微秒

直接上代码吧,没啥好说的。头疼。 #include <iostream>#include <string>#include <ctime>#include <sstream>#include <iomanip>#include <thread>#include <chrono>using ......

muqiusangyang ⋅ 今天 ⋅ 0

Mac环境下svn的使用

在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还需做一下简...

故久呵呵 ⋅ 今天 ⋅ 0

破解公司回应苹果“USB限制模式”:已攻破

本周四,苹果发表声明称 iOS 中加入了一项名为“USB 限制模式”的功能,可以防止 iPhone 在连接其他设备的时候被破解,并且强调这一功能并不是针对 FBI 等执法部门,为的是保护用户数据安全。...

六库科技 ⋅ 今天 ⋅ 0

MyBtais整合Spring Boot整合,TypeHandler对枚举类(enum)处理

概要 问题描述 我想用枚举类来表示用户当前状态,枚举类由 code 和 msg 组成,但我只想把 code 保存到数据库,查询处理,能知道用户当前状态,这应该怎么做呢?在 Spring 整合MyBatis 的时候...

Wenyi_Feng ⋅ 今天 ⋅ 0

synchronized与Lock的区别

# <center>王梦龙的读书笔记第一篇</center> ## <center>-synchronized与Lock的区别</centre> ###一、从使用场景来说 + synchronized 是能够注释代码块、类、方法但是它的加锁是和解锁使用一......

我不想加班 ⋅ 今天 ⋅ 0

VConsole的使用

手机端控制台打印输出,方便bug的排查。 首先需要引入vconsole.min.js 文件,然后在文件中创造实例。就能直接使用了。 var vConsole = new VConsole(); vConsole的文件地址...

大美琴 ⋅ 今天 ⋅ 0

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 今天 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 今天 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部