通過 MediaMetadataRetriever 獲取視頻縮略圖字節數組 byte[],需保存為本地圖片文件。
public static boolean saveImageToFile(byte[] imageData, File destination) {
if (imageData == null || imageData.length == 0) return false;
FileOutputStream fos = null;
try {
// 確保父目錄存在
File parent = destination.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
fos = new FileOutputStream(destination);
fos.write(imageData);
fos.flush(); // 確保寫入磁盤
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if (fos != null) {
try { fos.close(); } catch (IOException ignored) {}
}
}
}
// 使用示例
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(videoUrl);
byte[] thumbnail = mmr.getEmbeddedPicture();
mmr.release();
if (thumbnail != null) {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "thumb_" + System.currentTimeMillis() + ".jpg");
if (saveImageToFile(thumbnail, file)) {
// 可選:發送媒體掃描廣播,讓相冊應用識別
MediaScannerConnection.scanFile(this, new String[]{file.getAbsolutePath()}, null, null);
}
}
| 環節 | 注意事項 |
|---|---|
| 目錄創建 | parent.mkdirs() 避免 FileNotFoundException |
| 資源關閉 | finally 塊關閉流,Java 7+ 可用 try-with-resources |
| 線程 | 耗時寫入**不可在主線程**,放入線程池/RxJava/Coroutines |
| 權限 | Android 10+ 使用 getExternalFilesDir() 或 MediaStore,無需存儲權限 |
| 媒體掃描 | MediaScannerConnection.scanFile 讓圖片立即出現在相冊 |
public static void saveImage(byte[] data, File file) throws IOException {
File parent = file.getParentFile();
if (parent != null) parent.mkdirs();
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(data);
}
}
public void extractAndSaveThumbnail(String videoPath) {
Executors.newSingleThreadExecutor().execute(() -> {
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
try {
mmr.setDataSource(videoPath);
byte[] data = mmr.getEmbeddedPicture();
if (data != null) {
File dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = new File(dir, "video_thumb_" + System.currentTimeMillis() + ".jpg");
saveImageToFile(data, file);
runOnUiThread(() -> {
Toast.makeText(this, "縮略圖已保存: " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
MediaScannerConnection.scanFile(this, new String[]{file.getAbsolutePath()}, null, null);
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
mmr.release();
}
});
}
FileOutputStream.write(byte[]) 是核心 API。注意**異步執行、目錄創建、資源關閉、媒體掃描**,即可可靠保存圖片字節數組到文件系統。