Android 11 - 在外部存储上创建特定于应用程序的目录

Android 11 - Creating app-specific directory on external storage

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

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

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

// 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“无法在外部存储上创建自己的应用特定目录”是什么意思?

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

getExternalFilesDir()Context 上的类似方法是替代使用的好解决方案!

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

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

        return file
    }

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

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

Note: This is only work for Android 11.

请求用户访问所有文件:

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

Write code on OnCreate Method:

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")
        }

Declare two functions outside from 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
    }