You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android中实现跨应用无UI访问内部存储文件的方案咨询(替代API 29已废弃的同userId共享机制)

跨应用无UI文件共享 + 外部存储加密方案

嘿,我正好碰过类似的需求,给你分享几个靠谱的方案:

一、无UI交互实现App2访问App1文件

废弃同userId之后,FileProvider是官方推荐的无UI跨应用文件共享方式,完全匹配你的需求,具体步骤如下:

  1. 在App1中配置FileProvider

    • res/xml目录下创建file_paths.xml,指定要共享的内部存储目录(比如App1内部存储下的shared子目录):
      <?xml version="1.0" encoding="utf-8"?>
      <paths xmlns:android="http://schemas.android.com/apk/res/android">
          <files-path name="shared_files" path="shared/"/>
      </paths>
      
    • 在App1的AndroidManifest.xml中注册FileProvider:
      <provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="com.your.app1.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data
              android:name="android.support.FILE_PROVIDER_PATHS"
              android:resource="@xml/file_paths"/>
      </provider>
      
  2. App1给App2授权访问

    • 当需要让App2访问目标文件时,App1生成文件Uri并授予临时读取权限:
      val targetFile = File(context.filesDir, "shared/your_target_file.txt")
      val fileUri = FileProvider.getUriForFile(context, "com.your.app1.fileprovider", targetFile)
      // 给App2的包名授予临时读取权限
      context.grantUriPermission("com.your.app2", fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
      
    • 之后App2就能直接通过这个Uri读取文件,全程无用户交互:
      val inputStream = contentResolver.openInputStream(fileUri)
      // 读取文件内容逻辑...
      

    这种方式的权限是临时可控的,也能配置持久化授权(需提前约定App2的包名),安全性比旧的同userId方案高很多。

如果需要更灵活的权限控制,你也可以自定义ContentProvider,自己实现文件查询、读取逻辑,只允许指定包名的App(比如App2)访问,适合复杂的文件共享场景。

二、外部存储文件夹加密方案

对于外部存储的文件夹加密,有两种主流实现路径:

1. 系统自带API:EncryptedFile(API 23+)

Android原生提供了EncryptedFile类,可对单个文件加密,若要加密整个文件夹,只需遍历文件夹内所有文件逐个处理即可。密钥建议存在Android Keystore中,避免硬编码泄露:

// 创建并存储加密密钥到Keystore
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
keyGenerator.init(KeyGenParameterSpec.Builder("my_encryption_key", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
    .build())
val secretKey = keyGenerator.generateKey()

// 加密外部存储中的文件
val encryptedFile = EncryptedFile.Builder(
    context,
    File(Environment.getExternalStorageDirectory(), "encrypted_folder/target.txt"),
    secretKey,
    EncryptedFile.FileEncryptionScheme.AES_GCM_NO_PADDING
).build()
// 写入文件内容逻辑...

2. 第三方加密库

如果觉得系统API不够灵活,这些第三方库可以帮你简化文件夹加密流程:

  • Tink:Google官方维护的加密库,支持文件加密、对称加密等多种场景,文档完善,安全性有保障,适合批量处理文件夹内的文件。
  • Conceal:Facebook开源的轻量加密库,API简单易用,能快速实现文件加密,但近几年维护频次较低,需要注意版本兼容性。
  • 若需要底层控制,也可以基于CipherInputStream/CipherOutputStream自己实现文件夹遍历加密,但要做好密钥管理和异常处理。

不管用哪种方式,都要注意:外部存储的加密文件仍需申请对应存储权限(API 33+需READ_MEDIA_IMAGES等细粒度权限),且密钥一定要存在Android Keystore中,不要明文存储在代码或SharedPreferences里。

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

火山引擎 最新活动