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

如何捕获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卡目录可能受限,建议使用MediaStore API来查询音乐文件,避免权限问题。
  • 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:20:04