Android Binder机制浅谈以及使用Binder进行跨进程通信的俩种方式(AIDL以及直接利用Binder的transact方法实现)

这篇具有很好参考价值的文章主要介绍了Android Binder机制浅谈以及使用Binder进行跨进程通信的俩种方式(AIDL以及直接利用Binder的transact方法实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Binder机制学习

Binder机制是Android进行IPC(进程间通信)的主要方式

Binder跨进程通信机制:基于C/S架构,由Client、Server、ServerManager和Binder驱动组成。 进程空间分为用户空间和内核空间。用户空间不可以进行数据交互;内核空间可以进行数据交互,所有进程共用 一个内核空间 Client、Server、ServiceManager均在用户空间中实现,而Binder驱动程序则是在内核空间中实现的;

·为何新增Binder来作为主要的IPC方式

Android也是基于Linux内核,Linux现有的进程通信手段有管道/消息队列/共享内存/套接字/信号量。

既然有现有的IPC方式,为什么重新设计一套Binder机制呢?

主要是出于以上三个方面的考量:

1、效率:传输效率主要影响因素是内存拷贝的次数,拷贝次数越少,传输速率越高。从Android进程架构角度 分析:对于消息队列、Socket和管道来说,数据先从发送方的缓存区拷贝到内核开辟的缓存区中,再从内核缓存区拷 贝到接收方的缓存区,一共两次拷贝。

一次数据传递需要经历:用户空间 –> 内核缓存区 –> 用户空间,需要2次数据拷贝,这样效率不高。 

而对于Binder来说,数据从发送方的缓存区拷贝到内核的缓存区,而接收方的缓存区与内核的缓存区是映射到同 一块物理地址的,节省了一次数据拷贝的过程 : 共享内存不需要拷贝,Binder的性能仅次于共享内存。 
2、稳定性:上面说到共享内存的性能优于Binder,那为什么不采用共享内存呢,因为共享内存需要处理并发同 步问题,容易出现死锁和资源竞争,稳定性较差。 Binder基于C/S架构 ,Server端与Client端相对独立,稳定性较 好。
3、安全性:传统Linux IPC的接收方无法获得对方进程可靠的UID/PID,从而无法鉴别对方身份;而Binder机制 为每个进程分配了UID/PID,且在Binder通信时会根据UID/PID进行有效性检测。

2. binder是什么?

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

从进程间通信的角度看,Binder 是一种进程间通信的机制;

从 Server 进程的角度看,Binder 指的是 Server 中的 Binder 实体对象(Binder类 IBinder);

从 Client 进程的角度看,Binder 指的是对 Binder 代理对象,是 Binder 实体对象的一个远程代理

从传输过程的角度看,Binder 是一个可以跨进程传输的对象;Binder 驱动会自动完成代理对象和本地对象之间 的转换。 从Android Framework角度来说,Binder是ServiceManager连接各种Manager和相应ManagerService的桥梁

3.Binder 跨进程通信机制 模型

·模型原理图:Binder 跨进程通信机制 模型 基于 Client - Server 模式

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

· 模型组成角色说明

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

4.Binder驱动的作用 & 原理:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

模型工作原理:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

模型原理步骤说明

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

注意:
Client进程、Server进程 & Service Manager 进程之间的交互 都必须通过Binder驱动(使用 open 和 ioctl文件操作函数),而非直接交互

原因:Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互
Binder驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互
Binder驱动 & Service Manager进程 属于 Android基础架构(即系统已经实现好了);而Client 进程 和 Server 进程 属于Android应用层(需要开发者自己实现)

所以,在进行跨进程通信时,开发者只需自定义Client & Server 进程 并 显式使用上述3个步骤,最终借助 Android的基本架构功能就可完成进程间通信
# Binder请求的线程管理
Server进程会创建很多线程来处理Binder请求

Binder模型的线程管理 采用Binder驱动的线程池,并由Binder驱动自身进行管理,而不是由Server进程来管理的

一个进程的Binder线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程。

所以,在进程间通信时处理并发问题时,如使用ContentProvider时,它的CRUD(创建、检索、更新和删除)方法只能同时有16个线程同时工作

利用binder进行通信的实现代码Demo:

1. 直接利用Binder的transact实现:

server端:(注意,要在注册清单中注册,并且标注进程号(在其他进程中运行))

public class IPCService extends Service {
private static final String DESCRIPTOR = "IPCService";
private final String[] names = {"B神","艹神","基神","J神","翔神"};
private MyBinder mBinder = new MyBinder();
private class MyBinder extends Binder {
  @Override
  protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
      switch (code){
          case 0x001: {
              Log.d("TAG", "MyBinder Switch块 -----" + android.os.Process.myPid());
              data.enforceInterface( "IPCService");
              int num = data.readInt();
              int num1 = data.readInt();
              int num2 = data.readInt();
              String test = data.readString();
              reply.writeNoException();
              reply.writeString(names[num] + "  " + android.os.Process.myPid() + "    " + num1 + "   " + num2 + "   " + test);
              reply.writeInt(1);
              reply.writeString("收到");
              return true;
          }
      }
      Log.d("TAG", "MyBinder   OnTransact块 ----- " + android.os.Process.myPid());
      return super.onTransact(code, data, reply, flags);
  }
}
@Override
public IBinder onBind(Intent intent) {
  return mBinder;
}
}
/**
 * AndroidManifest.xml
         <service android:name="net.binderlearning.IPCService"
                 android:process=".myservice"/>
*/

client:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private EditText edit_num;
    private Button btn_query;
    private TextView txt_result;
    private IBinder mIBinder;
    private ServiceConnection PersonConnection  = new ServiceConnection()
    {
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            mIBinder = null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            mIBinder =  service;
            Log.d("TAG", "客户端-----" + android.os.Process.myPid());
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
        //绑定远程Service
        Intent service = new Intent(this,IPCService.class);
        bindService(service, PersonConnection, BIND_AUTO_CREATE);
        btn_query.setOnClickListener(this);
    }
    private void bindViews() {
        edit_num = (EditText) findViewById(R.id.edit_num);
        btn_query = (Button) findViewById(R.id.btn_query);
        txt_result = (TextView) findViewById(R.id.txt_result);
    }
    @Override
    public void onClick(View v) {
        int num = Integer.parseInt(edit_num.getText().toString());
        if (mIBinder == null)
        {
            Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
        } else {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            String _result = null;
            try{
                _data.writeInterfaceToken("IPCService");
                _data.writeInt(num);
                _data.writeInt(4);
                mIBinder.transact(0x001, _data, _reply, 0);
                _reply.readException(); //读取异常
                _result = _reply.readString();
                String test = _reply.readString();
                int test1 = _reply.readInt();
                Toast.makeText(this, "我收到的内容是:" + test + "    " + test1, Toast.LENGTH_SHORT).show();
                txt_result.setText(_result);
                edit_num.setText("");
                Log.d("TAG", "客户端-----" + android.os.Process.myPid());
            }catch (RemoteException e)
            {
                e.printStackTrace();
            } finally
            {
                _reply.recycle();
                _data.recycle();
            }
        }
    }
}

运行结果:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

方法说明及其注意点:
1. Parcel的读写顺序要一致。 比如写的时候先 writeInt ,然后再writeString。 那么读的时候也是要先readInt 然后再writeString。 (原因应该是跟Parcelable差不多,调用的是native层的序列化写入,用的是c/c++的指针顺序写入,如果没有按顺序读取,读取地址的时候读到的内容就会很奇怪了)

例如,服务端写入顺序:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

客户端读取顺序:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

结果:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

收到的数据不理想

2. Parcel的writeInterfaceToken(接口名)以及enforceInterface(接口名)

·writeInterfaceToken以及writeInterfaceToken的接口名要一致(类似于验证要访问的接口是否一致)。

不一致,如果找不到binder找不到要调用的接口,就会报异常

java.lang.SecurityException: Binder invocation to an incorrect interface

例如:服务端

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

客户端:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

报错:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

·writeInterfaceToken以及writeInterfaceToken的调用时期必须在读写数据前调用,否则会报错:

java.lang.SecurityException: Binder invocation to an incorrect interface

例如:在写入数据后才调用时:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

结果报错:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

源码对这俩个函数的描述:

    /**
     * Store or read an IBinder interface token in the parcel at the current
     * {@link #dataPosition}. This is used to validate that the marshalled
     * transaction is intended for the target interface. This is typically written
     * at the beginning of transactions as a header.
     * 翻译:
        在包中当前数据位置存储或读取IBinder接口令牌。这用于验证编组的事务是否用于目标接口。这通常在事务开始时作为标头写入。
     */

    public final void writeInterfaceToken(@NonNull String interfaceName) {
        nativeWriteInterfaceToken(mNativePtr, interfaceName);
    }
    /**
     * Read the header written by writeInterfaceToken and verify it matches
     * the interface name in question. If the wrong interface type is present,
     * {@link SecurityException} is thrown. When used over binder, this exception
     * should propagate to the caller.
     * 翻译:
     读取writeInterfaceToken所写的报头,并验证它是否与所讨论的接口名称匹配。如果存在错误的接口类型,则抛出SecurityException。在绑定器上使用时,此异常应传播给调用方。
     */
    public final void enforceInterface(@NonNull String interfaceName) {
        nativeEnforceInterface(mNativePtr, interfaceName);
    }

3.Parcel的readException()

作用是读取异常,如果读写的时候有异常,那么就能获取到改异常(获取异常不catch就会导致程序奔溃)。 上述代码可以选择不加这个,不加的话如果有异常就获取不到,也不会导致程序奔溃,但读不到数据

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

4. transact和onTransact

protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)

参数说明: 1.code,服务端和客户端约定的标识码,这样在服务端中就可以根据改标识码来处理不同的事件

​ 2.data, 用于读取和写入 要通信的数据

​ 3.reply,用于读取和写入 返回的数据 4. flags 可以不管

transact在客户端中调用,ontransact在服务端中调用。 (当然一个进程可以同时为服务端和客户端。 也就是binder机制支持"递归化调用",比如A跟B通信,A可以调用B提供的Ibinder对象的transact跟B通信,同时B也可以调用A提供的IBinder对象的transact跟A通信。 然后他们在各自的onTransact方法中处理即可)

上面的Demo只是验证了通信,并没有真正意义上的调用另一个进程的接口方法,因此再测试了一个Demo调用另外一个进程的方法:

定义接口方法:一定要继承IInterface

import android.os.IInterface;

public interface IPlus extends IInterface {
      int add(int a, int b);
}

服务端代码:

public class IPCService extends Service {
    private static final String DESCRIPTOR = "add two int";
    private final String[] names = {"B神","艹神","基神","J神","翔神"};
    private MyBinder mBinder = new MyBinder();

    private IInterface plus = new IPlus() {
        @Override
        public int add(int a, int b) {
            return a + b;
        }

        @Override
        public IBinder asBinder() {
            return null;
        }
    };
    public IPCService(){
        mBinder.attachInterface(plus,"add two int");
    }
    private class MyBinder extends Binder {
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            switch (code){
                case 0x001: {
                    Log.d("TAG", "MyBinder Switch块 -----" + android.os.Process.myPid());
                    data.enforceInterface(DESCRIPTOR);
                    int a = data.readInt();
                    int b = data.readInt();
                    int result = ((IPlus)this.queryLocalInterface("add two int")).add(a,b);
                    reply.writeNoException();
                    reply.writeInt(result);
                    return true;
                }
            }
            Log.d("TAG", "MyBinder   OnTransact块 ----- " + android.os.Process.myPid());
            return super.onTransact(code, data, reply, flags);
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

客户端代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private EditText edt_arg1;
    private EditText edt_arg2;
    private Button add;
    private TextView addResult;
    private IBinder mIBinder;
    private ServiceConnection PersonConnection  = new ServiceConnection()
    {
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            mIBinder = null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            mIBinder =  service;
            Log.d("TAG", "客户端-----" + android.os.Process.myPid());
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
        //绑定远程Service
        Intent service = new Intent(this,IPCService.class);
        bindService(service, PersonConnection, BIND_AUTO_CREATE);
        add.setOnClickListener(this);
    }
    private void bindViews() {
        edt_arg1 = (EditText) findViewById(R.id.arg1);
        edt_arg2 = (EditText) findViewById(R.id.arg2);
        add = (Button) findViewById(R.id.add);
        addResult = (TextView) findViewById(R.id.result);
    }
    @Override
    public void onClick(View v) {
        int arg1 = Integer.parseInt(edt_arg1.getText().toString());
        int arg2 = Integer.parseInt(edt_arg2.getText().toString());
        if (mIBinder == null)
        {
            Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
        } else {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            int _result = -1;
            try{
                _data.writeInterfaceToken("add two int");
                _data.writeInt(arg1);
                _data.writeInt(arg2);
                mIBinder.transact(0x001, _data, _reply, 0);
                _reply.readException();
                _result  = _reply.readInt();
                addResult.setText(""+_result );
            }catch (RemoteException e)
            {
                e.printStackTrace();
            } finally
            {
                _reply.recycle();
                _data.recycle();
            }
        }
    }
}

运行结果:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

区别第一个Demo:

这里多使用了IInterface,即IPlus

并且在服务端的代码里多写了:

    public IPCService(){
        mBinder.attachInterface(plus,"add two int");
    }
    /**
     *   void attachInterface(IInterface plus, String descriptor);
          // 作用:
          // 1. 将(descriptor,plus)作为(key,value)对存入到Binder对象中的一个Map<String,IInterface>对象中
          // 2. 之后,Binder对象 可根据descriptor通过queryLocalIInterface()获得对应IInterface对象(即plus)的引用,可依靠该引用完成对请求方法的调用
    *      
    */
                    data.enforceInterface(DESCRIPTOR);
                    int a = data.readInt();
                    int b = data.readInt();
                    int result = ((IPlus)this.queryLocalInterface("add two int")).add(a,b);

/**
 *         IInterface queryLocalInterface(Stringdescriptor) ;
        作用:根据 参数 descriptor 查找相应的IInterface对象(即plus引用)
**/

Binder跨进程的通信AIDL方案:

AIDL使用步骤:

  1. 创建AIDL文件

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

  1. 写上服务端需要提供的接口方法

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

  1. 重新build一下模块,就会自动生成aidl文件对应的java文件

测试Demo1:(同一模块下时)

AIDL文件代码:

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);  //默认生成,可以删除

    //以下俩个是自定义方法
    void say(String word);
    int tell(String word,int age);
}

服务端代码:

public class MyAidlServer extends Service {
    private String TAG = "MyAidlService";
    //使用生成的java文件中的stub作为binder对象
    private IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.d(TAG, android.os.Process.myPid() + "   basicTypes:  " + anInt + "   " + aLong + "   " + aBoolean + "   "
                  + aFloat + "   " + aDouble + "   " + aString);
        }

        @Override
        public void say(String word) throws RemoteException {
            Log.d(TAG, android.os.Process.myPid() + "   say:  "  + word);
        }

        @Override
        public int tell(String word, int age) throws RemoteException {
            Log.d(TAG, android.os.Process.myPid() +  "   tell:   " + word + "    " + age);
            return 100;
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return stub;
    }
}

客户端代码:

public class MainActivity extends AppCompatActivity {
    private static final  String TAG = "MainActivity";
    TextView bindService;
    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); //获取到服务端的binder代理对象,也就是上面stub
            try {
                iMyAidlInterface.say("I am handsome boy");
                int result = iMyAidlInterface.tell("我是个靓仔", 20);
                Log.d(TAG, android.os.Process.myPid() +"    " + "onServiceConnected:   " + result);
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService = findViewById(R.id.bind_service);
        bindService.setOnClickListener((v) -> {
            Intent intent = new Intent(MainActivity.this, MyAidlServer.class);
            bindService(intent,serviceConnection,BIND_AUTO_CREATE); //绑定服务
        });
    }
}

结果:不同进程的日志需要指令抓取才可以显示出来

客户端进程:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

服务端进程:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

测试Demo2:(不同模块时)

服务端aidl:

interface IServiceAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void setData(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString,byte anByte);   //aidl不支持short类型,但可以考虑把short转换成int解决
    void saySomething(String word);
    String saySomethingAndRespon(String word);
}

服务端Service:

public class AidlService extends Service {
    private String TAG = "AidlService";
    private IServiceAidlInterface.Stub stub = new IServiceAidlInterface.Stub() {
        @Override
        public void setData(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString, byte anByte) throws RemoteException {
            Log.d(TAG,android.os.Process.myPid() +  "   服务端收到客户端调用setData传入的数据为:  " + anInt + "   " + aLong + "   "
            + aBoolean + "   " + aFloat + "    " + aDouble + "    " + aString + "     " + (int) anByte);
        }

        @Override
        public void saySomething(String word) throws RemoteException {
            Log.d(TAG, android.os.Process.myPid() + "    服务端收到客户端调用saySomethingAndRespon传入的数据为: " + word);
        }

        @Override
        public String saySomethingAndRespon(String word) throws RemoteException {
            Log.d(TAG, android.os.Process.myPid() + "    服务端收到客户端调用saySomethingAndRespon传入的数据为: " + word);
            return "我是服务端,我已经接收到你发送过来的数据了。 ---> " + word;
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return stub;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestory: ");
    }
}

服务端的注册清单: 此处只为注册service。 且exported属性为true是一定要的

        <service android:name="net.aidl_server.AidlService"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.AIDLService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

客户端:aidl文件直接从服务端复制过来(自建 包名会跟着客户端)

绑定服务的代码:

public class MainActivity extends AppCompatActivity {
    private final String TAG = "ClientMainActivity";
    Button bind_service;
    Intent intent;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IServiceAidlInterface aidlInterface = IServiceAidlInterface.Stub.asInterface(service);
            try {
                aidlInterface.setData(10,100L,true,50.01f,79.0,"XIAO JIAN", (byte) 90);
                aidlInterface.saySomething("服务端你好呀");
                String respon = aidlInterface.saySomethingAndRespon("你是个靓仔");
                Log.d(TAG, android.os.Process.myPid()+"      我是客户端,收到服务端传送过来的消息为: " + respon);
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bind_service = findViewById(R.id.bind_service);
        bind_service.setOnClickListener((v)->{
            intent = new Intent("android.intent.action.AIDLService");
            intent.setPackage("net.aidl_server");
            bindService(intent,connection,BIND_AUTO_CREATE);
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: " );
    }


}

运行结果:

服务端

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

客户端:

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

Aidl传输复杂数据注意事项:

数据需要实现Parceable接口,并且格式要跟Parceable实现格式一样,可以把鼠标指在Parceable那,然后Alt + 回车

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

需要在aidl文件中加入Parceable实现类

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

定义接口参数需要加上in

android binder通信使用,Android基础,android,binder,java,AIDL,Binder跨进程通信

在AIDL中,in、out和inout是定向标记,用于指示数据在跨进程通信中的流向。其中,
in表示数据只能从客户端流向服务端,
out表示数据只能从服务端流向客户端,
inout表示数据可以在服务端和客户端之间双向流动
需要注意的是,in 和 out 的作用只是为了告诉系统参数的传递方向,实际上在 AIDL 中,所有的参数都是通过值传递的,即传递的是参数的副本,而不是参数本身。因此,如果需要修改参数的值,需要使用 inout 或者返回值的方式来实现。

引用和参考

Carson带你学Android–Android跨进程通信:图文详解 Binder机制 原理文章来源地址https://www.toymoban.com/news/detail-586627.html

到了这里,关于Android Binder机制浅谈以及使用Binder进行跨进程通信的俩种方式(AIDL以及直接利用Binder的transact方法实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 面试笔记整理-Binder机制

    作者:浪人笔记 面试可能会问到的问题 从IPC的方式问到Binder的优势 为什么zygote跟其他服务进程的通讯不使用Binder Binder线程池和Binder机制 等等这些问题都是基于你对Binder的理解还有对其他IPC通讯的理解 IPC方式有多少种 传统的IPC方式有Socket、共享内存、管道、信号量等 安卓

    2024年02月12日
    浏览(27)
  • Android IPC Binder机制学习(一)

    一、多进程系统设计及意义 Android系统分为5层,不过Android一般岗位只关注上三层就够用了即:应用层、framework层、native层。 Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。 Android中不同的应用属于不同的进程中 Android应用和系统服务运行在不同的进

    2023年04月09日
    浏览(29)
  • Android Binder通信原理(一):简介

    源码基于: Android R 在Linux 系统中现有的进程间通信(IPC)方式: 管道(PIPE): 在创建时分配一个page大小的内存,缓存区大小比较有限; 命名管道(FIFO): 考虑 PIPE_BUF 和原子操作; 消息队列: 信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信; 共享内存:  无须

    2024年02月10日
    浏览(25)
  • 【Android Framework系列】第2章 Binder机制大全

       Binder是Android中主要的跨进程通信方式 。Android系统中,每个应用程序是由Android的Activity,Service,BroadCast,ContentProvider这四剑客中一个或多个组合而成,这四剑客所涉及的多进程间的通信底层都是依赖于BinderIPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需

    2024年02月10日
    浏览(33)
  • Android Binder通信原理(三):service注册

    源码基于: Android R 上一文中详细分析了 servicemanger 的启动流程 ,我们知道 servicemanager 作为 binder 机制中的一个特殊service,利用service map管理所有service,也是所有binder 通信的入口。 本文着重分析 service 的注册流程,下一文着重分析service 的获取流程。 Binder 中每个进程都会有

    2024年02月11日
    浏览(27)
  • Android Binder通信原理(二):servicemanager启动

    源码基于: Android R 下图是android 8.0 之前binder 的软件框架,依赖的驱动设备是/dev/binder,binder机制的四要素分别是client、server、servicemanager和binder驱动。 对于android 8.0后的binder 和vndbinder依然同这个框架,只不过驱动的设备多加/dev/vndbinder 这篇主要分析servicemanger的流程,hwserv

    2024年02月11日
    浏览(31)
  • Android Binder——Java层通信实例(十六)

            前面的文章中我们介绍了 Java 层服务的注册流程,以及代理文件的查找。这里我们看一个 Binder 通信的实例,为了方便我们就以 Android 源码中现有的功能 PMS 的 install 为例,PMS 在进行 APK 安装时,会进行 dex 的翻译,依赖守护进程 installd 完成。         在 Binder

    2024年04月23日
    浏览(37)
  • Android Binder通信原理(七):java 下的C-S

    源码基于: Android R 在之前的几篇博文中,对Android binder 的通信原理进行的深入的剖析,这些博文包括: binder 简介 、 servicemanager启动 、 service注册 、 service获取 、 Java 端的service 注册和获 取。 在前一文中,通过实例,详细地说明了 native 下 的C-S 通信原理 。 本文在之前的基

    2024年02月11日
    浏览(29)
  • Android Binder通信原理(五):Java 端的service 注册和获取

    源码基于: Android R 在阐述相关的知识点,先整理个框架图,后面带着框架图来分析过程: Java 端对于binder 使用大致分为: Java client Java service Java client native service Java 端service 的注册使用 ServiceManager.addService() Java 端service 的获取使用 ServiceManager.getService() 入口都是通过 Servic

    2024年02月11日
    浏览(28)
  • BpBinder与PPBinder调用过程——Android开发Binder IPC通信技术

    在Android系统中,进程间通信(IPC)是一个非常重要的话题。Android系统通过Binder IPC机制实现进程间通信,而Binder IPC通信技术则是Android系统中最为重要的进程间通信技术之一。本文将介绍Binder IPC通信技术的原理,并详细解析BpBinder与PPBinder调用过程的使用以及注意事项。 Bind

    2024年02月13日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包