You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现多进程Android EncryptedSharedPreferences?求技术指引

多进程共享EncryptedSharedPreferences的实现方案

EncryptedSharedPreferences本身不支持MULTI_MODE_PROCESS,谷歌Jetpack Security库也未提供相关配置选项,直接多进程访问会导致文件锁冲突、数据不一致甚至崩溃——因为它的加密实现依赖单进程的文件访问上下文。以下是两种可行的技术方案:

方案一:用ContentProvider封装EncryptedSharedPreferences

ContentProvider是Android官方跨进程通信组件,天然支持多进程访问,可作为统一入口封装EncryptedSharedPreferences的读写操作,避免直接操作文件带来的冲突。

实现步骤:

  1. 创建EncryptedPreferencesProvider类
class EncryptedPreferencesProvider : ContentProvider() {
    private lateinit var encryptedPrefs: SharedPreferences

    override fun onCreate(): Boolean {
        // 初始化MasterKey,所有进程共用系统密钥库生成的密钥
        val masterKey = MasterKey.Builder(context!!)
            .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
            .build()

        // 初始化EncryptedSharedPreferences
        encryptedPrefs = EncryptedSharedPreferences.create(
            context!!,
            "cross_process_encrypted_prefs",
            masterKey,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        )
        return true
    }

    // 实现读取逻辑
    override fun query(
        uri: Uri,
        projection: Array<String>?,
        selection: String?,
        selectionArgs: Array<String>?,
        sortOrder: String?
    ): Cursor? {
        val targetKey = selection ?: return null
        val value = encryptedPrefs.getString(targetKey, null)
        // 使用MatrixCursor封装结果返回
        val cursor = MatrixCursor(arrayOf("key", "value"))
        cursor.addRow(arrayOf(targetKey, value))
        return cursor
    }

    // 实现写入逻辑
    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<String>?
    ): Int {
        values ?: return 0
        val editor = encryptedPrefs.edit()
        values.keySet().forEach { key ->
            when (val value = values[key]) {
                is String -> editor.putString(key, value)
                is Int -> editor.putInt(key, value)
                is Boolean -> editor.putBoolean(key, value)
                // 按需支持更多数据类型
            }
        }
        return if (editor.commit()) 1 else 0
    }

    // 其他方法按需实现(insert/delete/getType),此处简化
    override fun insert(uri: Uri, values: ContentValues?): Uri? = null
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
    override fun getType(uri: Uri): String? = null
}
  1. 在AndroidManifest中注册Provider
<provider
    android:name=".EncryptedPreferencesProvider"
    android:authorities="com.your.package.cross_process_encrypted_prefs"
    android:exported="false" <!-- 同一应用内进程访问设为false即可,无需对外暴露 -->
    android:process=":remote" /> <!-- 若需指定进程可添加,不指定则默认主进程 -->
  1. 多进程中通过ContentResolver访问
  • 读取数据:
val resolver = applicationContext.contentResolver
val uri = Uri.parse("content://com.your.package.cross_process_encrypted_prefs")
resolver.query(uri, null, "auth_token", null, null)?.use { cursor ->
    if (cursor.moveToFirst()) {
        val token = cursor.getString(cursor.getColumnIndexOrThrow("value"))
        // 使用令牌
    }
}
  • 写入数据:
val resolver = applicationContext.contentResolver
val uri = Uri.parse("content://com.your.package.cross_process_encrypted_prefs")
val values = ContentValues().apply {
    put("auth_token", "your_secure_token_here")
}
resolver.update(uri, values, null, null)

注意事项:

  • 密钥安全性:每个进程独立初始化MasterKey即可,无需传递密钥,MasterKey基于Android系统密钥库生成,多进程可安全获取。
  • 并发控制:ContentProvider内部会自动处理多进程的并发访问,加上EncryptedSharedPreferences的commit操作是原子性的,能保证数据一致性。
  • 权限控制:如果是跨应用访问,需设置自定义权限限制访问范围,避免敏感数据泄露。

方案二:使用支持多进程的加密存储替代

如果不想封装ContentProvider,可以直接使用MMKV加密版,它原生支持多进程,同时提供加密功能,实现更简洁:

// 初始化MMKV(全局初始化一次即可)
MMKV.initialize(applicationContext)

// 获取加密多进程实例
val encryptedMMKV = MMKV.mmkvWithID(
    "encrypted_token_store",
    MMKV.MULTI_PROCESS_MODE,
    "your_32_byte_encryption_key" // 建议使用32位密钥保证AES256加密强度
)

// 写入令牌
encryptedMMKV.putString("auth_token", "your_token")

// 读取令牌
val token = encryptedMMKV.getString("auth_token", null)

内容的提问来源于stack exchange,提问作者Anusha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:46:05