【Android】Binder(一)Binder的介绍和AIDL使用Binder的实例

news2024/11/28 18:50:23

Binder介绍

Android 中的 Binder 是一个进程间通信机制,它允许不同进程之间相互调用方法和传递数据。Binder 主要用于实现系统服务和应用程序之间的通信,以及实现 IPC(Inter-Process Communication,进程间通信)。

Binder 的核心是 Binder 驱动程序,它负责管理不同进程之间的通信。每个进程都可以创建自己的 Binder 对象作为服务提供者,也可以获取其他进程提供的 Binder 对象作为客户端使用。这些 Binder 对象都必须通过 Binder 驱动来进行跨进程通信。

机制来说: Binder是一种进程间通信机制
驱动来说: Binder是一个虚拟物理设备驱动
应用层来说:Binder是一个能发起通信的Java类

在 Android 开发中,我们可以通过 AIDL(Android Interface Definition Language)来定义自己的 Binder 接口,并实现相应的服务提供者和客户端。AIDL 生成的代码可用于在不同进程之间进行 IPC 通信。


Binder和其他进程通信方案的比较

Binder与传统IPC对比
Binder共享内存Socket
性能需要拷贝一次 无需拷贝需要拷贝两次
特点基于C/S架构,易用性高控制复杂,易用性差基于C/S 架构,作为一款通用接口,其传输效率低,开销大
安全性为每个APP分配UID,同时支持实名和匿名依赖上层协议访问,接入点是开放的,不安全

Binder 机制组成

Binder(IInterface 接口)该类定义了远程服务的接口,用于在客户端和服务端之间通信
IBinder 接口该类是 Binder 的实现类,提供了轻量级的进程间通信能力
ServiceManager该类提供了一种注册和查找 Binder 服务的机制
Binder驱动程序该驱动程序是 Binder 进程间通信的核心,用于管理 Binder 连接、数据传输、线程等操作

Binder 机制为 Android 开发提供了一种高效、灵活的进程间通信方式,使得应用程序能够更加方便地进行跨进程数据共享和调用远程服务。


AIDL与 Binder 的关系

AIDL(Android Interface Definition Language,Android 接口定义语言)是 Android 系统中用于实现进程间通信(IPC)的一种机制。AIDL 可以帮助开发者在不同的应用程序之间或不同进程之间实现远程方法调用,从而实现跨进程的数据共享和交互。

Binder 是 Android 系统中用于实现 IPC 的核心驱动程序,它可以为 AIDL 定义的接口提供底层支持。Binder 驱动程序通过管理进程间的连接、数据传输等操作,完成了基于 AIDL 的进程间通信功能。

AIDL 与 Binder 的关系可以理解为:AIDL 提供了描述跨进程间通信接口的语言,而 Binder 则是实现 AIDL 接口调用的内部框架。在 Android 应用程序中,一般都是通过在 AIDL 文件中定义跨进程访问的接口,并通过 Binder 实现这些接口,从而实现应用程序之间的通信。


使用Binder进行进程间通信例子

首先,我们需要创建两个端,分别是服务端客户端

服务端

创建一个项目,名字叫MyBinderService
在这里插入图片描述
然后创建AIDL文件

注意:aidl文件夹是需要自己创建的,且文件夹在main文件夹下面,和 java文件夹平级

在这里插入图片描述

当我们在aidl文件夹创建aidl文件时,遇到这个错误:
在这里插入图片描述

这个提示意味着需要在 build.gradle 文件中设置 buildFeatures.aidl 为 true 才能使用 AIDL 技术
在这里插入图片描述

 buildFeatures {
    aidl = true
 }

此时我们看到上面的aidl文件夹也变颜色了。

服务端应用程序中,我们需要先定义一个 AIDL 接口,为客户端提供数据获取的方法。
在这里插入图片描述
然后我们需要实现接口方法并注册到系统中,这里使用一个 Service 来实现:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整代码

public class MyService extends Service {

    private static final int NOTIFICATION_ID = 1001; // 前台通知 ID

    private final IBinder mBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("Binder响应:", "已经绑定到Binder上面了");
        return mBinder;
    }

    static class MyBinder extends IMyService.Stub {
        @Override
        public long getCurrentTimestamp() throws RemoteException {
            long time = System.currentTimeMillis();
            Log.e("Binder数据:", "服务端的时间戳:" + time);
            return time;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager manager = getSystemService(NotificationManager.class);
            NotificationChannel channel = new NotificationChannel(
                    "channel_id",
                    "前台通知渠道名称",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            manager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("Binder服务端")
                .setContentText("测试Binder的前台Service");

        startForeground(NOTIFICATION_ID, builder.build());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.e("Binder的服务", "在Service做耗时任务的话,请使用子线程,因为Service是在主线程运行的");
                Log.e("Binder的服务", "此时的线程:" + Thread.currentThread().getName());
            }
        }).start();
        return START_STICKY;
    }
}

主页面:
在这里插入图片描述
完整代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tvStartService = findViewById(R.id.tv_startService);
        TextView tvStopService = findViewById(R.id.tv_stopService);
        tvStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(intent);
                } else {
                    startService(intent);
                }
            }
        });
        tvStopService.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                stopService(intent);
            }
        });
    }
}

注意:

需要在AndroidManifest.xml文件中添加这个权限:

  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

不然会报错:

Permission Denial: startForeground from pid=16363, uid=10134 requires android.permission.FOREGROUND_SERVICE

同时在此文件里面注册完善MyService文件

<service
     android:name=".MyService"
     android:enabled="true"
     android:exported="true">
     <intent-filter>
           <action android:name="com.shsany.mybinderservice"/>
     </intent-filter>
</service>

此时配置好之后,要记得Build一下项目,这样Android Studio会自动生成AIDL的代码
在这里插入图片描述
生成的代码:
在这里插入图片描述

客户端

在客户端需要配置的和服务端的步骤方法一样,不再叙述。

注意:

在客户端的AIDL文件不要自己重新写,要从服务端复制过来,保证两边是一样的。

服务端

在这里插入图片描述

客户端

在这里插入图片描述

这两个端的这个文件无论是包名还是里面的代码都要一样的,所以直接复制最好。

客户端命名为MyBinder,只有一个文件

在这里插入图片描述

MainActivity代码

在这里插入图片描述
在这里插入图片描述
完整代码:

public class MainActivity extends AppCompatActivity {
    private IMyService mMyService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tvGetData = findViewById(R.id.tv_getBinderData);

        Intent intent = new Intent();
        intent.setAction("com.shsany.mybinderservice");
        intent.setPackage("com.shsany.mybinderservice");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        tvGetData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    // 在使用服务端方法时,先判断服务是否可用
                    if (mMyService != null) {
                        long currentTime = mMyService.getCurrentTimestamp();
                        Log.e("Binder数据:", "从服务端接收到的时间戳:" + currentTime);
                    } else {
                        Log.e("Binder数据:", "无法连接到服务端");
                    }
                } catch (Exception e) {
                    Log.e("Binder错误:", e.getMessage());
                }
            }
        });
    }

    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //远程Service绑定
            Log.e("Binder数据:", "已经连接到服务端");
            mMyService = IMyService.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //Service被意外销毁
            Log.e("Binder数据:", "服务端被意外销毁");
            mMyService = null;
        }
    };
}
测试

首先需要先启动服务端
在这里插入图片描述
然后再启动客户端
在这里插入图片描述
此时连接到服务端之后,服务端的显示
在这里插入图片描述
然后再客户端上面调用getCurrentTimestamp方法获取数据:
在这里插入图片描述
此时再看服务端
在这里插入图片描述
至此,一个简单的AIDL使用Binder跨进程通信就完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/597704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

陪诊APP小程序开发 陪伴就医告别孤独

生活工作忙碌&#xff0c;很多情况下父母或者其他亲人需要去医院的时候没办法陪同&#xff0c;让其单独去又不放心成为令很多人苦恼的问题。随着移动互联网的深入到我们生活的方方面面&#xff0c;医疗行业也出现了很多陪诊服务APP小程序系统软件&#xff0c;让孤独就医者有人陪…

Android H5拉起安卓原生方案的介绍与实战(六一篇)

一、介绍 今天是6.1儿童节&#xff0c;祝大家儿童节快乐。 言归正传&#xff0c;开始介绍H5拉起原生。如今&#xff0c;在APP应用中&#xff0c;消息大多数采用推送方式比较多&#xff0c;到达率很低或者说无法满足业务的需求。在一些大型活动中&#xff0c;依然需要短信的参与…

网络安全:SQL 注入漏洞

一、漏洞描述 WordPress是一个用PHP编写的免费开源内容管理系统&#xff0c;由于clean_query函数的校验不当&#xff0c;导致了可能通过插件或主题以某种方式从而触发SQL注入的情况。这已经在WordPress5.8.3中进行了修复。影响版本可以追溯到3.7.37。 二、漏洞分析 在分析整…

平台使用篇 | 批处理(bat)脚本使用教程(四)

导读 一个开启多机软件在环仿真的批处理文件 (对应卓面RflyTools文件夹中SITLRun快捷方式)&#xff0c;双击它&#xff0c;输入想要生成的飞机数量&#xff0c;即可生成多机软件在环仿真&#xff0c;等待RflySim3D显示3DFixed 4/4&#xff0c;然后可通过QGC控制飞机起飞。运行…

Unity API详解——Time类

Time类是Unity中获取时间信息的接口类&#xff0c;只有静态属性。本博客介绍Time类的一些静态属性。 一、Time类静态属性 在Time类中&#xff0c;涉及的静态属性有realtimeSinceStartup、smoothDeltaTime和time属性&#xff0c;在介绍time属性时涉及了Time类的多个其他属性的…

学姐生日快到了~这不得用Python把她的照片做成视频当礼物送给她....

前言 这不是学姐生日快到了&#xff0c;于是我学了一手Python~ 来把学姐的照片生成为视频&#xff0c;到时候给她一个惊喜&#xff01; 好了先不说了&#xff0c;下面分享一下用python代码 实现多张图片合成MP4视频为实例&#xff0c;做下详细代码讲解。 一、需要调入的模块…

设计模式之~迭代器模式

迭代器模式&#xff1a; 迭代器&#xff08;Iterator&#xff09;模式&#xff0c;又叫做游标&#xff08;Cursor&#xff09;模式。GOF 给出的定义为&#xff1a;提供一种方法顺序访问一个容器&#xff08;container&#xff09;对象中各个元素&#xff0c;而又不需暴露该对象…

数据库DBMS并发控制(1)

pgsql&#xff08;PostgreSQL&#xff09;常用命令行操作_pgsql常用命令_石头wang的博客-CSDN博客 重要&#xff1a;事务的操作和事务的性质 操作演示 四种典型数据不一致现象: 串行调度和可串行调度 串行调度 顾名思义 就是可以进行调度的意思 可串行调度 就是 一种和串行…

C Primer Plus第十六章编程练习答案

学完C语言之后&#xff0c;我就去阅读《C Primer Plus》这本经典的C语言书籍&#xff0c;对每一章的编程练习题都做了相关的解答&#xff0c;仅仅代表着我个人的解答思路&#xff0c;如有错误&#xff0c;请各位大佬帮忙点出&#xff01; 由于使用的是命令行参数常用于linux系…

常见的ACL攻击方式,集权设施如何防御攻击?

本文主要介绍了 WindowsAD域中基于访问控制列表&#xff08;ACL&#xff09;的攻击&#xff0c;在AD域的攻击手法中&#xff0c;基于ACL的攻击由于理解起来比较困难&#xff0c;现有的安全设备也很少有对ACL的监控&#xff0c;这种类型的攻击通常会被安全人员所忽视。 1.什么是…

[SpringBoot]创建聚合项目

首先&#xff0c;创建父级项目&#xff1a; 因为手动添加依赖&#xff0c;以下只选版本不打钩 因为父项目不写代码&#xff0c;所以删除src 调整pom.xml文件&#xff08;并刷新maven&#xff09;&#xff0c;如下&#xff1a; <?xml version"1.0" encoding&qu…

如何入门渗透测试

1. 什么是渗透测试 渗透测试就是模拟真实黑客的攻击手法对目标网站或主机进行全面的安全评估&#xff0c;与黑客攻击不一样的是&#xff0c;渗透测试的目的是尽可能多地发现安全漏洞&#xff0c;而真实黑客攻击只要发现一处入侵点即可以进入目标系统。 一名优秀的渗透测试工程…

Flink SQL之Regular Joins

1.Regular Joins&#xff08;双流join&#xff09; 双流join是最通用的联接类型&#xff08;支持 Batch\Streaming&#xff09;&#xff0c;其中任何新记录或联接两侧的更改都是可见的&#xff0c;并影响整体的Join结果。 特点&#xff1a; 对于流式查询&#xff0c;双流join…

深入分析 OpenShift 内部 DNS

深入分析 OpenShift 内部 DNS OpenShift 中的DNS 相关组件及其配置1.1 Pod 中的 DNS 配置1.2 Pod 所在宿主机上的 DNS 配置及服务1.2.1 resolv.conf 文件 DNS 配置DNS 查询流程为什么需要内部 DNS&#xff1f; 本文基于 OpenShift 3.11&#xff0c;Kubernetes 1.11 进行测试 O…

Linux服务器禁止密码登录,设置秘钥登录

生成SSH密钥 (客户机端) 执行ssh-keygen -t rsa命令创建RSA密钥对&#xff0c;执行结果如下(键入3次回车)&#xff1a; [rootnode01 .ssh]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): [回车] En…

【十五】设计模式~~~行为型模式~~~状态模式(Java)

【学习难度&#xff1a;★★★☆☆&#xff0c;使用频率&#xff1a;★★★☆☆】 4.1. 模式动机 在很多情况下&#xff0c;一个对象的行为取决于一个或多个动态变化的属性&#xff0c;这样的属性叫做状态&#xff0c;这样的对象叫做有状态的(stateful)对象&#xff0c;这样的…

向后切片,正向切片和其他形式的切片

向后切片,正向切片和其他形式的切片 向后切片Backward Slices 假设我们希望确定哪些语句影响节点 n。 这是由 n 和在 n 处引用的变量。 我们只是&#xff1a; 从 n 回溯控制和流依赖边。 我们保留由此到达的节点。 一般后向切片 通常&#xff0c;我们的切片标准是一个节点和一…

【CMake 入门与进阶(1)】一个例子搞懂什么是CMakeLists——从“Hello World”开始(附代码)

在前面两篇内容中&#xff0c;我们编写了很多示例程序&#xff0c;但这些示例程序都只有一个.c 源文件&#xff0c;非常简单。因此&#xff0c;编译这些示例代码其实都非常简单&#xff0c;直接使用 GCC 编译器编译即可&#xff0c;连 Makefile 都不需要。但是&#xff0c;在实…

中国人民大学与加拿大女王大学金融硕士项目——在职攻读金融硕士,努力迈进高阶人生

学历重要吗&#xff1f;入职门槛、晋升、考公等多方面都考核学历。学历代表的并不只是学习经历&#xff0c;也是学习能力的体现。在快速发展的社会&#xff0c;学历越高&#xff0c;学习能力越强&#xff0c;机会就越多。金融行业在职的你&#xff0c;有计划在职攻读硕士学位吗…

如何在 K3s 中使用网络策略

本文将介绍如何在示例项目中使用网络策略&#xff0c;并解释它在 K3s 中的工作原理&#xff0c;从而帮助用户提高部署的安全性。 关于 K3s 对网络策略的支持存在一个普遍的误解&#xff0c;因为 K3s 默认使用 Flannel CNI&#xff0c;而 Flannel CNI 不支持网络策略。其实&…