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

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.lryc.cn/news/2394837.html

相关文章:

  • 5G 核心网 UE 状态深度剖析:机制、迁移与演进
  • HomeKit 基本理解
  • [SC]SystemC在CPU/GPU验证中的应用(三)
  • gunicorn多线程部署django导致的登陆错误
  • (LeetCode 每日一题) 909. 蛇梯棋 (广度优先搜索bfs)
  • PostgreSQL ERROR: out of shared memory处理
  • 生成https 证书步骤
  • 34、请求处理-【源码分析】-Model、Map原理
  • 设计模式——适配器设计模式(结构型)
  • 小黑大语言模型通过设计demo进行应用探索:langchain中chain的简单理解demo
  • 秒杀系统—5.第二版升级优化的技术文档三
  • [SC]SystemC在CPU/GPU验证中的应用(六)
  • 【STM32】HAL库 之 CAN 开发指南
  • WPF的基础设施:XAML基础语法
  • DeepSeek R1-0528 新开源推理模型(免费且快速)
  • Go 语言的 GC 垃圾回收
  • [git每日一句]your branch is behind ‘origin/master‘
  • 【QT】在QT6中读取文件的方法
  • 安全帽目标检测
  • Java工厂方法模式详解
  • 【pytorch学习】土堆pytorch学习笔记2
  • Eclipse 插件开发 5.3 编辑器 监听输入
  • iOS 集成网易云信IM
  • Parasoft C++Test软件单元测试_实例讲解(对多次调用的函数打桩)
  • azure web app创建分步指南系列之二
  • 题海拾贝:P8598 [蓝桥杯 2013 省 AB] 错误票据
  • MySQL 8.0:解析
  • Python量化交易12——Tushare全面获取各种经济金融数据
  • 封装一个小程序选择器(可多选、单选、搜索)
  • Dest建筑能耗模拟仿真功能简介