package com.xsh.rpgmvp2pngAndroid;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ImageCopyUtil {
private static final String TAG = "ImageCopyUtil";
/**
* 复制 raw 资源图片到 Pictures 文件夹
* @param context 上下文
* @param rawResId raw 资源 ID
* @param fileName 保存的文件名(带扩展名)
* @return 返回保存的 Uri,失败返回 null
*/
public static Uri copyRawImageToPictures(Context context, int rawResId, String fileName) {
if (fileName == null || fileName.isEmpty()) {
fileName = "image_" + System.currentTimeMillis() + ".jpg";
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10 及以上使用 MediaStore
return copyImageUsingMediaStore(context, rawResId, fileName);
} else {
// Android 10 以下使用传统方法
return copyImageToExternalStorage(context, rawResId, fileName);
}
}
/**
* Android 10 及以上使用 MediaStore 保存
*/
private static Uri copyImageUsingMediaStore(Context context, int rawResId, String fileName) {
ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
// 设置文件信息
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
Uri imageUri = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 插入到 MediaStore
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
if (imageUri == null) {
Log.e(TAG, "Failed to create new MediaStore record.");
return null;
}
// 打开输入流(从 raw 资源)
inputStream = context.getResources().openRawResource(rawResId);
// 打开输出流(保存到 Pictures)
outputStream = resolver.openOutputStream(imageUri);
if (outputStream == null) {
Log.e(TAG, "Failed to open output stream.");
return null;
}
// 复制文件
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
Log.i(TAG, "Image saved successfully: " + fileName);
return imageUri;
} catch (Exception e) {
Log.e(TAG, "Failed to save image", e);
// 如果失败,尝试删除已创建的空文件
if (imageUri != null) {
resolver.delete(imageUri, null, null);
}
return null;
} finally {
try {
if (inputStream != null) inputStream.close();
if (outputStream != null) outputStream.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close streams", e);
}
}
}
/**
* Android 10 以下使用传统方法保存
*/
private static Uri copyImageToExternalStorage(Context context, int rawResId, String fileName) {
// 检查存储权限和可用性
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Log.e(TAG, "External storage not available");
return null;
}
File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
// 确保目录存在
if (!picturesDir.exists()) {
if (!picturesDir.mkdirs()) {
Log.e(TAG, "Failed to create directory");
return null;
}
}
File outputFile = new File(picturesDir, fileName);
InputStream inputStream = null;
FileOutputStream outputStream = null;
try {
// 打开输入流
inputStream = context.getResources().openRawResource(rawResId);
// 打开输出流
outputStream = new FileOutputStream(outputFile);
// 复制文件
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
// 通知系统媒体扫描新文件
Uri uri = Uri.fromFile(outputFile);
context.sendBroadcast(new android.content.Intent(
android.content.Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
Log.i(TAG, "Image saved successfully: " + outputFile.getAbsolutePath());
return uri;
} catch (Exception e) {
Log.e(TAG, "Failed to save image", e);
// 如果保存失败,删除可能已创建的部分文件
if (outputFile.exists()) {
outputFile.delete();
}
return null;
} finally {
try {
if (inputStream != null) inputStream.close();
if (outputStream != null) outputStream.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close streams", e);
}
}
}
/**
* 使用 Bitmap 方式复制(如果需要修改图片质量等)
*/
public static Uri copyRawImageAsBitmap(Context context, int rawResId, String fileName) {
try {
InputStream inputStream = context.getResources().openRawResource(rawResId);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
if (bitmap == null) {
Log.e(TAG, "Failed to decode bitmap from raw resource");
return null;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
return saveBitmapToMediaStore(context, bitmap, fileName);
} else {
return saveBitmapToExternalStorage(context, bitmap, fileName);
}
} catch (Exception e) {
Log.e(TAG, "Failed to copy image as bitmap", e);
return null;
}
}
private static Uri saveBitmapToMediaStore(Context context, Bitmap bitmap, String fileName) {
ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
Uri imageUri = null;
OutputStream outputStream = null;
try {
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
if (imageUri == null) {
Log.e(TAG, "Failed to create new MediaStore record.");
return null;
}
outputStream = resolver.openOutputStream(imageUri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
Log.i(TAG, "Bitmap saved successfully: " + fileName);
return imageUri;
} catch (Exception e) {
Log.e(TAG, "Failed to save bitmap", e);
if (imageUri != null) {
resolver.delete(imageUri, null, null);
}
return null;
} finally {
try {
if (outputStream != null) outputStream.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close output stream", e);
}
bitmap.recycle();
}
}
private static Uri saveBitmapToExternalStorage(Context context, Bitmap bitmap, String fileName) {
File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (!picturesDir.exists()) {
if (!picturesDir.mkdirs()) {
Log.e(TAG, "Failed to create directory");
return null;
}
}
File outputFile = new File(picturesDir, fileName);
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(outputFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
Uri uri = Uri.fromFile(outputFile);
context.sendBroadcast(new android.content.Intent(
android.content.Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
Log.i(TAG, "Bitmap saved successfully: " + outputFile.getAbsolutePath());
return uri;
} catch (Exception e) {
Log.e(TAG, "Failed to save bitmap", e);
if (outputFile.exists()) {
outputFile.delete();
}
return null;
} finally {
try {
if (outputStream != null) outputStream.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close output stream", e);
}
bitmap.recycle();
}
}
}