1.Binder的原理
Binder主要是解决跨进程通信。分为Client和Server两个进程。
Client和Server是相对的,也就是说谁发消息谁就是Client,然后收消息就是Server。ServiceManager负责吧Binder Server注册到一个容器中。
Binder的通信过程。
①首先Server在ServerManager容器中注册。
②如果Client若要调用Server的方法,首先要获取到Server对象,但是ServerManager不会把真正的Server对象返回给Client,而是返回Service的一个代理对象Proxy。
③Client调用Proxy的方法,ServiceManager会帮它调用Server的方法,并且返回到Client中。
2.AIDL的原理
AIDL的使用: https://blog.csdn.net/yuezheyue123/article/details/83029018
学习AIDL需要知道的几个类
IBinder
IInterface
Binder
Proxy
Stub
自动生成的AIDL的代码:
public interface IMyAidlInterface extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.aldltest1.IMyAidlInterface {
private static final java.lang.String DESCRIPTOR = "com.example.aldltest1.IMyAidlInterface";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.aldltest1.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.aldltest1.IMyAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.aldltest1.IMyAidlInterface))) {
return ((com.example.aldltest1.IMyAidlInterface) iin);
}
return new com.example.aldltest1.IMyAidlInterface.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getNameOut: {
data.enforceInterface(descriptor);
java.lang.String _result = this.getNameOut();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getUserBeanOut: {
data.enforceInterface(descriptor);
com.example.aldltest1.bean.User _result = this.getUserBeanOut();
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setUserIn: {
data.enforceInterface(descriptor);
com.example.aldltest1.bean.User _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.aldltest1.bean.User.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.setUserIn(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getUserOut: {
data.enforceInterface(descriptor);
com.example.aldltest1.bean.User _arg0;
_arg0 = new com.example.aldltest1.bean.User();
this.getUserOut(_arg0);
reply.writeNoException();
if ((_arg0 != null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_getUserInOut: {
data.enforceInterface(descriptor);
com.example.aldltest1.bean.User _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.aldltest1.bean.User.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.getUserInOut(_arg0);
reply.writeNoException();
if ((_arg0 != null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.example.aldltest1.IMyAidlInterface {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.lang.String getNameOut() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getNameOut, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public com.example.aldltest1.bean.User getUserBeanOut() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.example.aldltest1.bean.User _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getUserBeanOut, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = com.example.aldltest1.bean.User.CREATOR.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
//跨进程 从当前进程向Service中传递数据
//注意in out inout的使用 双向通讯
@Override
public void setUserIn(com.example.aldltest1.bean.User user) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((user != null)) {
_data.writeInt(1);
user.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_setUserIn, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void getUserOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getUserOut, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
user.readFromParcel(_reply);
}
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void getUserInOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((user != null)) {
_data.writeInt(1);
user.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_getUserInOut, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
user.readFromParcel(_reply);
}
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getNameOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getUserBeanOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_setUserIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_getUserOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
static final int TRANSACTION_getUserInOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
}
public java.lang.String getNameOut() throws android.os.RemoteException;
public com.example.aldltest1.bean.User getUserBeanOut() throws android.os.RemoteException;
//跨进程 从当前进程向Service中传递数据
//注意in out inout的使用 双向通讯
public void setUserIn(com.example.aldltest1.bean.User user) throws android.os.RemoteException;
public void getUserOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException;
public void getUserInOut(com.example.aldltest1.bean.User user) throws android.os.RemoteException;
}
①从Client看,对于AIDL的使用者:
MyAidl.Stub.asInterface(binder).xxxx();
asInterface方法的作用就是判断IBinder对象是否和自己处于同一个进程
如果是,那么就直接将转换使用,接下来和Binder的跨进程通讯无关
如果不是,那么就要把IBinder包装成一个Proxy对象,这时候通过Proxy来调用其中的方法。
②直接使用的情况:
首先可以发现Stub是实现了IMyAidlInterface接口,然后在MyService类中,已经自定义了类Stub类,并且重写了getNameOut()等方法。因此在activity中直接就可以进行使用。
③转化成Proxy的情况
在代理类中,已经自动生成了相应的方法的代码,比如getNameOut()方法,这里的mRemote其实就是Stub的对象。然后调用的是Stub的transact()方法。这样将数据传递给Service端。
具体的实现是在Binder类中,它会默认调用自身的onTransact()方法。
④从Server上看,会通过onTransact方法接受Client进程传递过来的数据。
这里应该会调用Stub的onTransact方法
注意:在service中的binder对象和再activity中接受的binder对象是不一致的
在activity中返回的是一个BinderProxy