基本完成图片设置流程。繁琐步骤未测试。。。

This commit is contained in:
2025-12-03 19:04:59 +08:00
parent c6a6826102
commit 4a31b9eef0
4 changed files with 61 additions and 173 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Dec 03 09:19:24 GMT 2025
#Wed Dec 03 10:59:39 GMT 2025
stageCount=13
libraryProject=
baseVersion=15.11
publishVersion=15.11.12
buildCount=122
buildCount=129
baseBetaVersion=15.11.13

View File

@@ -45,6 +45,7 @@ import java.util.List;
import android.app.Activity;
import android.os.Environment;
import cc.winboll.studio.powerbell.utils.FileUtils;
import cc.winboll.studio.powerbell.dialogs.YesNoAlertDialog;
/**
* 背景设置Activity图片选择/拍照/裁剪/预览/保存核心页面)
@@ -77,9 +78,6 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
private File mfTakePhoto;
// 配置标记(是否提交设置)
boolean isCommitSettings = false;
// 预览图片信息(用于退出确认)
//private String preViewFilePath = "";
//private String preViewFileUrl = "";
@Override
public Activity getActivity() {
@@ -969,4 +967,27 @@ public class BackgroundSettingsActivity extends WinBoLLActivity implements Backg
LogUtils.d(TAG, "【选图权限】已添加持久化读取权限");
}
}
@Override
public void finish() {
if(isCommitSettings) {
super.finish();
} else{
YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
mBgSourceUtils.commitPreviewSourceToCurrent();
isCommitSettings = true;
finish();
}
@Override
public void onNo() {
isCommitSettings = true;
finish();
}
});
}
}
}

View File

@@ -47,6 +47,8 @@ public class MainViewFragment extends Fragment {
Switch mswIsEnableService;
TextView mtvTips;
private BackgroundSourceUtils mBgSourceUtils;
// 背景布局
//LinearLayout mLinearLayoutloadBackground;
@@ -79,14 +81,11 @@ public class MainViewFragment extends Fragment {
mView = inflater.inflate(R.layout.fragment_mainview, container, false);
_mMainViewFragment = MainViewFragment.this;
mAppConfigUtils = App.getAppConfigUtils(getActivity());
mBgSourceUtils = BackgroundSourceUtils.getInstance(getActivity());
// 获取指定ID的View实例
mBackgroundView = mView.findViewById(R.id.fragmentmainviewBackgroundView1);
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(getActivity());
BackgroundBean bean = utils.getCurrentBackgroundBean();
int nPixelColor = bean.getPixelColor();
mBackgroundView.setBackgroundColor(nPixelColor);
loadBackground();
/*final View mainImageView = mView.findViewById(R.id.fragmentmainviewImageView1);
// 注册OnGlobalLayoutListener
@@ -149,16 +148,18 @@ public class MainViewFragment extends Fragment {
return mView;
}
void loadBackground() {
BackgroundBean bean = mBgSourceUtils.getCurrentBackgroundBean();
mBackgroundView.loadBackground(bean);
}
@Override
public void onResume() {
super.onResume();
BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(getActivity());
BackgroundBean bean = utils.getCurrentBackgroundBean();
int nPixelColor = bean.getPixelColor();
mBackgroundView.setBackgroundColor(nPixelColor);
loadBackground();
}
void setViewData() {
int nChargeReminderValue = mAppConfigUtils.getChargeReminderValue();

View File

@@ -311,49 +311,6 @@ public class BackgroundSourceUtils {
}
}
/**
* 核心优化函数:带原图参数的裁剪路径创建(优先使用原图,不复制)
* 替代原逻辑中"复制原图到BackgroundSource再裁剪"的流程
*/
// File createFileProviderPath(File originalImageFile) {
// Log.d(TAG, "【裁剪优化】createCropFileProviderPath(原图) 触发,优先使用原图路径");
//
// // 核心逻辑1直接使用裁剪前的原图不复制仅校验合法性和权限
// if (originalImageFile != null && originalImageFile.exists()
// && originalImageFile.isFile() && originalImageFile.length() > 0) {
// // 校验原图目录是否可写(系统裁剪工具需读写权限)
// if (isDirectoryWritable(originalImageFile.getParentFile())) {
// // 强制开放原图权限(解决跨进程访问问题)
// //setFileReadWritePermission(originalImageFile);
// Log.d(TAG, "【裁剪优化】直接使用原图启动裁剪(无复制):" + originalImageFile.getAbsolutePath());
// return originalImageFile; // 直接返回原图,不做任何复制
// } else {
// Log.w(TAG, "【裁剪优化】原图目录不可写,切换到临时文件兜底");
// }
// } else {
// Log.w(TAG, "【裁剪优化】原图无效(空/不存在/0大小切换到临时文件兜底");
// }
// Log.e(TAG, "【裁剪优化】所有裁剪路径创建失败,裁剪功能不可用");
// return null;
// }
// 辅助方法:校验目录是否可写(新增,保障裁剪权限)
// private boolean isDirectoryWritable(File dir) {
// if (dir == null) return false;
// // 目录存在且可写,或目录不存在但能创建
// return (dir.exists() && dir.isDirectory() && dir.canWrite())
// || (!dir.exists() && dir.mkdirs());
// }
// 辅助方法:设置文件读写权限(新增,解决系统裁剪跨进程访问)
// private void setFileReadWritePermission(File file) {
// if (file == null || !file.exists()) return;
// // 开放读写权限兼容Android 10+
// file.setReadable(true, false);
// file.setWritable(true, false);
// file.setExecutable(true, false);
// }
/**
* 加载背景图片配置数据核心确保current/preview是两份独立的BackgroundBean实例
*/
@@ -453,9 +410,13 @@ public class BackgroundSourceUtils {
* 保存配置核心将两份独立Bean实例分别写入各自的JSON文件
*/
public void saveSettings() {
BackgroundBean.saveBeanToFile(currentBackgroundBeanFile.getAbsolutePath(), currentBackgroundBean); // 正式Bean→正式JSON
BackgroundBean.saveBeanToFile(previewBackgroundBeanFile.getAbsolutePath(), previewBackgroundBean); // 预览Bean→预览JSON
LogUtils.d(TAG, "【配置管理】两份配置保存成功正式JSON=" + currentBackgroundBeanFile.getAbsolutePath() + "预览JSON=" + previewBackgroundBeanFile.getAbsolutePath());
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());
return;
}
LogUtils.d(TAG, "【配置管理】两份配置保存失败。currentBackgroundBean 与 previewBackgroundBean 有空值。");
}
/**
@@ -544,11 +505,24 @@ public class BackgroundSourceUtils {
currentBackgroundBean.setBackgroundHeight(previewBackgroundBean.getBackgroundHeight());
currentBackgroundBean.setPixelColor(previewBackgroundBean.getPixelColor());
// 拷贝一份缓存图片文件到正式背景文件夹
String previewFileName = previewBackgroundBean.getBackgroundFileName();
String previewCropFileName = previewBackgroundBean.getBackgroundScaledCompressFileName();
File previewFile = new File(previewBackgroundBean.getBackgroundFilePath());
File previewCropFile = new File(previewBackgroundBean.getBackgroundScaledCompressFilePath());
File currentFile = new File(fBackgroundSourceDir, previewFileName);
File currentCropFile = new File(fBackgroundCompressDir, previewCropFileName);
FileUtils.copyFile(previewFile, currentFile);
FileUtils.copyFile(previewCropFile, currentCropFile);
// 更新当前背景文件路径
currentBackgroundBean.setBackgroundFilePath(currentFile.getAbsolutePath()); // 原图路径BackgroundSource
currentBackgroundBean.setBackgroundScaledCompressFilePath(currentCropFile.getAbsolutePath()); // 压缩图路径BackgroundCrops
saveSettings(); // 分别保存正式Bean→currentJSON预览Bean→previewJSON两份独立
LogUtils.d(TAG, "【配置管理】预览背景深拷贝到正式Bean两份实例独立压缩图统一存储到BackgroundCrops");
LogUtils.d(TAG, "【配置管理】预览背景深拷贝到正式Bean两份实例独立压缩图统一存储到BackgroundCrops");
ToastUtils.show("背景图片应用成功");
}
/**
* 将正式背景同步到预览背景正式Bean → 预览Bean深拷贝新建预览Bean实例+逐字段拷贝)
* 核心深拷贝后修改预览Bean不会影响正式Bean两份实例完全独立压缩图路径统一指向BackgroundCrops
@@ -572,75 +546,6 @@ public class BackgroundSourceUtils {
LogUtils.d(TAG, "【配置管理】正式背景深拷贝到预览Bean两份实例独立压缩图统一存储到BackgroundCrops");
}
// ------------------------------ 必需保留的工具方法(与业务/权限强相关无法复用FileUtils------------------------------
/**
* 工具方法:递归设置目录及子目录/文件的读写权限(适配系统公共目录/Pictures/PowerBell
* @param dir 要设置权限的目录
*/
// private void setDirPermissionsRecursively(File dir) {
// if (dir == null || !dir.exists()) {
// String dirPath = (dir != null) ? dir.getAbsolutePath() : "null";
// LogUtils.d(TAG, "【权限管理】目录无效,无需设置权限:" + dirPath);
// return;
// }
// try {
// // 设置目录权限(允许所有用户读写,系统裁剪应用/预览功能必需)
// dir.setReadable(true, false);
// dir.setWritable(true, false);
// dir.setExecutable(false, false);
//
// LogUtils.d(TAG, "【权限管理】目录权限设置完成:路径=" + dir.getAbsolutePath() + ",可写=" + dir.canWrite() + ",可读=" + dir.canRead());
//
// // 递归处理子目录和文件Java7 普通for循环兼容语法
// File[] files = dir.listFiles();
// if (files != null && files.length > 0) {
// for (int i = 0; i < files.length; i++) {
// File file = files[i];
// if (file.isDirectory()) {
// setDirPermissionsRecursively(file);
// } else {
// // 设置文件权限(与目录一致,确保可读写)
// file.setReadable(true, false);
// file.setWritable(true, false);
// file.setExecutable(false, false);
// // 裁剪/压缩/预览相关文件单独打印日志
// if (file.getName().contains(CROP_TEMP_FILE_NAME) ||
// file.getName().contains(CROP_RESULT_FILE_NAME) ||
// file.getName().startsWith("ScaledCompress_")) {
// LogUtils.d(TAG, "【权限管理】关键文件权限设置:文件名=" + file.getName() + ",可写=" + file.canWrite());
// }
// }
// }
// }
// } catch (SecurityException e) {
// LogUtils.e(TAG, "【权限管理】设置目录权限失败(系统禁止):" + dir.getAbsolutePath() + ",错误:" + e.getMessage(), e);
// ToastUtils.show("目录权限设置失败,请授予应用存储权限");
// } catch (Exception e) {
// LogUtils.e(TAG, "【权限管理】设置目录权限异常:" + dir.getAbsolutePath() + ",错误:" + e.getMessage(), e);
// }
// }
/**
* 工具方法:设置单个文件权限(确保系统裁剪应用/预览功能可读写,适配/Pictures/PowerBell目录
* 【关键调整】public修饰适配BackgroundSettingsActivity的外部调用
* @param file 要设置权限的文件
*/
// public void setFilePermissions(File file) {
// if (file == null || !file.exists()) {
// LogUtils.d(TAG, "【权限管理】文件无效,无需设置权限:" + (file != null ? file.getAbsolutePath() : "null"));
// return;
// }
// try {
// // 核心:允许所有用户读写(系统裁剪应用非本应用进程,需开放权限)
// file.setReadable(true, false);
// file.setWritable(true, false);
// file.setExecutable(false, false);
// LogUtils.d(TAG, "【权限管理】文件权限设置完成(/Pictures/PowerBell下路径=" + file.getAbsolutePath() + ",可写=" + file.canWrite() + ",可读=" + file.canRead());
// } catch (Exception e) {
// LogUtils.e(TAG, "【权限管理】设置文件权限失败:" + file.getAbsolutePath() + ",错误:" + e.getMessage(), e);
// }
// }
/**
* 工具方法:清理旧文件(避免文件锁定/残留,适配系统公共目录)【内部私有,不对外暴露】
* @param file 要清理的文件
@@ -667,45 +572,6 @@ public class BackgroundSourceUtils {
mCropResultFile = null;
}
/**
* 工具方法验证目录实际写入能力解决Android14+ canWrite()假阳性问题,适配/Pictures/PowerBell
* 原理:通过创建临时空文件并删除,验证目录是否真的可写
* @param dir 要验证的目录
* @return true=实际可写false=实际不可写
*/
// private boolean isDirActuallyWritable(File dir) {
// if (dir == null || !dir.exists() || !dir.isDirectory()) {
// return false;
// }
// // 创建临时空文件(随机文件名,避免冲突)
// File testFile = new File(dir, "test_write_" + System.currentTimeMillis() + ".tmp");
// try {
// boolean createSuccess = testFile.createNewFile();
// if (createSuccess) {
// boolean canWrite = testFile.canWrite();
// boolean canRead = testFile.canRead();
// testFile.delete(); // 删除临时文件,不占用空间
// LogUtils.d(TAG, "【权限校验】目录实际写入校验(/Pictures/PowerBell下" + dir.getAbsolutePath() + ",创建成功=" + createSuccess + ",可写=" + canWrite + ",可读=" + canRead + ",结果=" + (canWrite ? "通过" : "失败"));
// return canWrite;
// } else {
// LogUtils.d(TAG, "【权限校验】目录实际写入校验失败:" + dir.getAbsolutePath() + "创建临时文件失败Permission denied");
// return false;
// }
// } catch (IOException e) {
// LogUtils.e(TAG, "【权限校验】目录实际写入校验异常:" + dir.getAbsolutePath() + ",错误:" + e.getMessage(), e);
// return false;
// }
// }
/**
* 对外接口清理指定旧文件适配BackgroundSettingsActivity调用支持/Pictures/PowerBell目录
* @param file 要清理的文件
* @param fileDesc 文件描述(用于日志打印)
*/
// public void clearOldFileByExternal(File file, String fileDesc) {
// clearOldFile(file, fileDesc); // 调用内部private方法复用逻辑
// }
/**
* 适配原调用mBgSourceUtils.copyFile(new File(""), parentDir)
* 核心复用FileUtils支持「空源文件→仅创建目标目录」和「正常文件复制」两种场景