如何捕获SD卡及音乐等文件夹中的所有歌曲?附MP3查找代码
如何捕获SD卡根目录及子文件夹中的所有歌曲?
你的当前代码只遍历了/storage/目录下的直接文件,没有深入到子文件夹中,所以会漏掉那些存放在子目录里的音乐文件。要解决这个问题,我们需要实现递归遍历所有层级目录的逻辑,同时还要注意Android的权限限制。
解决方案:递归遍历所有目录
我们可以写一个递归方法,遍历指定目录下的所有文件和子目录,遇到目录就继续深入,遇到符合条件的音乐文件就收集起来。
修改后的完整代码示例
import java.io.File; import java.util.ArrayList; import java.util.HashMap; public class MusicScanner { // 存储所有找到的歌曲 private ArrayList<HashMap<String, String>> songList = new ArrayList<>(); // 定义需要过滤的音乐扩展名(可根据需求扩展) private final String[] MUSIC_EXTENSIONS = {".mp3", ".flac", ".wav", ".m4a"}; public ArrayList<HashMap<String, String>> scanAllMusic(String rootPath) { File rootDir = new File(rootPath); if (rootDir.exists() && rootDir.isDirectory()) { traverseDirectory(rootDir); } return songList; } // 递归遍历目录的核心方法 private void traverseDirectory(File dir) { File[] files = dir.listFiles(); if (files == null) return; // 防止目录不可访问的情况 for (File file : files) { if (file.isDirectory()) { // 如果是子目录,递归遍历 traverseDirectory(file); } else { // 如果是文件,检查扩展名是否符合音乐格式 if (isMusicFile(file)) { HashMap<String, String> song = new HashMap<>(); String fileName = file.getName(); // 去掉扩展名作为标题 song.put("title", fileName.substring(0, fileName.lastIndexOf("."))); song.put("path", file.getAbsolutePath()); // 额外存储文件路径,方便后续使用 songList.add(song); } } } } // 判断是否为音乐文件 private boolean isMusicFile(File file) { String fileName = file.getName().toLowerCase(); for (String ext : MUSIC_EXTENSIONS) { if (fileName.endsWith(ext)) { return true; } } return false; } // 使用示例 public static void main(String[] args) { // 注意:Android中SD卡路径可能因设备而异,比如/storage/emulated/0是内置存储,/storage/xxxx-xxxx是外置SD卡 String sdCardPath = "/storage/"; MusicScanner scanner = new MusicScanner(); ArrayList<HashMap<String, String>> allSongs = scanner.scanAllMusic(sdCardPath); // 打印测试 for (HashMap<String, String> song : allSongs) { System.out.println("歌曲标题:" + song.get("title") + ",路径:" + song.get("path")); } } }
关键注意事项
- Android权限问题:
- Android 6.0(API 23)及以上,需要动态申请
READ_EXTERNAL_STORAGE权限; - Android 10(API 29)及以上,启用了分区存储,直接访问SD卡目录可能受限,建议使用
MediaStoreAPI来查询音乐文件,避免权限问题。
- Android 6.0(API 23)及以上,需要动态申请
- SD卡路径正确性:不同设备的外置SD卡路径可能不同,比如
/storage/XXXX-XXXX(XXXX是随机字符),可以通过Environment.getExternalStorageDirectory()获取内置存储路径,外置SD卡需要通过遍历/storage/下的目录来确认。 - 性能优化:如果SD卡文件很多,递归遍历可能耗时,建议在子线程中执行扫描操作,避免阻塞主线程。
针对Android 10+的替代方案(MediaStore)
如果你的应用目标是Android 10及以上,推荐使用MediaStore来查询所有音乐文件,这样更符合系统权限规范:
import android.content.ContentResolver; import android.database.Cursor; import android.provider.MediaStore; import android.content.Context; import java.util.ArrayList; import java.util.HashMap; public class MediaStoreMusicScanner { public ArrayList<HashMap<String, String>> getMusicFromMediaStore(Context context) { ArrayList<HashMap<String, String>> songList = new ArrayList<>(); ContentResolver resolver = context.getContentResolver(); // 查询媒体库中的音乐文件 Cursor cursor = resolver.query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DATA}, null, null, null ); if (cursor != null) { while (cursor.moveToNext()) { HashMap<String, String> song = new HashMap<>(); song.put("title", cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE))); song.put("path", cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA))); songList.add(song); } cursor.close(); } return songList; } }
这个方法不需要直接访问SD卡目录,而是通过系统媒体库获取所有音乐文件,兼容性更好。
内容的提问来源于stack exchange,提问作者Tara
相关产品推荐
相关产品推荐

