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.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成功
  • 29
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

习惯就好zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值