ADIL简单测试实例

参考资料:https://blog.csdn.net/geyichongchujianghu/article/details/130045373
这个连接是Java的代码,我根据它的链接写了一个kotlin版本的。

AIDL(Android Interface Definition Language)是Android平台上用于进程间通信(IPC)的一种接口定义语言。它允许不同进程中的组件(如服务和服务、服务和活动等)相互通信。

AIDL的主要特点包括:

  1. 跨进程通信:AIDL允许不同进程中的组件相互通信,这使得应用可以更好地利用设备的多核处理器,提高性能和响应速度。
  2. 接口定义:通过AIDL,开发者可以定义一个接口,并在这个接口中声明需要跨进程传递的方法和数据类型。
  3. 自动生成代码:Android SDK提供了一个编译器,它可以根据AIDL接口定义自动生成Java代码,这些代码负责处理跨进程通信的细节。
  4. 支持多种数据类型:AIDL支持基本数据类型、字符串、列表、映射等多种数据类型,以及自定义的Parcelable对象。
  5. 安全性:AIDL通信是通过Binder机制实现的,Binder机制提供了进程间通信的安全性,确保只有授权的进程可以访问服务。

使用AIDL的步骤通常包括:

  • 定义AIDL接口(.aidl文件)。
  • 实现AIDL接口的服务端。
  • 在客户端使用AIDL接口与服务端通信。

AIDL是Android平台上实现跨进程通信的重要工具,它为开发者提供了一种方便、高效的方式来实现不同进程间的数据交换和方法调用。

下面介绍了AIDL的使用例子,创建了两个App,一个是服务端的mainapp,一个是客户端的otherapp,它们会被创建在一个工程里,这样也会方便调试。

一、创建两个App

新建一个mainapp,我新建了一个aidlTest,创建了一个mainapp,这个aidlTest文件夹并没有什么用。
image.jpg
把MainActivity重命名成MainAppActivity
image.jpg
再添加一个otherapp的module
image.jpg
模块名字为otherapp
image.jpg

二、在mainapp里创建一个service

先在mainapp中实现一个service,MainAppActivity类中创建了service
image.jpg
service名字为MainAppService
image.jpg
修改MainAppAcitvity里的代码

class MainAppActivity : AppCompatActivity() {private val TAG = "AIDL-MainAppActivity"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(R.layout.activity_main)ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)insets}Log.v(TAG, "onCreate()")}override fun onDestroy() {super.onDestroy()Log.v(TAG, "onDestroy()")}
}

MainAppService里的改动,我们又重写了onCreate()、onStartCommand()和onDestroy()这3个方
法,它们是每个Service中最常用到的3个方法了。其中:

  • onCreate()方法会在Service创建的时候调用
  • onStartCommand()方法会在每次Service启动的时候调用,
  • onDestroy()方法会在Service销毁的时候调用。
  • onBind是被客户端绑定时执行
  • onUnbind(Intent intent):被客户端解绑时执行
class MainAppService : Service() {private val TAG = "AIDL-MainAppService"override fun onCreate() {super.onCreate()}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {return super.onStartCommand(intent, flags, startId)}override fun onBind(intent: Intent): IBinder {TODO("Return the communication channel to the service.")}override fun onUnbind(intent: Intent?): Boolean {Log.v(TAG, "onUnbind()")return super.onUnbind(intent)}override fun onDestroy() {super.onDestroy()Log.v(TAG, "onDestroy()")}
}

三、mainapp里实现AIDL

在创建aidl前,需要在mainapp的gradle里,配置打开aidl

buildFeatures {aidl = true
}

在mainapp的main目录下创建一个名为IAppAidlInterface.aidl的文件
image.jpg

image.jpg
在IAppAidlInterface里添加setStringData这个AIDL接口定义了一个名为IAppAidlInterface的接口,它包含了两个方法:basicTypessetStringData

  • basicTypes方法展示了在AIDL接口中可以使用的一些基本数据类型作为参数。这些基本数据类型包括整型(int)、长整型(long)、布尔型(boolean)、浮点型(float)、双精度浮点型(double)和字符串型(String)。这个方法没有返回值,它的目的是演示如何在AIDL接口中使用这些基本数据类型。
  • setStringData方法接受一个字符串参数(String strData),并将其设置为某个值。这个方法也没有返回值,它的目的是演示如何在AIDL接口中传递字符串数据。

这个AIDL接口定义了两个没有返回值的方法,它们可以用于跨进程通信。在实际应用中,你可以根据需要定义更多的方法和参数,以实现不同进程间的数据交换和方法调用。

interface IAppAidlInterface {/*** 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 setStringData(String strData);
}

在AIDL创建完成后,点击重新编译后就有生成的java类了。在Android中,当你定义了一个AIDL(Android Interface Definition Language)接口后,Android的编译器会自动为你生成一个Java接口类。这个生成的接口类继承自android.os.IInterface,并包含了你在AIDL文件中定义的方法。
image.jpg

四.otherapp中也实现AIDL

把mainapp里的aidl文件复制到otherapp里,并开启aidl后,就也能看到生成的aidl java文件
image.jpg

五、在mainapp中添加代码

现在MainAppService中实例化Binder

package com.example.mainappimport android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Logclass MainAppService : Service() {private val TAG = "AIDL-MainAppService"private val mStub = AppAidlInterfaceStub()/* * 实现IAppAidlInterface.Stub抽象类,* 用于实现IAppAidlInterface.aidl中的接口函数* onBinder()时返回匿名内部类实例*/inner class AppAidlInterfaceStub : IAppAidlInterface.Stub() {var mStrData = ""var mSetServiceRunning = trueoverride fun basicTypes(anInt: Int,aLong: Long,aBoolean: Boolean,aFloat: Float,aDouble: Double,aString: String?) {}override fun setStringData(strData: String?) {mStrData = strData.toString()}}override fun onCreate() {Log.v(TAG, "onCreate()")super.onCreate()}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {Log.v(TAG, "onStartCommand()")return super.onStartCommand(intent, flags, startId)}//在onBinder()中启动一个线程,每1秒轮询接收客户端发送过来的数据override fun onBind(intent: Intent): IBinder {mStub.mSetServiceRunning = trueThread {while(mStub.mSetServiceRunning) {try {Thread.sleep(1000);Log.v(TAG, "mStrData:${mStub.mStrData}")} catch (e: InterruptedException) {e.printStackTrace()}}}.start()return mStub		//返回AppAidlInterfaceStub实例}//在unBind里清除运行标志,让线程能够退出override fun onUnbind(intent: Intent?): Boolean {Log.v(TAG, "onUnbind()")mStub.mSetServiceRunning = falsereturn super.onUnbind(intent)}override fun onDestroy() {super.onDestroy()Log.v(TAG, "onDestroy()")}
}

需要确保mainappservice在AndroidMainfiest.xml里添加了Service标签

<applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Mainapp"tools:targetApi="31"><serviceandroid:name=".MainAppService"android:enabled="true"android:exported="true"></service><!-- .... -->
</application>

六、OtherApp里OtherAppMainActivity添加代码

package com.example.otherappimport ....class OtherAppMainActivity : AppCompatActivity() {private val TAG = "AIDL-OtherAppMainActivity"private lateinit var binding : ActivityOtherAppMainBindingprivate lateinit var mServiceIntent: Intentprivate var mBinder : IAppAidlInterface? = nullprivate var mICount = 0//创建Service连接和断开的两个基础函数onServiceConnected()和onServiceDisconnected()private val connection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName?, service: IBinder?) {if(mBinder == null) {mBinder = IAppAidlInterface.Stub.asInterface(service)mICount++Log.v(TAG, "onServiceConnected() the time $mICount")try {val strData = "第 $mICount 次连接service成功"mBinder!!.setStringData(strData)} catch (e: RemoteException) {e.printStackTrace()}} else {mICount++Log.v(TAG, "mBinder is not null")}}override fun onServiceDisconnected(name: ComponentName?) {Log.v(TAG, "onServiceDisconnected")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()binding = ActivityOtherAppMainBinding.inflate(layoutInflater)setContentView(binding.root)ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)insets}//新建intent来连接服务端mainapp,Intent的Component设置为Sevice的包名和类名mServiceIntent = Intent()mServiceIntent.component = ComponentName("com.example.mainapp", "com.example.mainapp.MainAppService")// 检查服务是否存在val resolveInfo = packageManager.resolveService(mServiceIntent, PackageManager.MATCH_DEFAULT_ONLY)if (resolveInfo != null) {// 服务存在,Intent有效Log.v(TAG, "Intent is valid")} else {// 服务不存在,Intent无效Log.v(TAG, "Intent is not valid")}//点击bind时与service绑定binding.bindServiceBtn.setOnClickListener {val bindResult = bindService(mServiceIntent, connection, Context.BIND_AUTO_CREATE)Log.v(TAG, "bindServiceBtn clicked bindResult:$bindResult")}//点击unbindg时与service解绑binding.unbindServiceBtn.setOnClickListener {Log.v(TAG, "unbindServiceBtn clicked")unbindService(connection)mBinder = null		//把mBinder清空}}}

在otherapp里新建两个button用来控制bindService()和unbindService()

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".OtherAppMainActivity"><Buttonandroid:id="@+id/bindService"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Bind Service" /><Buttonandroid:id="@+id/unbindService"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Unbind Service" /></LinearLayout>

七、验证

把两个apk安装并启动:
image.jpg
点击bind会建立连接,点击ubind断开。再次点击bind计数会增加
测试结果:

2024-05-28 17:25:31.545  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  Intent is valid
2024-05-28 17:25:34.879  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  bindServiceBtn clicked bindResult:true
2024-05-28 17:25:34.882  1505-1505  AIDL-MainAppService     com.example.mainapp                  V  onCreate()
2024-05-28 17:25:34.891  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  onServiceConnected() the time 1
2024-05-28 17:25:35.885  1505-2363  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 1 次连接service成功
2024-05-28 17:25:36.886  1505-2363  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 1 次连接service成功
2024-05-28 17:25:37.887  1505-2363  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 1 次连接service成功
2024-05-28 17:25:38.888  1505-2363  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 1 次连接service成功
2024-05-28 17:25:39.613  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  unbindServiceBtn clicked
2024-05-28 17:25:39.621  1505-1505  AIDL-MainAppService     com.example.mainapp                  V  onUnbind()
2024-05-28 17:25:39.623  1505-1505  AIDL-MainAppService     com.example.mainapp                  V  onDestroy()
2024-05-28 17:25:39.888  1505-2363  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 1 次连接service成功
2024-05-28 17:25:42.022  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  bindServiceBtn clicked bindResult:true
2024-05-28 17:25:42.024  1505-1505  AIDL-MainAppService     com.example.mainapp                  V  onCreate()
2024-05-28 17:25:42.037  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  onServiceConnected() the time 2
2024-05-28 17:25:43.037  1505-2399  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 2 次连接service成功
2024-05-28 17:25:44.038  1505-2399  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 2 次连接service成功
2024-05-28 17:25:45.039  1505-2399  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 2 次连接service成功
2024-05-28 17:25:45.692  2285-2285  AIDL-Other...inActivity com.example.otherapp                 V  unbindServiceBtn clicked
2024-05-28 17:25:45.701  1505-1505  AIDL-MainAppService     com.example.mainapp                  V  onUnbind()
2024-05-28 17:25:45.702  1505-1505  AIDL-MainAppService     com.example.mainapp                  V  onDestroy()
2024-05-28 17:25:46.040  1505-2399  AIDL-MainAppService     com.example.mainapp                  V  mStrData:第 2 次连接service成功

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

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

相关文章

AI办公自动化:kimi批量新建文件夹

工作任务&#xff1a;批量新建多个文件夹&#xff0c;每个文件夹中的年份不一样 在kimi中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个编写关于录制电脑上的键盘和鼠标操作的Python脚本的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&…

FFmpeg编解码的那些事(1)

看了网上很多ffmpeg的编解码的文章和代码&#xff0c;发现有很多文章和代码都过时了&#xff0c;主要还是ffmpeg有很多接口都已经发生变化了。 这里简单说一下&#xff0c;什么是编码和解码。 1.视频编码 对于视频来说&#xff0c;可以理解为多张&#xff08;rgb或者yuv&…

Python散点图矩阵代码模版

本文分享Python seaborn实现散点图矩阵代码模版&#xff0c;节选自&#x1f449;嫌Matplotlib繁琐&#xff1f;试试Seaborn&#xff01; 散点图矩阵&#xff08;scatterplot matrix&#xff09;展示原始数据中所有变量两两之间关系&#xff0c;可以规避单一统计指标的偏差&…

Neural Filters:照片恢复

Ps菜单&#xff1a;滤镜/Neural Filters/恢复/照片恢复 Neural Filters/RESTORATION/Photo Restoration 照片恢复 Photo Restoration借助 AI 强大功能快速恢复旧照片&#xff0c;提高对比度、增强细节、消除划痕。将此滤镜与着色相结合以进一步增强效果。 “照片恢复”滤镜利用…

Scikit-Learn随机森林

Scikit-Learn随机森林 1、随机森林1.1、集成学习1.2、Bagging方法1.3、随机森林算法1.4、随机森林的优缺点2、Scikit-Learn随机森林回归2.1、Scikit-Learn随机森林回归API2.2、随机森林回归实践(加州房价预测)1、随机森林 随机森林是一种由决策树构成的集成算法,它在大多情况…

mac安装的VMware虚拟机进行桥接模式配置

1、先进行网络适配器选择&#xff0c;选择桥接模式 2、点击网络适配器 设置... 3、选择WiFi&#xff08;我使用的是WiFi&#xff0c;所以选择这个&#xff09;&#xff0c;注意看右边的信息&#xff1a;IP和子网掩码&#xff0c;后续配置虚拟机的ifcfg-ens文件会用到 4、编辑if…

【论文阅读笔记】The Google File System

1 简介 Google File System (GFS) 是一个可扩展的分布式文件系统&#xff0c;专为快速增长的Google数据处理需求而设计。这篇论文发表于2003年&#xff0c;此前已在Google内部大规模应用。 GFS不仅追求性能、可伸缩性、可靠性和可用性等传统分布式文件系统的设计目标&#xf…

P9 【力扣+知识点】【算法】【二分查找】C++版

【704】二分查找&#xff08;模板题&#xff09;看到复杂度logN&#xff0c;得想到二分 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0…

企业微信hook接口协议,ipad协议http,语音转文字

语音转文字 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信msgid是int要转文字的语音消息id 请求示例 {"uuid":"a4ea6a39-4b3a-4098-a250-2a07bef57355","msgid":1063645 } 返回示例 {"data&…

电源模块测试系统怎么测试输入电压范围?

在现代电子设备中&#xff0c;电源模块的性能直接影响着整个系统的稳定性和效率。其中&#xff0c;电源输入电压范围是指电源能够接受的输入电压的最小值和最大值&#xff0c;它是确保电源正常工作的重要参数。为了提高测试效率和精度&#xff0c;自动化的测试方法逐渐取代了传…

【Game】Rumble Heroes

文章目录 1 英雄2 守护兽3 符文4 祝福5 阵容推荐6 Boss7 兑换码 1 英雄 &#xff08;1&#xff09;力量 神话英雄 圣骑士-乌瑟尔 传说英雄 双刀-宫本武藏死亡骑士-阿萨斯冰霜骑士-亚瑟疾风焰刃-缘壹熊猫武僧-阿宝 史诗英雄 大剑-克劳德狂战士-奎托斯魔山-克里刚猎人-奈辛瓦里 稀…

宝塔部署Java+Vue前后端分离项目

1. 服务器 服务器选择Linux的CentOS7的版本 2. 宝塔Linux面板 2.1 百度搜索宝塔 2.2 进去之后点击立即免费安装 2.3 选择Linux在线安装&#xff0c;输入服务器信息进行安装(也可以选择其他方式) 安装完成之后会弹一个宝塔的应用面板&#xff0c;并附带有登录名称和密码&…

多模态大模型:系统、趋势与问题

引言 多模态大模型是当今人工智能领域的热门方向之一。它不仅能处理文本&#xff0c;还能理解和生成图像、视频、语音等多种模态的数据。这种能力使得多模态大模型在自然语言处理、计算机视觉等多个领域展示出巨大的潜力和应用价值。那么&#xff0c;多模态大模型是如何训练出…

AI菜鸟向前飞 — LangChain系列之十五 - Agent系列:从现象看机制(中篇)一个Agent的“旅行”

Agent基本架构 先谈谈Agent基本架构概念&#xff0c;如果看得云里雾里&#xff0c;等看完本篇之后&#xff0c;再回头看就会豁然开朗的&#xff0c;而我尽量写得更易懂&#xff1a; &#xff09; 这里面会穿插着上一篇的内容&#xff0c;请大家记得往回翻翻&#xff0c;传送门&…

C语言 | Leetcode C语言题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; int** generate(int numRows, int* returnSize, int** returnColumnSizes) {int** ret malloc(sizeof(int*) * numRows);*returnSize numRows;*returnColumnSizes malloc(sizeof(int) * numRows);for (int i 0; i < numRows; i) {re…

前端API: IntersectionObserver的那一二三件事

IntersectionObserver 基础 IntersectionObserver 可以监听一个元素和可视区域相交部分的比例&#xff0c;然后在可视比例达到某个阈值的时候触发回调。比如可以用来处理图片的懒加载等等 首先我们来看下基本的格式&#xff1a; const observer new IntersectionObserver(c…

yolov10 使用自己的数据集训练目标检测模型

1 环境配置(使用anaconda) conda create -n yolov10 python=3.9 //创建虚拟环境 conda activate yolov10 //激活虚拟环境 pip install -r requirements.txt //执行yolov10 路径下requirements.txt 安装依赖 pip install -e .2.数据集制作 使用lableImage制作数据集(win版…

华为云Astro Zero低代码平台案例:小、轻、快、准助力销售作战数字化经营

客户背景&#xff1a; 随着业务的不断扩展&#xff0c;华为云某一线作战团队发现&#xff0c;原本基于线上Excel的项目跟踪方式面临新的挑战&#xff1a;多区域、多场景下的业务管理越来越复杂&#xff0c;项目管道存在多种不可控因素&#xff0c;客户关系、进展跟踪同步不及时…

【Qt秘籍】[003]-Qt环境变量配置-磨刀不误砍柴工

一、为什么要设置环境变量 &#xff1f;[原因] 配置PATH环境变量的主要用处在于让操作系统能够识别并执行不在当前工作目录下的可执行文件。具体来说&#xff0c;它的作用包括&#xff1a; 命令执行便捷性&#xff1a;当你在命令行输入一个命令&#xff08;如java, python或np…

【Unity程序】Unity游戏开发中常用的设计模式【一】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…