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

2023-11-09

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

Android系统架构
Android是怎么启动的
Android 10.0系统启动之init进程
Android10.0系统启动之Zygote进程
Android 10.0 系统启动之SystemServer进程
Android 10.0 系统服务之ActivityMnagerService
Android10.0系统启动之Launcher(桌面)启动流程
Android10.0应用进程创建过程以及Zygote的fork流程
Android 10.0 PackageManagerService(一)工作原理及启动流程
Android 10.0 PackageManagerService(二)权限扫描
Android 10.0 PackageManagerService(三)APK扫描
Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》

Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​
《Binder通信原理》:

Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
Android10.0 Binder通信原理(二)-Binder入门篇
Android10.0 Binder通信原理(三)-ServiceManager篇
Android10.0 Binder通信原理(四)-Native-C\C++实例分析
Android10.0 Binder通信原理(五)-Binder驱动分析
Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
Android10.0 Binder通信原理(七)-Framework binder示例
Android10.0 Binder通信原理(八)-Framework层分析
Android10.0 Binder通信原理(九)-AIDL Binder示例
Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
Android10.0 Binder通信原理(十一)-Binder总结

《HwBinder通信原理》

HwBinder入门篇-Android10.0 HwBinder通信原理(一)
 HIDL详解-Android10.0 HwBinder通信原理(二)
HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
HwServiceManager篇-Android10.0 HwBinder通信原理(五)
Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》

编译系统入门篇-Android10.0编译系统(一)
编译环境初始化-Android10.0编译系统(二)
make编译过程-Android10.0编译系统(三)
Image打包流程-Android10.0编译系统(四
Kati详解-Android10.0编译系统(五)
Blueprint简介-Android10.0编译系统(六)
Blueprint代码详细分析-Android10.0编译系统(七)
Android.bp 语法浅析-Android10.0编译系统(八)
Ninja简介-Android10.0编译系统(九)
Ninja提升编译速度的方法-Android10.0编译系统(十)
Android10.0编译系统(十一)

0.什么是AIDL
AIDL:Android Interface Definition Language,即Android接口定义语言。

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

 

下面将通过一个示例来说明两个APP之间的AIDL通信。

 

1.工程环境准备
1)通过Android Studio 首先创建一个项目  New Project ->Empty Activity,Name:AIDLDemo, Pakcage:com.android.myservice ,用作Server

2)在项目中再创建一个Module,用来做Client, 在项目文件上 右键 ->New-> Module -> Phone & Tablet Module, 名称填client  -> Empty Activity

 

3)这样Server和Client的两个环境就准备好了

 

2.服务端设计

2.1 创建一个AIDL 文件 IMyService

在服务的文件夹app 中,执行下面的步骤:

右键 -> New -> AIDL->AIDL File, 名称为IMyService

AIDL创

建完成

填入一个add的函数,我们用来做加法计算:

Code:

// IMyService.aidl
package com.android.myservice;
 
// Declare any non-default types here with import statements
 
interface IMyService {
    /**
     * 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);
 
    int add(int num1, int num2);
}

选择 Build -> Make Module "app",会把AIDL进行编译,会自动生成IMyService 这个服务接口,其中实现了stub、proxy的class,以及TRANSACTION的code,用来通信处理

 

2.2 服务实现
在Framework层我们还可以使用addService进行服务注册,但是在应用层,我们不具备相应的权限,只能通过集成Service,开放Service,让Client进行bind。

在JAVA->com.android.myservice 上新建一个Java Class---MyService

package com.android.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
 
public class MyService extends Service {
static final String TAG = "MyTestService";
//服务实体
    IMyService.Stub mStub = new IMyService.Stub() {
 
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
 
        }
 
        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.d(TAG,"add");
            //服务的接口实现,这里做一个加法运算
            return num1 + num2;
        }
    };
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG,"onBind");
        return mStub;//通过ServiceConnection在activity中拿到MyService
    }
}

2.3 AndroidManifest.xml配置

在AndroidManifest.xml中配上Service的信息,其中enable:ture设置可用,exported:ture对外暴露, 这样其他的Activity才能访问。

 
<service android:name=".MyService"
    android:enabled="true"
    android:exported="true">
    <!--enable:ture设置可用
       exported:ture对外暴露 -->
    <intent-filter>
       <action android:name="com.android.myservice.myservice"/>
    </intent-filter>
</service>

执行编译,服务端准备完成,编译一个APK进入手机\模拟器

 

3.Client端设计

3.1 AIDL拷贝

把服务端的AIDL以及包目录完整的拷贝到client的mian目录下,让Client和Server的服务对象对等。

 

接着执行编译 Build-> Make Module "Client",对应的IMyService.java也在client中编译出来

 

3.2 Client的UI实现

在layout->activity_main.xml 中添加相应的控件,效果如下:

 

布局:

 
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <Button
        android:id="@+id/toAdd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="计算"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/result" />
 
    <Button
        android:id="@+id/bindbtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="绑定服务"
        app:layout_constraintStart_toStartOf="@+id/toAdd"
        app:layout_constraintTop_toBottomOf="@+id/toAdd" />
 
    <Button
        android:id="@+id/unbindbtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="解除绑定"
        app:layout_constraintStart_toStartOf="@+id/bindbtn"
        app:layout_constraintTop_toBottomOf="@+id/bindbtn" />
 
    <EditText
        android:id="@+id/num1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ececec"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <EditText
        android:id="@+id/num2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ececec"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/add" />
 
    <EditText
        android:id="@+id/result"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#eceaea"
        android:inputType="none"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/value" />
 
    <TextView
        android:id="@+id/add"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="+"
        android:textSize="25sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/num1" />
 
    <TextView
        android:id="@+id/value"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp"
        android:text="="
        android:textSize="25sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/num2" />
 
</androidx.constraintlayout.widget.ConstraintLayout>

3.3 Client服务绑定和功能实现

通过bindService进行服务的绑定,unbindService 进行服务的解绑

 
package com.android.client;
 
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
 
import android.content.ComponentName;
import android.content.DialogInterface;
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.EditText;
 
import com.android.myservice.IMyService;
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
       static final String TAG = "AIDLClient";
    IMyService myService;
    private EditText num1;
    private EditText num2;
    private EditText result;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate ");
        setContentView(R.layout.activity_main);
        initView();
    }
 
    private void initView() {
        num1 = (EditText) findViewById(R.id.num1);
        num2 = (EditText) findViewById(R.id.num2);
        result = (EditText) findViewById(R.id.result);
 
        Button toAdd = (Button) findViewById(R.id.toAdd);
        Button bindbtn = (Button) findViewById(R.id.bindbtn);
        Button unbindbtn = (Button) findViewById(R.id.unbindbtn);
        toAdd.setOnClickListener(this);
        bindbtn.setOnClickListener(this);
        unbindbtn.setOnClickListener(this);
    }
 
    private ServiceConnection connection = new ServiceConnection() {
        //绑定上服务的时候
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            //接受到了远程的服务
            Log.d(TAG, "onServiceConnected: ");
            myService = IMyService.Stub.asInterface(service);
        }
 
        // 当服务断开的时候调用
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected: ");
            //回收资源
            myService = null;
 
        }
    };
 
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bindbtn://绑定服务
                Log.d(TAG, "start to bindMyServce");
                bindMyService();
                break;
            case R.id.unbindbtn://解除绑定
                Log.d(TAG, "start to unbindMyServce");
                unbindMyService();
                break;
            case R.id.toAdd://计算数据
                int number1 = Integer.valueOf(num1.getText().toString());
                int number2 = Integer.valueOf(num2.getText().toString());
                try {
                    Log.d(TAG, "start to add");
                    int valueRes = myService.add(number1, number2);
                    result.setText(valueRes + "");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
 
    private void bindMyService() {
        Intent intent = new Intent();
        intent.setAction("com.android.myservice.myservice");
        intent.setPackage("com.android.myservice"); // server's package name
        bindService(intent, connection, BIND_AUTO_CREATE);
        new AlertDialog.Builder(this)
                .setTitle("Tips")
                .setMessage("绑定成功!")
                .setPositiveButton("确定",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int whichButton) {
 
                            }
                        }).show();
        Log.d("AIDLClient", "bindMyService: bind on end");
    }
 
    private void unbindMyService() {
        unbindService(connection);
        new AlertDialog.Builder(this)
                .setTitle("Tips")
                .setMessage("解除绑定成功!")
                .setPositiveButton("确定",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                                int whichButton) {
 
                            }
                        }).show();
        Log.d("AIDLClient", "unbindMyService: unbind on end");
    }
}

执行编译,生成client.apk,在手机\模拟器中展示

 

4.测试:

点击“绑定服务”,成功后弹出“绑定成功”:

log:
   Client:

03-21 19:32:49.986 30794 30794 D AIDLClient: start to bindMyServce
03-21 19:32:50.023 30794 30794 D AIDLClient: bindMyService: bind on end
03-21 19:32:50.044 30794 30794 D AIDLClient: onServiceConnected:
03-21 19:32:57.062 30794 30794 D AIDLClient: start to add

Server:

03-21 19:32:49.996 31091 31091 D MyTestService: onCreate
03-21 19:32:49.997 31091 31091 D MyTestService: onBind

在输入框分别输入1,2, 点击计算,执行“1+2”,结果为3,从服务端返回成功

log:
Client:

 03-21 19:32:57.062 30794 30794 D AIDLClient: start to add

Server

03-21 19:32:57.063 31091 31160 D MyTestService: add

点击“解除绑定”,成功后弹出“解除绑定成功”:

log:
Client:

03-21 19:35:57.109 30794 30794 I AIDLClient: start to unbindMyServce
03-21 19:35:57.147 30794 30794 D AIDLClient: unbindMyService: unbind on end

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android10.0 Binder通信原理(九)-AIDL Binder示例 的相关文章

  • github代码推送总是失败

    github代码推送问题 因为github仓库代码的推送总是失败 所以改了一个方案采用ssh的方式来进行代码的推送 并记录操作步骤 方案 https方式换成ssh方式 git ssh 生成 假如已经生成的话 可以略过此步骤 ssh keyg

随机推荐

  • Android启动service的方法

    在 Android 中启动 service 的方法如下 创建 service 的类 并在 AndroidManifest xml 文件中注册该 service 使用 Intent 类来启动 service 例如 Intent intent
  • [转]公司管理混乱,从哪里入手?

    案例分析 我们是一个40人左右的小公司 规模虽小 但管理起来感觉力不从心 经常碰到工人抵抗 情绪化 上班迟到 旷工 不服从管理 即使勉强接受 也不会用心去做 草草应付了事 每次都提议是否弄个规章制度 但也是白纸一张 到了月底 实施不了 因为
  • 使用OpenGL 立方体贴图

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一 OpenGL 立方体贴图 二 使用步骤 1 代码 2 着色器程序 运行结果 注意 源码下载 参考 前言 对于室外3D 场景 通常可以通过在地平线上创造一些逼真的效果 来
  • SpringBoot利用AOP写一个日志管理(Log)

    1 需求 目前有这么个问题 有两个系统CSP和OMS 这俩系统共用的是同一套日志操作 Log 目前想区分下这俩系统的日志操作 那没办法了 只能重写一份Log的日志操作 你也可以参照若依框架的日志系统实现 2 新建一张日志表 sys oper
  • libevent学习篇之一:libevent快速入门

    https www jianshu com p 8ea60a8d3abb LibEvent快速入门 简介 基本的socket变成是阻塞 同步的 每个操作除非已经完成 出错 或者超时才会返回 这样对于每一个请求 要使用一个线程或者单独的进程去
  • 岁月划过生命线(16.02 ~ 10 -提前转正)

    岁月划过生命线 16 02 10 提前转正 标签 coder 10月9号收到了提前转正通知后就想写些总结 总结在微店的一年里见过的人 读过的书 做过的事儿 不然怕很多有意思的细节以后都忘了 但一直找借口迟迟懒得动笔 这篇总结断断续续竟写了一
  • Linux驱动入门必须get的知识点-01.基本框架与操作

    0 编写编译驱动的Makefile 指定驱动的测试的路径 ROOM DIR nfs rootfs home 2 study 指定测试Demo的交叉编译工具链 DEMO DIR home linux 1 DataShare 0 交叉编译工具链
  • Mybatis-Plus代码生成器快速上手示例

    Mybatis Plus代码生成器 实验脚本 Table structure for parent list DROP TABLE IF EXISTS parent list CREATE TABLE parent list p id in
  • Audacity如何改变音频节奏?Audacity调整音频节奏方法

    很多人在录完音频后都会试听效果 经常会发现音频的节奏要么太快 要么太慢 可是自己又不愿意花时间 花人力 物力再去录制音频 为了解决这问题 我们可以用Audacity改变音频的节奏 加快或者减慢某个音频片段或者整个音频的节奏 只是很多人不懂怎
  • Windows 11 & Server 2022 HLK kit WHQL认证注意事项

    微软已经发布Windows 11 Server2022 HLK WHQL 测试套装 针对这一版HLK 有一个地方十分值得注意 在创建Porject的时候会出现 is windows driver Project 选择框 这一选项目前是用于工
  • (小米系统系列一)小米/红米BL解锁,解BL锁方法(亲测可用)

    文章参考自原作者 原作者链接 https www bilibili com read cv3305336 https www xiaomi cn post 17982230 http www miui com unlock download
  • Java Eclipse如何调试代码

    下面通过一个简单的例子来了解一下 Eclipse 调试程序的方法 public class Test1 public static void main String args for循环 如果for后面 内的条件一直成立 内的代码一直执行
  • Pandas基础操作

    Pandas基础 文章目录 Pandas基础 一 Series 二 DataFrame 三 索引值 四 索引和选取 loc和iloc函数讲解 五 行和列的操作 map apply applymap函数讲解 Pandas的函数应用 层级索引
  • 数据结构与算法之快速排序

    package com yg sort author GeQiLin date 2020 2 26 21 00 import java util Arrays public class QuickSort private static in
  • [SWPUCTF 2021 新生赛]easyupload2.0

    打开以后是一个文件上传的界面 然后用burp抓包看一下 传入一个php文件 发现php是不行滴 然后想到用phtml改一下后缀 看是否可以略过 然后发现掠过了 爆出来了路径 上传成功 直接用蚁建 lianjie 链接成功 然后目录寻找fla
  • pthread_mutex_t 和 pthread_cond_t 配合使用的简要分析

    pthread mutex t 和 pthread cond t 配合使用的简要分析 1 原理 假设有两个线程同时访问一个全局变量 n 这个全局变量的初始值等于0 Int n 0 消费者线程 A 进入临界区 访问 n A 必须等到 n 大于
  • idea~不定时更新

    idea 不定时更新 类结构图 全局搜索和替换 修改鼠标停留 并显示api描述 开启idea下方边框 https www jetbrains com help idea 2019 2 using code editor html utm s
  • python运算符讲解

    作者 小刘在这里 每天分享云计算网络运维课堂笔记 疫情之下 你我素未谋面 但你一定要平平安安 一 起努力 共赴美好人生 夕阳下 是最美的 绽放 愿所有的美好 再疫情结束后如约而至 目录 运算符 python运算符 一 运算符类型 二 实际应
  • 【超详细】gitee+picgo个人图床搭建+插件安装bug处理

    超详细 gitee picgo个人图床搭建 各种插件安装bug处理 你好我是久远 最近在搭个人静态网页 到了最后一步了 传了几篇文章上去 结果文章传上去 了 图片全都失效了 没有办法 用现成的图床吧 担心哪天网站不稳定 图片全炸掉 所以最后
  • Android10.0 Binder通信原理(九)-AIDL Binder示例

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系