IPC机制之Messenger示例(二)
IPC机制之AIDL传递Parcelable(三)
IPC机制之AIDL实现客户端回调(四)
Q:为什么标题是基础类型呢?
- 这个需要我简单介绍下,在Binder基础上的IPC通信主要分为Messenger和AIDL,Messenger的本质也是AIDL,所以我们需要知道AIDL支持传递哪些类型的数据,见下图。
图片来自任玉刚的《Android开发艺术探索》
Q:Messenger和AIDL的区别?
- Messenger底层也是AIDL,只是屏蔽了其细节;
- 服务端的Messenger是串行的方式执行客户端发来的消息,说明即使在有并发的情况下,Messenger也会一个个执行,而AIDL我们可以自己去处理并发;
- Messenger主要是传递消息,但我们时常需要跨进程调用方法;
如果需要了解Messenger传递消息可以查看 IPC机制之Messenger示例。
Show me the code.
Client#IMyAidlInterface.aidl
package com.aidl.wzf.aidl;
interface IMyAidlInterface {
int add(int num1,int num2);
}
Client#MainActivity.java
package com.aidl.wzf.aidl;
import 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.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private IMyAidlInterface aidlInterface;
private Button btnCalc;
private TextView tvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnCalc = (Button) findViewById(R.id.btn_calc);
tvResult = (TextView) findViewById(R.id.tv_result);
btnCalc.setOnClickListener(this);
bindService();
}
private void bindService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.aidl.wzf.aidl", "com.aidl.wzf.aidl.IRemoteService"));
this.bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
aidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
try {
// 绑定远程服务死亡代理,如果远程服务有断开,将会在binderDied中有回调
iBinder.linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
aidlInterface = null;
}
};
IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (aidlInterface == null) return;
aidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
aidlInterface = null;
// 重新绑定
bindService();
}
};
@Override
public void onClick(View view) {
try {
int mTotal = aidlInterface.add(2, 5);
tvResult.setText("" + mTotal);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
Server#IMyAidlInterface.aidl
package com.aidl.wzf.aidl;
interface IMyAidlInterface {
int add(int num1,int num2);
}
Server#IRemoteService.java
package com.aidl.wzf.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
public class IRemoteService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private IBinder iBinder = new IMyAidlInterface.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
Log.i("info", "触发服务端");
return num1 + num2;
}
};
}
AndroidManifest
<service
android:name=".IRemoteService"
android:exported="true"
android:process=":remote" />
注意:
1. 服务端和客户端是2个Module;
2. 服务端和客户端的.aidl文件的包名必须相同;
3. Manifest中的Service必须设置 android:exported=”true”以保证允许其他组件调用,适用于四大组件;
4. 如果已经确定了Servcer和Client在不同进程,可以删除 android:process=”:remote”属性。