大佬教程收集整理的这篇文章主要介绍了Android Binder,AIDL跨进程通讯详解与实现,看一遍就懂,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
Binder 是一种进程间通信机制 整个app属于客户端,系统是服务端,他们之间的通讯就是通过IPC交互,中间服务就是serviceSystem 优点:性能,稳定性,安全性 设计:Client/Server/ServiceManager/驱动 实现:AIDL
1.可以通过AndroidStudio创建:
1.1选中一个包进行新建一个aidl,系统会自动生成一个aidl的文件夹
1.2手动创建文件夹,创建包名,然后在包内创建aidl文件。
1.3我们创建两个AIDL文件 IMsgManager.aidl,IReceiverMsgListener
IMsgManager:消息管理类,提供消息的接口
IReceiverMsgListener:消息接收类,做转发使用
1.4Msg是对象,aidl常见的参数只支持简单的数据类型,对象需要通过Parcelable序列化处理。
1.4.1 先定义一个Msg 实现 Parcelable接口,,注意这个类的包名一定要与aidl文件下的包名一致,因为我们要定义一个空的Msg.aidl文件,这样Msg.aidl文件才会与Msg.Java文件关联起来
Msg.aidl文件:删除interface Msg,将Msg申明为 parcelable;
这样就就可以了。
IMsgManager:
由于aidl文件不能关联,使用类都需要手动导入包名。
IReceiveMsgListener:
定义好AIDL文件,我们要生成对应的java文件:点击
将项目编译一下,aidl文件对应的java文件出现在这个下方。
这个时候有人会发现少了一个Msg的java文件,由于我们将Msg.aidl申明为 parcelable,将会关联Parcelable的实体,和java文件已关联起来。
这样,我们就可以通过aidl发送自定义对象。
2.Service的处理(C/S)
2.1我们需要创建一个Service ,作为服务端在监控
public class MySevice extends Service { //AIDL不支持正常的接口回调,使用RemoteCallbackList实现接口回调 private RemoteCallbackList<IReceiveMsgListener> mReceiveListener = new RemoteCallbackList<IReceiveMsgListener>(); @Nullable @Override public IBinder onBind(Intent intent) { return new MyIBinder(); } public class MyIBinder extends IMsgManager.Stub { @Override public void sendMsg(Msg msg) throws RemoteException { receiveMsg(msg); } @Override public void registerReceiveListener(IReceiveMsgListener receiveListener) throws RemoteException { mReceiveListener.register(receiveListener); } @Override public void unregisterReceiveListener(IReceiveMsgListener receiveListener) throws RemoteException { boolean success = mReceiveListener.unregister(receiveListener); if (success){ Log.d("tag","=== 解除注册成功"); }else { Log.d("tag","=== 解除注册失败 "); } } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { return super.onTransact(code, data, reply, flags); } }; //收到消息处理 public void receiveMsg(Msg msg) { //通知Callback循环开始,返回size为实现mReceiveListener回调的个数 final int size = mReceiveListener.beginBroadcast(); msg.setMsg("我是服务器,我收到了:"+msg.getMsg()); for (int i = 0; i < size; i++){ IReceiveMsgListener listener = mReceiveListener.getBroadcastItem(i); if (listener != null){ try { listener.onReceive(msg); } catch (RemoteException e) { e.printStackTrace(); } } } //通知通知Callback循环结束 mReceiveListener.finishBroadcast(); } }
2.2将service注册到AndroidManifest
<service android:name="com.example.mydemo.service.MySevice" android:process=":remote"//同一应用内跨进程通信需 android:enabled="true" android:exported="true" //暴露 > <intent-filter> <action android:name="com.test.aidl.action"/> </intent-filter> </service>
3.1绑定服务
IMsgManager myIBinder = null; private TextView textView; private Button button_1, button_2, button_3; public static final String ACTIO_SERVICE = "com.test.aidl.action"; IMsgManager iMsgManager; private EditText editText_1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { editText_1=findViewById(R.id.edit_1); textView = findViewById(R.id.text_1); button_1 = findViewById(R.id.btn_1); button_2 = findViewById(R.id.btn_2); button_3 = findViewById(R.id.btn_3); button_1.setOnClickListener(this); button_2.setOnClickListener(this); button_3.setOnClickListener(this); } @Override public void onClick(View v) { if (v == button_1) { //绑定 bindService(); } else if (v == button_2) { //发送 try { if (myIBinder != null) { if (editText_1.getText().toString().isEmpty()) return; Msg msg = new Msg("服务端发送:"+editText_1.getText()); myIBinder.sendMsg(msg); } } catch (RemoteException e) { e.printStackTrace(); } } else if (v == button_3) { //解绑 unbindService(connection); } } private void bindService() { //注册service Intent intent = new Intent(this, MySevice.class); intent.setAction(ACTIO_SERVICE); bindService(intent, connection, Service.BIND_AUTO_CREATE); } //service的链接 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myIBinder = IMsgManager.Stub.asInterface(service); iMsgManager = IMsgManager.Stub.asInterface(service); try { //注册binder连接 iMsgManager.asBinder().linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { e.printStackTrace(); } try { iMsgManager.registerReceiveListener(mReceiveMsgListener); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { //断开连接 } }; private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { // //当承载IBinder的进程消失时接收回调的接口 @Override public void binderDied() { if (null == iMsgManager) { return; } //解绑 iMsgManager.asBinder().unlinkToDeath(mDeathRecipient, 0); iMsgManager = null; } }; private IReceiveMsgListener mReceiveMsgListener = new IReceiveMsgListener.Stub() { @Override public void onReceive(Msg msg) throws RemoteException { //消息分发 textView.append("n" + msg.getMsg()); } };
这样就完成再App的消息分发
由于我们已完成了一个service端的开发,我们在创建一个新的app,作为令一个进程。
4.1同样把所service APP中的aidl复制到B的app中,Msg对象也要一同复制到对应的包下(两边保持一致)
把Msg自定义的实体也复制过来。两边要保持包名一致。接下我们还是需要make一下项目。
执行完,会生成一下
4.2 实现service的绑定,可以把A app的代码复制过来。修改注册service方法
IMsgManager myIBinder = null;
private TextView textView;
private Button button_1, button_2, button_3;
public static final String ACTIO_SERVICE = "com.test.aidl.action";
IMsgManager iMsgManager;
EditText edit_1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
edit_1=findViewById(R.id.edit_1);
textView = findViewById(R.id.text_1);
button_1 = findViewById(R.id.btn_1);
button_2 = findViewById(R.id.btn_2);
button_3 = findViewById(R.id.btn_3);
button_1.setOnClickListener(this);
button_2.setOnClickListener(this);
button_3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == button_1) {
//绑定
bindService();
} else if (v == button_2) {
//接收
try {
if (myIBinder != null) {
if (edit_1.getText().toString().isEmpty())
return;
Msg msg = new Msg("客户端发送:"+edit_1.getText());
myIBinder.sendMsg(msg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
} else if (v == button_3) {
//解绑
unbindService(connection);
}
}
private void bindService() {
//绑定需要注意一下,由于我们启动其他应用的,需要知道包名和,filter-action
Intent intent = new Intent();
intent.setPackage("com.example.mydemoa");//包名,服务端的包名(service)
intent.setAction(ACTIO_SERVICE);//action
bindService(intent, connection, Service.BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myIBinder = IMsgManager.Stub.asInterface(service);
iMsgManager = IMsgManager.Stub.asInterface(service);
try {
iMsgManager.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
try {
iMsgManager.registerReceiveListener(mReceiveMsgListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private void showUI() throws RemoteException {
}
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
// //当承载IBinder的进程消失时接收回调的接口
@Override
public void binderDied() {
if (null == iMsgManager) {
return;
}
iMsgManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
iMsgManager = null;
}
};
private IReceiveMsgListener mReceiveMsgListener = new IReceiveMsgListener.Stub() {
@Override
public void onReceive(Msg msg) throws RemoteException {
msg.setTime(System.currentTimeMillis());
textView.append("n" + msg.getMsg());
}
};
4.4这样基本完成,接下来开始测试。测试先启动service的app。然后在打开b的,否则B打开,service没有启动,导致消息无法传递
五、结果:
这样就完成了跨进程消息传递
注意:关于自定义对象,是先创建一个实体对象,实现Parcelable接口,再在aidl文件夹下的包内创建一个aidl文件名为java一样的。同事包名也一样,删除aidl文件内接口代码行,
interface Msg{
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
}
然后改成申明为:parcelable Msg;即可。不然会报错。网上大多数教程都没有交会如何关联自定义java文件与aidl文件。
*************************************************************************************************************
很感谢官方,今天刚整理好,就推上了领域内容热榜第八名。以后将会写出更好的博客回馈大家。
以上是大佬教程为你收集整理的Android Binder,AIDL跨进程通讯详解与实现,看一遍就懂全部内容,希望文章能够帮你解决Android Binder,AIDL跨进程通讯详解与实现,看一遍就懂所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。