20251208_212749_544重新调整背景资源图片存储流程。

This commit is contained in:
2025-12-08 21:28:49 +08:00
parent 489b72b582
commit 016b3b5e48
3 changed files with 170 additions and 40 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sun Dec 07 15:19:14 HKT 2025
#Mon Dec 08 12:53:13 GMT 2025
stageCount=2
libraryProject=
baseVersion=15.12
publishVersion=15.12.1
buildCount=0
buildCount=5
baseBetaVersion=15.12.2

View File

@@ -35,6 +35,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.powerbell.utils.UriUtil;
import cc.winboll.studio.powerbell.utils.FileUtils;
public class BackgroundSettingsActivity extends WinBoLLActivity implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener {
@@ -50,6 +52,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
private BackgroundView mBackgroundView;
private File mfTakePhoto;
volatile boolean isCommitSettings = false;
volatile boolean isPreviewBackgroundChanged = false;
@Override
public Activity getActivity() {
@@ -68,34 +71,40 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
mBackgroundView = (BackgroundView) findViewById(R.id.background_view);
mBgSourceUtils = BackgroundSourceUtils.getInstance(this);
mBgSourceUtils.loadSettings();
mPermissionUtils = PermissionUtils.getInstance();
File tempDir = new File(App.getTempDirPath());
if (!tempDir.exists()) {
tempDir.mkdirs();
}
mfTakePhoto = new File(tempDir, "TakePhoto.jpg");
File selectTempDir = new File(mBgSourceUtils.getBackgroundSourceDirPath(), "SelectTemp");
if (!selectTempDir.exists()) {
selectTempDir.mkdirs();
LogUtils.d(TAG, "【选图初始化】选图临时目录创建完成:" + selectTempDir.getAbsolutePath());
}
// File tempDir = new File(App.getTempDirPath());
// if (!tempDir.exists()) {
// tempDir.mkdirs();
// }
// mfTakePhoto = new File(tempDir, "TakePhoto.jpg");
//
// File selectTempDir = new File(mBgSourceUtils.getBackgroundSourceDirPath(), "SelectTemp");
// if (!selectTempDir.exists()) {
// selectTempDir.mkdirs();
// LogUtils.d(TAG, "【选图初始化】选图临时目录创建完成:" + selectTempDir.getAbsolutePath());
// }
initToolbar();
initClickListeners();
initBackgroundViewByPreviewBean();
handleShareIntent();
if (!handleShareIntent()) {
mBgSourceUtils.setCurrentSourceToPreview();
}
Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath()));
fix it>> mBgSourceUtils.createCropFileProviderBackgroundBean(uriSelectedImage);
LogUtils.d(TAG, "【初始化】BackgroundSettingsActivity 初始化完成");
}
private void initBackgroundViewByPreviewBean() {
LogUtils.d(TAG, "【Bean初始化】正式Bean → 预览Bean");
mBgSourceUtils.setCurrentSourceToPreview();
doubleRefreshPreview();
LogUtils.d(TAG, "【Bean初始化】预览Bean初始化完成");
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
doubleRefreshPreview();
}
private void initToolbar() {
mToolbar = findViewById(R.id.toolbar);
@@ -123,7 +132,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
findViewById(R.id.activitybackgroundpictureAButton8).setOnClickListener(onCleanPixelClickListener);
}
private void handleShareIntent() {
private boolean handleShareIntent() {
Intent intent = getIntent();
if (intent != null) {
String action = intent.getAction();
@@ -132,8 +141,10 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
BackgroundPicturePreviewDialog dlg = new BackgroundPicturePreviewDialog(this);
dlg.show();
LogUtils.d(TAG, "【分享处理】收到分享图片意图");
return true;
}
}
return false;
}
boolean isImageType(String lowerMimeType) {
@@ -478,11 +489,9 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
LogUtils.d(TAG, "【选图权限】已添加持久化权限");
}
mBgSourceUtils.createCropFileProviderBackgroundBean(selectedImage);
LogUtils.d(TAG, "【选图同步】路径绑定完成");
// 选图后启动固定比例裁剪(调用工具类)
mBgSourceUtils.loadSettings();
putUriFileToPreviewSource(selectedImage);
ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
mBgSourceUtils.getPreviewBackgroundBean(),
mBackgroundView.getWidth(),
@@ -492,6 +501,17 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
);
}
boolean putUriFileToPreviewSource(Uri srcUriFile) {
File srcFile = new File(UriUtil.getFilePathFromUri(this, srcUriFile));
return putUriFileToPreviewSource(srcFile);
}
boolean putUriFileToPreviewSource(File srcFile) {
mBgSourceUtils.loadSettings();
File dstFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath());
return FileUtils.copyFile(srcFile, dstFile);
}
private void handleCropImageResult(int requestCode, int resultCode, Intent data) {
LogUtils.d(TAG, "handleCropImageResult: 处理裁剪结果");
File cropTempFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundScaledCompressFilePath());
@@ -501,6 +521,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
boolean isCropSuccess = (resultCode == RESULT_OK) && isFileExist && isFileReadable && fileSize > 100;
if (isCropSuccess) {
isPreviewBackgroundChanged = true;
LogUtils.d(TAG, "handleCropImageResult: 裁剪成功");
BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
previewBean.setIsUseBackgroundFile(true);
@@ -697,9 +718,10 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
private void handleOperationCancelOrFail() {
initBackgroundViewByPreviewBean();
mBgSourceUtils.setCurrentSourceToPreview();
LogUtils.d(TAG, "【操作回调】取消或失败");
ToastUtils.show("操作已取消");
ToastUtils.show("操作回调】取消或失败");
doubleRefreshPreview();
}
@@ -753,20 +775,27 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
if (isCommitSettings) {
super.finish();
} else {
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
mBgSourceUtils.commitPreviewSourceToCurrent();
isCommitSettings = true;
finish();
}
// 如果预览背景改变过就提示是否更换背景
if (isPreviewBackgroundChanged) {
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
mBgSourceUtils.commitPreviewSourceToCurrent();
isCommitSettings = true;
finish();
}
@Override
public void onNo() {
isCommitSettings = true;
finish();
}
});
@Override
public void onNo() {
isCommitSettings = true;
finish();
}
});
} else {
// 如果预览背景未改变就直接退出
isCommitSettings = true;
finish();
}
}
}
}

View File

@@ -0,0 +1,101 @@
package cc.winboll.studio.powerbell.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;
import cc.winboll.studio.libappbase.LogUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/08 21:11
* @Describe 把 R.drawable 中的图片保存为 File 对象的工具类
* 适配 PowerBell 项目支持指定保存路径、自动创建目录、处理PNG图片压缩
*/
public class DrawableToFileUtils {
private static final String TAG = "DrawableToFileUtils";
/**
* 核心方法:将 R.drawable 图片保存为 File 对象
* @param context 上下文(用于获取 Resources
* @param drawableResId 图片资源ID如 R.drawable.ic_test_png
* @param fileName 保存的文件名(需带 .png 后缀,如 "test_drawable.png"
* @return 保存成功返回 File 对象,失败返回 null
*/
public static File saveDrawableToFile(Context context, int drawableResId, String filePath) {
// 1. 校验参数(避免空指针/无效参数)
if (context == null || drawableResId == 0 || filePath == null || filePath.isEmpty()) {
LogUtils.e(TAG, "【保存失败】参数无效context为空/资源ID为0/文件名为空)");
return null;
}
if (!filePath.endsWith(".png")) {
filePath += ".png"; // 强制添加 .png 后缀,确保图片格式正确
LogUtils.d(TAG, "【格式适配】自动添加.png后缀最终文件名" + filePath);
}
// 3. 构建目标 File 对象(最终保存的文件路径)
File targetFile = new File(filePath);
LogUtils.d(TAG, "【保存路径】目标文件路径:" + targetFile.getAbsolutePath());
// 4. 读取 drawable 资源为 Bitmap处理高清图/缩放问题)
Bitmap bitmap = null;
try {
// 读取 drawable 资源(适配不同分辨率的图片,避免变形)
bitmap = BitmapFactory.decodeResource(context.getResources(), drawableResId);
if (bitmap == null) {
LogUtils.e(TAG, "【读取失败】无法读取drawable资源资源ID" + drawableResId + "");
return null;
}
LogUtils.d(TAG, "【读取成功】drawable资源转Bitmap成功" + bitmap.getWidth() + ",高:" + bitmap.getHeight() + "");
// 5. 将 Bitmap 写入 FilePNG格式无损保存
FileOutputStream fos = new FileOutputStream(targetFile);
// 压缩参数PNG格式质量100无损写入输出流
boolean isSaved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush(); // 刷新输出流
fos.close(); // 关闭输出流
// 6. 校验保存结果(文件是否存在且有效)
if (isSaved && targetFile.exists() && targetFile.length() > 100) {
LogUtils.d(TAG, "【保存成功】drawable图片保存为File" + targetFile.getAbsolutePath());
return targetFile; // 保存成功返回File对象
} else {
LogUtils.e(TAG, "【保存失败】图片写入文件无效(文件大小:" + (targetFile.exists() ? targetFile.length() : 0) + "字节)");
// 保存失败,删除无效文件
if (targetFile.exists()) {
targetFile.delete();
LogUtils.d(TAG, "【清理无效文件】已删除无效文件:" + targetFile.getAbsolutePath());
}
return null;
}
} catch (IOException e) {
LogUtils.e(TAG, "【保存异常】写入文件时出错:" + e.getMessage());
LogUtils.e(TAG, "【异常堆栈】" + Log.getStackTraceString(e));
return null;
} finally {
// 回收Bitmap资源避免内存溢出
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
LogUtils.d(TAG, "【资源回收】Bitmap资源已回收");
}
}
}
/**
* 重载方法:自定义保存路径(灵活适配不同场景)
* @param context 上下文
* @param drawableResId 图片资源ID
* @param saveDirPath 自定义保存目录路径(如 "/storage/emulated/0/PowerBell/custom/"
* @param fileName 保存的文件名(带.png后缀
* @return 保存成功返回File对象失败返回null
*/
public static File saveDrawableToFile(Context context, int drawableResId, String saveDirPath, String fileName) {
File filePath = new File(saveDirPath, fileName);
return saveDrawableToFile(context, drawableResId, filePath.getAbsolutePath());
}
}