Android 11(API 30)无远程服务器时卸载重装如何保留复用本地应用数据
Android 11 应用重装后读取公共目录历史文件解决方案
你遇到的权限问题除了重装后UID变化的原因外,核心是Android 11开始强制启用分区存储规则,第三方应用对公共目录的文件访问不再受传统Linux文件权限控制,你之前设置的全局可读可写属性会被系统直接忽略,即便是同包名应用之前创建的文件,重装后也无法直接通过原生File API访问。
目前有多个可落地的合规方案,不存在只能二选一的限制:
可行解决方案
方案1:使用存储访问框架(SAF)授权(优先推荐,可正常过审)
这是官方推荐的通用方案,不需要申请特殊权限,流程如下:
- 首次安装在公共Documents目录创建应用专属文件夹时,调用SAF引导用户给该文件夹授予持久化访问权限,将权限对应的Uri持久化存储在本地
- 重装应用后检测到历史文件夹存在时,先判断是否已持有对应访问权限,如未持有则弹出引导让用户再次选中该文件夹完成授权
- 后续所有文件读写操作都通过SAF提供的
ContentResolver和Uri操作,不要直接用File API访问原生路径
示例代码片段:
// 唤起SAF选择目录的Intent val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { // 预先定位到公共Documents下的应用专属目录 putExtra(DocumentsContract.EXTRA_INITIAL_URI, DocumentsContract.buildDocumentUriUsingTree( DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY, "primary:Documents/你的应用专属文件夹名" )) // 申请持久化读写权限 flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION } startActivityForResult(intent, REQUEST_CODE_SAF) // 授权成功后持久化权限 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_SAF && resultCode == Activity.RESULT_OK) { data?.data?.let { uri -> contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) // 将授权后的uri存入SharedPreferences供后续读写使用 } } }
方案2:申请全文件访问权限(仅特定场景适用)
如果你的应用属于文件管理、备份、办公类需要高频访问公共目录文件的类型,可以申请MANAGE_EXTERNAL_STORAGE权限:
- 在AndroidManifest.xml中声明对应权限
- 引导用户跳转到系统设置页开启「允许访问所有文件」权限
- 注意:普通非工具类应用如果申请该权限,Google Play和国内主流应用商店的审核大概率会被拒绝,仅适合企业内部自用应用或者符合权限使用场景的公开应用使用
方案3:引导用户手动导入导出数据
如果你的应用数据量不大,也可以设计独立的备份恢复功能:
- 应用运行过程中支持用户主动将全量数据导出为单个备份文件,用户可自由选择存储位置
- 重装应用后引导用户选择之前导出的备份文件完成数据恢复
- 该方案完全符合系统权限规则,不需要申请额外权限,用户感知清晰
内容的提问来源于stack exchange,提问作者user16083509
相关产品推荐
相关产品推荐

