家有两猫~ 2026-01-30 11:50 采纳率: 0%
浏览 3

uri转文件绝对路径问题

已知:api34
问题:无法获取uri的绝对路径
断点uri:content://com.android.providers.media.documents/document/document%3A1000131087
代码:


```kotlin
 fun uriToFile(context: Context, uri: Uri): File? {
            var fileDescriptor: ParcelFileDescriptor? = null
            return try {
                fileDescriptor = context.contentResolver.openFileDescriptor(uri, "r") ?: return null

                // 根据URI类型获取实际的文件路径
                when (uri.scheme) {
                    "file" -> File(uri.path ?: return null)
                    "content" -> {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                            // Android 10+ 使用MediaStore API
                            val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
                            val cursor =
                                context.contentResolver.query(uri, projection, null, null, null)
                            cursor?.use {
                                if (cursor.moveToFirst()) {
                                    val columnIndex =
                                        cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)
                                    if (columnIndex >= 0) {
                                        val path = cursor.getString(columnIndex)
                                        if (!path.isNullOrEmpty()) File(path) else null
                                    } else {
                                        null
                                    }
                                } else {
                                    null
                                }
                            }
                        } else {
                            // Android 10以下版本
                            val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
                            val cursor =
                                context.contentResolver.query(uri, projection, null, null, null)
                            cursor?.use {
                                if (cursor.moveToFirst()) {
                                    val columnIndex =
                                        cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA)
                                    if (columnIndex >= 0) {
                                        val path = cursor.getString(columnIndex)
                                        if (!path.isNullOrEmpty()) File(path) else null
                                    } else {
                                        null
                                    }
                                } else {
                                    null
                                }
                            }
                        }
                    }

                    else -> null
                }
            } catch (e: Exception) {
                e.printStackTrace()
                null
            } finally {
                try {
                    fileDescriptor?.close()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }

```

  • 写回答

3条回答 默认 最新

  • 紫雾凌寒 新星创作者: 人工智能技术领域 2026-01-30 11:50
    关注

    让 “紫雾凌寒” 来帮你回答,本回答结合 DeepSeek

    如果还有问题,请评论或点击头像私信,如果有帮助到您, 请关注、采纳、点赞

    1. 关键点分析
      - 核心问题是在API 34环境下无法获取Uri的绝对路径。这可能是由于Android系统权限管理和文件访问机制在高版本中的变化导致的。
    2. 解决方案
      - 在API 34及以上版本,content://类型的Uri不能直接获取绝对路径。需要使用ContentResolver结合openFileDescriptor来获取文件描述符,再通过文件描述符获取文件路径。
      - 示例代码如下:
    fun uriToFile(context: Context, uri: Uri): File? {
        val contentResolver = context.contentResolver
        val fileDescriptor = contentResolver.openFileDescriptor(uri, "r")
        if (fileDescriptor == null) {
            return null
        }
        val file = FileDescriptorAutoCloseable(fileDescriptor).let {
            File(it.fileDescriptor)
        }
        return file
    }
    
    class FileDescriptorAutoCloseable(private val fileDescriptor: FileDescriptor) : AutoCloseable {
        override fun close() {
            fileDescriptor.close()
        }
    }
    
    1. 方案优缺点
      - 优点
      • 这种方式能够适应Android系统在高版本中的权限和文件访问机制变化,确保在API 34及以上版本也能正确获取文件路径。
      • 缺点
      • 代码相对复杂一些,需要额外处理文件描述符的关闭操作,通过自定义FileDescriptorAutoCloseable类来辅助。
    2. 总结
      - 在API 34及以上版本获取Uri对应的文件绝对路径时,不能再像低版本那样简单处理。需要利用ContentResolveropenFileDescriptor方法来获取文件描述符,进而得到文件路径,同时要注意文件描述符的正确关闭。

    请注意,上述代码中的FileDescriptorAutoCloseable类是为了确保文件描述符能在使用后正确关闭,在实际使用中可以根据具体需求进行调整和优化。

    希望以上解答对您有所帮助。如果您有任何疑问,欢迎在评论区提出。

    评论

报告相同问题?

问题事件

  • 修改了问题 1月30日
  • 创建了问题 1月30日