核心遞迴函式
public static void collectImages(File dir, List result) {
if (!dir.exists() || !dir.isDirectory()) return;
File[] files = dir.listFiles();
if (files == null) return; // 權限不足或 I/O 錯誤
for (File f : files) {
if (f.isDirectory()) {
collectImages(f, result); // 遞迴進入子目錄
} else if (isImageFile(f)) {
result.add(f);
}
}
}
private static boolean isImageFile(File f) {
String name = f.getName().toLowerCase();
return name.endsWith(".jpg") || name.endsWith(".jpeg") ||
name.endsWith(".png") || name.endsWith(".bmp") ||
name.endsWith(".webp") || name.endsWith(".gif");
}
呼叫範例
File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
// 或指定目錄:new File("/sdcard/MyApp/Images")
List allImages = new ArrayList<>();
collectImages(root, allImages);
// allImages 即為所有圖片檔案,可進一步按父目錄分組
權限與效能注意
- Android 10+ (API 29+) **分區存儲**限制:需在 Manifest 宣告
android:requestLegacyExternalStorage="true" (API 29) 或改用 MediaStore API 查詢圖片,避免直接訪問檔案系統。
- 大量檔案遞迴可能導致 **StackOverflowError** 或 ANR,建議在**背景執行緒** (RxJava/Coroutines/ThreadPool) 執行,並分批回調更新 UI。
- 使用
File.listFiles() 可能返回 null(權限拒絕),必須判空。