简体   繁体   English

如何获取 Android 10 及更高版本的路径 /storage/emulated/0/Download/file_name.mime_type

[英]How to get path /storage/emulated/0/Download/file_name.mime_type for Android 10 and above

I am saving a file inside the Downloads directory of the device (Android 11) to be viewed later by my app.我正在设备(Android 11)Downloads目录中保存一个文件,以便我的应用稍后查看。 I'm allowing multiple file types like pdf , word etc. I was able to save the file like this: (I got this code sample from here )我允许使用多种文件类型,如pdfword等。我能够像这样保存文件:(我从这里得到了这个代码示例)

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

But when I tried to retrieve the file, I tried with the following ways that did not work:但是当我试图检索文件时,我尝试了以下不起作用的方法:

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)

This approach threw an exception:这种方法引发了异常:

java.lang.IllegalArgumentException: Failed to find configured root that contains /external/downloads/78 java.lang.IllegalArgumentException:找不到包含 /external/downloads/78 的已配置根目录

I got this ID (here 78) from the query and cursor from ContentResolver.query() and I hoped it to return the Uri from which I could get the File.我从query中得到了这个ID (这里是 78),从ContentResolver.query()中得到了cursor ,我希望它返回我可以从中获取文件的Uri

The second approach was this:第二种方法是这样的:

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

I used external as the directory based on this answer, but this approach also threw the same exception我根据这个答案使用external作为目录,但是这种方法也抛出了同样的异常

java.lang.IllegalArgumentException: Failed to find configured root that contains /external/downloads/78 java.lang.IllegalArgumentException:找不到包含 /external/downloads/78 的已配置根目录

At the end what ended up working was hardcoding something like this after I used a file explorer app to view the exact directory path:在我使用文件资源管理器应用程序查看确切的目录路径后,最终的工作是硬编码这样的东西:

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

So my question is, how do I get the value of this path dynamically, and is this path the same for all devices that can be used like this way?所以我的问题是,我如何动态地获取这条路径的值,这条路径对于所有可以这样使用的设备来说都是一样的吗?

EDIT: I also wanted to know if I am using the filename and it's extension to view the file, then if user downloads another file with same name then how do I make sure that correct file is opened?编辑:我还想知道我是否使用filename及其extension来查看文件,那么如果用户下载另一个具有相同名称的文件,那么我如何确保打开正确的文件? (even if i make a separate directory for my app inside Download , user could still download the same file twice that has a name like storage/emulated/0/Download/myDir/file(2).extension ) (即使我在Download中为我的应用程序创建了一个单独的目录,用户仍然可以下载同一个文件两次,其名称类似于storage/emulated/0/Download/myDir/file(2).extension

Try with the following code it will help you.试试下面的代码,它会帮助你。

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

You can use您可以使用

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

/storage/emulated/0/Download/12d82c65-00a5-4c0a-85bc-238c28005c33.bin /存储/模拟/0/下载/12d82c65-00a5-4c0a-85bc-238c28005c33.bin

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Android 10 及更高版本中获取共享存储文件夹的文件路径? - How to get file path of shared storage folder in Android 10 and above? 如何在Android 6上获得模拟的存储路径? - How to get emulated storage path on Android 6? Android设备上的file:/// storage / emulated / 0路径 - file:///storage/emulated/0 path on android device 从 data.getData() 类型的 URI 获取真实路径 file:///storage/emulated/0/LenovoReaper/did - get real path from URI of type data.getData() file:///storage/emulated/0/LenovoReaper/did 如何进入存储/模拟/0 - How to get to storage/emulated/0 如何在android中获取mime文件类型 - How to get mime file type in android FileSystemException:无法打开文件,路径 = '目录:'/storage/emulated/0/Android/data/ - FileSystemException: Cannot open file, path = 'Directory: '/storage/emulated/0/Android/data/ 如何在Android的下载目录中获取每个文件的完整路径和名称 - How to get complete path and name of each file in Download directory in Android 如何将非媒体文件从 /storage/emulated/0/Download 移动到 getExternalFilesDir() - How to move a non media file from /storage/emulated/0/Download to getExternalFilesDir() 将文件保存在/ Download下,其名称为/ storage / emulated / 0 / Download。 有时文件无法访问 - Saving file under /Download gives name /storage/emulated/0/Download. Sometimes the file is not accessable
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM