
在多用户 android 设备上,若需让一个计数器(或其他变量)被同一应用的所有用户配置文件共同读写且严格隔离于其他应用,应使用应用私有的内部存储(internal storage),而非 sharedpreferences、settings.global 或外部文件。
Android 系统为每个应用分配独立的内部存储目录(如 getFilesDir() 或 getCacheDir() 返回的路径),该目录具有以下关键特性:
- ✅ 跨用户共享:同一应用包名在不同用户配置文件下访问的是同一物理路径(由系统自动映射),因此变量可自然实现跨用户读写;
- ✅ 应用私有:无需声明任何权限,其他应用(包括同设备其他用户下的其他应用)无法访问或修改该目录内容,即使拥有 root 权限也无法绕过 SELinux 策略直接篡改(除非设备已破解且策略被禁用);
- ✅ 生命周期绑定:目录随应用安装而创建,随应用卸载而自动清除,避免残留数据;
- ❌ 不适用于需要跨应用共享的场景(此时应考虑 ContentProvider + 签名权限等方案)。
推荐实现方式:基于内部存储的线程安全计数器
以下是一个轻量、安全、可复用的示例,使用 JSON 文件 + FileOutputStream 原子写入(配合 AtomicFile 保障一致性):
class CrossUserCounter private constructor(private val context: Context) {
private val counterFile = File(context.filesDir, "cross_user_counter.json")
fun get(): Int = try {
val json = counterFile.readText(Charsets.UTF_8)
Json.decodeFromString(json).value
} catch (e: Exception) {
0 // 初始化为 0
}
fun increment(): Int {
val newValue = get() + 1
val data = CounterData(newValue)
val json = Json.encodeToString(data)
// 使用 AtomicFile 实现原子写入,避免读写冲突
val atomicFile = AtomicFile(counterFile)
atomicFile.startWrite().use { outputStream ->
outputStream.write(json.toByteArray(Charsets.UTF_8))
}
atomicFile.finishWrite()
return newValue
}
data class CounterData(val value: Int)
companion object {
@Volatile private var INSTANCE: CrossUserCounter? = null
fun getInstance(context: Context): CrossUserCounter =
INSTANCE ?: synchronized(this) {
INSTANCE ?: CrossUserCounter(context.applicationContext).also { INSTANCE = it }
}
}
}
// 使用示例(在任意用户配置文件下均有效)
val counter = CrossUserCounter.getInstance(this)
Log.d("Counter", "Current value: ${counter.get()}") // 如:5
counter.increment() // → 返回 6,所有用户可见更新 注意事项与最佳实践
- 避免使用 getExternalFilesDir():该路径虽也属应用私有,但按用户隔离(即不同用户看到的是不同目录),不满足跨用户需求;
- 勿手动拼接路径或使用硬编码路径:始终通过 context.filesDir 获取,确保兼容性与安全性;
- 敏感数据需额外加密:若计数器本身不涉密,JSON 明文足够;若需防逆向分析,可在序列化前后叠加 AES 加密(密钥建议硬编码+混淆,或使用 Android Keystore 生成并保护对称密钥);
- SQLite 数据库同样适用内部存储:Room 或原生 SQLiteDatabase.openDatabase() 若指定路径为 context.getDatabasePath("xxx.db"),该数据库文件默认位于内部存储,天然跨用户且应用私有——因此 SqlDelight(底层仍走 SQLite)同样满足需求,无需额外配置;
- 测试验证建议:在支持多用户的设备(如 Pixel 平板或 Android TV)上,分别以主用户和访客用户启动同一应用,确认计数器值同步更新。
综上,内部存储是官方推荐、零权限、高隔离、跨用户一致的首选方案。它平衡了安全性、简洁性与可维护性,是解决此类问题最符合 Android 架构原则的方式。






