Android IPC机制之 理解Binder

服务端 IBinder类的创建

Binder是Android一个类实现了Ibinder接口,Binder也是Android跨进程通信的一种方式,Binder是连接Android各种manager和ManagerService的桥梁,Binder还是服务端和客户端通信的媒介,
bindService时,服务端会返回一个包含了服务端一些方法的Binder对象,通过该对象我们可以调用服务端的服务。

我们通常使用AIDL来创建自己的Binder类,AIDL是系统为我们提供的快速创建Binder接口的工具,创建一个实现了parcelable的类,创建一个aidl文件,将需要使用到的类导入到aidl文件中尽管在头一个包下,sdk会自动生成一个Binder接口。

该接口继承自IInterface,内部类Stub 和Stub的内部类Proxy 是该接口的核心实现。

首先,来看看sdk根据aidl文件自动生成的Binder接口的内容.

首先创建三个文件Book.java ,Book.aidl, IBookManager

package com.example.learnipc.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable{

    public int bookId;
    public String bookString;



    public Book(int bookId, String bookString) {
        super();
        this.bookId = bookId;
        this.bookString = bookString;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(bookId);
        dest.writeString(bookString);
    }

    //反序列化
    public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
        //反序列化
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }
    };

    private Book (Parcel in){
        bookId = in.readInt();
        bookString = in.readString();
    }
}

Book.aidl是Book类在aidl中的声明,需要在进程间传输的类都要进行声明,所以都要创建类对应的aidl文件

package com.example.learnipc.aidl;

parcelable Book;

IBookManager.aidl,定义一个接口,该接口用于IPC的类服务端进行实现,注意需要导入需要使用的类,如Book

package com.example.learnipc.aidl;

import com.example.learnipc.aidl.Book;

interface IBookManager{
    List<Book> getBookList();
    void addBook(in Book book);
}

写完上面的三个文件之后,在gen目录下,自动生成的IBookManager.java

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: F:\\houson_record\\learnIPC\\src\\com\\example\\learnipc\\aidl\\IBookManager.aidl
 */
package com.example.learnipc.aidl;

//继承自IIterface,
public interface IBookManager extends android.os.IInterface {

    public java.util.List<com.example.learnipc.aidl.Book> getBookList() throws android.os.RemoteException;

    public void addBook(com.example.learnipc.aidl.Book book) throws android.os.RemoteException;

    /** Local-side IPC implementation stub class. */
    //IBookManager 的核心类Stub,继承Binder实现了外部类IBookManager接口,即上面两个方法,Binder也是继承IInterface
    //Stub是抽象类具体实现由子类去实现,一般在service中创建自己的Binder类时实现

    public static abstract class Stub extends android.os.Binder implements com.example.learnipc.aidl.IBookManager {

        private static final java.lang.String DESCRIPTOR = "com.example.learnipc.aidl.IBookManager";//Binder 的唯一标识
        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);//标识IBookManager接口的方法id
        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

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

        /**
         * Cast an IBinder object into an com.example.learnipc.aidl.IBookManager
         * interface, generating a proxy if needed.
         */
         //这里将binder转为我们自己定义的IBoolManager类型,客户端请求时使用这种类型请求的
        public static com.example.learnipc.aidl.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }

            //当在同一进程下时返回这个
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.learnipc.aidl.IBookManager))) {
                return ((com.example.learnipc.aidl.IBookManager) iin);
            }
            //在不同进程下返回Stub的内部累Proxy,会走transact流程
            return new com.example.learnipc.aidl.IBookManager.Stub.Proxy(obj);
        }

        //直接返回BInder自己
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        //当客户端跨进程调用服务端时,该方法被调用.根据客户端的请求的方法id来调用不同服务端方法
        //返回false,客户端会调用失败,可以做权限验证
        //该方法运行在服务端的Binder线程池中
        @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_getBookList: {
                data.enforceInterface(DESCRIPTOR);//输入的data中取出参数
                java.util.List<com.example.learnipc.aidl.Book> _result = this.getBookList();//执行服务端方法
                reply.writeNoException();//将返回值写入reply
                reply.writeTypedList(_result);
                return true;
            }
            case TRANSACTION_addBook: {
                data.enforceInterface(DESCRIPTOR);
                com.example.learnipc.aidl.Book _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.example.learnipc.aidl.Book.CREATOR.createFromParcel(data);//反序列化
                } else {
                    _arg0 = null;
                }
                this.addBook(_arg0);
                reply.writeNoException();
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        //Stub的内部类 用于远程调用 ,实现BookManager接口
        //执行transact()
        private static class Proxy implements com.example.learnipc.aidl.IBookManager {
            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 java.util.List<com.example.learnipc.aidl.Book> getBookList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.example.learnipc.aidl.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.example.learnipc.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBook(com.example.learnipc.aidl.Book book) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((book != null)) {
                        _data.writeInt(1);
                        book.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }


    }


}

需要注意:

1.IBookManager是在服务端被实现的,运行在服务端的Binder线程池内,所以不需要在方法内部创建线程,被客户端调用客户端是阻塞的,如果服务端的方法耗时,客户端不能在UI线程下调用服务.
2.使用aidl使系统生成的IBookManager只是方便我们定义Binder类(即内部的Stub类),我们可以手动定义Binder类.

Binder的工作机制如下图

image

对服务端的binder死亡进行监听

binder死亡如果没有监听,客户端调用就会失败,Binder提供了linkTODeath()和unlinkToDeath()方法

1.需要一个IBinder.DeathRecipient对象,实现器binderDied()方法,在该方法中重新绑定到service
2.在客户端绑定成功后使用服务端返回的binder.linkToDeath(DeathRecipient对象,flag);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值