当前位置: 首页 > ops >正文

Android bindservice绑定服务,并同步返回service对象的两个方法

先上一段代码:

private  IDeviceService deviceService = null;
private ServiceConnection conn=null;
private synchronized void bindyourservice() {    Intent intent = new Intent();intent.setPackage("servicepackagename");intent.setAction("serviceactionname");conn=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {               deviceService = IDeviceService.Stub.asInterface(iBinder);}@Overridepublic void onServiceDisconnected(ComponentName componentName) {.....................................             }};try {if (bindService(intent, mConn, Service.BIND_AUTO_CREATE)) {...............................} else {....................}} catch (SecurityException e) {.........................}}

这个是最早绑定服务的方式,bindService返回绑定服务状态,访问服务接口需在取到ServiceConnection连接后再访问,整个过程是异步的,而且就算开线程去绑定服务、加锁也没办法在一个方法里面返回这个service对象,原因是这个方法里面的实现:

/frameworks/base/core/java/android/app/ContextImpl.java

看下这个的代码:

  public boolean bindService(Intent service, ServiceConnection conn, int flags) {warnIfCallingFromSystemProcess();return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,getUser());}@Overridepublic boolean bindService(Intent service, int flags, Executor executor, ServiceConnection conn) {return bindServiceCommon(service, conn, flags, null, null, executor, getUser());}@Overridepublic boolean bindIsolatedService(Intent service, int flags, String instanceName,Executor executor, ServiceConnection conn) {warnIfCallingFromSystemProcess();if (instanceName == null) {throw new NullPointerException("null instanceName");}return bindServiceCommon(service, conn, flags, instanceName, null, executor, getUser());}@Overridepublic boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,UserHandle user) {return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, user);}/** @hide */@Overridepublic boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,Handler handler, UserHandle user) {if (handler == null) {throw new IllegalArgumentException("handler must not be null.");}return bindServiceCommon(service, conn, flags, null, handler, null, user);}.....................private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,String instanceName, Handler handler, Executor executor, UserHandle user) {....................
}

 bindServiceCommon是个私有方法,里面又套了几层代码,太长,翻起来就是整个系统bindservice的流程了。

关键点,bindservice执行的时候接收的Handler是 mMainThread.getHandler(),这个是APP的主线程,也就是无论外部怎么折腾,这个是在主线程接收的。

在上面这段系统代码段里面,有两个方法是可以使用的:

//method 1
public boolean bindService(Intent service, int flags, Executor executor, ServiceConnection conn)
//method 2
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,Handler handler, UserHandle user)

1、bindService

在bindService有一个传参executor,接收ServiceConnection放到了这个里面:

private boolean[] isBind = {false};
private CountDownLatch latch = new CountDownLatch(1);
private boolean bindyourservice(final Context context){if(deviceService==null){latch = new CountDownLatch(1);Executor executor= Executors.newSingleThreadExecutor();executor.execute(new Runnable() {@Overridepublic void run() {mConn=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName className, IBinderiBinder) {deviceService = IDeviceService.Stub.asInterface(iBinder);isBind[0] =true;latch.countDown();}@Overridepublic void onServiceDisconnected(ComponentName className) {                          isBind[0] =false;latch.countDown();}};Intent intent = new Intent();intent.setPackage("yourservicename");intent.setAction("yourserviceaction");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {boolean bind=bindService(intent, Context.BIND_AUTO_CREATE,executor,mConn);if(!bind){                               isBind[0] =false;latch.countDown();}}}});if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {                   try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}                   if(!isBind[0])return false;}else{                   return false;}}         return true;}

需要注意的是Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q,这个方法是android7.0及以后提供的。

2、bindServiceAsUser

也可以实现方法1的功能,只不过把接收对象换成了Handler ,bindServiceAsUser是系统隐藏方法,需通过反射方法使用,至于bindServiceAsUser是否早于android7.0之前就有,无法确认。

http://www.xdnf.cn/news/9820.html

相关文章:

  • 易经六十四卦象解释数据集分享!智能体知识库收集~
  • PostgreSQL 修改表结构卡住不动
  • MySQL索引与事务
  • 华为防火墙NAPT配置
  • 大模型是什么?
  • 金额高精度计算-BigDecimal
  • CSformer:结合通道独立性和混合的稳健多变量时间序列预测
  • 【QQ音乐】sign签名| data参数加密 | AES-GCM加密 | webpack (下)
  • 理解教材意图轻松积累常见数列
  • 外贸邮件营销推广怎么做才有效果?
  • 浏览器本地存储
  • 计算机图形学:(六)渲染管线
  • java24
  • 信创改造选择C86,相比于ARM架构有什么优势?
  • HOW - 简历和求职面试宝典(八)
  • 代理模式核心概念
  • 实时操作系统在脑机接口中的技术平衡:满足实时性与 AI 算力需求
  • 深入理解C#泛型:提升代码复用与类型安全的利器
  • STM32CUBE打印浮点数据-cmake配置
  • MySQL、PostgreSQL、Oracle 区别详解
  • 一个超简易的RMAN备份并保留到异地的方案,仅适用于小规模环境
  • 【大模型MCP】MCP 深度解析:AI 时代的「USB-C」接口——原理、对比、实战代码与行业落地
  • 国产三维CAD皇冠CAD(CrownCAD)在专用设备建模教程:液压升降机
  • qlora
  • 电网中三相不平衡治理的全面解析
  • 什么是范式?三大范式分别是什么?
  • JavaScript 中的 BigInt:当普通数字不够“大“时的救星
  • 企业级网络管理实战:Linux、云与容器的深度融合与优化
  • 苹果签名应用掉签频繁原因排查以及如何避免
  • 实测,大模型谁更懂数据可视化?