Android实现在ServiceManager中加入自定义服务的方法详解
发布时间 - 2026-01-11 03:00:25 点击率:次本文实例讲述了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文件
<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;
}
}
}
附:在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程序设计有所帮助。
# Android
# ServiceManager
# 自定义服务
# Android服务应用ClockService实现闹钟功能
# Android 系统服务TelecomService启动过程原理分析
# Android8.0适配前台定位服务service的示例代码
# 浅谈Android Service服务的高级技巧
# 说说在Android如何使用服务(Service)的方法
# Android7.0指纹服务FingerprintService实例介绍
# Android实现Service在前台运行服务
# Android服务Service教程
# 自己的
# 都是
# 当我们
# 就会
# 要使
# 自定义
# 创建一个
# 的是
# 开机时
# 是一个
# 进阶
# 操作技巧
# 是在
# 相关内容
# 右键
# 会在
# 把它
# 它是
# 感兴趣
# 我们可以
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
EditPlus 正则表达式 实战(3)
标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
Android 常见的图片加载框架详细介绍
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
如何快速生成ASP一键建站模板并优化安全性?
长沙企业网站制作哪家好,长沙水业集团官方网站?
VIVO手机上del键无效OnKeyListener不响应的原因及解决方法
微信小程序 canvas开发实例及注意事项
MySQL查询结果复制到新表的方法(更新、插入)
成都网站制作公司哪家好,四川省职工服务网是做什么用?
轻松掌握MySQL函数中的last_insert_id()
Laravel如何自定义分页视图?(Pagination示例)
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】
Laravel怎么上传文件_Laravel图片上传及存储配置
详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)
node.js报错:Cannot find module 'ejs'的解决办法
在线制作视频网站免费,都有哪些好的动漫网站?
如何在阿里云ECS服务器部署织梦CMS网站?
Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
Laravel如何创建自定义Artisan命令?(代码示例)
如何确保西部建站助手FTP传输的安全性?
如何用JavaScript实现文本编辑器_光标和选区怎么处理
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
如何在云虚拟主机上快速搭建个人网站?
,交易猫的商品怎么发布到网站上去?
如何基于云服务器快速搭建网站及云盘系统?
青岛网站建设如何选择本地服务器?
如何快速完成中国万网建站详细流程?
如何在阿里云高效完成企业建站全流程?
如何在IIS7中新建站点?详细步骤解析
Laravel怎么实现微信登录_Laravel Socialite第三方登录集成
Laravel如何实现一对一模型关联?(Eloquent示例)
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
在Oracle关闭情况下如何修改spfile的参数
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
如何在服务器上三步完成建站并提升流量?
再谈Python中的字符串与字符编码(推荐)
无锡营销型网站制作公司,无锡网选车牌流程?
Laravel DB事务怎么使用_Laravel数据库事务回滚操作
Laravel如何与Inertia.js和Vue/React构建现代单页应用
北京网站制作的公司有哪些,北京白云观官方网站?
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
如何快速登录WAP自助建站平台?
Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册
Java垃圾回收器的方法和原理总结
Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件
如何在 Pandas 中基于一列条件计算另一列的分组均值

