You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Android Kotlin开发:无法将Download文件夹音频复制到应用内部存储

解决Android中无法找到Download目录下WAV文件的问题

问题核心原因

你遇到的moveToFirst()返回false的主要问题有两点:

  1. 手动复制到模拟器Download目录的文件未被系统媒体扫描器索引,导致MediaStore中没有该文件的记录
  2. 你使用MediaStore.Audio.Media查询,但Download目录下的文件可能未被归类到音频媒体库,应该针对Download目录做专门查询

具体解决方案

1. 触发媒体扫描(确保文件被系统索引)

手动复制文件后,系统不会自动触发媒体扫描,可通过以下方式让系统识别文件:

  • 直接重启模拟器
  • 调用媒体扫描API主动触发:
val targetFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
    .resolve("original.wav")
MediaScannerConnection.scanFile(
    context,
    arrayOf(targetFile.absolutePath),
    arrayOf("audio/wav"),
    null
)

2. 修正MediaStore查询代码

针对Download目录的文件,改用MediaStore.Downloads进行查询,修改后的代码如下:

val sourceUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL)

val projection = arrayOf(MediaStore.Downloads._ID)
val selection = "${MediaStore.Downloads.DISPLAY_NAME} = ?"
val selectionArgs = arrayOf("original.wav")

val cursor = contentResolver.query(sourceUri, projection, selection, selectionArgs, null)
cursor?.use {
    if (it.moveToFirst()) {
        val id = it.getLong(it.getColumnIndexOrThrow(MediaStore.Downloads._ID))
        val fileUri = Uri.withAppendedPath(sourceUri, id.toString())

        contentResolver.openInputStream(fileUri)?.use { inputStream ->
            // destFile为应用内部存储路径,例如context.filesDir.resolve("original_copy.wav")
            FileOutputStream(destFile).use { outputStream ->
                inputStream.copyTo(outputStream)
            }
        }
    } else {
        Log.e("FileCopy", "未找到目标文件original.wav,请确认媒体扫描已完成")
    }
}

3. 确保完成动态权限申请

Android 6.0及以上版本,仅在Manifest声明权限不够,还需运行时申请:

// 在Activity中添加权限申请逻辑
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
    != PackageManager.PERMISSION_GRANTED
) {
    ActivityCompat.requestPermissions(
        this,
        arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
        1001
    )
}

注意:Android 13+版本,针对音频文件可申请READ_MEDIA_AUDIO权限,若需访问Download目录所有文件,仍可使用READ_EXTERNAL_STORAGE

4. 替代方案:直接访问文件路径(仅适用于Android 9及以下,或持有特殊权限)

若不想依赖MediaStore,可直接访问Download目录文件,但Android 10+默认禁止该方式,除非申请MANAGE_EXTERNAL_STORAGE权限(不推荐常规应用使用):

val sourceFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
    .resolve("original.wav")
val destFile = filesDir.resolve("original_copy.wav")

if (sourceFile.exists()) {
    sourceFile.copyTo(destFile, overwrite = true)
} else {
    Log.e("FileCopy", "源文件不存在")
}

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

火山引擎 最新活动