Binder连接池
先创建不同需求的AIDL接口
1
2
3
4
5
6
7
8
9
10interface ICompute {
//计算加法的功能
int add(int a,int b);
}
interface ISecurityCenter {
//加密
String encrypt(String content);
//解密
String decrypt(String password);
}对创建的接口进行实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public class ComputeImpl extends ICompute.Stub{
public int add(int a, int b) throws RemoteException {
return a+b;
}
}
public class SecurityCenterImpl extends ISecurityCenter.Stub{
private static final char SECRET_CODE='^';
public String encrypt(String content) throws RemoteException {
char[] chars = content.toCharArray();
for (int i = 0; i < chars.length; i++) {
// 核心加密逻辑
chars[i] ^= SECRET_CODE;
}
return new String(chars);
}
public String decrypt(String password) throws RemoteException {
return encrypt(password);
}
}为Binder连接池创建AIDL接口
1
2
3
4
5
6
7
8// IBinderPool.aidl
package com.example.contentprovider;
// Declare any non-default types here with import statements
interface IBinderPool {
IBinder queryBinder(int binderCode);
}Binder连接池的具体实现(首先要去绑定远程服务,绑定成功后,客户端可以通过queryBinder方法去获取各自对应的Binder,拿到所需的Binder后,就可以进行各自的操作了)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import java.util.concurrent.CountDownLatch;
/**
* Binder连接池的客户端实现。
* 这是一个采用单例模式设计的核心类,负责管理与远程BinderPoolService的连接,
* 并作为客户端获取各种具体业务Binder的统一入口。
* 它将异步的bindService过程封装成了同步的调用方式,简化了客户端的使用。
*/
public class BinderPool {
// 日志标签
private static final String TAG = "BinderPool";
// Binder代号:无效Binder
public static final int BINDER_NONE = -1;
// Binder代号:计算服务
public static final int BINDER_COMPUTE = 0;
// Binder代号:安全中心服务
public static final int BINDER_SECURITY_CENTER = 1;
// 应用上下文,使用getApplicationContext()防止内存泄漏
private Context mContext;
// 远程Binder池服务的代理对象,用于调用远程方法
private IBinderPool mBinderPool;
// BinderPool的唯一静态实例,volatile关键字确保多线程下的可见性
private static volatile BinderPool sInstance;
// 同步辅助工具,用于在连接建立完成前阻塞线程
private CountDownLatch mConnectBinderPoolCountDownLatch;
/**
* 私有构造函数,确保只能通过getInstance()方法获取实例(单例模式)。
* @param context 上下文对象
*/
private BinderPool(Context context) {
mContext = context.getApplicationContext();
// 构造时立即开始连接服务
connectBinderPoolService();
}
/**
* 获取BinderPool的唯一实例(线程安全的双重检查锁定单例模式)。
* @param context 上下文对象
* @return BinderPool的单例
*/
public static BinderPool getInstance(Context context) {
if (sInstance == null) {
// synchronized 锁就像一个单人房间,一次只允许一个线程进入,保证线程安全
synchronized (BinderPool.class) {
// 第二次检查,防止多个线程同时通过第一次检查后重复创建实例
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
/**
* 同步连接远程服务的方法。
* 该方法会阻塞调用线程,直到与服务的连接成功建立。
*/
private synchronized void connectBinderPoolService() {
// 初始化一个计数为1的CountDownLatch,作为阻塞的“门闩”
mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext, BinderPoolService.class);
// 异步绑定服务,绑定结果通过 mBinderPoolConnection 回调
mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
try {
// 阻塞当前线程,等待门闩被打开(即等待onServiceConnected中的countDown()被调用)
mConnectBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 从Binder连接池中查询具体的业务Binder。
* 这是提供给外部调用的核心方法。
* @param binderCode 业务Binder的代号(如 BINDER_COMPUTE)
* @return 对应的业务Binder接口;如果连接未建立或发生异常则返回null
*/
public IBinder queryBinder(int binderCode) {
IBinder binder = null;
try {
// 确保连接池代理不为空,然后发起跨进程调用
if (mBinderPool != null) {
binder = mBinderPool.queryBinder(binderCode);
}
} catch (RemoteException e) {
// 捕获远程调用异常
e.printStackTrace();
}
return binder;
}
/**
* ServiceConnection的实现,用于监听与服务的连接状态。
*/
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
/**
* 当与服务的连接成功建立时被回调(运行在主线程)。
*/
public void onServiceConnected(ComponentName name, IBinder service) {
// 将返回的原始IBinder对象转换为我们定义的IBinderPool接口
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
// 设置死亡代理,监听远程Binder的死亡事件,增强健壮性
mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
// 连接成功,打开“门闩”,唤醒所有等待的线程
mConnectBinderPoolCountDownLatch.countDown();
}
/**
* 当与服务的连接意外断开时被回调(例如服务进程崩溃)。
* 注意:正常解绑不会触发此方法。
*/
public void onServiceDisconnected(ComponentName name) {
// 此处可以添加重连逻辑
}
};
/**
* 死亡代理的实现。当远程服务进程意外死亡时,binderDied()方法会被回调。
*/
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
public void binderDied() {
Log.w(TAG, "binder died");
// 1. 解除之前与已死亡Binder的死亡监听
mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
// 2. 将持有的Binder代理置为空,防止误用
mBinderPool = null;
// 3. 立即尝试重新连接服务,实现自动恢复
connectBinderPoolService();
}
};
/**
* 这是IBinderPool接口的服务端实现。
* 它作为Binder连接池的“工厂”,根据客户端请求的binderCode,返回对应的具体业务Binder。
* (通常这个类会放在服务端,这里放在一起是为了演示方便)
*/
public static class BinderPoolImpl extends IBinderPool.Stub {
public BinderPoolImpl() {
super();
}
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
// 使用switch-case结构分发不同的Binder实现
switch (binderCode) {
case BINDER_SECURITY_CENTER: {
// 如果客户端请求安全中心,就创建一个SecurityCenterImpl实例
binder = new SecurityCenterImpl();
break;
}
case BINDER_COMPUTE: {
// 如果客户端请求计算服务,就创建一个ComputeImpl实例
binder = new ComputeImpl();
break;
}
default:
break;
}
return binder;
}
}
}服务端实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class BinderPoolService extends Service {
private static final String TAG="BinderPoolService";
//这一行代码的作用是创建并持有一个“Binder 管理员”的实例。
//这个实例就是客户端在绑定服务后,第一个也是唯一一个直接交互的对象。
private Binder mBinderPool=new BinderPool.BinderPoolImpl();
public void onCreate() {
super.onCreate();
}
public BinderPoolService() {
}
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
return mBinderPool;
}
public void onDestroy() {
super.onDestroy();
}
}使用实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26private void doWork(){
// 1. 获取 BinderPool 的单例实例。
BinderPool binderPool=BinderPool.getInstance(this);
// 2. 向远程服务查询用于安全加密的 Binder。
IBinder securityBinder=binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
//3. 将底层的 IBinder 对象转换为我们定义的 AIDL 接口 ISecurityCenter。
ISecurityCenter mSecurityCenter=(ISecurityCenter) SecurityCenterImpl.asInterface(securityBinder);
//4.使用接口方法
String msg="Android";
System.out.println("content:"+msg);
try {
String password=mSecurityCenter.encrypt(msg);
System.out.println("encrypt:"+password);
System.out.println("decrypt:"+mSecurityCenter.decrypt(password));
}catch (RemoteException e){
e.printStackTrace();
}
Log.d(TAG, "visit ICompute");
IBinder computeBinder=binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
ICompute mCompute=ComputeImpl.asInterface(computeBinder);
try {
System.out.println("3+5="+mCompute.add(3,5));
}catch (RemoteException e){
e.printStackTrace();
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Auroraの世界!




