安卓进阶——跨进程通信
本文介绍了Android平台四种主要的跨进程通信方式: AIDL:通过定义接口实现Binder通信,支持同步/异步调用和Parcelable数据传输,适用于复杂IPC场景; Socket:基于TCP/IP的通用通信方案,需手动处理线程和JSON序列化,适合网络或非Android环境通信; Binder:Android核心IPC机制,通过内存映射实现高效数据传输,结合AIDL简化开发,系统服务广泛采
✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。
🍎个人主页:Meteors.的博客
💞当前专栏:知识分享
✨特色专栏:知识分享
🥭本文内容:安卓进阶——跨进程通信
📚 ** ps ** :阅读文章如果有问题或者疑惑,欢迎在评论区提问或指出。
目录
(1)创建 Service并定义用于处理消息的 Handler
(2)创建 Messenger,并重写 onBind()方法
(3)在 AndroidManifest.xml中注册 Service
(2)创建自己的 Handler和 Messenger来接收服务端的回复
一、 AIDL
(一)AIDL基础使用
AIDL(Android Interface Definition Language)让Binder通信更加简单规范。
1. 定义AIDL接口
// IUserManager.aidl package com.example.ipc interface IUserManager { void addUser(in User user) List<User> getUserList() int getUserCount() } // User.aidl parcelable User2. 定义Parcelable数据类
@Parcelize data class User( val name: String, val age: Int ) : Parcelable3. 实现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? = null private var bound = false private 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?.userCount Log.d("IPC", "User count: $count") } override fun onServiceDisconnected(name: ComponentName?) { bound = false userManager = 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? = null private var isRunning = false private 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 = true while (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 = false serverSocket?.close() clientHandlers.forEach { it.socket.close() } } override fun onBind(intent: Intent?): IBinder? = null }(二)客户端实现
class SocketClientActivity : AppCompatActivity() { private var socket: Socket? = null private var output: PrintWriter? = null private var input: BufferedReader? = null private 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() { @Override public int add(int a, int b) { // 这里是在服务端进程中执行的! return a + b; } }; @Override public 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() { @Override public 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(); } } @Override public void onServiceDisconnected(ComponentName name) { myService = null; isBound = false; } }; @Override protected 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); } @Override protected 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. 单向通信模型
服务端:创建一个
Handler来处理消息,并由此创建一个Messenger。在onBind()中返回这个Messenger底层的Binder对象。客户端:绑定服务后,利用服务返回的
Binder对象创建一个Messenger。客户端:使用
messenger.send(Message msg)方法向服务端发送消息。服务端:在它的
Handler的handleMessage()方法中接收到这条消息并进行处理。2. 双向通信模型
在单向通信的基础上,客户端在发送消息时,需要将自己的一个 Messenger通过
Message.replyTo字段附带过去。服务端在
handleMessage()中收到消息后,可以从消息中取出客户端的Messenger。服务端现在也可以用这个
Messenger向客户端发送消息了。客户端也需要一个自己的
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; // 用于向客户端回复的 Messenger private Messenger clientMessenger; public IncomingHandler(Application application) { this.application = application; } @Override public void handleMessage(Message msg) { switch (msg.what) { // 定义消息类型,例如 MSG_FROM_CLIENT case 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); } } } // 服务端的信使,其内部关联了处理消息的 Handler private final Messenger mMessenger = new Messenger(new IncomingHandler(getApplication())); @Override public 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); } @Override public void handleMessage(Message msg) { MainActivity activity = mActivity.get(); if (activity != null) { switch (msg.what) { // 定义消息类型,例如 MSG_FROM_SERVER case 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() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 用服务端返回的 Binder 对象创建指向服务端的 Messenger mServiceMessenger = 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(); } } @Override public void onServiceDisconnected(ComponentName name) { mServiceMessenger = null; isBound = false; } }; @Override protected 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); } @Override protected void onDestroy() { super.onDestroy(); if (isBound) { unbindService(mConnection); isBound = false; } } }
更多推荐


所有评论(0)