往Android系统中添加服务的方法教程

前言

最近因为公司的平台要从Android 4.4.4 转战 Android 6.0, 带来的问题是之前我们在系统中添加了一些服务, 于是要将一些系统级的服务迁移过去,以及一些Framework 的自定义包.

碰巧在Gerrit上看到了添加系统服务这一块的patch.正好做个总结.虽然我不是Framework工程师, 但是了解Android系统还是很有好处的.

如何获取系统服务

我们获取系统服务都是在context中,getSystemService获取到的. 那么我们看一下getSystemService发生了哪些些事情.

getSystemService的实现是ContextImpl,我们去看一下ContextImpl的源码就知道了.

Android 4.4.4 (KitKat)

这里是Android4.4.4的源码, 6.0的源码过会儿看.

 //这是我们获取服务的路口
 @Override
 public Object getSystemService(String name) {
  //可以看到我们是从一个HashMap中拿的服务.
  ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
  return fetcher == null ? null : fetcher.getService(this);
 }

 private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
    new HashMap<String, ServiceFetcher>();
 //这是注册服务的方法,请注意是静态方法
 private static void registerService(String serviceName, ServiceFetcher fetcher) {
  if (!(fetcher instanceof StaticServiceFetcher)) {
   fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
  }
  SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
 } 

我们还在ContextImpl中看到很多静态代码块.全是在注册服务,并且全是我们常用的系统服务.

 static {
   registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
     public Object getService(ContextImpl ctx) {
      return AccessibilityManager.getInstance(ctx);
     }});

   registerService(CAPTIONING_SERVICE, new ServiceFetcher() {
     public Object getService(ContextImpl ctx) {
      return new CaptioningManager(ctx);
     }});
  ....
 }

这么看来,这不就是我们注册服务的地方么?

So. 我们找到了注册系统服务的地方, 这里我们只需要把我们自己想注册的服务添加进去,完成new ServiceFetcher() 的抽象方法就行啦. 这样我们以后再getSystemService,传入注册时的名称,就可以获取到我们的服务对象了了.当然,这是4.4的方法.

Android 6.0 (Marshmallow)

我们来看一下ContextImpl的代码

 @Override
 public Object getSystemService(String name) {
  return SystemServiceRegistry.getSystemService(this, name);
 }

我们发现,与 KitKat 大大不同, Marshmallow这里是从一个叫做SystemServiceRegistry的类去获取的.

好了,那我们去看它的源码,原来还是和以前一样的套路,不过是单独封装了一个类来管理这些注册的服务. 这么设计的确好,代码上的耦合度看上去小多了,且不会使得ContextImpl这个类越来月臃肿.

final class SystemServiceRegistry {
 private final static String TAG = "SystemServiceRegistry";

 // Service registry information.
 // This information is never changed once static initialization has completed.
 private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
   new HashMap<Class<?>, String>();
 private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
   new HashMap<String, ServiceFetcher<?>>();
 private static int sServiceCacheSize;

 // Not instantiable.
 private SystemServiceRegistry() { }

 static {
  registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
    new CachedServiceFetcher<AccessibilityManager>() {
   @Override
   public AccessibilityManager createService(ContextImpl ctx) {
    return AccessibilityManager.getInstance(ctx);
   }});

  registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
    new CachedServiceFetcher<CaptioningManager>() {
   @Override
   public CaptioningManager createService(ContextImpl ctx) {
    return new CaptioningManager(ctx);
   }});
 ....

So.我们 Marshmallow 的系统服务应该在SystemServiceRegistry类中添加.一样的方式. 之后我们再getSystemService,传入注册时的名称,就可以获取到我们的服务对象了了.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android编程获取系统隐藏服务实现锁屏的方法

    本文实例讲述了Android编程获取系统隐藏服务实现锁屏的方法.分享给大家供大家参考,具体如下: 实现原理:当按锁屏键时,会发出一个广播,当界面接收到一个广播就可以实现锁频.我们可以调用IDevicePolicyManager服务中的lockNow方法来发送一个广播实现锁屏. IDevicePolicyManager是被系统隐藏掉的,需要通过反射还获取此服务. 步骤: 1.创建MyAdmin的广播接收者继承DeviceAdminReceiver 2.通过反射 ,获取IDevicePolicyMa

  • Android中获得正在运行的程序和系统服务的方法

    ActivityManager.RunningAppProcessInfo类与获取正在运行的应用程序 每一个应用程序都会运行在它独立的进程里,但是为了节省资源或者这些应用程序是为了完成某一共同工作,它们 也可能会运行在一个进程里. 知识点介绍: ActivityManager.RunningAppProcessInfo类 说明: 封装了正在运行的进程信息 常用字段: int   pid    进程ID int   uid    进程所在的用户ID String   processName 进程名

  • 往Android系统中添加服务的方法教程

    前言 最近因为公司的平台要从Android 4.4.4 转战 Android 6.0, 带来的问题是之前我们在系统中添加了一些服务, 于是要将一些系统级的服务迁移过去,以及一些Framework 的自定义包. 碰巧在Gerrit上看到了添加系统服务这一块的patch.正好做个总结.虽然我不是Framework工程师, 但是了解Android系统还是很有好处的. 如何获取系统服务 我们获取系统服务都是在context中,getSystemService获取到的. 那么我们看一下getSystemS

  • Android编程中HTTP服务用法详解

    本文实例讲述了Android编程中HTTP服务用法.分享给大家供大家参考,具体如下: 在Android中,除了使用java.net包下的API访问HTTP服务之外,我们还可以换一种途径去完成工作.Android SDK附带了Apache的HttpClient API.Apache HttpClient是一个完善的HTTP客户端,它提供了对HTTP协议的全面支持,可以使用HTTP GET和POST进行访问.下面我们就结合实例,介绍一下HttpClient的使用方法. 我们新建一个http项目,项目

  • Android编程中黑名单的实现方法

    本文实例讲述了Android编程中黑名单的实现方法.分享给大家供大家参考,具体如下: 说明:由于挂断电话android   api不是对外开放的,所以需要使用反射的方法得到拨打电话的服务. 1.将android源代码中的"aidl"文件拷贝到项目中 这样项目中会生成两个包:android.telephony:此包中文件为:NeighboringCellInfo.aidl com.android.internal.telephony;此包中文件为:ITelephony.aidl 2.通过

  • 在Android系统中使用gzip进行数据传递实例代码

    接下来,让我解说一下如何在Android系统中使用gzip进行数据传递 HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术.大流量的WEB站点常常使用GZIP压缩技术来减少文件大小,减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.作者在写这篇博客时经过测试,4.4MB的文本数据经过Gzip传输到客户端之后变为392KB,压缩效率极高. 一.服务端 服务端有2种方式去压缩,一种可以自己压缩,但是更推荐第二种方式,用PrintWrite

  • 详解如何在Android Studio中添加RecyclerView-v7支持包

    一直知道RecyclerView可以代替ListView.GridView使用,听说功能很强大,但还没有去学习过.今天想学习,没想到还没开始便撞墙了.输入Recycler,只有这两个东西,没有提示RecyclerView,说明支持包中没有. 最后一番百度后,终于解决(真不敢想象没有网络的情况下,怎么开发.怎么解决问题). 1.打开SDK Manager,在Extras树下找到Android Support Library,下载好支持包.RecyclerView在v7-21版本就出来了.我这里不用

  • Android Studio中导入module的方法(简单版)

    1.把要导入成Mudle的项目修改成符合Library的格式 修改该项目中bulid.gradle文件中第一行代码 把 apply plugin: 'com.android.application' 修改为 apply plugin: 'com.android.library' 然后,修改AndroidManifiest.xml文件中配置信息,此处主要是把原来配置的项目Style等配置以及MainActivity配置删除,这样处理是为了防止重复.以下以一个我的Moudle文件的AndroidMa

  • windows 系统防火墙 添加端口号方法

    目前在大部分公司内使用的台式机和部分服务器都采用了Windows操作系统,而我么都知道相当一部分病毒.恶意程序.黑客都是利用扫描端口号,利用开放的端口进行入侵,此时大型企业都会将服务器的系统防火墙打开来关闭非常用端口.有些程序安装后可能会自动添加开放需要用到的端口,而有些软件则没有这么智能:又或者我们需要改变某个程序的端口号,改变后如果没有在系统防火墙中添加的话,那么连接就会被防火墙阻止掉,导致连接失败. 添加方法: 1.在<控制面板>中找到<Windows防火墙>点击打开. 2.

  • Linux系统中SSH服务基于key认证实践的过程

    众所周知ssh是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议,它默认工作在tcp的22号端口,具体实现的软件有:openssh(centos默认安装的),dropbear.ssh协议目前有两个版本v1和v2,v1基于CRC-32做MAC,不安全.v2基于DH算法做密钥交换,基于RSA或DSA实现身份认证.所以目前大多流行的Linux都是使用的V2版本. 简单了解了下ssh,我们再来说说它的两种用户登录认证方式,第一种基于用户名口令的方式,这种认证方式想必大家都应该知道,就是我们要想

  • Ubuntu 20.04系统中安装vncserver的方法步骤

    Ubuntu 20.04已经在2020年4月份正式发布,笔者今天正式安装了一个镜像系统,并在该系统中安装vncserver以便于远程图形化管理和使用.安装vncserver的步骤如下: 第一步:安装桌面环境和VNCServer #更新 apt update #安装桌面环境 sudo apt install xfce4 xfce4-goodies #安装vncserver apt install tightvncserver #启动vncserver vncserver 随后按照提示,输入vncs

  • python编程之requests在网络请求中添加cookies参数方法详解

    哎,好久没有学习爬虫了,现在想要重新拾起来.发现之前学习爬虫有些粗糙,竟然连requests中添加cookies都没有掌握,惭愧.废话不宜多,直接上内容. 我们平时使用requests获取网络内容很简单,几行代码搞定了,例如: import requests res=requests.get("https://cloud.flyme.cn/browser/index.jsp") print res.content 你没有看错,真的只有三行代码.但是简单归简单,问题还是不少的. 首先,这

随机推荐