Android IPC通信
概述
- 进程时系统资源分配的最小单位;进程间的资源和数据相互隔离;进程内可以运行多个线程,线程的崩溃会影响到进程
- 进程间通信指通过内核提供的机制完成数据交换,IPC(Inter Progress Communication)
- Linux跨进程通信方式:管道、消息队列、信号、共享内存、信号量、套接字
- Android跨进程通信方式
- Binder:稳定性好,优于共享内存方式;性能好,数据拷贝次数优于管道、消息队列、socket;安全性高,UID/PID可见
- AIDL:基于Binder机制,定义IPC过程中接口的一种描述语言,AIDL文件在编译过程中生成接口的实现类,用于IPC通信;支持基本数据类型,实现Parcelable接口的对象,List,Map
- Messenger:基于Binder机制,只支持串行实时通信;只支持bundle传输的数据类型
AIDL
-
AIDL即Android Interface Definition Language,接口定义语言,定义IPC过程中一种描述语言
-
AIDL文件以
.aidl
为后缀名 -
AIDL支持数据类型:
- 基本数据类型:byte、char、short、int、long、float、double、boolean
- String、CharSequence
- 实现Parcelable接口类型
- List和Map类型
-
定向Tag,定义数据的流向
- in:数据只能由客户端向服务端
- out:数据只能服务端向客户端
- inout:客户端与服务端双向流向
-
oneway关键字:单向调用,不需要等待另一个进程的返回结果,不会产生阻塞问题,不能有返回值
-
明确导包,在AIDL文件中需要明确导包定义的数据类型
-
所有IPC调用的方法执行都是在binder线程里,可能需要切换主线程
代码结构
定义AIDL文件
在aidl目录下新建以前文件
package com.example.myapplication;
//关联实体类
//消息类
parcelable Message;
package com.example.myapplication;
/**
* 连接状态服务
*/
interface IConnectionService {
//建立连接
oneway void connect();
//断开连接
void disconnect();
//判断是否已连接
boolean isConnected();
}
package com.example.myapplication;
//导包
import com.example.myapplication.Message;
import com.example.myapplication.MessageReceiveListener;
/**
* 发送消息服务
*/
interface IMessageService {
//发送消息
//实体类需要标记关键字in,基本类型不用
void sendMessage(in Message message);
//注册监听
void registerMessageReceiveListener(MessageReceiveListener messageReceiveListener);
//取消注册
void unregisterMessageReceiveListener(MessageReceiveListener messageReceiveListener);
}
package com.example.myapplication;
//导包
import com.example.myapplication.Message;
/**
* 管理消息监听
*/
interface MessageReceiveListener {
//接收消息
void onReceiveMessage(in Message message);
}
package com.example.myapplication;
//管理类
interface IServiceManager {
IBinder getService(String serviceName);
}
定义消息类
public class Message implements Parcelable {
private String content;
private boolean isSendSuccess;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public boolean isSendSuccess() {
return isSendSuccess;
}
public void setSendSuccess(boolean sendSuccess) {
isSendSuccess = sendSuccess;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.content);
dest.writeByte(this.isSendSuccess ? (byte) 1 : (byte) 0);
}
public void readFromParcel(Parcel source) {
this.content = source.readString();
this.isSendSuccess = source.readByte() != 0;
}
public Message() {
}
protected Message(Parcel in) {
this.content = in.readString();
this.isSendSuccess = in.readByte() != 0;
}
public static final Parcelable.Creator<Message> CREATOR = new Parcelable.Creator<Message>() {
@Override
public Message createFromParcel(Parcel source) {
return new Message(source);
}
@Override
public Message[] newArray(int size) {
return new Message[size];
}
};
}
定义客户端代码
public class MainActivity extends AppCompatActivity {
private IServiceManager serviceManagerProxy;
private IConnectionService connectionServiceProxy;
private IMessageService messageServiceProxy;
private MessageReceiveListener.Stub messageReceiverListener = new MessageReceiveListener.Stub() {
@Override
public void onReceiveMessage(Message message) throws RemoteException {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//接收服务端的消息
Utils.log(message.getContent());
}
});
}
};
@Override
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Intent intent = new Intent(this, RemoteService.class);
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
serviceManagerProxy = IServiceManager.Stub.asInterface(service);
connectionServiceProxy = IConnectionService.Stub.asInterface(serviceManagerProxy.getService(IConnectionService.class.getSimpleName()));
messageServiceProxy = IMessageService.Stub.asInterface(serviceManagerProxy.getService(IMessageService.class.getSimpleName()));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);
binding.connect.setOnClickListener(v -> {
try {
connectionServiceProxy.connect();
} catch (RemoteException e) {
e.printStackTrace();
}
});
binding.disconnect.setOnClickListener(v -> {
try {
connectionServiceProxy.disconnect();
} catch (RemoteException e) {
e.printStackTrace();
}
});
binding.isconnected.setOnClickListener(v -> {
try {
boolean isconnected = connectionServiceProxy.isConnected();
Utils.toast(isconnected ? "连接成功" : "连接失败");
} catch (RemoteException e) {
e.printStackTrace();
}
});
binding.sendMessage.setOnClickListener(v -> {
Message message = new Message();
message.setContent("主进程发送消息-BBB");
try {
//向服务端发送消息
messageServiceProxy.sendMessage(message);
} catch (RemoteException e) {
e.printStackTrace();
}
});
binding.register.setOnClickListener(v -> {
try {
messageServiceProxy.registerMessageReceiveListener(messageReceiverListener);
} catch (RemoteException e) {
e.printStackTrace();
}
});
binding.unregister.setOnClickListener(v -> {
try {
messageServiceProxy.unregisterMessageReceiveListener(messageReceiverListener);
} catch (RemoteException e) {
e.printStackTrace();
}
});
}
}
定义服务端代码
public class RemoteService extends Service {
private Handler handler = new Handler(Looper.getMainLooper());
private boolean isConnected = false;
private RemoteCallbackList<MessageReceiveListener> receiverList = new RemoteCallbackList<>();
private ScheduledThreadPoolExecutor mScheduledThreadPoolExecutor;
private ScheduledFuture mScheduledFuture;
private IConnectionService.Stub connectionService = new IConnectionService.Stub() {
@Override
public void connect() throws RemoteException {
handler.post(() -> Utils.toast("开始连接,等待5s"));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(() -> Utils.toast("连接成功"));
isConnected = true;
mScheduledFuture = mScheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int size = receiverList.beginBroadcast();
for (int i = 0; i < size; i++) {
Message message = new Message();
message.setContent("子进程发送消息-AAA");
try {
//向客户端发送消息
receiverList.getBroadcastItem(i).onReceiveMessage(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
receiverList.finishBroadcast();
}
}, 5000, 5000, TimeUnit.MILLISECONDS);
}
@Override
public void disconnect() throws RemoteException {
handler.post(new Runnable() {
@Override
public void run() {
Utils.toast("断开连接");
}
});
isConnected = false;
mScheduledFuture.cancel(true);
}
@Override
public boolean isConnected() throws RemoteException {
return isConnected;
}
};
private IMessageService.Stub messageService = new IMessageService.Stub() {
@Override
public void sendMessage(Message message) throws RemoteException {
//接收客户端的消息
handler.post(() -> Utils.toast(message.getContent()));
message.setSendSuccess(isConnected);
}
@Override
public void registerMessageReceiveListener(MessageReceiveListener messageReceiveListener) throws RemoteException {
receiverList.register(messageReceiveListener);
}
@Override
public void unregisterMessageReceiveListener(MessageReceiveListener messageReceiveListener) throws RemoteException {
receiverList.unregister(messageReceiveListener);
}
};
private IServiceManager.Stub serviceManager = new IServiceManager.Stub() {
@Override
public IBinder getService(String serviceName) throws RemoteException {
if (IConnectionService.class.getSimpleName().equals(serviceName)) {
return connectionService.asBinder();
} else if (IMessageService.class.getSimpleName().equals(serviceName)) {
return messageService.asBinder();
} else {
return null;
}
}
};
@Override
public void onCreate() {
super.onCreate();
mScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return serviceManager.asBinder();
}
}
AndroidManifest.xml
文件注册
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true"
android:process=":remote1"></service>
Messenger
- Messenger相比AIDL则简单很多
- Messenger需要借助Handler&Message进行通信
获取Messenger对象
sendMessenger = new Messenger(serviceManagerProxy.getService(Messenger.class.getSimpleName()));
定义客户端代码
Messenger向服务端发送消息
Message message = new Message();
message.setContent("messenger发送了一个消息");
android.os.Message data = android.os.Message.obtain();
data.replyTo = receiveMessenger;//设置用于接收消息的Messenger
Bundle bundle = new Bundle();
bundle.putParcelable("message", message);
data.setData(bundle);
sendMessenger.send(data);
定义服务端
private Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(@NonNull android.os.Message msg) {
super.handleMessage(msg);
receive(msg);
send(msg);
}
//接收客户端的消息
private void receive(@NotNull android.os.Message msg) {
Bundle data = msg.getData();
data.setClassLoader(Message.class.getClassLoader());//防止序列化问题
Message message = data.getParcelable("message");
Utils.toast(message.getContent());
}
//向客户端回复消息
private void send(@NonNull android.os.Message msg) {
try {
Message message = new Message();
message.setContent("Messenger回复一个消息");
android.os.Message data = android.os.Message.obtain();
Bundle bundle = new Bundle();
bundle.putParcelable("message", message);
data.setData(bundle);
Messenger m = msg.replyTo;
m.send(data);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
private Messenger messenger = new Messenger(handler);