Android 手写Binder 教你理解android中的进程间通信_Ciruy B.Heimerdinger的博客-程序员宅基地_手写binder

技术标签: android  

关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难。今天就教你如何从 app层面来理解好Binder。

其实就从我们普通app开发者的角度来看,仅仅对于android应用层的话,Binder就是客户端和服务端进行通信的媒介。

AIDL就是我们理解Binder 最好的事例。

我们都知道 我们写好aidl 文件以后,开发工具 会自动帮我们生成好代码。实际上 我们最终apk里面 是只有这些代码的,我们写的aidl文件

是不会被打包进去的,也就是说aidl文件 实际上 就是我们用来 生成 实际binder代码用的。所以 我们只要能够分析好,ide自动帮我们生成的

代码,就可以自己手写binder,从而在app层面上真正理解binder的用法和含义 以及原理。

首先我先来定义一个实体类:Person.java

package com.example.administrator.writebindercodeexample;

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

/**
 * Created by Administrator on 2016/1/27.
 */
public class Person implements Parcelable {

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public int getGender() {
        return gender;
    }

    public String getName() {
        return name;
    }

    private int gender;

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.gender);
    }

    public Person() {
    }

    protected Person(Parcel in) {
        this.name = in.readString();
        this.gender = in.readInt();
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        public Person createFromParcel(Parcel source) {
            return new Person(source);
        }

        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

注意看  我们这个person 类 是实现了android自带的序列化接口的,所以 如果你要在aidl里使用这个类,那你必须要额外在aidl里生命下 这个类。

1 // Person.aidl.aidl
2 package com.example.administrator.writebindercodeexample;
3 
4 // Declare any non-default types here with import statements
5 parcelable Person;
// IPersonManager.aidl
package com.example.administrator.writebindercodeexample;

// Declare any non-default types here with import statements
import com.example.administrator.writebindercodeexample.Person;
interface IPersonManager {
    List<Person> getPersonList();
    //关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说
    void addPerson(in Person person);
}

好,然后给你们看一下 文件结构:

好 这里就是一个典型的 应用aidl 技术的 一个例子,我们现在 让studio 编译这个project,然后看看生成的binder代码。 把这份binder代码 分析好了,我们以后就可以不借助ide 来自己手写binder了。

我们来看看 生成的代码在哪里:

最后我们来看一下 这个生成的代码 是啥样的:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\Users\\Administrator\\WriteBinderCodeExample\\app\\src\\main\\aidl\\com\\example\\administrator\\writebindercodeexample\\IPersonManager.aidl
 */
package com.example.administrator.writebindercodeexample;
public interface IPersonManager extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.administrator.writebindercodeexample.IPersonManager
{
private static final java.lang.String DESCRIPTOR = "com.example.administrator.writebindercodeexample.IPersonManager";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.example.administrator.writebindercodeexample.IPersonManager interface,
 * generating a proxy if needed.
 */
public static com.example.administrator.writebindercodeexample.IPersonManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.administrator.writebindercodeexample.IPersonManager))) {
return ((com.example.administrator.writebindercodeexample.IPersonManager)iin);
}
return new com.example.administrator.writebindercodeexample.IPersonManager.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_getPersonList:
{
data.enforceInterface(DESCRIPTOR);
java.util.List<com.example.administrator.writebindercodeexample.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addPerson:
{
data.enforceInterface(DESCRIPTOR);
com.example.administrator.writebindercodeexample.Person _arg0;
if ((0!=data.readInt())) {
_arg0 = com.example.administrator.writebindercodeexample.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.administrator.writebindercodeexample.IPersonManager
{
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.administrator.writebindercodeexample.Person> getPersonList() 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.administrator.writebindercodeexample.Person> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.example.administrator.writebindercodeexample.Person.CREATOR);
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
//关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说

@Override public void addPerson(com.example.administrator.writebindercodeexample.Person person) 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 ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getPersonList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public java.util.List<com.example.administrator.writebindercodeexample.Person> getPersonList() throws android.os.RemoteException;
//关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说

public void addPerson(com.example.administrator.writebindercodeexample.Person person) throws android.os.RemoteException;
}

看上去呢,杂乱无章, 但其实也就是100多行,所以 我调整了一下 这个代码的顺序 ,你们可以看的更清楚,同时也增加了注释:

package com.example.administrator.aidlmessagetest;

//为了让大家看的更清楚 我把生成的binder代码 给拷贝到另外一个工程下面了,并且用ide 给他format
//所以包名和我们一开始前面的代码都不一样,大家理解意思就行。


//从前面几行就能看出来 生成的代码是一个 interface ,只不过这个interface是 android.os.IInterface 的子类!
public interface IPersonManager extends android.os.IInterface {

    //并且这个接口里 有一个静态的抽象类Stub(注意这个名字是固定的 永远都是Stub 不会是其他)
    //并且这个Stub是Binder的子类,并且实现了IPersonManager 这个接口
    public static abstract class Stub extends android.os.Binder implements com.example.administrator.aidlmessagetest.IPersonManager {
        //这个东西就是唯一的binder标示 可以看到就是IPersonManager的全路径名
        private static final java.lang.String DESCRIPTOR = "com.example.administrator.aidlmessagetest.IPersonManager";

        /**
         * 这个就是Stub的构造方法,回顾一下 我们如果写好aidl文件以后 写的service里面 是怎么写的?
         *
         * private final IPersonManager.Stub mBinder = new IPersonManager.Stub() {}
         * 我们都是这么写的 对吧~~所以想想我们的service里面的代码 就能辅助理解 这里的代码了
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }


        //这个方法 其实就做了一件事,如果是同一个进程,那么就返回Stub对象本身
        //如果不是同一个进程,就返回Stub.Proxy这个代理对象了
        public static com.example.administrator.aidlmessagetest.IPersonManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            //如果是同1个进程,也就是说进程内通信的话 我们就返回括号内里的对象
            if (((iin != null) && (iin instanceof com.example.administrator.aidlmessagetest.IPersonManager))) {
                return ((com.example.administrator.aidlmessagetest.IPersonManager) iin);
            }
            //如果不是同一进程,是2个进程之间相互通信,那我们就得返回这个Stub.Proxy 看上去叫Stub 代理的对象了
            return new com.example.administrator.aidlmessagetest.IPersonManager.Stub.Proxy(obj);
        }

        //返回当前对象
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        //只有在多进程通信的时候 才会调用这个方法 ,同一个进程是不会调用的。

        //首先 我们要明白 这个方法 一般情况下 都是返回true的,也只有返回true的时候才有意义,如果返回false了 就代表这个方法执行失败,
        //所以我们通常是用这个方法来做权限认证的,其实也很好理解,既然是多进程通信,那么我们服务端的进程当然不希望谁都能过来调用
        //所以权限认证是必须的,关于权限认证的代码 以后我再讲 先略过。

        //除此之外 ,onTransact 这个方法 就是运行在Binder线程池中的,一般就是客户端发起请求,然后android底层代码把这个客户端发起的
        //请求 封装成3个参数 来调用这个onTransact方法,第一个参数code 就代表客户端想要调用服务端 方法的 标志位。
        //其实也很好理解 服务端可能有n个方法 每个方法 都有一个对应的int值来代表,这个code就是这个int值,用来标示客户端想调用的服务端的方法
        //data就是方法参数,reply就是方法返回值。都很好理解

        //其实隐藏了很重要的一点,这个方法既然是运行在binder线程池中的,所以在这个方法里面调用的服务器方法也是运行在Binder线程池中的,
        //所以我们要记得 如果你的服务端程序 有可能和多个客户端相联的话,你方法里使用的那些参数 必须要是支持异步的,否则的话
        //值就会错乱了!这点一定要记住!结论就是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_getPersonList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.example.administrator.aidlmessagetest.Person> _result = this.getPersonList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addPerson: {
                    data.enforceInterface(DESCRIPTOR);
                    com.example.administrator.aidlmessagetest.Person _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.example.administrator.aidlmessagetest.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addPerson(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        //注意这里的Proxy 这个类名也是不变的,从前文我们知道 只有在多进程通信的情况下  才会返回这个代理的对象
        private static class Proxy implements com.example.administrator.aidlmessagetest.IPersonManager {
            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;
            }


            //这里我们一共有2个方法 一个getPersonList 一个addPerson 我们就分析一个方法就可以了
            //并且要知道 这2个方法运行在客户端!!!!!!!!!!!!!!!!
            //首先就是创建了3个对象_data 输入对象,_reply输出对象,_result返回值对象
            //然后把参数信息 写入到_data里,接着就调用了transact这个方法 来发送rpc请求,然后接着
            //当前线程挂起, 服务端的onTransace方法才被调用,调用结束以后 当前线程继续执行,直到
            //从_reply中取出rpc的返回结果 然后返回_reply的数据

            //所以这里我们就要注意了,客户端发起调用远程请求时,当前客户端的线程就会被挂起了,
            //所以如果一个远程方法 很耗时,我们客户端就一定不能在ui main线程里在发起这个rpc请求,不然就anr了。
            @Override
            public java.util.List<com.example.administrator.aidlmessagetest.Person> getPersonList() 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.administrator.aidlmessagetest.Person> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.example.administrator.aidlmessagetest.Person.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            //你看自动生成binder代码的时候 连你的注释也一起拷贝过来了。。。。。是不是很有趣
            //关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说

            @Override
            public void addPerson(com.example.administrator.aidlmessagetest.Person person) 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 ((person != null)) {
                        _data.writeInt(1);
                        person.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_getPersonList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public java.util.List<com.example.administrator.aidlmessagetest.Person> getPersonList() throws android.os.RemoteException;
//关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说

    public void addPerson(com.example.administrator.aidlmessagetest.Person person) throws android.os.RemoteException;
}

到这里 相信大家 至少在应用层上面,就对Binder就一个很直观的理解了,对于进程间通信来说,具体的流程就分为如下几步:

1.Client 发起远程调用请求 也就是RPC 到Binder。同时将自己挂起,挂起的原因是要等待RPC调用结束以后返回的结果

2.Binder 收到RPC请求以后 把参数收集一下,调用transact方法,把RPC请求转发给service端。

3.service端 收到rpc请求以后 就去线程池里 找一个空闲的线程去走service端的 onTransact方法 ,实际上也就是真正在运行service端的 方法了,等方法运行结束 就把结果 写回到binder中。

4.Binder 收到返回数据以后 就唤醒原来的Client 线程,返回结果。至此,一次进程间通信 的过程就结束了

搞明白以后 我们就可以来尝试着 手下一下Binder:(前面我们aidl 帮我们生成的binder 是人,也就是person,那这次我们自己写的时候 就用狗吧,用DOG)

首先定义一个Dog.java: 实际上和person 一样的 所以这里暂时把代码折叠起来。

package com.example.administrator.writebindercodeexample;

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

/**
 * Created by Administrator on 2016/1/27.
 */
public class Dog implements Parcelable {

    public int getGender() {
        return gender;
    }

    public String getName() {
        return name;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public void setName(String name) {
        this.name = name;
    }

    private int gender;
    private String name;


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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.gender);
        dest.writeString(this.name);
    }

    public Dog() {
    }

    protected Dog(Parcel in) {
        this.gender = in.readInt();
        this.name = in.readString();
    }

    public static final Parcelable.Creator<Dog> CREATOR = new Parcelable.Creator<Dog>() {
        public Dog createFromParcel(Parcel source) {
            return new Dog(source);
        }

        public Dog[] newArray(int size) {
            return new Dog[size];
        }
    };
}

然后写一个接口IDogManager

package com.example.administrator.writebindercodeexample;

import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;

import java.util.List;

/**
 * Created by Administrator on 2016/1/27.
 */
public interface IDogManager extends IInterface {

    static final String DESCRIPTOR = "com.example.administrator.writebindercodeexample.IDogManager";
    static final int TRANSACTION_getDogList = IBinder.FIRST_CALL_TRANSACTION + 0;
    static final int TRANSACTION_addDog = IBinder.FIRST_CALL_TRANSACTION + 1;

    public List<Dog> getDogList() throws RemoteException;

    public void addDog(Dog dog) throws RemoteException;

}

然后写我们的binder,注意我们的binder 我这里是写的抽象类,因为你写成实体类的话 就必须要实现IDogManger里的2个方法 ,然而为了结构清晰 我们并不准备把binder 放在service里 实现。

所以这里binder 我们还是用抽象类来做,然后在service里 实现 getDogList和addDog方法即可。

package com.example.administrator.writebindercodeexample;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

/**
 * Created by Administrator on 2016/1/27.
 */
public abstract class DogManagerImpl extends Binder implements IDogManager {

    public DogManagerImpl() {
        this.attachInterface(this, DESCRIPTOR);
    }

    public static com.example.administrator.writebindercodeexample.IDogManager asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        //如果是同1个进程,也就是说进程内通信的话 我们就返回括号内里的对象
        if (((iin != null) && (iin instanceof com.example.administrator.writebindercodeexample.IDogManager))) {
            return ((com.example.administrator.writebindercodeexample.IDogManager) iin);
        }
        //如果不是同一进程,是2个进程之间相互通信,那我们就得返回这个Stub.Proxy 看上去叫Stub 代理的对象了
        return new com.example.administrator.writebindercodeexample.DogManagerImpl.Proxy(obj);
    }


    @Override
    public IBinder asBinder() {
        return this;
    }

    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_getDogList: {
                data.enforceInterface(DESCRIPTOR);
                java.util.List<com.example.administrator.writebindercodeexample.Dog> _result = this.getDogList();
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            }
            case TRANSACTION_addDog: {
                data.enforceInterface(DESCRIPTOR);
                com.example.administrator.writebindercodeexample.Dog _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.example.administrator.writebindercodeexample.Dog.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.addDog(_arg0);
                reply.writeNoException();
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }

    private static class Proxy extends DogManagerImpl {
        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.administrator.writebindercodeexample.Dog> getDogList() 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.administrator.writebindercodeexample.Dog> _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                mRemote.transact(DogManagerImpl.TRANSACTION_getDogList, _data, _reply, 0);
                _reply.readException();
                _result = _reply.createTypedArrayList(com.example.administrator.writebindercodeexample.Dog.CREATOR);
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }

        @Override
        public void addDog(com.example.administrator.writebindercodeexample.Dog dog) 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 ((dog != null)) {
                    _data.writeInt(1);
                    dog.writeToParcel(_data, 0);
                } else {
                    _data.writeInt(0);
                }
                mRemote.transact(DogManagerImpl.TRANSACTION_addDog, _data, _reply, 0);
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }
    }

}

到这,我们的手写binder 就完成了,然后看看 service 以及客户端 怎么调用。

先看service:

package com.example.administrator.writebindercodeexample;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class RemoteService extends Service {

    private List<Dog> mDogsList = new ArrayList<Dog>();

    private final DogManagerImpl mBinder = new DogManagerImpl() {
        @Override
        public List<Dog> getDogList() throws RemoteException {
            return mDogsList;
        }

        @Override
        public void addDog(Dog dog) throws RemoteException {
            mDogsList.add(dog);
        }
    };

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

然后看看 启动如何在客户端bind 这个service:

private IDogManager mService;

    private ServiceConnection sc = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = DogManagerImpl.asInterface(service);

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
    };

到这 就基本写完了,手写binder的好处就是 你可以自己在binder方法里 写一些log,能够更加深刻的认识到 Binder 作为 进程间通信 媒介的重要作用以及原理。

熟悉以后,还是用aidl 的方法 自动生成代码 最好。

 

个人评价:

其实对我而言,讲了和没讲差不多,我想知道的东西他貌似都绕过去了。比如INTERFACE_TRANSACTION到底起到什么作用之类的。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31433709/article/details/102509007

智能推荐

Android IPC进程间通信,Binder机制原理及AIDL实例

我们知道,Android的底层是使用Linux内核运行的,而Linux为了保证系统的稳定...但是,有时候我们也会遇到不同进程间需要通信的情况,那么,这时候就需要使用Android系统进程间通信IPC(Inter-Process Communication)。

一篇文章了解相见恨晚的 Android Binder 进程间通讯机制

Android-Binder进程间通讯机制 概述 最近在学习Binder机制,在网上查阅了大量的资料,也看了老罗的Binder系列的博客和Innost的深入理解Binder系列的博客,都是从底层开始讲的,全是C代码,虽然之前学过C和C++,...

Android10.0 Binder通信原理(二)-Binder入门篇

Modify the binder to request 1M - 2 pages instead of 1M. The backing store in the kernel requires a guard page, so 1M allocations fragment memory very badly. Subtracting a couple of pages so that they...

Android Binder通信一次拷贝你真的理解了吗?

最近有读者在询问一个关于Binder通信"一次拷贝"的问题,说在学习Binder驱动的实现中看到有多次调用了copy_from_user和copy_to_user来进行数据的跨用户空间和内核空间的拷贝,但是为啥Android官方和绝大部分的博客...

Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击

摘要:本节主要来讲解Android10.0 Binder的驱动层分析 阅读本文大约需要花费30分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经之路] ...

Android 中的Binder跨进程通信机制与AIDL

IPC进程间通信/跨进程通信 http://blog.csdn.net/github_33304260/article/details/52895331为什么需要跨进程通信?答:两个对象能直接互相访问的前提是两个对象在相同的内存地址空间中,如果两个对象那个在两个...

Android8.0.0-r4的Binder进程间通信机制

Android8.0.0-r4的Binder进程间通信机制 Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一。Android中的四大组件Activity,Service,Broadcast,ContentProvider,不同的App...

Android跨进程通信Binder机制浅析

本文为自己多年来在Android实战开发过程中总结归纳的一些常见问题,现在分享出来希望对初学者有所帮助。 本文出自门心叼龙的博客,转载请注明出处: https://blog.csdn.net/geduo_83/article/details/86560675  ...

Android跨进程通信:图文详解 Binder机制 原理

如果你接触过 跨进程通信 (IPC),那么你对Binder一定不陌生 虽然 网上有很多介绍 Binder的文章,可是存在一些问题:浅显的讨论Binder机制 或 一味讲解 Binder源码、逻辑不清楚,最终导致的是读者们还是无法形成一...

Android10.0 Binder通信原理(十一)-Binder总结

摘要:本节主要来讲解Android10.0 Binder的通信原理总结 阅读本文大约需要花费17分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经之路...

Android开发知识(四)Android进程间Binder通信机制的源码分析(下)

虽然Android系统是基于Linux内核,但是 它的进程间通信方式并没有完全继承自Linux,它拥有自己独特的通信方式–Binder。通过Binder我们可以进行不同应用与进程之间的相互通信以及远程方法调用。

Android进程间通信Binder 浅析

Android中,每一个应用程序都是由一些Activity和Service组成的,这些Activity和Service有可能...这就是本文中要介绍的Binder进程间通信机制了。  Android系统是基于Linux内核的,而Linux内核继承和兼容了丰富的Unix系

Android10.0 Binder通信原理(五)-Binder驱动分析

摘要:本节主要来讲解Android10.0 Binder的驱动层分析 阅读本文大约需要花费35分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经之路] ...

Android10.0 Binder通信原理(三)-ServiceManager篇

摘要:本节主要来讲解Android10.0 Binder中守护进程ServiceManager是如何启动、注册、获取服务 阅读本文大约需要花费35分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,...

Android进程间通信 - 几种方式的对比总结

RPC(Remote Procedure Call)即远程过程调用,它是一种通过网络从远程计算机程序上请求服务,在不需要了解底层网络技术的协议下,即可获取计算机进程中的数据。RPC使得开发包括网络分布式多程序在内的应用程序更加...

Android Binder跨进程通信原理分析

我们知道进程之间,虚拟地址不同,是不能直接通信的,这是一种...用户空间可以通过System calls(系统回调)与内核空间通信的,如果在内核空间中有一个模块,能够完成数据的转发,那么是不是两个进程就可以通信了呢?

初识Android进程间通信之----Binder机制

【转载请注明出处:http://blog.csdn.net/feiduclear_up/article/details/51385868 CSDN废墟的树】前言前面两篇博客分别介绍了Android进程间通信之AIDL的使用,以及使用AIDL传递复杂对象以及Bitmap对象。...

Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式

摘要:本节主要来讲解Android10.0 AIDL的通信原理 阅读本文大约需要花费24分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经之路] 的...

Android开发知识(三)Android进程间Binder通信机制的源码分析(上)

AIDL,全称名为:Android Interface Definition Language...它是安卓中一种跨进程通信的实现方式,使得不同进程不同应用之间可以保持通信。 本篇内容为基础使用篇,下面将写一个例子,来实现不同应用进程之间的通信。

Android 进阶8:进程通信之 Binder 机制浅析

读完本文你将了解: ...Thanks上篇文章 Android 进阶7:进程通信之 AIDL 中我们虽然跨进程通信成功,但是还是有很多疑问的,比如: AIDL 帮我们做了什么? 为什么要这么写? 什么是 Binder? 知其然还要知其

Android进阶——Android跨进程通讯机制之Binder、IBinder、Parcel、AIDL

Binder机制是Android系统提供的跨进程通讯机制,这篇文章开始会从Linux相关的基础概念知识开始介绍,从基础概念知识中引出Binder机制,归纳Binder机制与Linux系统的跨进程机制的优缺点,接着分析Binder的通信模型和...

AndroidBinder进程间通信系统

问题本次主要介绍Android平台下Binder进程间通信库。所谓通信库,就是Adroid在应用程序框架层中将各种Binder驱动操作封装成一个Binder库,应用程序可以方便地调用库中提供的接口进行通信。这次将介绍Binder库的结构...

Android之AIDL使用binder进程间通信原理

这次我们来研究一下AIDL线程间通信原理。 Binder机制 首先我们需要知道一下什么是Binder机制,具体什么是Binder机制推荐多查一查其他博客,由于太过于偏向底层,稍微做一些了解即可。 代码分析 还是先上代码,首先看...

Android HIDL 官方文档(六)—— 使用 Binder 进程间通信机制(Using Binder IPC)

1. Binder 驱动的改变 1.1 多个 Binder 域(上下文) 1.2 散集列表 1.3 更细化地加锁 1.4 实时优先级继承 1.5 用户空间更改 1.6 公共内核中的一些 SHA 2. 使用 Binder IPC 2.1 vndbinder 2.2 vndservicemanager ...

Android10.0 Binder通信原理(四)-Native-C\C++实例分析

摘要:本节主要来讲解Android10.0 Binder的Native层实例流程 阅读本文大约需要花费35分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经...

Android中的Binder跨进程通信机制与AIDL

在Code中,两个对象直接相互访问的前提是这两个对象都存在于...就需要使用一种跨进程通信技术,使存在于两个不同进程的对象能够相互访问,传统的跨进程通信方式:Socket、信号量、管道、共享内存、消息队列等。 Bi...

Android10.0 Binder通信原理(九)-AIDL Binder示例

摘要:本节主要来讲解Android10.0 Binder中如何使用AIDL 阅读本文大约需要花费20分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android取经之路...

Android Binder原理(一)学习Binder前必须要了解的知识点

本文首发于微信公众号「后厂村码农」 ...Android深入理解Context系列 Android深入理解JNI系列 Android解析WindowManager Android解析WMS系列 Android解析AMS系列 Android包管理机制系列 Android输入系统系...

Android10.0 Binder通信原理(七)-Framework binder示例

摘要:本节主要来讲解Android10.0 Binder在Framework中的示例 阅读本文大约需要花费15分钟。 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! [Android...

Android studio binder 进程间通信

服务端的开启方式为bindService( ),不是startService()3.android 5.0之后隐式调用被屏蔽,需要使用新的方式4.Binder通信原理,系统自动生成aidl代码作用分析5.android studio中生成aidl注意事项6.client端清单文件和...

随便推点

推荐文章

热门文章

相关标签