热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

Android实现在ServiceManager中加入自定义服务的方法详解

这篇文章主要介绍了Android实现在ServiceManager中加入自定义服务的方法,结合实例形式分析了Android开发中ServiceManager自定义服务的相关创建与使用方法,需要的朋友可以参考下

本文实例讲述了Android实现在ServiceManager中加入自定义服务的方法。分享给大家供大家参考,具体如下:

当我们要使用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包,添加方式可参考在Eclipse中使用SDK中@hide函数的方法附加说明。另外,添加服务,需要System用户,所以manifest文件中需要加上android:sharedUserId="android.uid.system", 并且要使用platform签名签名apk。

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

下面我们就来编码。

先在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文件



注意,这个应用需要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;
    }
  }
}

附:在Eclipse中使用SDK中@hide函数的方法

我们使用Eclipse进行android开发时,使用的是ADT中提供的SDK,里面是不包含@hide函数和变量的。因为android为了兼容、安全等原因,在提供SDK时,把这些函数给隐藏了。但是,很多时候,我们又需要使用这些函数,因此我们需要手动添加android SDK。例如,当我们使用AudioManager时,当需要看某种streamType是否mute时,可以调用isStreamMute(int streamType)这个方法,但是因为它是@hide的,所以我们就需要引入自己的sdk,才能编译通过。

1. android系统编译时,当编译“include $(BUILD_JAVA_LIBRARY)”时,会在$ANDROID_SOURCE_BASE/out/target/common/obj/JAVA_LIBRARIES生成中间文件,当我们需要使用某些类库时,可以从这里面找。

isStreamMute(int streamType)在framework.jar中,我们从out/target/common/obj/JAVA_LIBRARIES/framework_intermediates中,将classes.jar拷贝到本地,并重命名为framework.jar。

2. 在eclipse中右键工程->Properties->Java Build Path->Libraries->Add External JAR

3. 点击Order and Export,将framework.jar 置顶

4. 现在,我们就可以使用AudioManager中的isStreamMute(int streamType)方法了

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android基本组件用法总结》、《Android视图View技巧总结》、《Android资源操作技巧汇总》、《Android操作json格式数据技巧总结》、《Android开发入门与进阶教程》、《Android编程之activity操作技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。


推荐阅读
  • 并发编程:深入理解设计原理与优化
    本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 当iOS设备越狱后,某些插件可能会导致系统崩溃(白苹果)。此时,可以通过进入安全模式来排查并删除有问题的插件。本文将详细介绍如何通过特定按键组合进入不加载MobileSubstrate的安全模式,并提供相关背景知识。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文介绍如何通过SQL查询从JDE(JD Edwards)系统中提取所有字典数据,涵盖关键表的关联和字段选择。具体包括F0004和F0005系列表的数据提取方法。 ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 高效解决应用崩溃问题!友盟新版错误分析工具全面升级
    友盟推出的最新版错误分析工具,专为移动开发者设计,提供强大的Crash收集与分析功能。该工具能够实时监控App运行状态,快速发现并修复错误,显著提升应用的稳定性和用户体验。 ... [详细]
  • 使用Python在SAE上开发新浪微博应用的初步探索
    最近重新审视了新浪云平台(SAE)提供的服务,发现其已支持Python开发。本文将详细介绍如何利用Django框架构建一个简单的新浪微博应用,并分享开发过程中的关键步骤。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
author-avatar
炯炯800
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有