Android Kotlin开发:无法将Download文件夹音频复制到应用内部存储
解决Android中无法找到Download目录下WAV文件的问题
问题核心原因
你遇到的moveToFirst()返回false的主要问题有两点:
- 手动复制到模拟器Download目录的文件未被系统媒体扫描器索引,导致MediaStore中没有该文件的记录
- 你使用
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




