【问题标题】:How to get path /storage/emulated/0/Download/file_name.mime_type for Android 10 and above如何为 Android 10 及更高版本获取路径 /storage/emulated/0/Download/file_name.mime_type
【发布时间】:2021-06-28 02:33:35
【问题描述】:

我正在设备(Android 11)Downloads 目录中保存一个文件,以供我的应用稍后查看。我允许多种文件类型,如pdfword 等。我可以像这样保存文件:(我从here 得到这个代码示例)

@TargetApi(29)
private suspend fun downloadQ(
    url: String,
    filename: String,
    mimeType: String
) =
    withContext(Dispatchers.IO) {
        val response = ok.newCall(Request.Builder().url(url).build()).execute()

        if (response.isSuccessful) {
            val values = ContentValues().apply {
                put(MediaStore.Downloads.DISPLAY_NAME, filename)
                put(MediaStore.Downloads.MIME_TYPE, mimeType)
                put(MediaStore.Downloads.IS_PENDING, 1)
            }

            val resolver = context.contentResolver
            val uri =
                resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)

            uri?.let {
                resolver.openOutputStream(uri)?.use { outputStream ->
                    val sink = outputStream.sink().buffer()

                    response.body()?.source()?.let { sink.writeAll(it) }
                    sink.close()
                }

                values.clear()
                values.put(MediaStore.Downloads.IS_PENDING, 0)
                resolver.update(uri, values, null, null)
            } ?: throw RuntimeException("MediaStore failed for some reason")
        } else {
            throw RuntimeException("OkHttp failed for some reason")
        }
    }

但是当我尝试检索文件时,我尝试了以下不起作用的方法:

val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID)
val id = cursor.getLong(idColumn)
Log.d("uri id ","$id")
val contentUri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI,id)

这种方法引发了异常:

java.lang.IllegalArgumentException: 未能找到包含 /external/downloads/78 的已配置根

我从querycursorContentResolver.query() 得到了这个ID(这里是78),我希望它返回Uri,我可以从中获取文件。

第二种方法是这样的:

val uri = MediaStore.Downloads.getContentUri("external",id)
uri.path?.let { filePath ->
Log.d("uri path ",filePath)
val file = File(filePath)
} ?: Log.d("uri path ","null")

我使用external作为基于this答案的目录,但是这种方法也抛出了同样的异常

java.lang.IllegalArgumentException: 未能找到包含 /external/downloads/78 的已配置根

在我使用文件资源管理器应用程序查看确切的目录路径后,最终的工作是硬编码这样的东西:

val file = File("storage/emulated/0/Download/$name.$extension")

所以我的问题是,我如何动态地获取这条路径的值,这条路径对于所有可以像这种方式使用的设备来说都是一样的吗?

编辑:我还想知道我是否使用filenameextension 来查看文件,那么如果用户下载另一个同名文件,那么我如何确保打开了正确的文件? (即使我在Download 中为我的应用程序创建了一个单独的目录,用户仍然可以两次下载名称为storage/emulated/0/Download/myDir/file(2).extension 的同一个文件)

【问题讨论】:

    标签: android kotlin android-fileprovider android-storage


    【解决方案1】:

    试试下面的代码,它会对你有所帮助。

    private fun readFile(){
    val FILENAME = "user_details.txt"
    val dir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                .toString() + "/" + "folderName"
        )
    } else {
        File(
            Environment.getExternalStorageDirectory()
                .toString() + "/${Environment.DIRECTORY_DOWNLOADS}/" + "folderName"
        )
    }
    dir.apply {
       if(this.exists()) File(this, FILENAME).apply {
           FileInputStream(this).apply {
               val stringBuffer = StringBuffer()
               var i: Int
               while (this.read().also { i = it } != -1) {
                   stringBuffer.append(i.toChar())
               }
               close()
           }
       }
      }
    }
    

    【讨论】:

    • 此解决方案确实解决了硬编码路径的问题,但是当我使用我提到的代码保存文件时,没有任何方法向我显示已弃用的警告,但 Environment.getExternalStorageDirectory() 显示为已弃用.如果我尝试使用context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) 读取,则应用程序崩溃,因为它尝试从Android/data/.../files/Download/ 之类的路径读取,但文件存储在storage/emulated/0/Download/,如cmets 中所述:stackoverflow.com/q/62745567/13343177。请看那条评论:)
    【解决方案2】:

    你可以使用

    {Environment.DIRECTORY_DOWNLOADS} + "/folderName/file_name.mime_type"

    【讨论】:

      【解决方案3】:

      /storage/emulated/0/Download/12d82c65-00a5-4c0a-85bc-238c28005c33.bin

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-01
      • 2019-09-17
      • 1970-01-01
      • 2021-01-09
      相关资源
      最近更新 更多