Android跨进程通信(AIDL、Binder

目录

Binder​编辑​编辑

一次完整的通信过程​编辑

IPC&&RPC

Binder原理简介

Framework Binder

Binder架构图​编辑

Binder类图​编辑

Binder类分层

如何使用Binder

Service端

Client端


  1. Binder

    Android系统中,每个应用程序是由Android的ActivityServiceBroadcastContentProvider这四大组件的中一个或多个组合而成,这四大组件所涉及的多进程间的通信底层都是依赖于Binder IPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于Binder IPC。不仅于此,整个Android系统架构中,大量采用了Binder机制作为IPC(进程间通信)方案,当然也存在部分其他的IPC方式,比如Zygote通信便是采用socket。

  2. 一次完整的通信过程

  1. IPC&&RPC

  • IPC(进程间通讯),RPC(远程过程调用)

  • 从组件的角度,通信涉及三部分:

    • 源程序:假设是A进程

    • 目的进程:假设为B进程,假设提供led服务

    • 数据:char buf[512],数据就是一个buff,双方约定好数据格式;

  • 进程A怎么知道进程B提供的led的服务?为什么不是其他进程?

    • 进程B向service_manager注册led服务;

    • 进程A向service_manager查询led服务,得到一个handle,这个handle指向某个的某个服务,是服务的引用;binder驱动会自动根据服务对应的handle值,确定这个服务所在进程;

  • RPC关注的一些问题:

    • RPC:称为远程过程调用,Client调用Server端函数时,要调用哪个函数?

      • 对server的函数编号,要调用哪个函数,把函数编号(这个编号最后会被封装成txn->code)发给server;

    • 调用的函数,给被调用的函数传什么参数?这些参数怎么传递过去的?

      • 通过IPC的buffer传递给server

    • 调用的返回值是什么?

      • server端通过buffer将返回值传递给client端的调用;

  1. Binder原理简介

  • Binder通信采用C/S架构,从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务;

  • 从流程的角度:Binder分为三大基础流程,分别是:

    • 注册服务(addService)

    • 获取服务(getService)

    • 使用服务

  • 可以看出无论是注册服务和获取服务的过程都需要ServiceManager,需要注意的是此处的Service Manager是指Native层的ServiceManager(C++),并非指framework层的ServiceManager(Java);

  • ServiceManager是整个Binder通信机制的大管家,是Android进程间通信机制Binder的守护进程,要掌握Binder机制,首先需要了解系统是如何首次启动Service Manager;

  • 当Service Manager启动之后,Client端和Server端通信时都需要先获取Service Manager接口,才能开始通信服务;

  • 注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端;

  • 获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端;

  • 使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。

  1. Framework Binder

  1. Binder架构图

  1. Binder类图

  • 图中浅蓝色都是Interface,其余都是Class

  • ServiceManager:通过getIServiceManager方法获取的是ServiceManagerProxy对象; ServiceManager的addService, getService实际工作都交由ServiceManagerProxy的相应方法来处理;

  • ServiceManagerProxy:其成员变量mRemote指向BinderProxy对象,ServiceManagerProxy的addService, getService方法最终是交由mRemote来完成。

  • ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy对象,ServiceManager便是借助ServiceManagerNative类来找到ServiceManagerProxy;

  • Binder:其成员变量mObject和方法execTransact()用于native方法

  • BinderInternal:内部有一个GcWatcher类,用于处理和调试与Binder相关的垃圾回收。

  • IBinder:接口中常量FLAG_ONEWAY:客户端利用binder跟服务端通信是阻塞式的,但如果设置了FLAG_ONEWAY,这成为非阻塞的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外IBinder接口有一个内部接口DeathDecipient(死亡通告)。

  1. Binder类分层

  • 整个Binder从kernel至,native,JNI,Framework层所涉及的全部类

  1. 如何使用Binder

  1. Service端

package com.transsion.binderdemo;

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

public class HelloService extends Service {
    private static final String TAG = "HelloService";

    public HelloService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to t;he service.
        Log.d(TAG, "on service bind");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "on service unbind");
        return super.onUnbind(intent);
    }
    //实现server端
    private IHelloService.Stub mBinder = new IHelloService.Stub() {
        @Override
        public String SayHello() throws RemoteException {
            Log.d(TAG, "on say hello");
            String content = "say hello";
            return content;
        }

        @Override
        public String SayGoodBye() throws RemoteException {
            Log.d(TAG, "on say good bye");
            String content = "say good bye";
            Toast.makeText(getApplicationContext(), content, Toast.LENGTH_SHORT).show();
            return content;
        }
    };
}
  1. Client端

package com.transsion.binderdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "BinderDemoMainActivity";
    private IHelloService mHelloService;
    private Button btBind;
    private Button btUnBind;
    private Button btHello;
    private Button btBye;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btBind = findViewById(R.id.bt_bind);
        btUnBind = findViewById(R.id.bt_unbind);
        btHello = findViewById(R.id.bt_hello);
        btBye = findViewById(R.id.bt_bye);
        btBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                bindHelloService();
            }
        });
        btUnBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                unbindRemoteService();
            }
        });
        btHello.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mHelloService != null) {
                    Log.d(TAG, "on bt hello clicked ,hello service is not null");
                    try {
                        String content = mHelloService.SayHello();
                        if (content != null && !content.isEmpty()) {
                            Toast.makeText(getApplicationContext(), content, Toast.LENGTH_SHORT).show();
                        }
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    Log.d(TAG, "on bt hello clicked ,hello service is null");
                }
            }
        });
        btBye.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mHelloService != null) {
                    Log.d(TAG, "on bt good bye clicked ,hello service is not null");
                    try {
                        String content = mHelloService.SayGoodBye();
                        if (content != null && !content.isEmpty()) {
                            Toast.makeText(getApplicationContext(), content, Toast.LENGTH_SHORT).show();
                        }
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    Log.d(TAG, "on bt good bye clicked ,hello service is null");
                }
            }
        });
    }
    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mHelloService = IHelloService.Stub.asInterface(iBinder);
            Log.d(TAG, "onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected");
        }
    };
    void bindHelloService() {
        Intent intent = new Intent(MainActivity.this, HelloService.class);
        intent.setAction(HelloService.class.getName());
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }
    private void unbindRemoteService() {
        unbindService(mConnection);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值