Android Binder通信机制浅析

Android Binder进程间通信机制 今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。 阅读详情

一.实现Binder简单版本(我们模仿AIDL方式生成的接口文件,来自己实现Binder.代替AIDL的创建方式)

1.定义接口

package netease.com.canvasdemo;

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

/**
 * Created by zhukkun on 7/25/16.
 */
public interface IBank extends IInterface {

    static final String DESCRIPTOR = "netease.com.canvasdemo.IBank";

    static final int TRANSACTION_queryMoney = (IBinder.FIRST_CALL_TRANSACTION + 0);

    public long queryMoney(int uid) throws RemoteException;

}

2.Binder实现类

package netease.com.canvasdemo;

import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;

/**
 * Created by zhukkun on 7/25/16.
 */
public class BankImpl extends Binder implements IBank {

    public BankImpl() {
        Log.d("ClientActivity", "BankImpl Construct,pid"+Process.myPid()+"," + this);
        this.attachInterface(this, DESCRIPTOR);
    }

    public static IBank asInterface(IBinder obj) {
        if ((obj == null)) {
            return null;
        }

        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        Log.d("ClientActivity", "queryInterface return iin:" + iin +",this,"+obj);
        if (((iin != null) && (iin instanceof IBank))) {
            return ((IBank) iin);
        }
        return new BankImpl.Proxy(obj);
    }

    @Override
    public IInterface queryLocalInterface(String descriptor) {
        Log.d("ClientActivity", "queryInterface" + descriptor);
        Log.d("ClientActivity", "getInterfaceDescriptor" + getInterfaceDescriptor());
        if (getInterfaceDescriptor().equals(descriptor)) {
            return this;
        }
        return null;
    }

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

    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_queryMoney: {
                data.enforceInterface(DESCRIPTOR);
                int uid = data.readInt();
                long result = this.queryMoney(uid);
                reply.writeNoException();
                reply.writeLong(result);
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }

    @Override
    public long queryMoney(int uid) throws RemoteException {
        Log.d("ClientActivity", "query Money,remote pid:" + Process.myPid());
        return uid * 10l;
    }

    private static class Proxy implements IBank {
        private IBinder mRemote;

        Proxy(IBinder remote) {
            mRemote = remote;
        }

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

        public java.lang.String getInterfaceDescriptor() {
            return DESCRIPTOR;
        }

        @Override
        public long queryMoney(int uid) throws RemoteException {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            long result;
            try {
                data.writeInterfaceToken(DESCRIPTOR);
                data.writeInt(uid);
                mRemote.transact(TRANSACTION_queryMoney, data, reply, 0);
                reply.readException();
                result = reply.readLong();
            } finally {
                reply.recycle();
                data.recycle();
            }
            return result;
        }

    }

}

3.Service

package netease.com.canvasdemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by zhukkun on 7/23/16.
 */
public class MyService extends Service {

    BankImpl mBank;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        mBank = new BankImpl();
        Log.d("ClientActivity", "onBind return:" + mBank);
        return mBank;

    }
}

4.Client

package netease.com.canvasdemo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;

/**
 * Created by zhukkun on 7/23/16.
 */
public class ClientActivity extends Activity {

    private IBank remote;

    private ServiceConnection con = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("ClientActivity", "onServiceConnected:" + service);
            try {
                remote =  BankImpl.asInterface(service);
                Log.d("ClientActivity", "query Money,client pid:" + Process.myPid());
                Log.d("ClientActivity", "money" + remote.queryMoney(10));
            }catch (Exception e){
                e.printStackTrace();
            }
        }

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent("netease.com.aidldemo.MyService");
        bindService(intent, con, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(con);
    }
}
4.首先我们不在AndroidManifest中专门制定MyService的进程,尝试运行,来看下结果。


我们可以看到,Service 与Client运行在相同的进程中,并且在onBind中创建的实例,就是onServiceConnected中拿到的实例。


5.我们再来看看如果在AndroidManifest中指定MyService的进程,使得Service与Client运行在不同的进程中,运行来看下结果。


可以看到,服务端在onBind中创建的的进程是pid=25143,创建的IBinder实现实例是 BankImpl@52827de8,并且返回的也是这个实例。但是,在onServiceConnected中拿到的IBinder实现实例却是BinderProxy@52832fc8, 这是为了实现IPC,Android底层对IBinder进行了包装,里面的实现机制日后再分析,我们只要了解拿到的实现类不是onBind中创建的那一个就Ok了,这点在后面的分析中很重要。

我们首先得出一个结论:根据是否是跨进程,onServiceConnected回调中传回的IBinder实现实例是不同的,如果是同一进程,返回的就是Service中创建的实例,如果是跨进程,Android底层会对IBinder的实现实例进行一层包装,返回BinderProxy。

二.返回的IBinder实例的不同所造成的影响

private ServiceConnection con = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("ClientActivity", "onServiceConnected:" + service);
            try {
                remote =  <span style="color:#ff0000;">BankImpl.asInterface(service);</span>
                Log.d("ClientActivity", "query Money,client pid:" + Process.myPid());
                Log.d("ClientActivity", "money" + remote.queryMoney(10));
            }catch (Exception e){
                e.printStackTrace();
            }
        }

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

public class BankImpl extends Binder implements IBank {
<span style="white-space:pre">	</span>
    public BankImpl() {
        Log.d("ClientActivity", "BankImpl Construct,pid"+Process.myPid()+"," + this);
        this.attachInterface(this, DESCRIPTOR); //设置当前的接口实例,和描述信息
    }

    public static IBank asInterface(IBinder obj) {
        if ((obj == null)) {
            return null;
        }

        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  //根据描述信息,取出接口实例
        Log.d("ClientActivity", "queryInterface return iin:" + iin +",this,"+obj);
        if (((iin != null) && (iin instanceof IBank))) {
            return ((IBank) iin);
        }
        return new BankImpl.Proxy(obj);
    } ...<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

按照我们上面的例子 BankImpl()是在Service的onBind()中创建的,this.attachInterface(this, DESCRIPTOR) ,我们看下代码:
/**
     * Convenience method for associating a specific interface with the Binder.
     * After calling, queryLocalInterface() will be implemented for you
     * to return the given owner IInterface when the corresponding
     * descriptor is requested.
     */
    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

再来看下,Binder的queryInterface

/**
 * Use information supplied to attachInterface() to return the
 * associated IInterface if it matches the requested
 * descriptor.
 */
public IInterface queryLocalInterface(String descriptor) {
    if (mDescriptor.equals(descriptor)) {
        return mOwner;
    }
    return null;
}

代码看完了以后,我们根据上面的运行catlog中进行分析。

1.在相同进程中,onBind中创建的实例就是onServiceConnect中返回的实例,所以能根据描述信息,直接返回该实例给Client,然后直接调用该实例的方法。

2.不同进程,因为返回的实例不是同一个,所以queryLocalInterface查找为null,故要将返回的实例再进行一次代理包装,把包装后的实例返回给Client进行调用。


三.使用Proxy来进行方法调用

private static class Proxy implements IBank {
        private IBinder mRemote;

        Proxy(IBinder remote) {
            mRemote = remote;
        }

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

        public java.lang.String getInterfaceDescriptor() {
            return DESCRIPTOR;
        }

        @Override
        public long queryMoney(int uid) throws RemoteException {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            long result;
            try {
                data.writeInterfaceToken(DESCRIPTOR);
                data.writeInt(uid);
                <span style="color:#ff0000;">mRemote.transact(TRANSACTION_queryMoney, data, reply, 0);</span>
                reply.readException();
                result = reply.readLong();
            } finally {
                reply.recycle();
                data.recycle();
            }
            return result;
        }

    }

实现跨进程调用的关键语句,是上面红色的部分。通过把数据包装成Parcel,通过管道的形式传递到服务端进程中,

再看下BankImpl的onTransct()
@Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_queryMoney: {
                data.enforceInterface(DESCRIPTOR);
                int uid = data.readInt();
                long result = <span style="color:#ff0000;">this.queryMoney(uid);</span>
                reply.writeNoException();
                reply.writeLong(result);
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }

然后在onTransct()中进行参数的解析,在调用自身的方法,最后把结果写回管道里,传回客户端进程。


至于如何返回给客户端的IBinder,是如何进行包装,还有管道的具体实现,太过于底层了,以后有机会再分析。

参考文章:https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/proxy/singwhatiwanna 

深入解析Android Binder通信机制及实例 本文还有配套的精品资源,点击获取 简介:AndroidBinder是实现进程间通信的核心机制,本篇将详细介绍Binder的工作原理、角色模型、代理与stub机制、事务处理,以及创建和使用Binder实例的具体步骤,包括接口定义、Binder类实现、服务中暴露Binder以及客户端使用Binder的过程。此外,还将解释"AddService"文件名可能的含义,以助于深入理解A... 阅读详情

相关推荐

PSOC Creator 入门教程超详细

最近工作原因需要使用到赛普拉斯的一款芯片,奈何以前没有用过,所以趁这次也学习了一些简单的用法,总结一下,希望能帮到有需要朋友,因为网上关于这方面的文章少的可怜,详细点的更是少之又少!废话少说,正文开始.

qm_mq的博客 5746

Android binder通信实现进程间通信

Binder 是 Android 系统中用于跨进程通信的一种机制,它允许一个进程中的组件与另一个进程中的组件进行通信,从而实现进程间通信 (IPC)。Binder 机制是基于 Linux 内核提供的进程间通信机制 (IPC) 实现的。

朝气蓬勃 4699

AnolisOS网卡驱动源码编译与安装实战指南

本文提供了一份详尽的AnolisOS网卡驱动源码编译与安装实战指南。针对系统自带通用驱动不兼容导致网络无法使用的问题,文章从环境准备、源码获取、编译安装到新旧驱动替换与持久化配置,一步步解析了如何通过源码编译安装官方驱动,解决硬件兼容性问题,并确保驱动在系统重启后自动生效。

weixin_28358083的博客 304

一文分析Binder机制和AIDL的理解

为什么要去理解Android的进程间通信机制 对于Android开发工程师来说,如果不去理解进程间通信机制也可以使用系统提供的API完成应用开发,但如果想要达到更高的层级,那么就不能简单只会调用API。无论是工作中遇到一些疑难问题,还是想要学习源码的一些功能实现,或者是想要提升APP的性能等,这些工作都需要我们去看系统的源码,而系统的源码中进程间通信无处不在,如果不理解进程间通信机制,那么很难看懂系统源码,而且容易迷失在大量的代码中。 Android 进程间通信机制 为什么使用Binder作为Android

nufuli123的博客 2974

如何加载交易策略EA到MT4/MT5

1、打开MT4/MT5软件 2、首先,必须有一个EA,而且必须是mq4/ex4为扩展名。点击左上角“文件”—“打开数据文件夹”,找到安装路径 3、将EA的ex4或mq4文件放到MT4目录\MQL4\Experts里面(本文以名为Demo的EA为例) 4、如果有DLL库文件,复制到experts目录下的libraries子目录中 5、如果有tpl模板文件,复制到templates目录中 6、添加完成后重启MT4,点击允许EA运行图标 7、在导航中找到刚才安装的EA,拖拽到...

weixin_41364817的博客 7362

高德地图可视化入门:零基础用Python+高德API打造你的第一个热力图

本文详细介绍了如何使用Python和高德地图API从零构建商业级热力图。通过环境配置、地理编码、数据清洗到最终可视化展示的全流程指南,帮助开发者快速掌握地图可视化技术,特别适合展示商圈人流、疫情热点等地理分布数据。

weixin_29053067的博客 306

Android:从源码角度来赏析Binder机制的优美

谈到android进程间通信,就不得不想到Binder,那么他到底是何方圣神呢?话不多说,咱们下面一起来解密一番!   IBinder 首先我们来看一下Binder的声明: public class Binder implements IBinder {...} 哟,那么IBinder又是什么呢? public interface IBinder { int FI...

weixin_43887839的博客 466

大众点评商家及评分数据(2012-2025)

大众点评及商家评分数据库全面覆盖全国范围内多个城市的商户信息,涵盖餐饮、购物、休闲娱乐等多个消费领域,包含商家基础信息、地理坐标、分类体系、经营状态、用户评价、消费水平及服务设施等共计28个字段。

Sunny9qx的博客 2694

Android IPC机制——Binder详解

IPC是指Android中的进程间通信,即在不同进程之间传递消息数据,Android中可实现进程通信的方法有很多,比如Intent、ContentProvider、Messenger、Binder或是利用文件,这些方式各有千秋,都有最适合使用的场景,这次要介绍的是Service跨进程访问的神器——Binder。 我们都知道启动一个service时可以使用startService()和bindSe

SiKang的博客 1967

【OpenClaw企业级智能体实战】第11篇:制造业设备预测性维护实战——OpenClaw+DeepSeek+Prometheus从零搭建(附完整代码)

本文聚焦制造业设备预测性维护的核心痛点,基于OpenClaw v2026.2.1、DeepSeek智能诊断、Prometheus监控等工具,拆解“设备状态监控→智能故障诊断→预测性维护”三大核心场景。从技术原理、算法构建、实操流程到完整代码实现,提供“数据采集→模型训练→智能调度→自动处置”的全链路方案。方案遵循工业安全规范,采用“只读优先、权限最小化”原则,适配中小制造企业落地需求。通过虚拟案例验证,可使设备非计划停机时间下降65%、平均修复时间缩短47%,既适合新手快速入门,也为进阶读者提供架构优化思路

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 606

VTK-9.5.0 1D2D3DWidget实现灰度图+深度图+3D点云显示(可轻松集成到自己的项目)

VTK1D2D3DWidget是一个基于Qt和VTK开发的3D点云可视化工具,支持RGB和深度点云数据的显示与处理。主要功能包括点云加载、可视化、保存为PLY格式文件,以及背景颜色、点间隔、坐标轴显示等参数的自定义设置。该工具采用模块化设计,核心组件包括主窗口管理类、VTK渲染组件和自定义鼠标交互样式,依赖Qt5+和VTK9.5.0库实现跨平台支持。项目提供完整的源码和构建指南,适用于点云数据的快速展示与分析。

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 385

Android Binder 机制

讲Android Binder机制的文章非常多,这篇文章主要是理一下我对Binder的理解。本文不是一篇介绍Binder的文章,也不是一篇探讨Binder实现的文章。 本文会以AndroidStudio根据aidl接口自动产生的java文件来看Binder,进而来理解Binder机制。 其实Android的Binder机制类似于:RPC(远程过程调用)。如果你理解它,相信Binder机制就更容...

weixin_43887839的博客 312

Open3D——点云构建Delaunay三角网【2026最新版】

点云构建Delaunay三角网

点云侠的博客 8368

Android跨进程通信Binder机制浅析

 本文为自己多年来在Android实战开发过程中总结归纳的一些常见问题,现在分享出来希望对初学者有所帮助。 本文出自门心叼龙的博客,转载请注明出处: https://blog.youkuaiyun.com/geduo_83/article/details/86560675     目录 1. 什么IPC?Linux中现有的IPC通信方式都有哪些? 2. 什么是Binder? 3. 为什么 And...

门心叼龙的专栏 3222

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

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

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

张拭心的博客 shixinzhang 2万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Android进程通信之 Binder 机制浅析

IBinder Binder继承自IBinder,所以我们先来了解下它。 IBinder 是一个接口,它代表了一种跨进程传输的能力。只要实现了这个接口,就能将这个对象进行跨进程传递。 IBinder 是高性能、轻量级远程调用机制的核心部分,它定义了远程操作对象的基本接口。 这些方法中最关键的一个是transact(): public boolean transact(int co...

android开发笔记 874

图解 | 不得错过的Binder浅析(一)

Framework和Binder的内容挺深的,本文还是站在应用层开发者的角度来建立基本认知,能在遇到问题的时候有思路和方向即可。(本文将带着关键问题和核心流程展开,不会面面俱到) 大纲: 背景 为什么要多进程 为什么要Binder Binder简单架构 简单示例 源码分析 客户端与驱动交互 服务端与驱动交互 总结 细节补充 Binder为什么高效 Binder为什么不用shm 提问 参考资料 本文约4.0k字,阅读大约17分钟。 Android源码基于8.0。 背景 为什么要多进程

哈利迪 765

【Android】Binder机制浅析

BInder机制是Android系统提供的跨进程通信机制。本篇文章会从Linux的基础知识开始介绍,从基础概念引出Binder机制,接着分析Binder的通信模型和原理,最后将会手动实现AIDL完成进程间的通信。侧重点在于原理和使用上,适合初学者。

2302_79323248的博客 1402

Android:安卓学习笔记之Binder 机制的简单理解和使用

Binder 机制 的简单理解和使用Binder 机制参考 Binder 机制 参考 1、图解Android中的Binder机制 2、Android Binder(也许是最容易理解的) 3、图文详解Binder跨进程通信原理 4、Android 接口定义语言 (AIDL) ...

JMW1407的博客 1万+

Android Binder机制的详解

1.Binder机制简介 Android Binder是源于Palm的OpenBinder,它为android设备跨进程访问而设计。Binder机制从表现上看可以实现java 和native层的对象实例可以从一个进程访问到另一个进程,从而透明的实现跨进程的调用。调用者感觉不到自己的请求是在另一个进程中完成并返回结果的。在android系统中使用Binder机制最多的是系统服务,这些服务一般运行在特...

cike110120的专栏 1万+

Android的Binder机制浅析

简要分析Android基础应用框架中的主要IPC实现方式Binder的运行机理,以多媒体框架中Surface和MediaPlayerService等为例说明。

quanben 9523

【Binder】Android跨进程通信:详解 Binder机制

粘合剂,意思为粘合了两个不同的进程。

qq_30885821的博客 1874

Android浅析Binder机制

为了更好理解Binder机制,下面举个生活中经常遇到的例子:A和B要打电话,A首先要有B的电话号码,电话号码在通信录获取,通信录中保存了B的昵称,电话号码之类的信息,得到电话号码之后,还需要电话基站的支持,A和B才可以进行电话交流;这里,我们发现,一次简单的打电话的过程,除了A和B两个主体对象外,还存在两个隐含的但是必不可少的东西,通信录和电话基站。我们可以做个类比,对于A和B相当于...

u010218230的博客 894
上一篇: Android AIDL 与 Service
下一篇: Handler Looper MessageQueue
kkdev
博客等级 码龄11年 1粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值