AIDL是进程间通信的一种方式,从以前学习AIDL后,很少用过,最近在复习了下其使用方法,以下为AIDL的使用方法,最后稍微分析了一下AIDL为我们生成的代码的逻辑
// PayInterface.aidl
package com.sendi.alipay;
interface PayInterface {
void pay();
}
4.build一下,as便会自动帮我们生成代码,很方便(生成的代码到后边再贴,方便于分析)
5.创建Service
public class PayService extends Service {
@Override
public IBinder onBind(Intent intent) {
//返回中间人
return new PayImpl();
}
class PayImpl extends PayInterface.Stub{
@Override
public void pay() throws RemoteException {
//调用服务的方法
PayService.this.pay();
}
}
public void pay(){
Log.i("PAYSERVICE", "pay:=== "+"支付");
}
}
到此服务端便模拟完成,接下来是客户端的创建。
Intent intent =new Intent();
intent.setAction("com.sendi.pay");//与服务端的Service的Action属性值一致
intent.setPackage("com.sendi.alipay");//与服务端包名一致
bindService(intent,new PayServiceCon(),BIND_AUTO_CREATE);
//完整代码如下
public class MainActivity extends AppCompatActivity {
private PayInterface pi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent =new Intent();
intent.setAction("com.sendi.pay");
intent.setPackage("com.sendi.alipay");
bindService(intent,new PayServiceCon(),BIND_AUTO_CREATE);//绑定远程服务
}
//点击支付
public void pay(View view){
try {
pi.pay();
} catch (RemoteException e) {
e.printStackTrace();
}
}
class PayServiceCon implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
pi=PayInterface.Stub.asInterface(iBinder);//绑定成功
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
}
经过成功的绑定,只要点击支付按钮,便可输出:
PAYSERVICE:pay:===支付
以上便是AIDL的用法,请注意的是AIDL只是帮我们生成AIDL代码的工具。
点击PayInterface这个接口进入源码:
public interface PayInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.sendi.alipay.PayInterface
{
private static final java.lang.String DESCRIPTOR = "com.sendi.alipay.PayInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.sendi.alipay.PayInterface interface,
* generating a proxy if needed.
*/
public static com.sendi.alipay.PayInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.sendi.alipay.PayInterface))) {
return ((com.sendi.alipay.PayInterface)iin);
}
return new com.sendi.alipay.PayInterface.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
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_pay:
{
data.enforceInterface(DESCRIPTOR);
this.pay();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.sendi.alipay.PayInterface
{
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;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override public void pay() 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_pay, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_pay = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void pay() throws android.os.RemoteException;
}
public static com.sendi.alipay.PayInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
//如果是服务端和客户端位于同一进程,则直接返回服务端的Stub对象本身
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.sendi.alipay.PayInterface))) {
return ((com.sendi.alipay.PayInterface)iin);
}
//否则返回封装的代理类对象
return new com.sendi.alipay.PayInterface.Stub.Proxy(obj);
}
此方法如果返回false说明客户端请求失败
在Proxy中可以看到提前定义的方法:
@Override public void pay() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
//这里没有参数和返回值
//为了体现出来,造一个假的有返回值和参数值
//_data.writeInt(c1);//将参数写进
//_data.writeInt(c2); //将参数写进
//_reply.readException();
//_result = _reply.readInt();//读取返回值
_data.writeInterfaceToken(DESCRIPTOR);
//此方法最终会调用onTransact方法
mRemote.transact(Stub.TRANSACTION_pay, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
其中的mRemote.transact(Stub.TRANSACTION_pay, _data, _reply, 0);
它最后会调用onTransact方法,也就是上面Stub类中的onTransact方法。
AIDL的使用跟生成代码的含义及逻辑大概是这些,如果要探究是如何进行进程间通信还需靠Binder的机制去实现。