Android AIDL通信之注册和解注册监听器

简介: 笔记

使用场景


在AIDL通信时,通常我们可以利用观察者模式将客户端注册到服务端,接着有消息的时候服务端相应的通知各个客户端就可以了,这种方式在客户端和服务端处于同一进程的时候使用是没有问题的,因为同一进程内部是可以直接传递对象的,并不会出现注册绑定到服务端和解注册的对象不同的情况。但是如果放到不同进程间的话,因为通信过程中涉及到了序列化反序列化过程,那么势必会造成你注册的对象和解注册的对象并不是同一对象的情况。这时使用普通的解注册方法就无效了。下面列出了我的使用场景。


普通方式注册和解注册


监听器AIDL接口

// IATServiceListener.aidl
package com.flyscale.atclient.service;
import com.flyscale.atclient.bean.SubPhone;
interface IATServiceListener {
    void onSubPhoneCallStateChanged(String id, int status);
    void onRefreshRegisteredSubPhone(out List<SubPhone> subPhones);
}

注册和解注册监听器:

//保存监听器的列表
private CopyOnWriteArrayList<IATServiceListener> mATServieListeners = new CopyOnWriteArrayList<IATServiceListener>();
//注册
public void addATServiceListener(IATServiceListener listener) {
    mATServieListeners.add(listener);
}
//解注册
public void removeATServiceListener(IATServiceListener listener) {
    Log.i(TAG, "removeATServiceListener");
    if(mATServieListeners.contains(listener)){
        Log.d(TAG, "remove listener success!");
        mATServieListeners.remove(listener);
    }
}

测试情况:

在跨进程情况下,调用注册和解注册接口,最终是没有打印Log.d(TAG, "remove listener success!");这一行的。这是为什么呢?

原因就在于我们的注册对象listener是在进程间传输的,Binder在服务端会把客户端传递过来的对象重新转换为新的对象,因而注册和解注册的根本就不是一个对象。它们在内存中的地址是不同的。


Binder的跨进程机制


AIDL其实就是使用的Binde机制来跨进程通信,所以它肯定有办法把两个不同进程中的两个对象联系起来。其实在注册和解注册时加上如下log就会发现:

Log.d(TAG, listener.asBinder());

两个对象的Binder是一样的,这样就好办了。我们通过直接判断它们的Binder是否相同就可以了。

public void removeATServiceListener(IATServiceListener listener) {
    Log.i(TAG, "removeATServiceListener");
    for(IATServiceListener:localListener: mATServieListeners){
        if(localListener.asBinder == listener.asBinder()){
            Log.d(TAG, "remove listener success!");
            mATServieListeners.remove(listener);
        }
    }   
}

问题解决了!

目录
相关文章
|
19天前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
117 4
|
3月前
|
Java Android开发 Spring
Android Spingboot 实现SSE通信案例
【7月更文挑战第14天】以下是使用Android和Spring Boot实现SSE(Server-Sent Events)通信的案例摘要: 在`MainActivity`中: - 初始化界面元素并设置按钮点击事件。 - `startSseRequest`方法创建`WebClient`对象,设置请求头,发送请求,并处理响应和错误。 请确保将`your-server-url`替换为实际的服务器地址。
76 14
|
3月前
|
监控 Android开发 开发者
Android经典面试题之实战经验分享:如何简单实现App的前后台监听判断
本文介绍在Android中判断应用前后台状态的两种方法:`ActivityLifecycleCallbacks`和`ProcessLifecycleOwner`。前者提供精细控制,适用于需针对每个Activity处理的场景;后者简化前后台检测,适用于多数应用。两者各有优劣:`ActivityLifecycleCallbacks`更精确但复杂度高;`ProcessLifecycleOwner`更简便但可能在极端场景下略有差异。根据应用需求选择合适方法。
29 2
|
2月前
|
Android开发
Android项目架构设计问题之C与B通信如何解决
Android项目架构设计问题之C与B通信如何解决
12 0
|
2月前
|
移动开发 前端开发 weex
Android项目架构设计问题之模块化后调用式通信如何解决
Android项目架构设计问题之模块化后调用式通信如何解决
12 0
|
2月前
|
Java Android开发 UED
安卓scheme_url调端:如果手机上多个app都注册了 http或者https 的 intent。 调端的时候,调起哪个app呢?
当多个Android应用注册了相同的URL Scheme(如http或https)时,系统会在尝试打开这类链接时展示一个选择对话框,让用户挑选偏好应用。若用户选择“始终”使用某个应用,则后续相同链接将直接由该应用处理,无需再次选择。本文以App A与App B为例,展示了如何在`AndroidManifest.xml`中配置对http与https的支持,并提供了从其他应用发起调用的示例代码。此外,还讨论了如何在系统设置中管理这些默认应用选择,以及建议开发者为避免冲突应注册更独特的Scheme。
|
3月前
|
API Android开发
Android 监听Notification 被清除实例代码
Android 监听Notification 被清除实例代码
|
4月前
|
Android开发
技术经验分享:Android前后台切换的监听
技术经验分享:Android前后台切换的监听
50 2
|
4月前
|
数据库 Android开发 数据安全/隐私保护
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
178 2
|
3月前
|
Dart Android开发 Windows
Flutter和Native 通信 android端
Flutter和Native 通信 android端