binder通信过程中,服务端和客户端异常处理

binder通信过程中,服务端和客户端异常处理,第1张

    起因是在使用第三方app的时候,鼠标进入第三方app后,退出进入其他app卡顿的问题。通过分析log发现有大量的Systemerr: androidosDeadObjectException产生。
    这个异常的产生是因为app和鼠标服务组成的cs模型中,app client突然挂掉导致,服务端产生DeadObjectException。
    这里涉及到binder的死亡监听机制对服务端和客户端的处理,客户端需要调用linkToDeath去获取服务端binder的生存状态,如果binder突然挂掉,客户端就要讲binder连接remove掉。同样,如果客户端突然挂掉,服务端也需要去及时的进行处理,否则就会出现DeadObjectException。网上大多介绍了如何去对服务端的binder进行死亡监听,但是没有简洁的服务端对客户端的死亡监听(这里相当于对服务端的listener进行处理)。
    首先新建一个继承 implements IBinderDeathRecipient的listener类,然后在服务端的registerAIDLListener函数内新建一个类,然后添加linkToDeath。

    实际上,测试的时候,先进入app,然后开始kill掉app进程,采用

方法,并没有成功kill掉进程,采用

的方法会让app不在自动起,因为项目中launch会自动起该app,disable后,就无法被唤起,需要再度唤起需要

    同时,如果关联进程比较多,binder可能并不会挂掉,可以尝试多杀几个关联进程,来确保binder连接挂掉
    第二部分
关于对服务器binder进行的监听,网上版本比较多,同时上诉方法中,没有考虑client列表的情况,如果有多个client的情况下,需要进行listener的添加和移除,可以考虑参看如下blog

Android App开发中的IPC(进程间通信)无处不在。比如我们使用的 AlarmManager 、 InputMethodService 都是系统为我们提供的服务,处于单独的进程中。如果需要在自己的App进程中使用这些服务就需要进行IPC通信。

除此之外,我们自己的程序中也会存在进程通信的可能(特别是在一些大型APP中)

QQ:未登陆

微信:使用一段时间后:

场景:在Service中开启定位服务,Service处于单独的进程,需要在App主进程或者其他APP中获得定位结果。

服务中提供暴露给其他进程使用的方法并提供一个 ServiceId 注解标记,而服务实现中必须给到相同的 ServiceId 与方法实现,不强制要求 LocationManager 一定需要继承 ILocationManager j接口,但是为了保证方法签名统一建议继承。(不然一个是getLocation,另一个是getLocation2就不好玩了)

在Service进行定位,定位结果在 LocationManager 中记录。在这个Service中使用框架注册 LocationManager 。

不需要返回 Binder 对象,这意味着使用者不需要编写繁琐没任何提示的AIDL文件。

框架内部会提供 comenjoyipcIPCService$IPCServiceX 多个预留Service,用于与其他进程通信,如果一个App存在多个进程都需要提供各自进程的服务,可以使用不同的Service。所以本质上依然是借助的Service+Binder通信,但框架将细节封装隐藏,使用更加简单。

获得结果对象后就能像调用本地方法一样调用远程方法(RPC调用)。

在使用中简化了:

1、不需要自己定义AIDL接口,使用的JavaBean也不要求实现 Parcelable 接口;

2、在客户端不需要直接使用 bindService 获得 Binder 对象;

服务端需要定义暴露服务的接口(ILocationManager),客户端如果是其他APP,则需要将接口类放到自己的源码中(不需要接口实现)。接口中定义的方法就是服务端提供给其他进程使用的方法。

整个框架包含了服务端与客户端两端接口。

在服务进程中会缓存 ServiceId 与对应的服务实现Class对象: 服务表 ,同时服务实现中的所有方法列表也需要进行记录: 方法表 。由于一个服务中可能存在多个方法,所以其数据结构为 Map<Class,Map<String,Method>> ,外层 Map 的key为服务Class,内层 Map 的key则为方法标记。

当客户端需要调用服务时,将 ServiceId 、MethodName以及执行方法需要的参数传递给服务端,服务端查表利用反射 Method#invoke 即可执行服务中的方法。

其中客户端的请求被封装为 Request 对象,服务端响应则封装为 Response 对象

服务端只需要暴露服务接口给其他进程使用,所以服务端只需要调用框架的注册接口 regiest 对服务实现进行注册。( 注册的是服务实现,而不是服务接口 )

注册时,通过反射获得Class上的 ServiceId 即可记录 服务表 。同时利用反射获得Class中所有的public Method即可记录 方法表

由于框架本质还是利用Binder来完成通信,为了与其他进程通信,框架内部提供了多个预留的Service。

通信Service会返回一个AIDL生成的Binder类对象

客户端使用 send 方法向服务端发起请求。

服务端接收到请求后的实现:

客户端需要先与服务端建立连接,因此框架中提供了 connect 方法,内部封装 bindService 实现与服务端通信Service( IPCService )的绑定。

唯一需要注意的是:

当完成绑定后,客户端就可以获得服务端通信Service提供的 IIPCService 对象,客户端调用 IIPCService#send 发起请求。

当我们需要获得 Location 。则应该调用 LocationManagergetDefault()getLocation() 。这句调用会需要执行 LocationManager 的两个方法: getDefault 与 getLocation 。

然而这个对象存在服务端,客户端如何获得?

我们可以利用动态代理,在客户端创建一个 "假的" 服务接口对象(代理)。

当我们执行这个代理对象的方法( getLocation )时,会回调 IPCInvocationHandler#invoke 方法,在这个方法中框架会向服务端发起请求: IIPCService#send

而 getLocation 会返回一个 Location 记录定位信息的对象,这个对象会被服务端json序列化发送过来,因此,客户端只需要在此处获得 Method 的返回类型并反序列化即可。

RPC指的是:从客户端上通过参数传递的方式调用服务器上的一个函数并得到返回的结果,隐藏底层的通讯细节。在使用形式上像调用本地函数一样去调用远程的函数。

比如我们使用Ok>

Service(服务)一个运行在后台执行长时间运行的 *** 作组件,它不提供任何用户界面,作为与Activity同级的组件,它依旧是运行在主线程中。
其它组件可以启动一个Service,当这个Service启动之后便会在后台执行,这里需要注意,由于是在主线程中,所以我们需要另外开启一个线程来执行我们的耗时 *** 作。
此外,一个组件还可以与一个Service进行绑定来实现组件之间的交互,甚至可以执行IPC(Inter-Process Communication)进程间通信。
Service可以在后台执行很多任务,比如处理网络事务,播放音乐,文件读写或者与一个内容提供者交互,等等。

本地服务(Local)
该服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外本地服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多,当主进程被Kill后,服务便会终止。一般使用在音乐播放器播放等不需要常驻的服务。

远程服务(Remote Service)
该服务是独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。一般定义方式 android:process=":service" 由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。由于是独立的进程,会占用一定资源,并且使用AIDL进行IPC比较麻烦。一般用于系统的Service,这种Service是常驻的。

startService启动的服务
用于启动一个服务执行后台任务,不与组件进行通信,停止服务使用stopService。 当一个应用组件比如activity通过调用startService()来启动一个服务的时候,服务便处于启动状态。一旦启动,服务可以在后台无限期地运行下去,即使当启动它的组件已经销毁。通常情况下,一个启动的service执行一个单一的 *** 作并且不会返回任何结果给调用者。

bindService启动的服务
用于启动的服务需要进行通信。停止服务使用unbindService。 当一个应用组件通过调用bindService()来与一个服务绑定时,服务便处于绑定状态。一个绑定的服务提供了一个客户端-服务器端接口来允许组件与服务进行交互,发送请求,得到结果甚至通过IPC进程间通信来完成 *** 作。只有当其它组件与服务进行绑定时,服务才会处于绑定状态。多个组件可以同时与服务绑定,但是当他们全部都解除绑定时,服务就会销毁。

2BindService:
如果一个Service在某个Activity中被调用bindService方法启动,不论bindService被调用几次,Service的 onCreate 方法只会执行一次,同时 onStartCommand 方法始终不会调用。当建立连接后,Service会一直运行,除非调用unbindService来接触绑定、断开连接或调用该Service的Context不存在了(如Activity被Finish——即通过bindService启动的Service的生命周期依附于启动它的Context),系统在这时会自动停止该Service。

3StartService AND BindService:
当一个Service在被启动(startService 的同时又被绑定(bindService ),该Service将会一直在后台运行,并且不管调用几次, onCreate 方法始终只会调用一次, onStartCommand 的调用次数与startService 调用的次数一致(使用bindService 方法不会调用 onStartCommand )。同时,调用unBindService 将不会停止Service,必须调用stopService 或Service自身的stopSelf 来停止服务。

4停止Service:
当一个服务被终止(stopService 、stopSelf 、unbindService )时, onDestory 方法将会被调用——所以我们需要在该方法中清除一些工作(依附该Service生命周期上的,比如:停止在Service中创建并运行的线程)。

1创建服务

如果你才用的是 startService的方式那么 onBind方法可以忽略
2注册服务

3开启服务
start:

bind

绑定服务,一般涉及到组件或进程之间的通信,既然需要通信,那么我们肯定需要一个连接,这里ServiceConnection就是我们所需要的连接,通过Ibinder的传递,我们可以获取到Service的Ibinder对象,从而进行相关 *** 作。

关于粘性服务,这里需要提到 Service的onStartCommand返回值

andorid:name

adroid:exported

android:enabled

android:label

android:process

android:icon

android:permission

关于服务,当我们在应用开发中,如果需要长时间的在后台运行,独立完成某一些事情的情况下,请使用Service!

此文综合: >

很多同学在昆明北大青鸟java学院学完java开发后因工作需要要求做android开发,于是问我们的咨询老师说:Java能转Android开发吗怎么转需要注意什么了昆明北大青鸟java培训老师为你解答。

1、Java和Android程序的区别

Android是主流智能手机的 *** 作系统,Java是一种开发语言,两者没有好坏优劣之分,只是两种职业岗位的选择。学安卓从事移动互联方向开发,学Java从事软件、网站开发。而安卓上的应用大多是Java编写的,所以建议在安卓前期的Java学习阶段中,要用心学好。

2、Java转Android前的准备

其实Java程序员要自学安卓开发的基础知识还是没有什么难度的,毕竟语言相通,特性相似,阅读安卓源代码的门槛以比较低一些,学习安卓也相对比较轻松一些。

所以Java程序员转安卓开发可以看做是一次“增量更新”,只需要学习一下安卓的基本组件:Activity、ContentProvider、Service、BroadcastReceiver;

了解一下安卓中的Intent,Handler,Adapter以及各类事件的传递方式(onClick,onTouch等);

同时辅助一定的代码量,像JNI、AIDL什么的都可以看一下;你还要摒弃“UI元素像素位置”这个概念,安卓本身是允许通过设定元素位置来制作UI的,如果你这样做导致的结果便是大批机器不适配,那么显示效果就有点惨不忍睹了,所以不要妄想通过获取屏幕大小来调整UI。

还有熟悉ide,安卓提供的开发框架、Java及其他编程知识等。

3、Java转Android经验分享

移动开发和PC上的开发带来了哪些不一样?

从2002年之后,传统桌面的开发者基本都转向了J2EE/NET/LAMP等以Web技术或者服务器端开发技术为主的开发方式。使用C/C++/MFC/Delphi等开发C/S模式的用户越来越少,甚至工作的需求也开始变得越来越少。

那对于移动开发上需要什么?

从桌面端转向移动端,一定要认识到二者不同的侧重点。桌面端包括web更侧重于逻辑复杂,高级的任务,而移动端的娱乐性明显更强。

就从 *** 作方式说起吧,桌面端主要靠鼠标键盘和touchpad,所以 *** 作精度要高得多,很容易将很多功能集成到一个界面里;但同样的思路就完全不适用于移动端了(反例我是实在想不起来了,大家可以帮忙想想),相信一个clutteredui的app,就算功能再强大,用户盯着你的界面超过3s就会头晕,点击某个button要点好几下才会成功,也必定是一个糟糕的app。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/13426607.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-08-03
下一篇 2023-08-03

发表评论

登录后才能评论

评论列表(0条)

保存