Binder通信

学习和使用Android Service也有一段时间了,今天有点总结和记录下个人感悟的想法。


首先,我们要明白,Binder只是Android中众多IPC方式中的一种。只不过相对于其它IPC方式,在Android中,Binder更为灵活和方便而已。

其次,Binder通信和业务之间的关系:

1>  Binder 是通信机制

2> 业务只是基于Binder进行通信,当然也可以使用别的IPC方式通信

说白了,Binder只是一种传递数据的方式,是为业务服务的。而Android帮我们把Binder的这种通信机制和我们的业务巧妙地封装融合在一起,使我们在实际应用过程中不用花费大量的精力和时间在IPC通信上,而是更加专注在业务逻辑的实现上。


AIDL 文件:


    package com.test.demo;   
      
    interface ITestService {       
        int Add();  
    }  

Build Java工程会根据ITestService.aidl文件生成ITestService.java文件:


/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\src\\com\\test\\demo\\ITestService.aidl
 */
package com.test.demo;
public interface ITestService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.test.demo.ITestService
{
private static final java.lang.String DESCRIPTOR = "com.test.demo.ITestService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.test.demo.ITestService interface,
 * generating a proxy if needed.
 */
public static com.test.demo.ITestService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.test.demo.ITestService))) {
return ((com.test.demo.ITestService)iin);
}
return new com.test.demo.ITestService.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_Add:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.Add();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.test.demo.ITestService
{
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 int Add() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_Add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_Add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int Add() throws android.os.RemoteException;
}

ITestService.java 中定义了ITestService接口和子类Stub以及Stub的子类Proxy

Stub类是一个抽象类,从Binder和ITestService接口派生而来,它是给Server端即Service使用的。我们要在Service中定义一个Stub类实例,并且实现这样一个Stub类实例中对应的ITestService的接口函数。

Proxy类也是从ITestService派生而来,它是给Client端用的。它其实就是Client访问Service的一个代理,它内部有一个BpBinder,通过它可以和Service里的BBinder进行通信。

Client访问Proxy感觉就像Client直接访问Service一样。


很好奇为什么Stub中的asInterface为什么不是直接返回Proxy对象?竟然有可能返回一个Stub对象?

/**
 * Cast an IBinder object into an com.test.demo.ITestService interface,
 * generating a proxy if needed.
 */
public static com.test.demo.ITestService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.test.demo.ITestService))) {
return ((com.test.demo.ITestService)iin);
}
return new com.test.demo.ITestService.Stub.Proxy(obj);
}

Binder类中的queryLocalInterface和attachInterface方法:

    public IInterface queryLocalInterface(String descriptor) {  
        if (mDescriptor.equals(descriptor)) {  
            return mOwner;  
        }  
        return null;  
    }


   public void attachInterface(IInterface owner, String descriptor) {  
     mOwner = owner;  
     mDescriptor = descriptor;  
   }  

而我们从Stub的构造函数中可以看到,owner就是Stub对象的this指针,即当前的Stub对象自己
    /** Construct the stub at attach it to the interface. */  
    public Stub() {  
        this.attachInterface(this, DESCRIPTOR);  
    }  

所以,asInterface从一个IBinder对象可以转换成一个Proxy或是一个Stub对象。Proxy对象,很好理解,即Proxy里是封装了BpBinder, 通过BpBinder和server端的BBinder进行通信。 那Stub对象呢,什么时候会返回一个Stub对象呢? 我个人的理解是当service是一个本地service的时候,只有这种情况的时候拿到IBinder对象后是不需要Proxy进行跨进程通信,而直接可以使用Server端实现的Stub对象来访问service的方法(个人猜测,未经证实。后面有时间可以去测试下)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值