当前位置: 首页 > news >正文

安卓进阶——跨进程通信

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。
🍎个人主页:Meteors.的博客
💞当前专栏:知识分享
✨特色专栏:知识分享
🥭本文内容:安卓进阶——跨进程通信
📚 ** ps **  :阅读文章如果有问题或者疑惑,欢迎在评论区提问或指出。


目录

一、 AIDL

(一)AIDL基础使用

1. 定义AIDL接口

2. 定义Parcelable数据类

3. 实现Service 

4. 客户端绑定服务

(二)AIDL高级特性

1. 异步回调接口

二、 Socket

(一)服务端实现

(二)客户端实现

三、 Binder

(一)介绍

(二)优势

(三)架构与核心组件

(四)使用

1. 定义 AIDL 接口文件

2. 实现服务端

3. 实现客户端

四、 Messenger

(一)介绍

(二)设计思想

(三)关键特点

(四)Messenger 的通信模型

1. 单向通信模型

2. 双向通信模型

(五)使用demo

1. 实现服务端

(1)创建 Service并定义用于处理消息的 Handler

(2)创建 Messenger,并重写 onBind()方法

(3)在 AndroidManifest.xml中注册 Service

2. 实现客户端

(1)绑定服务

(2)创建自己的 Handler和 Messenger来接收服务端的回复

(3)回调中创建服务端的 Messenger并发送消


一、 AIDL

(一)AIDL基础使用

AIDL(Android Interface Definition Language)让Binder通信更加简单规范。

1. 定义AIDL接口

// IUserManager.aidl
package com.example.ipcinterface IUserManager {void addUser(in User user)List<User> getUserList()int getUserCount()
}// User.aidl
parcelable User

2. 定义Parcelable数据类

@Parcelize
data class User(val name: String,val age: Int
) : Parcelable

3. 实现Service 

class UserManagerService : Service() {private val userList = CopyOnWriteArrayList<User>()private val binder = object : IUserManager.Stub() {override fun addUser(user: User) {userList.add(user)}override fun getUserList(): MutableList<User> {return userList}override fun getUserCount(): Int {return userList.size}}override fun onBind(intent: Intent): IBinder {return binder}
}

4. 客户端绑定服务

class MainActivity : AppCompatActivity() {private var userManager: IUserManager? = nullprivate var bound = falseprivate val connection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName?, service: IBinder?) {userManager = IUserManager.Stub.asInterface(service)bound = true// 使用服务userManager?.addUser(User("Alice", 30))val count = userManager?.userCountLog.d("IPC", "User count: $count")}override fun onServiceDisconnected(name: ComponentName?) {bound = falseuserManager = null}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)bindService()}private fun bindService() {val intent = Intent(this, UserManagerService::class.java)bindService(intent, connection, Context.BIND_AUTO_CREATE)}override fun onDestroy() {super.onDestroy()if (bound) {unbindService(connection)bound = false}}
}

(二)AIDL高级特性

1. 异步回调接口

// IDataCallback.aidl
interface IDataCallback {void onSuccess(in String result)void onError(int errorCode)
}// 在IUserManager.aidl中添加异步方法
interface IUserManager {void processDataAsync(String data, IDataCallback callback)
}// 服务端实现
class UserManagerService : Service() {private val binder = object : IUserManager.Stub() {override fun processDataAsync(data: String, callback: IDataCallback) {// 在后台线程处理thread {try {// 模拟耗时操作Thread.sleep(1000)val result = "Processed: $data"callback.onSuccess(result)} catch (e: Exception) {callback.onError(-1)}}}}
}

二、 Socket

(一)服务端实现

class SocketServerService : Service() {private var serverSocket: ServerSocket? = nullprivate var isRunning = falseprivate val clientHandlers = CopyOnWriteArrayList<ClientHandler>()inner class ClientHandler(private val socket: Socket) : Runnable {private val gson = Gson()override fun run() {try {val input = BufferedReader(InputStreamReader(socket.getInputStream()))val output = PrintWriter(socket.getOutputStream(), true)while (!socket.isClosed && isRunning) {val message = input.readLine() ?: break// 处理JSON消息val user = gson.fromJson(message, User::class.java)user?.let {// 处理用户数据processUser(it)// 返回响应val response = gson.toJson(mapOf("status" to "success", "user" to it))output.println(response)}}} catch (e: Exception) {e.printStackTrace()} finally {socket.close()clientHandlers.remove(this)}}private fun processUser(user: User) {// 处理用户逻辑}}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {startServer()return START_STICKY}private fun startServer() {thread {try {serverSocket = ServerSocket(8888)isRunning = truewhile (isRunning) {val client = serverSocket?.accept()client?.let {val handler = ClientHandler(it)clientHandlers.add(handler)thread { handler.run() }}}} catch (e: IOException) {e.printStackTrace()}}}override fun onDestroy() {super.onDestroy()isRunning = falseserverSocket?.close()clientHandlers.forEach { it.socket.close() }}override fun onBind(intent: Intent?): IBinder? = null
}

(二)客户端实现

class SocketClientActivity : AppCompatActivity() {private var socket: Socket? = nullprivate var output: PrintWriter? = nullprivate var input: BufferedReader? = nullprivate val gson = Gson()private fun connectToServer() {thread {try {socket = Socket("localhost", 8888)output = PrintWriter(socket?.getOutputStream(), true)input = BufferedReader(InputStreamReader(socket?.getInputStream()))// 发送用户数据sendUser(User("Charlie", 28))} catch (e: Exception) {e.printStackTrace()}}}private fun sendUser(user: User) {thread {try {val json = gson.toJson(user)output?.println(json)// 读取响应val response = input?.readLine()Log.d("Socket", "Response: $response")} catch (e: Exception) {e.printStackTrace()}}}
}

三、 Binder

(一)介绍

Binder 是 Android 系统中用于跨进程通信的主要机制。所谓跨进程通信,就是让运行在不同进程中的组件(例如,一个 App 调用系统相机服务)能够进行数据交换和调用方法,连接这些孤立的进程的“桥梁”就是 Binder。

(二)优势

  • 高性能:相比传统的 Linux IPC(如管道、消息队列、Socket),Binder 只需要一次数据拷贝,效率非常高。这是因为它利用了内存映射技术。

  • 安全性:Binder 机制继承了 Android 的 UID/PID 标识,支持通信双方的身份验证,这是 Socket 等机制不具备的。系统服务可以验证调用者的权限。

  • 面向对象:Binder 使用起来很像本地方法调用,对开发者更友好。你可以定义一个接口,然后在客户端调用,服务端实现,感觉就像在调用本地对象的方法一样。

(三)架构与核心组件

所在进程

职责

Binder 驱动

Linux 内核

IPC 通信的核心。它不是一个硬件驱动,而是一个字符设备驱动(/dev/binder)。负责进程间通信的建立、数据交换、线程管理等所有底层工作。

服务端

服务进程

提供具体服务的进程。它会创建 Binder 对象并实现其业务逻辑。

Binder 实体对象

服务进程

服务端创建的、真正提供功能的对象。它有一个唯一的标识,称为 Binder 引用

代理对象

客户端进程

客户端持有的一个接口。它对客户端来说看起来就像本地对象,但当客户端调用其方法时,它会将调用信息打包并传递给 Binder 驱动。

客户端

客户端进程

需要调用服务的进程。它持有服务端的 代理对象

(四)使用

1. 定义 AIDL 接口文件

// IMyService.aidl
package com.example.service;// 声明接口
interface IMyService {// 定义一些方法int add(int a, int b);String greet(String name);
}

2. 实现服务端

public class MyService extends Service {private final IMyService.Stub mBinder = new IMyService.Stub() {@Overridepublic int add(int a, int b) {// 这里是在服务端进程中执行的!return a + b;}};@Overridepublic IBinder onBind(Intent intent) {return mBinder;}
}

3. 实现客户端

// MainActivity.java
public class MainActivity extends Activity {private IMyService myService;private boolean isBound = false;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 关键步骤:将 IBinder 转换为 AIDL 接口myService = IMyService.Stub.asInterface(service);isBound = true;// 现在可以调用远程方法了!try {int result = myService.add(5, 3);String greeting = myService.greet("Android");Log.d("Client", "Result: " + result + ", Greeting: " + greeting);} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {myService = null;isBound = false;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent();intent.setAction("com.example.service.MY_SERVICE_ACTION");intent.setPackage("com.example.service"); // 设置包名用于精确匹配(Android 5.0+ 必须)bindService(intent, connection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {super.onDestroy();if (isBound) {unbindService(connection);isBound = false;}}
}

四、 Messenger

(一)介绍

Messenger 是 Android 提供的一种基于 消息(Message)的跨进程通信方式。它的底层实现完全依赖于 Binder,但因为它封装了 AIDL 的复杂细节,提供了类似 Handler的简单 API,所以使用起来非常方便,特别适合不需要并发操作的场景。

(二)设计思想

核心思想:将一个进程的 Handler对象“传递”给另一个进程,让另一个进程可以向这个 Handler发送 Message对象,从而实现通信。

你可以把它想象成进程间的“信使”

  • 服务端创建一个 Handler来处理消息。

  • 然后基于这个 Handler创建一个 Messenger(信使)。

  • 客户端拿到这个 Messenger的引用后,就可以用它来向服务端的 Handler发送消息了。

(三)关键特点

优点简单易用,无需编写 AIDL 文件,自动处理了线程排队(串行处理)。

缺点功能单一,只能单向传递消息(Message对象)。如果要实现双向通信,需要建立两个 Messenger。不适合需要远程方法调用的复杂场景。

(四)Messenger 的通信模型

Messenger 通信通常是 一对一的,遵循典型的客户端-服务器模型。

1. 单向通信模型

  1. 服务端:创建一个 Handler来处理消息,并由此创建一个 Messenger。在 onBind()中返回这个 Messenger底层的 Binder对象。

  2. 客户端:绑定服务后,利用服务返回的 Binder对象创建一个 Messenger

  3. 客户端:使用 messenger.send(Message msg)方法向服务端发送消息。

  4. 服务端:在它的 Handler的 handleMessage()方法中接收到这条消息并进行处理。

2. 双向通信模型

  1. 在单向通信的基础上,客户端在发送消息时,需要将自己的一个 Messenger通过 Message.replyTo字段附带过去。

  2. 服务端在 handleMessage()中收到消息后,可以从消息中取出客户端的 Messenger

  3. 服务端现在也可以用这个 Messenger向客户端发送消息了。

  4. 客户端也需要一个自己的 Handler和 Messenger来接收并处理服务端回传的消息。

(五)使用demo

1. 实现服务端

(1)创建 Service并定义用于处理消息的 Handler

(2)创建 Messenger,并重写 onBind()方法

// MessengerService.java
public class MessengerService extends Service {// 用于处理从客户端发送来的消息的线程private static class IncomingHandler extends Handler {private final Application application;// 用于向客户端回复的 Messengerprivate Messenger clientMessenger;public IncomingHandler(Application application) {this.application = application;}@Overridepublic void handleMessage(Message msg) {switch (msg.what) {// 定义消息类型,例如 MSG_FROM_CLIENTcase 1001:Log.i("Server", "Received from client: " + msg.getData().getString("data"));// 获取客户端信使(用于回复)clientMessenger = msg.replyTo;if (clientMessenger != null) {try {// 准备回复给客户端的消息Message replyMsg = Message.obtain(null, 1002);Bundle bundle = new Bundle();bundle.putString("data", "Hello Client, I‘m Server!");replyMsg.setData(bundle);// 向客户端发送回复clientMessenger.send(replyMsg);} catch (RemoteException e) {e.printStackTrace();}}break;default:super.handleMessage(msg);}}}// 服务端的信使,其内部关联了处理消息的 Handlerprivate final Messenger mMessenger = new Messenger(new IncomingHandler(getApplication()));@Overridepublic IBinder onBind(Intent intent) {// 将信使内部的 Binder 对象返回给客户端return mMessenger.getBinder();}
}

(3)在 AndroidManifest.xml中注册 Service

<service android:name=".MessengerService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.app.MESSENGER_SERVICE" /></intent-filter>
</service>

2. 实现客户端

(1)绑定服务

(2)创建自己的 Handler和 Messenger来接收服务端的回复

(3)回调中创建服务端的 Messenger并发送消息

// MainActivity.java
public class MainActivity extends AppCompatActivity {private Messenger mServiceMessenger; // 指向服务端的信使private Messenger mClientMessenger;  // 指向客户端自身的信使(用于接收回复)private boolean isBound;// 客户端的 Handler,用于处理服务端发来的回复private static class ClientHandler extends Handler {private final WeakReference<MainActivity> mActivity;public ClientHandler(MainActivity activity) {mActivity = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {MainActivity activity = mActivity.get();if (activity != null) {switch (msg.what) {// 定义消息类型,例如 MSG_FROM_SERVERcase 1002:String reply = msg.getData().getString("data");Log.i("Client", "Received reply from server: " + reply);Toast.makeText(activity, "Server says: " + reply, Toast.LENGTH_SHORT).show();break;}}}}private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 用服务端返回的 Binder 对象创建指向服务端的 MessengermServiceMessenger = new Messenger(service);isBound = true;// 准备一条要发送给服务端的消息Message msg = Message.obtain(null, 1001); // 1001 是消息类型Bundle bundle = new Bundle();bundle.putString("data", "Hello Server, I‘m Client!");msg.setData(bundle);// !!! 关键步骤:将客户端的信使设置到消息的 replyTo 字段,以便服务端回复msg.replyTo = mClientMessenger;try {// 通过服务端信使发送消息mServiceMessenger.send(msg);} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {mServiceMessenger = null;isBound = false;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 创建客户端自己的信使,用于接收回复mClientMessenger = new Messenger(new ClientHandler(this));// 绑定服务Intent intent = new Intent();intent.setAction("com.example.app.MESSENGER_SERVICE");intent.setPackage("com.example.app"); // 设置服务端包名(显式Intent)bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {super.onDestroy();if (isBound) {unbindService(mConnection);isBound = false;}}
}
http://www.dtcms.com/a/573404.html

相关文章:

  • 连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文
  • 自己做的网站怎么添加文档成都装修公司哪家口碑最好
  • 视频网站代言人建筑施工企业专职安全生产管理员
  • 保姆级教程 | 麒麟系统安装Edge浏览器
  • HAL库uint8_t,uint16_t,uint32_t类型报错error: #20: identifier “uint32_t“ is undefined
  • Java LinkedList集合全面解析:双向链表的艺术与实战
  • 【MySQL】--- 事务4种特性、隔离级别、MVCC
  • 上信考:【数据科学技术及应用】考试大纲题型示例、例题解析、模拟卷答案
  • 做游戏网站需要哪些许可黄页号码标记申诉
  • 网站建设钅金手指排名平面设计接单赚钱平台
  • 凡科轻站小程序怎么样全国十大软件开发培训机构
  • 北京多语言网站建设微网站 .net
  • 山东滨州网站建设公司做淘客都有什么网站
  • 免杀技巧 - 早鸟注入详细学习笔记
  • Tomcat安装和Servlet项目创建【保姆教程】
  • C++入门(二) (算法竞赛)
  • 【Svelte】如果是导入的组件,如何为其添加样式?
  • SpringBoot 实战(四十)集成 Statemachine
  • 网站制作教程手机杭州酒店网站设计公司推荐
  • 【设计题】如何实现限流器
  • 场外衍生品架构解析:TRS收益互换与场外个股期权的技术实现
  • 小程序定制开发实战:需求拆解、UI 设计与个性化功能落地流程
  • MATLAB基于变权理论和灰色云模型的海岛旅游地生态安全评价
  • 威联通nas 做网站长沙装修公司名单
  • 机器学习中的 fit()、transform() 与 fit_transform():原理、用法与最佳实践
  • 旅游景区网站建设的必要性织梦论坛
  • 【YashanDB认证】之三:用Docker制作YMP容器
  • 图文生视频的原理与应用
  • Java Spring Boot 项目 Docker 容器化部署教程
  • YOLOv8 模型 NMS 超时问题解决方案总结