diff --git a/powerbell/build.properties b/powerbell/build.properties index c9992b4..e7e273d 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -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 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 2af8fea..b06d1b1 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 @@ -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(); + } } } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/DrawableToFileUtils.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/DrawableToFileUtils.java new file mode 100644 index 0000000..d4bd3d1 --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/utils/DrawableToFileUtils.java @@ -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&豆包大模型 + * @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 写入 File(PNG格式,无损保存) + 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()); + } +} +