Blog #199: 跨进程通信IPC机制

难度:⭐⭐⭐⭐⭐

标签:Android IPC AIDL Binder 跨进程

🎯 核心问题

什么是IPC?Android有哪些跨进程通信方式?如何实现高效安全的跨进程通信?

💡 核心概念

**IPC(Inter-Process Communication,进程间通信)**是指不同进程间交换数据的机制。Android基于Linux,提供多种IPC方式:Binder(核心机制)、AIDL(接口定义)、Messenger(轻量级)、ContentProvider(数据共享)、Socket(网络通信)。

Binder机制核心

Binder是Android特有的IPC机制,基于客户端-服务端模型,通过内核驱动实现高效数据传输(只需一次拷贝)。

📝 详细说明

1. 多进程基础

1.1 配置多进程
<!-- AndroidManifest.xml -->
<manifest>
    <application>
        <!-- 主进程 -->
        <activity android:name=".MainActivity" />
        
        <!-- 独立进程 -->
        <activity
            android:name=".RemoteActivity"
            android:process=":remote" />
        
        <!-- 全局进程 -->
        <service
            android:name=".RemoteService"
            android:process="com.example.app.remote" />
        
        <!-- 私有进程(默认) -->
        <service
            android:name=".LocalService"
            android:process=":local" />
    </application>
</manifest>
1.2 多进程影响
class ProcessDemo : Application() {
    
    companion object {
        var counter = 0 // 每个进程独立的静态变量
    }
    
    override fun onCreate() {
        super.onCreate()
        
        counter++
        
        val processName = getCurrentProcessName()
        Log.d("Process", "进程: $processName, Counter: $counter")
        // 不同进程的counter互不影响
    }
    
    private fun getCurrentProcessName(): String {
        val pid = android.os.Process.myPid()
        val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        
        am.runningAppProcesses?.forEach { processInfo ->
            if (processInfo.pid == pid) {
                return processInfo.processName
            }
        }
        return "Unknown"
    }
}

class MultiProcessIssues : AppCompatActivity() {
    
    fun demonstrateIssues() {
        // 问题1: 静态变量失效
        ProcessDemo.counter = 100
        Log.d("Issues", "主进程counter: ${ProcessDemo.counter}")
        // 其他进程的counter不受影响
        
        // 问题2: SharedPreferences不同步
        val prefs = getSharedPreferences("data", Context.MODE_PRIVATE)
        prefs.edit().putString("key", "value").apply()
        // 其他进程可能读取不到最新值
        
        // 问题3: Application多次创建
        // 每个进程都会创建独立的Application实例
        
        // 问题4: 文件共享问题
        // 多进程同时写入同一文件可能冲突
    }
}

2. AIDL实现

2.1 定义AIDL接口
// IBookManager.aidl
package com.example.app;

import com.example.app.Book;

interface IBookManager {
    List<Book> getBookList();
    void addBook(in Book book);
    void registerListener(IOnNewBookArrivedListener listener);
    void unregisterListener(IOnNewBookArrivedListener listener);
}
// Book.aidl
package com.example.app;

parcelable Book;
// IOnNewBookArrivedListener.aidl
package com.example.app;

import com.example.app.Book;

interface IOnNewBookArrivedListener {
    void onNewBookArrived(in Book newBook);
}
2.2 数据类实现
@Parcelize
data class Book(
    val bookId: Int,
    val bookName: String,
    val author: String,
    val price: Double
) : Parcelable
2.3 Service端实现
class BookManagerService : Service() {
    
    private val bookList = CopyOnWriteArrayList<Book>()
    private val listenerList = RemoteCallbackList<IOnNewBookArrivedListener>()
    
    private val binder = object : IBookManager.Stub() {
        
        override fun getBookList(): List<Book> {
            // 延迟模拟
            SystemClock.sleep(2000)
            return bookList
        }
        
        override fun addBook(book: Book) {
            bookList.add(book)
            Log.d("Service", "添加书籍: ${book.bookName}")
            
            // 通知所有监听器
            notifyNewBook(book)
        }
        
        override fun registerListener(listener: IOnNewBookArrivedListener?) {
            listenerList.register(listener)
            Log.d("Service", "注册监听器,当前数量: ${listenerList.registeredCallbackCount}")
        }
        
        override fun unregisterListener(listener: IOnNewBookArrivedListener?) {
            listenerList.unregister(listener)
            Log.d("Service", "注销监听器,当前数量: ${listenerList.registeredCallbackCount}")
        }
    }
    
    override fun onCreate() {
        super.onCreate()
        // 初始化数据
        bookList.add(Book(1, "Android开发艺术探索", "任玉刚", 89.0))
        bookList.add(Book(2, "Kotlin实战", "Dmitry Jemerov", 79.0))
    }
    
    override fun onBind(intent: Intent): IBinder {
        // 权限检查
        val permission = checkCallingOrSelfPermission("com.example.app.BOOK_SERVICE")
        if (permission == PackageManager.PERMISSION_DENIED) {
            return null!!
        }
        return binder
    }
    
    private fun notifyNewBook(book: Book) {
        val count = listenerList.beginBroadcast()
        try {
            for (i in 0 until count) {
                val listener = listenerList.getBroadcastItem(i)
                try {
                    listener?.onNewBookArrived(book)
                } catch (e: RemoteException) {
                    e.printStackTrace()
                }
            }
        } finally {
            listenerList.finishBroadcast()
        }
    }
}
2.4 Client端实现
class BookManagerActivity : AppCompatActivity() {
    
    private lateinit var binding: ActivityBookManagerBinding
    private var bookManager: IBookManager? = null
    private var isBound = false
    
    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            bookManager = IBookManager.Stub.asInterface(service)
            isBound = true
            
            // 设置死亡监听
            service.linkToDeath(deathRecipient, 0)
            
            // 加载书籍列表
            loadBooks()
            
            // 注册监听器
            bookManager?.registerListener(bookArrivedListener)
        }
        
        override fun onServiceDisconnected(name: ComponentName) {
            bookManager = null
            isBound = false
        }
    }
    
    // Binder死亡监听
    private val deathRecipient = object : IBinder.DeathRecipient {
        override fun binderDied() {
            Log.d("Client", "Binder died")
            bookManager?.asBinder()?.unlinkToDeath(this, 0)
            bookManager = null
            
            // 重新连接
            bindServiceSafely()
        }
    }
    
    // 新书到达监听器
    private val bookArrivedListener = object : IOnNewBookArrivedListener.Stub() {
        override fun onNewBookArrived(newBook: Book) {
            // 在Binder线程池调用,需要切换到主线程
            runOnUiThread {
                Log.d("Client", "新书到达: ${newBook.bookName}")
                Toast.makeText(
                    this@BookManagerActivity,
                    "新书: ${newBook.bookName}",
                    Toast.LENGTH_SHORT
                ).show()
            }
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityBookManagerBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        setupClickListeners()
        bindServiceSafely()
    }
    
    private fun setupClickListeners() {
        binding.btnGetBooks.setOnClickListener {
            loadBooks()
        }
        
        binding.btnAddBook.setOnClickListener {
            addBook()
        }
    }
    
    private fun bindServiceSafely() {
        val intent = Intent(this, BookManagerService::class.java)
        bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }
    
    private fun loadBooks() {
        if (!isBound) return
        
        // AIDL调用是同步的,需要在子线程
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                val books = bookManager?.bookList ?: emptyList()
                
                withContext(Dispatchers.Main) {
                    displayBooks(books)
                }
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }
    }
    
    private fun displayBooks(books: List<Book>) {
        val text = books.joinToString("\n") {
            "${it.bookName} - ${it.author}${it.price})"
        }
        binding.tvBooks.text = text
    }
    
    private fun addBook() {
        if (!isBound) return
        
        val newBook = Book(
            bookId = (Math.random() * 1000).toInt(),
            bookName = "新书${System.currentTimeMillis() % 1000}",
            author = "作者",
            price = 99.0
        )
        
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                bookManager?.addBook(newBook)
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }
    }
    
    override fun onDestroy() {
        super.onDestroy()
        if (isBound) {
            // 注销监听器
            bookManager?.unregisterListener(bookArrivedListener)
            unbindService(connection)
            isBound = false
        }
    }
}

3. Messenger实现

// Service端(轻量级IPC)
class MessengerService : Service() {
    
    companion object {
        const val MSG_FROM_CLIENT = 1
        const val MSG_FROM_SERVICE = 2
    }
    
    private class ServiceHandler(
        context: Context
    ) : Handler(Looper.getMainLooper()) {
        
        private val appContext = context.applicationContext
        
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                MSG_FROM_CLIENT -> {
                    val data = msg.data.getString("data")
                    Log.d("Service", "收到客户端消息: $data")
                    
                    // 回复客户端
                    msg.replyTo?.send(
                        Message.obtain(null, MSG_FROM_SERVICE).apply {
                            data = Bundle().apply {
                                putString("reply", "收到: $data")
                            }
                        }
                    )
                }
            }
        }
    }
    
    private val messenger = Messenger(ServiceHandler(this))
    
    override fun onBind(intent: Intent): IBinder {
        return messenger.binder
    }
}

// Client端
class MessengerClient : AppCompatActivity() {
    
    private var serviceMessenger: Messenger? = null
    private val clientMessenger = Messenger(ClientHandler(this))
    
    private class ClientHandler(activity: MessengerClient) : Handler(Looper.getMainLooper()) {
        private val activityRef = WeakReference(activity)
        
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                MessengerService.MSG_FROM_SERVICE -> {
                    val reply = msg.data.getString("reply")
                    Log.d("Client", "收到服务端回复: $reply")
                }
            }
        }
    }
    
    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            serviceMessenger = Messenger(service)
            sendMessage("Hello")
        }
        
        override fun onServiceDisconnected(name: ComponentName) {
            serviceMessenger = null
        }
    }
    
    override fun onStart() {
        super.onStart()
        Intent(this, MessengerService::class.java).also {
            bindService(it, connection, Context.BIND_AUTO_CREATE)
        }
    }
    
    override fun onStop() {
        super.onStop()
        unbindService(connection)
    }
    
    private fun sendMessage(text: String) {
        val msg = Message.obtain(null, MessengerService.MSG_FROM_CLIENT).apply {
            data = Bundle().apply {
                putString("data", text)
            }
            replyTo = clientMessenger
        }
        
        try {
            serviceMessenger?.send(msg)
        } catch (e: RemoteException) {
            e.printStackTrace()
        }
    }
}

4. ContentProvider跨进程

class BookProvider : ContentProvider() {
    
    companion object {
        const val AUTHORITY = "com.example.app.provider"
        val BOOK_CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY/book")
        
        const val BOOK_URI_CODE = 0
        private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
            addURI(AUTHORITY, "book", BOOK_URI_CODE)
        }
    }
    
    override fun onCreate(): Boolean {
        // 初始化
        return true
    }
    
    override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
        // 查询数据
        return when (uriMatcher.match(uri)) {
            BOOK_URI_CODE -> {
                // 返回Cursor
                null
            }
            else -> null
        }
    }
    
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        // 插入数据
        return null
    }
    
    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<out String>?
    ): Int {
        // 更新数据
        return 0
    }
    
    override fun delete(
        uri: Uri,
        selection: String?,
        selectionArgs: Array<out String>?
    ): Int {
        // 删除数据
        return 0
    }
    
    override fun getType(uri: Uri): String? {
        return null
    }
}

5. IPC方式对比

object IPCComparison {
    
    data class IPCMethod(
        val name: String,
        val complexity: Complexity,
        val dataType: String,
        val useCase: String,
        val pros: List<String>,
        val cons: List<String>
    )
    
    enum class Complexity {
        LOW, MEDIUM, HIGH
    }
    
    val methods = listOf(
        IPCMethod(
            "Bundle",
            Complexity.LOW,
            "基本类型、Parcelable",
            "Activity/Service传参",
            listOf("简单", "官方支持"),
            listOf("不支持实时通信", "数据大小限制")
        ),
        IPCMethod(
            "文件共享",
            Complexity.LOW,
            "任意数据",
            "不要求实时性的数据共享",
            listOf("简单", "支持大数据"),
            listOf("不适合高并发", "需要同步")
        ),
        IPCMethod(
            "Messenger",
            Complexity.MEDIUM,
            "Message",
            "轻量级IPC,低并发",
            listOf("简单易用", "自动排队"),
            listOf("串行处理", "不支持RPC")
        ),
        IPCMethod(
            "AIDL",
            Complexity.HIGH,
            "基本类型、Parcelable、List、Map",
            "复杂跨进程调用",
            listOf("功能强大", "支持并发"),
            listOf("复杂", "需要处理线程同步")
        ),
        IPCMethod(
            "ContentProvider",
            Complexity.MEDIUM,
            "Cursor",
            "一对多数据共享",
            listOf("标准化", "支持多进程"),
            listOf("受限于表格模型", "主要用于数据")
        ),
        IPCMethod(
            "Socket",
            Complexity.HIGH,
            "字节流",
            "网络通信",
            listOf("功能强大", "跨设备"),
            listOf("复杂", "性能开销大")
        )
    )
}

⚡ 关键要点

  1. Binder机制 - Android IPC核心,一次拷贝,性能优秀
  2. AIDL - 复杂跨进程通信首选,支持并发和回调
  3. Messenger - 轻量级IPC,串行处理,适合低并发
  4. 线程安全 - AIDL方法在Binder线程池调用,需处理线程同步
  5. 生命周期 - 注意Service连接管理和Binder死亡监听

🔗 相关知识点


下一篇: Blog #200: Android组件详解系列总结

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐