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的方法(个人猜测,未经证实。后面有时间可以去测试下)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值