ADIL简单测试实例

news2024/11/27 7:36:03

参考资料: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.mainapp

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log

class 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 = true
        override 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 = true
        Thread {
            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 = false
        return super.onUnbind(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.v(TAG, "onDestroy()")
    }
}

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

<application
  android: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">
  <service
    android:name=".MainAppService"
    android:enabled="true"
    android:exported="true">
  </service>
  <!-- .... -->
</application>

六、OtherApp里OtherAppMainActivity添加代码

package com.example.otherapp

import ....

class OtherAppMainActivity : AppCompatActivity() {
    private val TAG = "AIDL-OtherAppMainActivity"
    private lateinit var binding : ActivityOtherAppMainBinding
    private lateinit var mServiceIntent: Intent
    private var mBinder : IAppAidlInterface? = null
    private 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">

    <Button
        android:id="@+id/bindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Bind Service" />

    <Button
        android: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.coloradmin.cn/o/1708691.html

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

相关文章

redis 主从复制薪火相传 哨兵sentinel配置以及底层原理

薪火相传 我们知道redis的主从复制还有一个常见的架构 ---薪火相传 使用这种结构可以有效减轻master节点的复制数据同步压力 注意这里的6380节点仍然是slave节点 可以理解为一个中间节点,仍然是不可以写只可以读取的 我们只需要使用 slaveof ip port 这里可能访问节点的时候出…

电力电子技术03 (1)---电路稳态分析方法

学习来源&#xff08;只用于个人学习笔记&#xff0c;建议对着老师视频学习理解更深入&#xff09;&#xff1a;2.2稳态分析的基本方法_哔哩哔哩_bilibili 一、Buck降压电路 Buck电路&#xff0c;也称为降压转换器&#xff0c;是一种DC-DC电压转换器&#xff0c;用于将输入电…

7个靠谱的副业赚钱方法,宝妈,上班族,学生党可以做的兼职副业

你是否也曾面临过这样的困境&#xff1a;生活费紧张&#xff0c;想要找份兼职来补贴家用或是满足自己的小心愿&#xff1f;别担心&#xff0c;今天我将带领你踏入这个丰富多彩的兼职世界&#xff0c;助你轻松达成月入过千的小目标&#xff01; 在我漫长的兼职探索旅程中&#…

Java GC问题排查的一些个人总结和问题复盘

个人博客 Java GC问题排查的一些个人总结和问题复盘 | iwts’s blog 是否存在GC问题判断指标 有的比较明显&#xff0c;比如发布上线后内存直接就起飞了&#xff0c;这种也是比较好排查的&#xff0c;也是最多的。如果单纯从优化角度&#xff0c;看当前应用是否需要优化&…

C++的算法:枚举法的原理及应用

在C++编程中,枚举法,又称穷举法或暴力法,是一种非常基础和常见的算法解题方法。它的核心思想在于:通过遍历所有可能的情况,然后逐一检查每个情况是否满足问题的要求,从而找到问题的解决方案。 一、枚举法的原理 枚举法的核心在于穷举和验证。它将问题的所有可能性一一列举…

高铁VR虚拟全景展示提升企业实力和形象

步入VR的神奇世界&#xff0c;感受前所未有的汽车展示体验。VR虚拟现实技术以其独特的沉浸式模拟&#xff0c;让你仿佛置身于真实展厅之中&#xff0c;尽情探索汽车的每一处细节。 一、定制化展示&#xff0c;随心所欲 VR汽车虚拟展厅打破空间束缚&#xff0c;让汽车制造商能够…

官宣|HelpLook现已入驻钉钉应用市场,助力企业知识管理知识

前一阵子OpenAI公司最新的GPT-4o技术震撼发布&#xff0c;人工智能的实际应用前景再次引起行业瞩目&#xff0c;或者被GPT4o的数据分析等特色功能折服。如您正寻求将AI技术融入企业知识管理&#xff0c;不要错过HelpLook&#xff01;HelpLook AI知识库已经正式入驻钉钉应用市场…

go语言初识别(五)

本博客内容涉及到&#xff1a;切片 切片 1. 切片的概念 首先先对数组进行一下回顾&#xff1a; 数组定义完&#xff0c;长度是固定的&#xff0c;例如&#xff1a; var num [5]int [5]int{1,2,3,4,5}定义的num数组长度是5&#xff0c;表示只能存储5个整形数字&#xff0c…

轻松拿捏C语言——自定义类型之【结构体】

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f389;创作不易&#xff0c;请多多支持&#x1f389; &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正 1. 结构体类型的…

《当微服务遇上Ribbon:一场负载均衡的华丽舞会》

在微服务的厨房里&#xff0c;如何确保每一道服务都恰到好处&#xff1f;揭秘Spring Cloud Ribbon如何像大厨一样精心调配资源&#xff0c;让负载均衡变得像烹饪艺术一样简单&#xff01; 文章目录 Spring Cloud Ribbon 详解1. 引言微服务架构中的负载均衡需求Spring Cloud Rib…

【chagpt】广泛使用API之前:考虑成本和数据隐私

文章目录 一. 定价和标记限制二. 安全和隐私 在广泛使用API之前&#xff0c;应该考虑两个重要因素&#xff1a;成本和数据隐私。 一. 定价和标记限制 OpenAI在Pricing页面上列出了模型的定价。请注意&#xff0c;OpenAI不一定及时更新该页面上的定价信息&#xff0c;因此实际…

爱岗敬业短视频:成都科成博通文化传媒公司

爱岗敬业短视频&#xff1a;传递正能量&#xff0c;塑造职场新风尚 在当今社会&#xff0c;短视频以其独特的传播方式和广泛的受众群体&#xff0c;成为了信息传播的重要渠道。在众多短视频内容中&#xff0c;以“爱岗敬业”为主题的短视频尤为引人注目&#xff0c;成都科成博…

链表mark

什么是链表&#xff0c;链表是一种通过指针串联在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个节点的指针&#xff09;&#xff0c;最后一个节点的指针域指向null&#xff08;空指针的意思&#xff09;。…

《TCP/IP网络编程》(第十一章)进程间通信

进程间通信意味着两个不同的进程间可以交换数据&#xff0c;它使得不同的进程能够协同工作&#xff0c;实现复杂的系统功能。 1.通过管道实现进程间通信 下图是基于 管道&#xff08;PIPE&#xff09; 的进程间通信结构模型 管道不属于进程的资源&#xff0c;属于操作系统的资…

怎么简单的把图片缩小?图片在线改大小的方法

在日常工作中经常需要在网上上传图片&#xff0c;但是一般网上不同的平台对上传的图片大小和尺寸都会有限定的要求&#xff0c;不符合要求无法正常上传使用。所以当遇到图片太大的问题时&#xff0c;该如何快速修改图片大小&#xff0c;有很多的小伙伴都很关注这个问题的解决方…

qmt量化交易策略小白学习笔记第7期【qmt策略之股票快照指标】

qmt策略之股票快照指标 qmt更加详细的教程方法&#xff0c;会持续慢慢梳理。 也可找寻博主的历史文章&#xff0c;搜索关键词查看解决方案 &#xff01; 感谢关注&#xff0c;需免费开通量化回测与咨询实盘权限&#xff0c;可以和博主联系&#xff01; 股票快照指标 提供标…

趣店集团golang一面要个20K,Channel什么情况下会出现死锁,有遇到过吗?

结束后面试官加了VX&#xff0c;并询问方便二面的时间&#xff0c;一直还没回复&#xff0c;拖着拖着给忘啦... 面试题 1、自我介绍 2、你在团队里头负责哪一块&#xff0c;这个物流开放平台流量多大 3、为什么今年3月份被从物流开放团队转到了finance财务部门&#xff0c;感…

VSCODE中F12无法跳转,快捷键设置F12和insert混淆了

异常现象 最近用新电脑&#xff08;华为&#xff09;的时候&#xff0c;发现VSCODE经常按F12无法跳转&#xff0c;在快捷键设置当中&#xff0c;也是设置成功的&#xff1b; 此时重新去快捷键设置&#xff0c;会发现按 F12变为了Insert 解决方法 华为笔记本的Fx按键&#x…

YashanDB携手慧点科技完成产品兼容认证 助力国产信创生态建设

近日&#xff0c;深圳计算科学研究院崖山数据库系统YashanDB与慧点科技顺利完成兼容性互认证。经严格测试&#xff0c;双方产品完全兼容&#xff0c;稳定运行&#xff0c;共同支撑政府、企业、金融等办公应用场景下的数字化转型升级&#xff0c;为企业的信息技术应用创新提供坚…

如何彻底卸载sql sever2022

目录 背景过程1、关闭sql sever服务2、打开控制面板&#xff0c;卸载SQL Sever3、手动删除 SQL Server 遗留文件4、清空注册表5、重启计算机以确保所有更改生效。 总结 背景 重装了电脑&#xff0c;安装sqlServer&#xff0c;一直报错&#xff0c;不成功&#xff0c;所以每次安…