第一条图片选择与剪裁流程调试通过。

This commit is contained in:
2025-12-10 14:52:43 +08:00
parent 016b3b5e48
commit 7c5f8c3cc2
5 changed files with 70 additions and 41 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #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 stageCount=2
libraryProject= libraryProject=
baseVersion=15.12 baseVersion=15.12
publishVersion=15.12.1 publishVersion=15.12.1
buildCount=5 buildCount=13
baseBetaVersion=15.12.2 baseBetaVersion=15.12.2

View File

@@ -89,14 +89,16 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
initToolbar(); initToolbar();
initClickListeners(); initClickListeners();
if (!handleShareIntent()) { if (handleShareIntent()) {
ToastUtils.show("handleShareIntent");
} else {
mBgSourceUtils.setCurrentSourceToPreview(); mBgSourceUtils.setCurrentSourceToPreview();
} }
Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath())); Uri uriSelectedImage = UriUtil.getUriForFile(this, new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath()));
fix it>> mBgSourceUtils.createCropFileProviderBackgroundBean(uriSelectedImage); // 创建预览数据剪裁环境
mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(mBgSourceUtils.getPreviewBackgroundBean());
doubleRefreshPreview();
LogUtils.d(TAG, "【初始化】BackgroundSettingsActivity 初始化完成"); LogUtils.d(TAG, "【初始化】BackgroundSettingsActivity 初始化完成");
} }
@@ -698,6 +700,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
private void doubleRefreshPreview() { private void doubleRefreshPreview() {
LogUtils.d(TAG, "【双重刷新】开始"); LogUtils.d(TAG, "【双重刷新】开始");
if (mBackgroundView != null && !isFinishing()) { if (mBackgroundView != null && !isFinishing()) {
mBgSourceUtils.loadSettings();
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean()); mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
LogUtils.d(TAG, "【双重刷新】第一重完成"); LogUtils.d(TAG, "【双重刷新】第一重完成");
} else { } else {
@@ -709,6 +712,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
@Override @Override
public void run() { public void run() {
if (mBackgroundView != null && !isFinishing()) { if (mBackgroundView != null && !isFinishing()) {
mBgSourceUtils.loadSettings();
mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean()); mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean());
LogUtils.d(TAG, "【双重刷新】第二重完成"); LogUtils.d(TAG, "【双重刷新】第二重完成");
} }

View File

@@ -218,7 +218,7 @@ public class BackgroundSourceUtils {
clearCropTempFiles(); clearCropTempFiles();
LogUtils.d(TAG, "【文件初始化】完成。"); LogUtils.d(TAG, "【文件初始化】完成。");
} }
// 【核心实现】定义 getFileProviderUri 方法:将 File 转为 ContentUri适配 FileProvider // 【核心实现】定义 getFileProviderUri 方法:将 File 转为 ContentUri适配 FileProvider
public Uri getFileProviderUri(File file) { public Uri getFileProviderUri(File file) {
Log.d("BackgroundSourceUtils", "getFileProviderUri: 生成FileProvider Uri文件路径" + file.getAbsolutePath()); Log.d("BackgroundSourceUtils", "getFileProviderUri: 生成FileProvider Uri文件路径" + file.getAbsolutePath());
@@ -245,13 +245,16 @@ public class BackgroundSourceUtils {
return contentUri; return contentUri;
} }
public boolean createCropFileProviderBackgroundBean(Uri uri) { /*
* 创建预览数据剪裁环境
*/
public boolean createAndUpdatePreviewEnvironmentForCropping(BackgroundBean oldPreviewBackgroundBean) {
InputStream is = null; InputStream is = null;
FileOutputStream fos = null; FileOutputStream fos = null;
loadSettings();
try { try {
clearCropTempFiles(); clearCropTempFiles();
Uri uri = UriUtil.getUriForFile(mContext, oldPreviewBackgroundBean.getBackgroundFilePath());
//String szType = mContext.getContentResolver().getType(uri); //String szType = mContext.getContentResolver().getType(uri);
// 2. 截取MIME类型后缀如从image/jpeg中提取jpeg【核心新增逻辑】 // 2. 截取MIME类型后缀如从image/jpeg中提取jpeg【核心新增逻辑】
String fileSuffix = FileUtils.getFileSuffix(mContext, uri); String fileSuffix = FileUtils.getFileSuffix(mContext, uri);
@@ -259,51 +262,63 @@ public class BackgroundSourceUtils {
mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix); mCropSourceFile = new File(fCropCacheDir, newCropFileName + "." + fileSuffix);
mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix); mCropResultFile = new File(fCropCacheDir, "SelectCompress_" + newCropFileName + "." + fileSuffix);
mCropSourceFile.createNewFile(); if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath())) {
mCropResultFile.createNewFile(); FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundScaledCompressFilePath()), mCropResultFile);
} else {
// 1. 打开Uri输入流兼容content:///file:// 等多种Uri格式 mCropResultFile.createNewFile();
is = mContext.getContentResolver().openInputStream(uri);
if (is == null) {
LogUtils.e(TAG, "【选图解析】ContentResolver打开Uri失败Uri" + uri.toString());
return false;
} }
// 2. 初始化选图临时文件输出流Java7 手动创建流不依赖try-with-resources if (FileUtils.isFileExists(oldPreviewBackgroundBean.getBackgroundFilePath())) {
fos = new FileOutputStream(mCropSourceFile); FileUtils.copyFile(new File(oldPreviewBackgroundBean.getBackgroundFilePath()), mCropSourceFile);
byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区平衡读写性能与内存占用 } else {
int readLen; // 每次读取的字节长度 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+语法 // 2. 初始化选图临时文件输出流Java7 手动创建流不依赖try-with-resources
while ((readLen = is.read(buffer)) != -1) { fos = new FileOutputStream(mCropSourceFile);
fos.write(buffer, 0, readLen); // 精准写入读取到的字节,避免空字节填充 byte[] buffer = new byte[1024 * 8]; // 8KB缓冲区平衡读写性能与内存占用
} int readLen; // 每次读取的字节长度
// 4. 强制同步写入磁盘解决Android 10+ 异步写入导致的文件无效问题 // 3. 流复制Java7 标准while循环避免Java8+语法
fos.flush(); while ((readLen = is.read(buffer)) != -1) {
if (fos != null) { fos.write(buffer, 0, readLen); // 精准写入读取到的字节,避免空字节填充
try { }
fos.getFD().sync(); // 确保数据写入物理磁盘,而非缓存
} catch (IOException e) { // 4. 强制同步写入磁盘解决Android 10+ 异步写入导致的文件无效问题)
LogUtils.w(TAG, "【选图解析】文件同步到磁盘失败用flush()兜底:" + e.getMessage()); fos.flush();
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.setBackgroundFileName(mCropSourceFile.getName());
previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath()); previewBackgroundBean.setBackgroundFilePath(mCropSourceFile.getAbsolutePath());
previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName()); previewBackgroundBean.setBackgroundScaledCompressFileName(mCropResultFile.getName());
previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath()); previewBackgroundBean.setBackgroundScaledCompressFilePath(mCropResultFile.getAbsolutePath());
// 保存数据模型数据更改
saveSettings(); saveSettings();
// 6. 解析成功日志(打印文件信息,便于问题排查) // 6. 解析成功日志(打印文件信息,便于问题排查)
LogUtils.d(TAG, "【选图解析】Uri解析成功"); LogUtils.d(TAG, "【选图解析】Uri解析成功");
LogUtils.d(TAG, "→ 原Uri" + uri.toString()); LogUtils.d(TAG, "→ 原Uri" + uri.toString());
LogUtils.d(TAG, "目标临时文件" + mCropSourceFile.getAbsolutePath()); LogUtils.d(TAG, "图片剪裁数据源" + mCropSourceFile.getAbsolutePath());
LogUtils.d(TAG, "目标临时文件大小:" + mCropSourceFile.length() + " bytes"); LogUtils.d(TAG, "图片剪裁数据源文件大小:" + mCropSourceFile.length() + " bytes");
LogUtils.d(TAG, "目标剪裁临时文件:" + mCropResultFile.getAbsolutePath()); LogUtils.d(TAG, "剪裁结果数据文件:" + mCropResultFile.getAbsolutePath());
LogUtils.d(TAG, "目标剪裁临时文件大小:" + mCropResultFile.length() + " bytes"); LogUtils.d(TAG, "剪裁结果数据文件大小:" + mCropResultFile.length() + " bytes");
return true; return true;
} catch (Exception e) { } catch (Exception e) {
@@ -424,7 +439,7 @@ public class BackgroundSourceUtils {
* 保存配置核心将两份独立Bean实例分别写入各自的JSON文件 * 保存配置核心将两份独立Bean实例分别写入各自的JSON文件
*/ */
public void saveSettings() { public void saveSettings() {
if(currentBackgroundBean != null && previewBackgroundBean != null) { if (currentBackgroundBean != null && previewBackgroundBean != null) {
BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean); // 正式Bean→正式JSON BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean); // 正式Bean→正式JSON
BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean); // 预览Bean→预览JSON BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean); // 预览Bean→预览JSON
LogUtils.d(TAG, "【配置管理】两份配置保存成功正式JSON=" + currentBackgroundBeanFile.getAbsolutePath() + "预览JSON=" + previewBackgroundBeanFile.getAbsolutePath()); LogUtils.d(TAG, "【配置管理】两份配置保存成功正式JSON=" + currentBackgroundBeanFile.getAbsolutePath() + "预览JSON=" + previewBackgroundBeanFile.getAbsolutePath());
@@ -531,12 +546,12 @@ public class BackgroundSourceUtils {
// 更新当前背景文件路径 // 更新当前背景文件路径
currentBackgroundBean.setBackgroundFilePath(currentFile.getAbsolutePath()); // 原图路径BackgroundSource currentBackgroundBean.setBackgroundFilePath(currentFile.getAbsolutePath()); // 原图路径BackgroundSource
currentBackgroundBean.setBackgroundScaledCompressFilePath(currentCropFile.getAbsolutePath()); // 压缩图路径BackgroundCrops currentBackgroundBean.setBackgroundScaledCompressFilePath(currentCropFile.getAbsolutePath()); // 压缩图路径BackgroundCrops
saveSettings(); // 分别保存正式Bean→currentJSON预览Bean→previewJSON两份独立 saveSettings(); // 分别保存正式Bean→currentJSON预览Bean→previewJSON两份独立
LogUtils.d(TAG, "【配置管理】预览背景深拷贝到正式Bean两份实例独立压缩图统一存储到BackgroundCrops"); LogUtils.d(TAG, "【配置管理】预览背景深拷贝到正式Bean两份实例独立压缩图统一存储到BackgroundCrops");
ToastUtils.show("背景图片应用成功"); ToastUtils.show("背景图片应用成功");
} }
/** /**
* 将正式背景同步到预览背景正式Bean → 预览Bean深拷贝新建预览Bean实例+逐字段拷贝) * 将正式背景同步到预览背景正式Bean → 预览Bean深拷贝新建预览Bean实例+逐字段拷贝)
* 核心深拷贝后修改预览Bean不会影响正式Bean两份实例完全独立压缩图路径统一指向BackgroundCrops * 核心深拷贝后修改预览Bean不会影响正式Bean两份实例完全独立压缩图路径统一指向BackgroundCrops

View File

@@ -277,5 +277,10 @@ public class FileUtils {
} }
return fileSuffix; return fileSuffix;
} }
public static boolean isFileExists(String path) {
File file = new File(path);
return file.exists();
}
} }

View File

@@ -103,6 +103,11 @@ public class UriUtil {
return filePath; 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) { public static Uri getUriForFile(Context context, File file) {
//Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file); //Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);