news 2026/5/26 9:43:53

AIDL进程间通信

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AIDL进程间通信

1. 项目概述本项目是一个基于Android AIDL(Android Interface Definition Language)的跨进程通信示例。项目包含两个模块:•aidlservice:提供AIDL服务的模块,实现了一个简单的计算器功能•aidlclient:接受AIDL服务的模块,通过绑定服务调用计算器功能

2. AIDL基本概念AIDL(Android接口定义语言)是Android提供的一种跨进程通信(IPC)机制,用于在不同的应用进程之间传递数据和调用方法。它允许一个应用程序的组件与另一个应用程序的组件进行通信,即使它们运行在不同的进程中。AIDL的主要特点:•支持基本数据类型、String、CharSequence、List、Map等•支持自定义Parcelable类型•支持双向通信•支持异步调用

3. 项目结构AIDL
├── aidlservice/ # 服务端模块
│ ├── src/main/
│ │ ├── aidl/com/example/aidl/
│ │ │ └── ICalculator.aidl # AIDL接口定义
│ │ ├── java/com/example/aidl/
│ │ │ ├── CalculatorService.kt # AIDL服务实现
│ │ │ └── MainActivity.kt # 服务端启动Activity
│ │ ├── res/layout/
│ │ │ └── activity_main.xml # 服务端布局
│ │ └── AndroidManifest.xml # 服务端配置
│ └── build.gradle.kts # 服务端构建配置
├── aidlclient/ # 客户端模块
│ ├── src/main/
│ │ ├── aidl/com/example/aidl/
│ │ │ └── ICalculator.aidl # AIDL接口定义(与服务端相同)
│ │ ├── java/com/example/aidlclient/
│ │ │ └── MainActivity.kt # 客户端Activity
│ │ ├── res/layout/
│ │ │ └── activity_main.xml # 客户端布局
│ │ └── AndroidManifest.xml # 客户端配置
│ └── build.gradle.kts # 客户端构建配置
└── settings.gradle.kts # 项目模块配置

4. AIDL接口定义AIDL接口定义文件位于两个模块的aidl/com/example/aidl/目录下,文件名为ICalculator.aidl。

文件内容:// ICalculator.aidl
package com.example.aidl;

//定义跨进程接口
interface ICalculator {
//计算两数之和
int add(int a, int b);
}这个AIDL接口定义了一个简单的计算器服务,只包含一个add方法,用于计算两个整数的和。

5. 服务端实现

5.1 CalculatorService.kt服务端的核心是CalculatorService类,它继承自Android的Service类,并实现了AIDL接口。文件内容:package com.example.aidl

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

class CalculatorService : Service() {
private val binder = object : ICalculator.Stub() {
override fun add(a: Int, b: Int): Int {
return a + b
}
}

override fun onBind(intent: Intent): IBinder {
return binder
}
}

代码分析:•CalculatorService继承自Service类,是一个后台服务组件•binder是ICalculator.Stub()的匿名实现类,它实现了AIDL接口中定义的add方法•onBind方法返回binder对象,用于客户端绑定服务时获取通信接口•add方法实现了简单的加法运算逻辑

5.2 AndroidManifest.xml服务端的配置文件,声明了服务和启动Activity。文件内容:<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AIDL" >
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".CalculatorService"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="com.example.aidl.CalculatorService" />
</intent-filter>
</service>
</application>
</manifest>

关键配置:•<activity>标签声明了MainActivity作为启动Activity,包含了MAIN和LAUNCHER意图过滤器•<service>标签声明了CalculatorService服务,设置android:exported="true"允许其他应用访问•<intent-filter>为服务设置了一个自定义的action,方便客户端通过Intent绑定服务

6. 客户端实现

6.1 MainActivity.kt客户端的核心是MainActivity类,它通过绑定服务的方式与服务端通信。文件内容:

package com.example.aidlclient

import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.aidlclient.R
import com.example.aidl.ICalculator

class MainActivity : AppCompatActivity() {
private var calculator: ICalculator? = null

private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
calculator = ICalculator.Stub.asInterface(binder)
try {
val result = calculator?.add(3, 5)
Toast.makeText(this@MainActivity, "3 + 5 = $result", Toast.LENGTH_SHORT).show()
} catch (e: RemoteException) {
e.printStackTrace()
}
}

override fun onServiceDisconnected(name: ComponentName?) {
calculator = null
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val intent = Intent().apply {
component = ComponentName("com.example.aidl", "com.example.aidl.CalculatorService")
}
bindService(intent, connection, BIND_AUTO_CREATE)
}

override fun onDestroy() {
super.onDestroy()
unbindService(connection)
}
}

代码分析:•calculator变量是ICalculator类型的接口引用,用于调用服务端的方法•connection是ServiceConnection的匿名实现类,用于监听服务的绑定状态•onServiceConnected方法在服务绑定成功时调用,通过ICalculator.Stub.asInterface(binder)将IBinder对象转换为AIDL接口引用•onServiceDisconnected方法在服务断开连接时调用,将接口引用置为null•onCreate方法中创建Intent并绑定服务,使用ComponentName指定服务的包名和类名•onDestroy方法中解除服务绑定,避免内存泄漏

6.2 AndroidManifest.xml客户端的配置文件,声明了启动Activity。文件内容:<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AIDL">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>关键配置:•<activity>标签声明了MainActivity作为启动Activity,包含了MAIN和LAUNCHER意图过滤器

7. 跨进程通信流程

1.服务端注册:CalculatorService在AndroidManifest.xml中注册,并设置为可导出

2.客户端绑定服务:MainActivity通过bindService方法绑定到服务端的CalculatorService

3.服务端返回Binder:CalculatorService的onBind方法返回ICalculator.Stub的实现对象

4.客户端获取接口:客户端在onServiceConnected方法中通过ICalculator.Stub.asInterface(binder)获取AIDL接口引用

5.客户端调用方法:客户端通过接口引用调用add方法,参数通过序列化传递给服务端

6.服务端执行方法:服务端执行add方法并返回结果

7.客户端处理结果:客户端接收结果并显示

8. 启动配置项目的默认启动项是aidlservice模块的MainActivity,因为它在AndroidManifest.xml中包含了以下配置:<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>这个配置表明该Activity是应用的入口点,当用户点击应用图标时,会启动这个Activity。

9. 代码优化建议

1.错误处理优化:客户端调用AIDL方法时,应增加更完善的错误处理机制,不仅打印异常,还应向用户显示错误信息

2.生命周期管理:确保在适当的时机绑定和解除服务绑定,避免内存泄漏

3.线程安全:如果AIDL方法需要长时间执行,应在服务端使用工作线程处理,避免阻塞主线程

4.权限控制:考虑为服务添加权限控制,只允许授权的应用访问

5.日志记录:添加适当的日志记录,方便调试和问题排查

10. 总结

本项目是一个简单但完整的AIDL跨进程通信示例,展示了如何使用AIDL实现两个应用之间的通信。通过这个项目,我们可以了解:•AIDL接口的定义和使用•服务端如何实现AIDL接口•客户端如何绑定服务并调用AIDL方法•跨进程通信的基本流程•AndroidManifest.xml的配置这个示例虽然简单,但包含了AIDL通信的核心概念和实现方式,可以作为学习Android跨进程通信的基础。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 1:08:15

SQL 注入基础:手工注入流程(判断注入点→爆库→爆表→爆数据)

目录 合规免责声明 手工注入核心流程 一、为什么要学手工 SQL 注入&#xff1f; 二、前置准备&#xff1a;靶场环境配置 2.1 环境要求 2.2 核心原理铺垫 三、手工注入全流程实战&#xff08;6 大步骤&#xff09; 步骤 1&#xff1a;判断注入点 —— 确认漏洞是否存在 …

作者头像 李华
网站建设 2026/5/26 9:27:03

【PHP 8.6 JIT性能迷局】:为什么你的FPM进程吃掉2GB内存?

第一章&#xff1a;PHP 8.6 的 JIT 内存占用PHP 8.6 即将引入对 JIT&#xff08;Just-In-Time&#xff09;编译器的进一步优化&#xff0c;但随之而来的内存占用问题也引起了开发者关注。JIT 在提升执行效率的同时&#xff0c;会将部分 PHP 脚本编译为原生机器码&#xff0c;这…

作者头像 李华
网站建设 2026/5/26 7:19:43

RIGOL示波器自研ASIC芯片在DS4000系列中的应用

在高端示波器领域&#xff0c;ASIC&#xff08;Application-SpecificRIGOL示波器IntegratedRIGOL示波器Circuit&#xff0c;专用集成电路&#xff09;芯片的应用已经非常普遍。ASIC芯片可以针对特定应用进行优化设计&#xff0c;从而在性能、功耗和成本等方面实现最佳平衡。近年…

作者头像 李华
网站建设 2026/5/26 4:23:10

农业IoT系统总是掉线?,PHP设备心跳机制设计全解析

第一章&#xff1a;农业IoT系统总是掉线&#xff1f;PHP设备心跳机制设计全解析在农业物联网&#xff08;IoT&#xff09;系统中&#xff0c;传感器设备常部署于偏远农田或温室环境&#xff0c;网络稳定性差、供电波动大&#xff0c;导致设备频繁掉线。若缺乏有效的在线状态监控…

作者头像 李华
网站建设 2026/5/26 7:12:16

Python编程实战:从类与对象到设计优雅代码

「编程类软件工具合集」 链接&#xff1a;https://pan.quark.cn/s/0b6102d9a66a 一、为什么需要面向对象编程&#xff1f; 想象你正在开发一个电商系统&#xff0c;需要管理商品、用户和订单。如果用过程式编程&#xff0c;代码会变成这样&#xff1a; # 过程式电商系统示例…

作者头像 李华
网站建设 2026/5/26 7:12:17

Laravel 13多模态权限架构深度解析(企业级安全控制方案)

第一章&#xff1a;Laravel 13多模态权限架构概述在现代 Web 应用开发中&#xff0c;权限管理是保障系统安全的核心环节。Laravel 13 引入了多模态权限架构&#xff0c;支持基于角色、策略、门面&#xff08;Gates&#xff09;和策略类&#xff08;Policies&#xff09;的复合权…

作者头像 李华