Android 10 / API 29 Kotlin - 下载视频到图片子目录

Android 10 / API 29 Kotlin - download video to sub directory in pictures

我正在使用此代码下载视频:

val path = "Pictures/Appname"
val fileName = "example.mp4"
    
val request = DownloadManager.Request(Uri.parse(fileURL))
        .setDestinationInExternalPublicDir(path, fileName)

但它只适用于 API < 29

来自 API 29 我只能通过以下方式将其下载到 Pictures 目录:

.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, fileName)

即使子文件夹 Appname 存在于其中。

这里有什么问题?

我也尝试了其他问题的答案,其中 none 有效:

.setDestinationInExternalPublicDir(path, fileName)
.setDestinationInExternalFilesDir(this@DownloadFile, path, fileName)
.setDestinationUri(Uri.fromFile(File(path, fileName)))

我也接受没有 DownloadManager 的解决方案,只要它将视频下载到 Pictures/Appname 就像我在 API >= 29

中看到的其他应用程序一样

这是解决方案:

.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, "/appName/" + fileName)

您是否请求访问要下载到的目录。由于 Android 10 及更高版本默认使用范围存储 (https://developer.android.com/about/versions/10/privacy/changes). The idea behind is that an App can only store data into /Android/data/com.app.package.name/... or it needs to ask the user explicitly. The user then selects the folder where the app is allowed access (https://developer.android.com/training/data-storage#scoped-storage)。这意味着将有一个面向用户的目录选择器。

示例将要求用户select 用于存储文件的文件夹:

val action = Intent.ACTION_CREATE_DOCUMENT
val intent = Intent(action)
        .addCategory(Intent.CATEGORY_OPENABLE)
        .setType("mime/type") // Change this
        .also { it.putExtra(Intent.EXTRA_TITLE, filename) } // Optional: proposed file name
startActivityForResult(intent, YOUR_REQUEST_CODE)

用户select之后的文件夹:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (resultCode == Activity.RESULT_OK) when (requestCode) {
        YOUR_REQUEST_CODE -> {
            val uri = data?.data
            // here you have the permission to write
            // into the file represented by the uri
        }
    }
}

下载管理器不需要存储到外部存储的权限。

创建子目录的答案在评论中。