diff --git a/powerbell/build.properties b/powerbell/build.properties index e7e273d..0463f22 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Mon Dec 08 12:53:13 GMT 2025 +#Wed Dec 10 06:50:20 GMT 2025 stageCount=2 libraryProject= baseVersion=15.12 publishVersion=15.12.1 -buildCount=5 +buildCount=13 baseBetaVersion=15.12.2 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java index b06d1b1..43d0839 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java @@ -89,14 +89,16 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg initToolbar(); initClickListeners(); - if (!handleShareIntent()) { + if (handleShareIntent()) { + ToastUtils.show("handleShareIntent"); + } else { mBgSourceUtils.setCurrentSourceToPreview(); } Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath())); - fix it>> mBgSourceUtils.createCropFileProviderBackgroundBean(uriSelectedImage); - - + // 创建预览数据剪裁环境 + mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(mBgSourceUtils.getPreviewBackgroundBean()); + doubleRefreshPreview(); LogUtils.d(TAG, "【初始化】BackgroundSettingsActivity 初始化完成"); } @@ -698,6 +700,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg private void doubleRefreshPreview() { LogUtils.d(TAG, "【双重刷新】开始"); if (mBackgroundView != null && !isFinishing()) { + mBgSourceUtils.loadSettings(); mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean()); LogUtils.d(TAG, "【双重刷新】第一重完成"); } else { @@ -709,6 +712,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg @Override public void run() { if (mBackgroundView != null && !isFinishing()) { + mBgSourceUtils.loadSettings(); mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean()); LogUtils.d(TAG, "【双重刷新】第二重完成"); } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BackgroundSourceUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BackgroundSourceUtils.java index 91c4e4c..f9a4508 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BackgroundSourceUtils.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/BackgroundSourceUtils.java @@ -218,7 +218,7 @@ public class BackgroundSourceUtils { clearCropTempFiles(); LogUtils.d(TAG, "【文件初始化】完成。"); } - + // 【核心实现】定义 getFileProviderUri 方法:将 File 转为 ContentUri(适配 FileProvider) public Uri getFileProviderUri(File file) { Log.d("BackgroundSourceUtils", "getFileProviderUri: 生成FileProvider Uri,文件路径:" + file.getAbsolutePath()); @@ -245,13 +245,16 @@ public class BackgroundSourceUtils { return contentUri; } - public boolean createCropFileProviderBackgroundBean(Uri uri) { + /* + * 创建预览数据剪裁环境 + */ + public boolean createAndUpdatePreviewEnvironmentForCropping(BackgroundBean oldPreviewBackgroundBean) { InputStream is = null; FileOutputStream fos = null; - loadSettings(); try { clearCropTempFiles(); + Uri uri = UriUtil.getUriForFile(mContext, oldPreviewBackgroundBean.getBackgroundFilePath()); //String szType = mContext.getContentResolver().getType(uri); // 2. 截取MIME类型后缀(如从image/jpeg中提取jpeg)【核心新增逻辑】 String fileSuffix = FileUtils.getFileSuffix(mContext, uri); @@ -259,51 +262,63 @@ public class BackgroundSourceUtils { mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix); mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix); - mCropSourceFile.createNewFile(); - mCropResultFile.createNewFile(); - - // 1. 打开Uri输入流(兼容content:///file:// 等多种Uri格式) - is = mContext.getContentResolver().openInputStream(uri); - if (is == null) { - LogUtils.e(TAG, "【选图解析】ContentResolver打开Uri失败,Uri:" + uri.toString()); - return false; + if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath())) { + FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath()), mCropResultFile); + } else { + mCropResultFile.createNewFile(); } - // 2. 初始化选图临时文件输出流(Java7 手动创建流,不依赖try-with-resources) - fos = new FileOutputStream(mCropSourceFile); - byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区,平衡读写性能与内存占用 - int readLen; // 每次读取的字节长度 + if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundFilePath())) { + FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundFilePath()), mCropSourceFile); + } else { + mCropSourceFile.createNewFile(); + // 1. 打开Uri输入流(兼容content:///file:// 等多种Uri格式) + is = mContext.getContentResolver().openInputStream(uri); + if (is == null) { + LogUtils.e(TAG, "【选图解析】ContentResolver打开Uri失败,Uri:" + uri.toString()); + return false; + } - // 3. 流复制(Java7 标准while循环,避免Java8+语法) - while ((readLen = is.read(buffer)) != -1) { - fos.write(buffer, 0, readLen); // 精准写入读取到的字节,避免空字节填充 - } + // 2. 初始化选图临时文件输出流(Java7 手动创建流,不依赖try-with-resources) + fos = new FileOutputStream(mCropSourceFile); + byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区,平衡读写性能与内存占用 + int readLen; // 每次读取的字节长度 - // 4. 强制同步写入磁盘(解决Android 10+ 异步写入导致的文件无效问题) - fos.flush(); - if (fos != null) { - try { - fos.getFD().sync(); // 确保数据写入物理磁盘,而非缓存 - } catch (IOException e) { - LogUtils.w(TAG, "【选图解析】文件同步到磁盘失败,用flush()兜底:" + e.getMessage()); - fos.flush(); + // 3. 流复制(Java7 标准while循环,避免Java8+语法) + while ((readLen = is.read(buffer)) != -1) { + fos.write(buffer, 0, readLen); // 精准写入读取到的字节,避免空字节填充 + } + + // 4. 强制同步写入磁盘(解决Android 10+ 异步写入导致的文件无效问题) + fos.flush(); + if (fos != null) { + try { + fos.getFD().sync(); // 确保数据写入物理磁盘,而非缓存 + } catch (IOException e) { + LogUtils.w(TAG, "【选图解析】文件同步到磁盘失败,用flush()兜底:" + e.getMessage()); + fos.flush(); + } } } + // 加载图片数据模型数据 + loadSettings(); + // 修改预览数据模型 previewBackgroundBean.setBackgroundFileName(mCropSourceFile.getName()); previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath()); previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName()); previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath()); + // 保存数据模型数据更改 saveSettings(); - + // 6. 解析成功日志(打印文件信息,便于问题排查) LogUtils.d(TAG, "【选图解析】Uri解析成功!"); LogUtils.d(TAG, "→ 原Uri:" + uri.toString()); - LogUtils.d(TAG, "→ 目标临时文件:" + mCropSourceFile.getAbsolutePath()); - LogUtils.d(TAG, "→ 目标临时文件大小:" + mCropSourceFile.length() + " bytes"); - LogUtils.d(TAG, "→ 目标剪裁临时文件:" + mCropResultFile.getAbsolutePath()); - LogUtils.d(TAG, "→ 目标剪裁临时文件大小:" + mCropResultFile.length() + " bytes"); + LogUtils.d(TAG, "→ 图片剪裁数据源:" + mCropSourceFile.getAbsolutePath()); + LogUtils.d(TAG, "→ 图片剪裁数据源文件大小:" + mCropSourceFile.length() + " bytes"); + LogUtils.d(TAG, "→ 剪裁结果数据文件:" + mCropResultFile.getAbsolutePath()); + LogUtils.d(TAG, "→ 剪裁结果数据文件大小:" + mCropResultFile.length() + " bytes"); return true; } catch (Exception e) { @@ -424,7 +439,7 @@ public class BackgroundSourceUtils { * 保存配置(核心:将两份独立Bean实例,分别写入各自的JSON文件) */ public void saveSettings() { - if(currentBackgroundBean != null && previewBackgroundBean != null) { + if (currentBackgroundBean != null && previewBackgroundBean != null) { BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean); // 正式Bean→正式JSON BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean); // 预览Bean→预览JSON LogUtils.d(TAG, "【配置管理】两份配置保存成功:正式JSON=" + currentBackgroundBeanFile.getAbsolutePath() + ",预览JSON=" + previewBackgroundBeanFile.getAbsolutePath()); @@ -531,12 +546,12 @@ public class BackgroundSourceUtils { // 更新当前背景文件路径 currentBackgroundBean.setBackgroundFilePath(currentFile.getAbsolutePath()); // 原图路径(BackgroundSource) currentBackgroundBean.setBackgroundScaledCompressFilePath(currentCropFile.getAbsolutePath()); // 压缩图路径(BackgroundCrops) - + saveSettings(); // 分别保存:正式Bean→currentJSON,预览Bean→previewJSON(两份独立) LogUtils.d(TAG, "【配置管理】预览背景深拷贝到正式Bean:两份实例独立,压缩图统一存储到BackgroundCrops"); ToastUtils.show("背景图片应用成功"); } - + /** * 将正式背景同步到预览背景(正式Bean → 预览Bean:深拷贝,新建预览Bean实例+逐字段拷贝) * 核心:深拷贝后,修改预览Bean不会影响正式Bean,两份实例完全独立,压缩图路径统一指向BackgroundCrops diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/FileUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/FileUtils.java index ed832d0..78bdb06 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/FileUtils.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/FileUtils.java @@ -277,5 +277,10 @@ public class FileUtils { } return fileSuffix; } + + public static boolean isFileExists(String path) { + File file = new File(path); + return file.exists(); + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/UriUtil.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/UriUtil.java index a4c312b..01060e1 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/UriUtil.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/UriUtil.java @@ -103,6 +103,11 @@ public class UriUtil { return filePath; } + + public static Uri getUriForFile(Context context, String filePath) { + File file = new File(filePath); + return getUriForFile(context, file); + } public static Uri getUriForFile(Context context, File file) { //Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);