開發相冊選圖功能時,常遇到 MediaStore.Images.Thumbnails 查無資料的問題。根因在於:Android 系統只有在使用者開啟系統相冊瀏覽過圖片後,才會在背景生成縮略圖快取。若用戶從未打開相冊,縮略圖表即為空。
Thumbnails.EXTERNAL_CONTENT_URI 返回空游標Cursor c = getContentResolver().query(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
null, null, null, null
);
while (c.moveToNext()) {
Map<String, Object> map = new HashMap<>();
map.put("imageId", c.getLong(c.getColumnIndex(Thumbnails.IMAGE_ID)));
map.put("filepath", c.getString(c.getColumnIndex(Thumbnails.DATA)));
allValues.add(map);
}
此處強依賴系統預生成的縮略圖,無快取則查無資料。
img.setImageURI(Uri.fromFile(new File(map.get("filepath").toString())));
直接載入原圖路徑,若為高解析度大圖極易導致 OOM。
放棄依賴系統快取,改用 ThumbnailUtils 或 BitmapFactory 就地生成:
// 方案一:ThumbnailUtils (API 8+)
Bitmap thumb = ThumbnailUtils.extractThumbnail(
BitmapFactory.decodeFile(originalPath), 200, 200
);
// 方案二:inSampleSize 縮放載入 (記憶體友善)
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(originalPath, opts);
opts.inSampleSize = calculateInSampleSize(opts, 200, 200);
opts.inJustDecodeBounds = false;
Bitmap thumb = BitmapFactory.decodeFile(originalPath, opts);
READ_EXTERNAL_STORAGE。ActivityResultContracts 或第三方庫(如 Matisse、PhotoPicker)。// 替換原有 Cursor 查詢邏輯
String[] projection = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, null, null, MediaStore.Images.Media.DATE_TAKEN + " DESC"
);
// 遍歷 cursor 獲取原圖路徑,交由圖片載入庫異步處理縮略圖顯示
總結:不要依賴 MediaStore.Thumbnails,改為查詢原圖資訊並由成熟圖片庫負責縮略圖生成與快取,兼容性與穩定性大幅提升。