You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中通过隐式Intent打开文件管理器并获取选中文件路径

嗨,我来帮你搞定这个需求!在Kotlin里用隐式Intent打开文件管理器并获取选中文件的路径其实不难,分几个关键步骤来就行,我给你一步步拆解:

第一步:注册文件选择回调(替代废弃的startActivityForResult)

从AndroidX开始,startActivityForResult已经被废弃了,现在我们用registerForActivityResult来处理文件选择后的回调。在你的Activity或Fragment里先注册一个启动器:

private val pickFileLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
    uri?.let { selectedUri ->
        // 这里就是选中文件后的处理逻辑,后面说怎么转路径
        handleSelectedFile(selectedUri)
    } ?: run {
        // 用户取消了选择
        println("用户取消了文件选择")
    }
}

如果需要支持多选文件,把ActivityResultContracts.GetContent()换成ActivityResultContracts.GetMultipleContents(),回调参数就变成List<Uri>?啦。

第二步:触发打开文件管理器

写一个简单的函数,调用上面的启动器,传入你想要允许选择的文件类型(比如"image/*"只选图片,"*/*"允许所有类型):

fun openFileManager() {
    pickFileLauncher.launch("*/*")
}

你可以在按钮点击事件里调用这个函数,比如:

btnOpenFile.setOnClickListener {
    openFileManager()
}
第三步:把Uri转换成真实文件路径

文件管理器返回的是Uri,不是直接的文件路径,我们需要把它转成真实路径。注意:Android 10(API 29)及以上的Scoped Storage限制了直接访问文件路径,所以这个方法对某些文件可能返回null,后面会说替代方案。

先写个转换函数:

private fun getRealPathFromUri(uri: Uri): String? {
    var filePath: String? = null
    val scheme = uri.scheme

    when (scheme) {
        "content" -> {
            // 从ContentResolver查询媒体库中的路径
            val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
            contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
                if (cursor.moveToFirst()) {
                    val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA)
                    filePath = cursor.getString(columnIndex)
                }
            }
        }
        "file" -> {
            // 直接获取file://类型Uri的路径
            filePath = uri.path
        }
    }
    return filePath
}

然后在之前的回调里调用它:

private fun handleSelectedFile(uri: Uri) {
    val filePath = getRealPathFromUri(uri)
    filePath?.let {
        println("选中的文件路径:$it")
        // 拿到路径后就可以做你需要的操作啦,比如上传、读取内容等
    } ?: run {
        // 无法获取路径的情况(比如Scoped Storage下的文件)
        // 建议用ContentResolver直接操作文件,而不是依赖路径
        readFileViaContentResolver(uri)
    }
}
第四步:Scoped Storage下的替代方案(Android 10+)

如果你的目标版本是Android 10及以上,很多文件可能无法拿到真实路径,这时候直接用ContentResolver操作文件是更合规的方式,比如读取文件内容:

private fun readFileViaContentResolver(uri: Uri) {
    contentResolver.openInputStream(uri)?.use { inputStream ->
        val fileContent = inputStream.bufferedReader().readText()
        println("文件内容:$fileContent")
        // 这里可以处理文件内容,比如上传的话就把inputStream传给上传接口
    } ?: run {
        println("无法打开文件输入流,权限不足或文件不存在")
    }
}
注意事项
  • 权限:如果你的App需要访问外部存储,在AndroidManifest.xml里添加权限(Android 10+不需要READ_EXTERNAL_STORAGE来访问媒体文件,但如果是其他文件可能需要):
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
    
  • 文件类型:launch()方法传入的type可以更具体,比如"application/pdf"只允许选PDF,"audio/*"只选音频文件,根据你的需求调整。

内容的提问来源于stack exchange,提问作者Reza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 12:37:48