僅將 Bitmap 寫入檔案 不會自動出現在相冊,必須發送 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 廣播通知 MediaStore 掃描。Android 7.0+ (API 24) 更需用 FileProvider 獲取 content:// URI,否則會拋 FileUriExposedException。
fun saveToGallery(context: Context, bitmap: Bitmap, fileName: String = "IMG_${System.currentTimeMillis()}.jpg") {
val dir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) ?: return
val file = File(dir, fileName)
FileOutputStream(file).use { bitmap.compress(Bitmap.CompressFormat.JPEG, 90, it) }
// Android 7.0+ 必須用 FileProvider
val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file)
} else {
Uri.fromFile(file)
}
val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).apply {
data = uri
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.sendBroadcast(intent)
Toast.makeText(context, "已保存至相冊", Toast.LENGTH_SHORT).show()
}
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
res/xml/file_paths.xml:
<paths>
<external-files-path name="pictures" path="Pictures/" />
</paths>
Uri.fromFile(file) 在 Android 7+ 會崩潰。FLAG_GRANT_READ_URI_PERMISSION 導致無權限讀取。getExternalStoragePublicDirectory 在 Android 10+ (API 29) 需申請 READ_EXTERNAL_STORAGE 權限;建議改用 getExternalFilesDir 無需權限且隨應用卸載自動清理。遵循上述流程,圖片即可即時出現在系統相冊與 Google Photos 等應用中。