移步Android跨进程通信IPC
简介
在创建完aidl文件并对项目Rebuild后系统会自动生成与之对应的java文件。下面将会对生成的java文件做注释分析,生成的java文件也将使用上篇文章的IService.aidl生成的java文件。
代码分析
全部源码
package com.wuyazhou.learn.IPC.aidl;
//在Binder中可以传输的接口都需要继承IInterface
public interface IService extends android.os.IInterface
{
//IService的内部类Stub,继承Binder,主体部分关联至服务端Service,内部类Proxy部分关联至客户端Client。Stub继承外部接口,也是接口实体类。
public static abstract class Stub extends android.os.Binder implements com.wuyazhou.learn.IPC.aidl.IService
{
private static final java.lang.String DESCRIPTOR = "com.wuyazhou.learn.IPC.aidl.IService";
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
//通过此静态方法可获取到aidl实体Stub,或者Stub的代理类Proxy
public static com.wuyazhou.learn.IPC.aidl.IService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//判断客户端和服务端是不是在一个进程内,如果是则直接返回Stub实体对象。如果不是则返回Stub的代理Proxy类。
if (((iin!=null)&&(iin instanceof com.wuyazhou.learn.IPC.aidl.IService))) {
return ((com.wuyazhou.learn.IPC.aidl.IService)iin);
}
return new com.wuyazhou.learn.IPC.aidl.IService.Stub.Proxy(obj);
}
@Override
//获取binder对象
public android.os.IBinder asBinder()
{
return this;
}
@Override
//客户端请求通过系统底层封装后交由此方法执行,此方法运行在服务端的Binder线程池中,将会根据请求标志位flag调用服务端Server的方法。
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
//根据标志位flag调用服务端方法
switch (code)
{
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_hello: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.hello(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(descriptor);
com.wuyazhou.learn.IPC.aidl.Book _result = this.addBook();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
//Stub的代理类Proxy,跨进程调用时将由此类作为客户端和服务端的连接。
private static class Proxy implements com.wuyazhou.learn.IPC.aidl.IService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
//获取Binder对象
@Override
public android.os.IBinder asBinder(){
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
//客户端方法对应转化,将调用交付给binder处理
@Override
public java.lang.String hello(java.lang.String name) 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);
_data.writeString(name);
//将请求参数和请求方法标志位flag和返回数据的存储器交付给Binder处理
mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
//客户端方法对应转化,将调用交付给binder处理
@Override
public com.wuyazhou.learn.IPC.aidl.Book addBook() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.wuyazhou.learn.IPC.aidl.Book _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//将请求参数和请求方法标志位flag和返回数据的存储器交付给Binder处理
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.wuyazhou.learn.IPC.aidl.Book.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
//客户端调用接口时会在Proxy的方法内将方法标志flag传入,以便Binder可以通过标志flag查找对应的方法在服务端调用
static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
//aidl定义的接口
public java.lang.String hello(java.lang.String name) throws android.os.RemoteException;
public com.wuyazhou.learn.IPC.aidl.Book addBook() throws android.os.RemoteException;
}
上面代码主要分为三部分
- 1. aidl接口部分
- 2. aidl内部类Stub部分
- 3. Stub内部类Proxy部分
1. aidl接口部分
//aidl定义的接口
public java.lang.String hello(java.lang.String name) throws android.os.RemoteException;
public com.wuyazhou.learn.IPC.aidl.Book addBook() throws android.os.RemoteException;
这部分只是单纯的声明一下aidl内写的接口,并抛出异常
3. Stub内部类Proxy部分
//Stub的代理类Proxy,跨进程调用时将由此类作为客户端和服务端的连接。
private static class Proxy implements com.wuyazhou.learn.IPC.aidl.IService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
//获取Binder对象
@Override
public android.os.IBinder asBinder(){
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
//客户端方法对应转化,将调用交付给binder处理
@Override
public java.lang.String hello(java.lang.String name) 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);
_data.writeString(name);
//将请求参数和请求方法标志位flag和返回数据的存储器交付给Binder处理
mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
//客户端方法对应转化,将调用交付给binder处理
@Override
public com.wuyazhou.learn.IPC.aidl.Book addBook() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.wuyazhou.learn.IPC.aidl.Book _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//将请求参数和请求方法标志位flag和返回数据的存储器交付给Binder处理
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = com.wuyazhou.learn.IPC.aidl.Book.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
此类为Stub的内部类主要是作为客户端Client到Binder的桥梁,内部也是继承Stub实现的aidl类,实现aidl的接口,主要是做一些跨进程进入Binder的准备工作,比如将参数放入Parcel容器内,创建一个Parcel容器用来存储返回结果。
需要注意的是在实现的aidl接口方法内调用了mRemote.transact()方法后当前线程会挂起
,经过一些列Binder操作后服务端的onTransact()方法会被调用,直到IPC过程返回后,当前线程继续执行。所以这里可能会导致ANR,使用时要特别注意。
2. aidl内部类Stub部分
//IService的内部类Stub,继承Binder,主体部分关联至服务端Service,内部类Proxy部分关联至客户端Client。Stub继承外部接口,也是接口实体类。
public static abstract class Stub extends android.os.Binder implements com.wuyazhou.learn.IPC.aidl.IService {
private static final java.lang.String DESCRIPTOR = "com.wuyazhou.learn.IPC.aidl.IService";
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
//通过此静态方法可获取到aidl实体Stub,或者Stub的代理类Proxy
public static com.wuyazhou.learn.IPC.aidl.IService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//判断客户端和服务端是不是在一个进程内,如果是则直接返回Stub实体对象。如果不是则返回Stub的代理Proxy类。
if (((iin!=null)&&(iin instanceof com.wuyazhou.learn.IPC.aidl.IService))) {
return ((com.wuyazhou.learn.IPC.aidl.IService)iin);
}
return new com.wuyazhou.learn.IPC.aidl.IService.Stub.Proxy(obj);
}
@Override
//获取binder对象
public android.os.IBinder asBinder()
{
return this;
}
@Override
//客户端请求通过系统底层封装后交由此方法执行,此方法运行在服务端的Binder线程池中,将会根据请求标志位flag调用服务端Server的方法。
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
//根据标志位flag调用服务端方法
switch (code)
{
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_hello: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.hello(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(descriptor);
com.wuyazhou.learn.IPC.aidl.Book _result = this.addBook();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
...
}
这个类是对aidl外部类的实现是binder层到Server层的桥梁,主要是通过onTransact()方法。也是获取客户端到binder层的桥梁proxy的入口,主要是通过asInterface()方法,获取Stub类的代理Proxy。