【问题标题】:Android 11 - Creating app-specific directory on external storageAndroid 11 - 在外部存储上创建特定于应用程序的目录
【发布时间】:2021-04-19 12:22:02
【问题描述】:

最近,我正在尝试将我的应用程序从 SDK-29 迁移到 SDK-30。 我最关心的一件事是范围存储。

我在official document 上看到“在 Android 11(API 级别 30)及更高版本上,应用无法在外部存储上创建自己的应用特定目录。”

所以我尝试在外部存储中创建自己的目录并向其中写入一个新文件。代码如下所示:

// creating new directory under external storage
val appDir = File(applicationContext.getExternalFilesDir(null), "play")
appDir.mkdir()

// writing new file under my own directory
val newFile = File(appDir.absolutePath, "test.jpg")
val outputStream = FileOutputStream(newFile)
val inputStream = resources.openRawResource(R.drawable.ic_launcher_foreground)
val data = byteArrayOf()
inputStream.read(data)
outputStream.write(data)
inputStream.close()
outputStream.close()

我预计这段代码会崩溃,但它可以工作。我在给定的路径找到文件。所以,我有点搞不懂那张纸条的意思。

Google 的“无法在外部存储上创建自己的应用特定目录”是什么意思?

【问题讨论】:

    标签: android scoped-storage


    【解决方案1】:

    他们指的是从外部存储根目录创建任意目录(例如,Environment.getExternalStorageDirectory()

    getExternalFilesDir()Context 上的类似方法是可以使用的很好的解决方案!

    【讨论】:

    • @t0m:是的!对于用户希望在卸载后保留文件的情况......对于可识别的媒体格式,请使用MediaStore,否则使用ACTION_CREATE_DOCUMENT 和存储访问框架。有关这些选项的说明,请参阅 this lengthy blog post series
    • 我完全被 MediaStore 和存储访问框架搞糊涂了。所有 Android 教程都使用 File API,我有应用程序在 100 多个地方使用 File API,现在我必须重构所有代码以使用 MediaStore、SAF 和 Uris? :-|这种情况没有解决方案:用户在 SD 卡根目录上选择/创建目录,例如与 ACTION_OPEN_DOCUMENT_TREE 相同,系统授予 r/w 权限并返回文件路径以供以后与文件 API 一起使用。
    【解决方案2】:

    在外部存储上创建特定于应用程序的目录,但要关闭根目录。

    private fun createDir(directoryName: String): File? {
            val file = File(applicationContext.getExternalFilesDir("/"),directoryName)
            if (!file?.mkdirs())
                print("Volume : " + "Directory not created")
    
            return file
        }
    

    注意:不需要任何存储权限。

    在根目录的外部存储上创建应用程序特定目录。

    注意:这仅适用于 Android 11。

    请求用户访问所有文件:

    1. 在清单中声明 MANAGE_EXTERNAL_STORAGE 权限。
    2. 使用 ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION 意图操作 将用户引导到系统设置页面,他们可以在其中启用 您的应用的以下选项:允许访问以管理所有文件。
    3. 确定您的应用是否已获得 MANAGE_EXTERNAL_STORAGE 权限,调用 Environment.isExternalStorageManager()

    在 OnCreate 方法上编写代码:

    if (!isExternalStorageReadable()) return
    
    if (!Environment.isExternalStorageManager()) {
                val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
                intent.addCategory("android.intent.category.DEFAULT")
                intent.data = Uri.parse(String.format("package:%s", applicationContext.packageName))
                startActivityForResult(intent, 20)
            } else {
                createDir("ddddd")
            }
    

    在 OnCreate 之外声明两个函数:

    private fun isExternalStorageReadable(): Boolean {
            return Environment.getExternalStorageState() in
                    setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY)
        }
    
    private fun createDir(directoryName: String): File? {
            val file = File(Environment.getExternalStoragePublicDirectory("/"),directoryName)
            if (!file?.mkdirs())
                print("Volume : " + "Directory not created")
    
            return file
        }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 2018-01-05
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 2018-03-11
    相关资源
    最近更新 更多