一、为什么使用RemoteCallbackList?
在使用aidl进行ipc的进程通信过程中,需要实时监听通信的信息和数据变化等,可以将callback保存到该RemoteCallbackList列表中,在需要使用的时候,进行调用。同时也可以防止重复调用同一个callback任务。
1、比较重要的几个方法
public class RemoteCallbackList<E extends IInterface> {
// 初始化方法
public RemoteCallbackList() {
throw new RuntimeException("Stub!");
}
// 用于将callback监听注册到列表中,以供后续调用
public boolean register(E callback) {
throw new RuntimeException("Stub!");
}
public boolean register(E callback, Object cookie) {
throw new RuntimeException("Stub!");
}
// 取消注册callback
public boolean unregister(E callback) {
throw new RuntimeException("Stub!");
}
// 开始对callback列表进行调用,返回值是回调集合的数量大小
public int beginBroadcast() {
throw new RuntimeException("Stub!");
}
// 获取index位置的callback
public E getBroadcastItem(int index) {
throw new RuntimeException("Stub!");
}
// 结束对callback列表的调用,并清除beginBroadcast的状态
public void finishBroadcast() {
throw new RuntimeException("Stub!");
}
/**
* 与beginBroadcast返回值不一定相同,如果初始化时调用,返回值一样
* 如果在使用过后或unregister/register,index不为0时调用,则返回值不同
*/
// 获取当前callback列表的需要处理的数量
public int getRegisteredCallbackCount() {
throw new RuntimeException("Stub!");
}
}
二、使用
1、服务端
i、编写aidl接口
// ICallbackTestCallback.aidl
package com.icallback;
oneway interface ICallbackTestCallback {
void onReceived(String msg);
}
package com.icallback;
// import callback
import com.icallback.ICallbackTestCallback;
oneway interface ICallbackTestInterface {
void registerListener(ICallbackTestCallback callback);
void unregisterListener(ICallbackTestCallback callback);
void sendMsg(String msg);
}
ii、调用service,开启服务
public class CallbackService extends Service {
private static final String TAG = "CallbackService";
private final RemoteCallbackList<ICallbackTestCallback> listenerList = new RemoteCallbackList<>();
private boolean isConnected = false;
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind()");
return mBinder;
}
@Override
public void onCreate() {
Log.i(TAG, "OnCreate()");
isConnected = true;
new Thread(runnable).start();
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "OnStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "OnDestroy()");
isConnected = false;
super.onDestroy();
}
/**
* 实现Binder方法
*/
private final ICallbackTestInterface.Stub mBinder = new ICallbackTestInterface.Stub() {
@Override
public void registerListener(ICallbackTestCallback callback) throws RemoteException {
Log.i(TAG, "registerListener(), from pid = " + Binder.getCallingPid());
listenerList.register(callback);
}
@Override
public void unregisterListener(ICallbackTestCallback callback) throws RemoteException {
Log.i(TAG, "unregisterListener(), from pid = " + Binder.getCallingPid());
listenerList.unregister(callback);
}
@Override
public void sendMsg(String msg) throws RemoteException {
Log.i(TAG, "received msg: " + msg + ", from client pid = " + Binder.getCallingPid());
}
};
/**
* 发送信息给客户端
* @param msg:信息
*/
private void sendMsgToClients(String msg) {
listenerList.beginBroadcast();
for (int i = 0; i < listenerList.getRegisteredCallbackCount(); i++) {
try {
listenerList.getBroadcastItem(i).onReceived(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
listenerList.finishBroadcast();
}
/**
* 发送信息给客户端的具体方法
*/
private final Runnable runnable = () -> {
int count = 0;
while (isConnected) {
try {
Thread.sleep(500);
sendMsgToClients(Integer.toString(count++));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
2、客户端
i、编写aidl接口
// ICallbackTestCallback.aidl
package com.zx.icallback;
interface ICallbackTestCallback {
void onReceived(String msg);
}
package com.zx.icallback;
import com.zx.icallback.ICallbackTestCallback;
interface ICallbackTestInterface {
void registerListener(ICallbackTestCallback callback);
void unregisterListener(ICallbackTestCallback callback);
void sendMsg(String msg);
}
ii、调用aidl
package com.binderclient;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.zx.icallback.ICallbackTestCallback;
import com.zx.icallback.ICallbackTestInterface;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private boolean isBind = false;
ICallbackTestInterface remoteServer = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
findViewById(R.id.register_btn).setOnClickListener(view -> registerCallback());
findViewById(R.id.unregister_btn).setOnClickListener(view -> unregisterCallback());
findViewById(R.id.bind_btn).setOnClickListener(view -> bindServer());
}
@Override
protected void onPause() {
if (isBind) {
registerCallback();
}
super.onPause();
}
@Override
protected void onResume() {
if (isBind) {
registerCallback();
}
super.onResume();
}
private final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i(TAG, "onServiceConnected()");
remoteServer = ICallbackTestInterface.Stub.asInterface(iBinder);
registerCallback();
isBind = true;
try {
iBinder.linkToDeath(() -> {
Log.i(TAG, "binder death");
},0);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i(TAG, "onServiceDisconnected()");
}
};
private final ICallbackTestCallback callback = new ICallbackTestCallback.Stub(){
@Override
public void onReceived(String msg) {
Log.d(TAG, "received msg : " + msg + ", from server pid = " + Binder.getCallingPid());
}
};
private void registerCallback(){
if (remoteServer != null) {
try {
remoteServer.registerListener(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
}else {
Log.e(TAG, "remoteServer is null!");
}
}
private void unregisterCallback(){
if (remoteServer != null) {
try {
remoteServer.unregisterListener(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
}else {
Log.e(TAG, "remoteServer is null!");
}
}
private void sendMsg(String msg) {
if (remoteServer != null) {
try {
remoteServer.sendMsg(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}else {
Log.e(TAG, "remoteServer is null!");
}
}
private void bindServer(){
Log.i(TAG, "bindServer");
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.icallback.server", "com.icallback.server.CallbackService"));
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
}