android的Binder

Binder:别针,回形针。生活中,我们用回形针将两张纸“别”在一起。android中,Binder用于进程间通信,即将两个进程“别”在一起。

Binder是一种架构,有3个模块(服务端接口,Binder驱动,客服端接口),如下图:

Binder服务端,实际上就是一个Binder类的对象,该对象一旦创建内部就会启动一个隐藏线程。

根据上面的架构,说说我所理解的。

客服端程序要想访问远程服务,那么它就需要获取到服务端的Binder引用---mRemote。Android工程师提供了一个解决方案,那就是Service。对于客服端来讲,可以使用两种方式来和服务端建立连接。

public ComponentaName startService(Intent intent)
public boolean bindService(Intent service, ServiceConnection conn, int flags)

第一种方式启动后,客服端暂时没有服务端Binder的引用。

而第二种方式启动后,ServiceConnection接口的onServiceConnected方法会被回调。

ServiceConnection代码如下:

public interface ServiceConnection {
       public void onServiceConnected(ComponentName name, IBinder service);
       public void onServiceDisconnected(ComponentName name);
}

onServiceConnected方法中的IBinder对象service就是远程服务的引用。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

我所理解的Binder机制到这里就结束了,那么AIDL的出现是为了解决什么?

编写一个aidl文件,看看它到底做了什么。如下所示:

package com.aprz.aidl;

interface IAidlTest{
    void test();
}

interface是关键字,有时在interface之前加上oneway表示service提供的方法都没有返回值,文件名以“I”开头是为了统一规范。文件编写完之后,android的开发环境会自动生成以下代码:

/*___Generated_by_IDEA___*/

/*

 * This file is auto-generated.  DO NOT MODIFY.

 * Original file: F:\\workspace\\AIDLService\\src\\com\\aprz\\aidl\\AidlTest.aidl

 */

package com.aprz.aidl;

public interface AidlTest extends android.os.IInterface {

    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.aprz.aidl.AidlTest {
        private static final java.lang.String DESCRIPTOR = "com.aprz.aidl.AidlTest";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.aprz.aidl.AidlTest interface,
         * generating a proxy if needed.
         */
        public static com.aprz.aidl.AidlTest asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }

            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

            if (((iin != null) && (iin instanceof com.aprz.aidl.AidlTest))) {
                return ((com.aprz.aidl.AidlTest) iin);
            }

            return new com.aprz.aidl.AidlTest.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_test: {
                    data.enforceInterface(DESCRIPTOR);
                    this.test();
                    reply.writeNoException();
                    return true;
                }
            }

            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.aprz.aidl.AidlTest {

            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 void test() 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_test, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public void test() throws android.os.RemoteException;
}

这些代码完成了三个任务:

1、这个文件本身是一个java interface,包含了aidl文件所声明的服务函数(文件最下面)。

2、定义了一个Proxy类,该类作为客服端访问服务端的代理,主要是为了统一包裹内写入参数的顺序(当我们在客服端使用Stub的asInterface将IBinder转换为具体的接口以便调用服务端的方法时,其实返回的Proxy对象,代理做的主要工作就是统一包裹内写入参数的顺序)。

这里需要详情解释一下这句话的意思。我们知道服务端是一个Binder对象,假设让我们来设计一个Service端,这个Service只提供两个方法:start(String filePath)和stop()。

那么其代码大致如下:

public class MusicPlayService extends Binder{

       public void start(String filePath) {
       }

       public void stop(){
    }

    //服务端必须要实现onTransact()方法
    @override
    protected boolean onTransact(int code, Parcel data, Pacel reply, int flags) throws RemoteException {
         return super.onTransact(code, data, reply, flags);
    }

}

onTransact的第二个参数data,就是客服端传递过来的参数,那么我如何正确读取这个参数呢(假设这里有多个参数)?

正确的读取方式应该是这样的:

data.enforceInterface(“MusicPlayService”);

String filePath = data.readString();

start(filePath);

enforceInterface()是为了某种校验,与客服端的writeInterfaceToken()方法对应。由于我写的aidl文件并没有带参数,从它生成的代码中也无法看出什么,你可以自己做测试,给aidl的文件的方法加上多个参数,看看生成的代码中Stub和Proxy类的方法,对比一下。

3、定义一个Stub类,主要由服务端来使用。这个类之所以是抽象类,是因为具体的函数服务必须由程序员来实现,如下:

public class AIDLService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private final AidlTest.Stub mBinder = new AidlTest.Stub() {
        public void test() throws RemoteException {
            Log.e("aidl", "输出从服务端");
        }
    };

}

我们需要返回一个IBinder对象,这个mBinder对象是Stub的一个实例对象,需要实现其抽象方法,Binder与IBinder的关系:public class Binder implements IBinder 。

另外,Stub中的一些常量,如TRANSACTION_test,这些常量与服务函数相对应,因为服务端收到调用消息之后,就会执行onTransact()方法,这个时候,就根据这个常量来判断,该执行哪个方法(TRANSACTION_test表示需要执行服务端的test方法)。Stub中还有一个asInterface函数,该方法返回一个Binder对象,需要注意的是,如果是从远程来获取服务端的Binder引用,会返回Binder驱动中的对象,如果是从服务端进程内部获取,则会返回服务端本身的Binder对象(当创建一个Binder对象的时候,服务端会创建一个,Binder驱动也会创建一个)。

时间: 2024-10-01 06:42:49

android的Binder的相关文章

【Android】Android Layout Binder——根据layout布局文件自动生成findViewById的java代码的神器

Android Layout Binder是一个网站,能够在线的根据layout布局文件自动生成findViewById的java代码. 网址是http://android.lineten.net/layout.php 如图:

转 理解Android系统Binder机制

一.Binder机制概述 在Android开发中,很多时候我们需要用到进程间通信,所谓进程间通信,实现进程间通信的机制有很多种,比如说socket.pipe等,Android中进程间通信的方式主要有三种: 1.标准Linux Kernel IPC 接口: 2.标准D-BUS接口: 3.Binder接口. 其中,Binder机制是使用最且最被认可的,因为Binder机制有以下优点: 1.相对于其它IPC机制,Binder机制更加简洁和快速: 2.消耗的内存相对更少: 3.传统的IPC机制可能会增加

android当中Binder机制,Looper与MessageQueue机制

上周四讨论内容:android 当中Binder机制,Looper与MessageQueue相关知识,相关链接: http://blog.csdn.net/innost/article/details/6124685 http://blog.csdn.net/innost/article/details/6055793 android当中Binder机制,Looper与MessageQueue机制,布布扣,bubuko.com

Android service binder aidl 关系

/********************************************************************************** * Android service binder aidl 关系 * 声明: * 最近一直被Android中的service.binder.aidl这三者之间的关系给搞得有点难受, * 于是就自己花了点时间,将他们之间的关系给画出来,这样思维上就清晰多了,也方便 * 和朋友沟通,减少沟通成本. * * 2016-1-10 晴 深圳

android 多进程 Binder AIDL Service

本文参考http://blog.csdn.net/saintswordsman/article/details/5130947 android的多进程是通过Binder来实现的,一个类,继承了Binder,那么它的对象就可以被远程的进程使用了(前提是远程进程获取了这个类的对象[对象的引用],至于如如何获得看下文),怎么使用呢?在Android中, 则采用AIDL(Android InterfaceDefinition Language:接口定义语言)方式实现,所以我们必须写后缀为.aidl的文件

Android aidl Binder框架浅析

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38461079 ,本文出自[张鸿洋的博客] 1.概述 Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务.这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架 Android Binder框架分为服务器接口.Binder驱动.以及客户端接口:简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客

Android 使用binder访问service的方式

binder机制是贯穿整个Android系统的进程间访问机制,经常被用来访问service,我们结合代码看一下binder在访问service的情形下是怎么具体使用的. service 你可以理解成没有的界面的activity,它是跑在后台的程序,所谓后台是相对于可以被看得到的程序的,后台程序是不能直接交互的程序. binder主要是用来进程间通信的,但也可用在和本地service通信. 1. 我们先来看一个与本地service通信的例子. package com.ckt.wangxin; im

Android Layout Binder(在线将XML中View find出来,生成java代码的工具)

废话不多说,这是地址:http://android.lineten.net/layout.php. 有图有真相,例如: 你的XML假如是这样: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fil

Android系统Binder机制学习总结

一.Binder机制概述 在Android开发中,很多时候我们需要用到进程间通信,所谓进程间通信,实现进程间通信的机制有很多种,比如说socket.pipe等,Android中进程间通信的方式主要有三种: 1.标准Linux Kernel IPC 接口: 2.标准D-BUS接口: 3.Binder接口. 其中,Binder机制是使用最且最被认可的,因为Binder机制有以下优点: 1.相对于其它IPC机制,Binder机制更加简洁和快速: 2.消耗的内存相对更少: 3.传统的IPC机制可能会增加