diff --git a/powerbell/build.properties b/powerbell/build.properties
index 1dda429..d49f89b 100644
--- a/powerbell/build.properties
+++ b/powerbell/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Sun Dec 21 01:45:57 GMT 2025
+#Sun Dec 21 03:13:26 GMT 2025
stageCount=14
libraryProject=
baseVersion=15.14
publishVersion=15.14.13
-buildCount=6
+buildCount=18
baseBetaVersion=15.14.14
diff --git a/powerbell/src/main/AndroidManifest.xml b/powerbell/src/main/AndroidManifest.xml
index c8ea92e..ebac690 100644
--- a/powerbell/src/main/AndroidManifest.xml
+++ b/powerbell/src/main/AndroidManifest.xml
@@ -4,54 +4,73 @@
xmlns:tools="http://schemas.android.com/tools"
package="cc.winboll.studio.powerbell">
-
-
+
-
-
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
-
-
+
+
+
+
+
-
-
-
-
-
+
@@ -68,17 +87,17 @@
android:supportsRtl="true"
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
-
+
-
+ android:exported="false"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:exported="false"/>
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
+
+
+
+
-
-
-
+
+ android:value="后台核心功能运行、持续保活"/>
+
-
+ android:process=".assistantservice">
+
+ android:value="辅助核心功能运行"/>
+
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
+
\ No newline at end of file
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 3c6fdf8..d1d5957 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
@@ -1,22 +1,26 @@
package cc.winboll.studio.powerbell.activities;
+import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
+import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.ToastUtils;
@@ -32,35 +36,38 @@ import cc.winboll.studio.powerbell.utils.FileUtils;
import cc.winboll.studio.powerbell.utils.ImageCropUtils;
import cc.winboll.studio.powerbell.utils.UriUtils;
import cc.winboll.studio.powerbell.views.BackgroundView;
-import com.a4455jkjh.colorpicker.ColorPickerDialog;
-import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
+import cc.winboll.studio.powerbell.dialogs.NetworkBackgroundDialog;
public class BackgroundSettingsActivity extends WinBoLLActivity {
- // ====================== 常量定义 ======================
+ // ====================== 常量定义(按功能分类置顶)======================
public static final String TAG = "BackgroundSettingsActivity";
+ // 系统版本常量
private static final int SDK_VERSION_TIRAMISU = 33;
-
+ // 请求码(按功能分组)
public static final int REQUEST_SELECT_PICTURE = 0;
public static final int REQUEST_TAKE_PHOTO = 1;
public static final int REQUEST_CROP_IMAGE = 2;
- private static final int REQUEST_PIXELPICKER = 1001;
+ private static final int REQUEST_PIXELPICKER = 1001;
+ private static final int REQUEST_CAMERA_PERMISSION = 1004;
+ // Bitmap解析常量
+ private static final int BITMAP_MAX_SIZE = 2048;
+ private static final int BITMAP_MAX_SAMPLE_SIZE = 16;
- // ====================== 成员变量 ======================
+ // ====================== 成员变量(按依赖优先级+功能分类)======================
+ // 工具类实例
private BackgroundSourceUtils mBgSourceUtils;
private BitmapCacheUtils mBitmapCache;
-
+ // 视图组件
private Toolbar mToolbar;
private BackgroundView mBackgroundView;
- private File mfTakePhoto;
- volatile boolean isCommitSettings = false;
- volatile boolean isPreviewBackgroundChanged = false;
+ // 状态标记(volatile保证多线程可见性)
+ private volatile boolean isCommitSettings = false;
+ private volatile boolean isPreviewBackgroundChanged = false;
- // ====================== 生命周期方法 ======================
+ // ====================== 生命周期方法(按执行顺序排列)======================
@Override
public Activity getActivity() {
return this;
@@ -74,49 +81,29 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_background_settings);
LogUtils.d(TAG, "【生命周期】onCreate 开始初始化");
+ setContentView(R.layout.activity_background_settings);
- // 初始化视图与工具类
- mBackgroundView = findViewById(R.id.background_view);
- mBgSourceUtils = BackgroundSourceUtils.getInstance(this);
- mBgSourceUtils.loadSettings();
- mBitmapCache = BitmapCacheUtils.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());
-// }
-
+ // 初始化核心组件
+ initCoreComponents();
// 初始化界面与事件
initToolbar();
initClickListeners();
+ LogUtils.d(TAG, "【初始化】界面与事件绑定完成");
// 处理分享意图或初始化预览
- if (handleShareIntent()) {
- ToastUtils.show("handleShareIntent");
- } else {
- mBgSourceUtils.setCurrentSourceToPreview();
- }
+ handleIntentOrPreview();
- mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(mBgSourceUtils.getPreviewBackgroundBean());
- doubleRefreshPreview();
+ // 初始化预览环境并刷新
+ initPreviewEnvironment();
LogUtils.d(TAG, "【生命周期】onCreate 初始化完成");
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
+ LogUtils.d(TAG, "【生命周期】onPostCreate 执行双重刷新预览");
doubleRefreshPreview();
- LogUtils.d(TAG, "【生命周期】onPostCreate 执行双重刷新");
}
@Override
@@ -126,29 +113,13 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
try {
if (resultCode != RESULT_OK) {
+ LogUtils.d(TAG, "【回调处理】结果非RESULT_OK,执行取消逻辑");
handleOperationCancelOrFail();
return;
}
-
- switch (requestCode) {
- case REQUEST_SELECT_PICTURE:
- handleSelectPictureResult(resultCode, data);
- break;
- case REQUEST_TAKE_PHOTO:
- handleTakePhotoResult(resultCode, data);
- break;
- case REQUEST_CROP_IMAGE:
- handleCropImageResult(requestCode, resultCode, data);
- break;
- case REQUEST_PIXELPICKER:
- handlePixelPickerResult(requestCode, resultCode, data);
- break;
- default:
- LogUtils.d(TAG, "【回调忽略】未知requestCode");
- break;
- }
+ handleActivityResult(requestCode, data);
} catch (Exception e) {
- LogUtils.e(TAG, "【回调异常】" + e.getMessage());
+ LogUtils.e(TAG, "【回调异常】requestCode:" + requestCode + ",异常信息:" + e.getMessage());
ToastUtils.show("操作失败");
}
}
@@ -159,32 +130,27 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
if (isCommitSettings) {
super.finish();
} else {
- if (isPreviewBackgroundChanged) {
- YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener() {
- @Override
- public void onYes() {
- //ToastUtils.show("onYes");
- mBgSourceUtils.commitPreviewSourceToCurrent();
- isCommitSettings = true;
- finish();
- }
-
- @Override
- public void onNo() {
- isCommitSettings = true;
- finish();
- }
- });
- } else {
- isCommitSettings = true;
- finish();
- }
+ handleFinishConfirmation();
}
}
- // ====================== 界面初始化方法 ======================
+ // ====================== 权限回调方法(单独分类)======================
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ LogUtils.d(TAG, "【权限回调】requestCode:" + requestCode + ",权限数量:" + permissions.length);
+ if (requestCode == REQUEST_CAMERA_PERMISSION) {
+ handleCameraPermissionResult(grantResults);
+ }
+ }
+
+ // ====================== 界面初始化方法(Toolbar + 点击事件)======================
private void initToolbar() {
mToolbar = findViewById(R.id.toolbar);
+ if (mToolbar == null) {
+ LogUtils.e(TAG, "【初始化异常】Toolbar未找到");
+ return;
+ }
setSupportActionBar(mToolbar);
mToolbar.setSubtitle(getTag());
mToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText);
@@ -192,34 +158,53 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- LogUtils.d(TAG, "【导航栏】点击返回");
+ LogUtils.d(TAG, "【导航栏】点击返回按钮");
finish();
}
});
+ LogUtils.d(TAG, "【界面初始化】Toolbar 配置完成");
}
private void initClickListeners() {
- LogUtils.d(TAG, "【界面初始化】绑定按钮点击事件");
- findViewById(R.id.activitybackgroundpictureAButton5).setOnClickListener(onOriginNullClickListener);
- findViewById(R.id.activitybackgroundpictureAButton4).setOnClickListener(onReceivedPictureClickListener);
- findViewById(R.id.activitybackgroundpictureAButton1).setOnClickListener(onTakePhotoClickListener);
- findViewById(R.id.activitybackgroundpictureAButton2).setOnClickListener(onSelectPictureClickListener);
- findViewById(R.id.activitybackgroundpictureAButton3).setOnClickListener(onCropPictureClickListener);
- findViewById(R.id.activitybackgroundpictureAButton6).setOnClickListener(onCropFreePictureClickListener);
- findViewById(R.id.activitybackgroundpictureAButton7).setOnClickListener(onPixelPickerClickListener);
- findViewById(R.id.activitybackgroundpictureAButton8).setOnClickListener(onCleanPixelClickListener);
- findViewById(R.id.activitybackgroundsettingsAButton1).setOnClickListener(onColorPaletteClickListener);
+ LogUtils.d(TAG, "【界面初始化】开始绑定按钮点击事件");
+ // 绑定所有按钮点击事件
+ bindClickListener(R.id.activitybackgroundsettingsAButton1, onOriginNullClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton2, onReceivedPictureClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton3, onTakePhotoClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton4, onSelectPictureClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton5, onNetworkBackgroundDialog);
+ bindClickListener(R.id.activitybackgroundsettingsAButton6, onCropPictureClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton7, onCropFreePictureClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton8, onPixelPickerClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton9, onColorPaletteClickListener);
+ bindClickListener(R.id.activitybackgroundsettingsAButton10, onCleanPixelClickListener);
+ LogUtils.d(TAG, "【界面初始化】按钮点击事件绑定完成");
}
- // ====================== 按钮点击事件 ======================
+ // 通用按钮绑定工具方法
+ private void bindClickListener(int resId, View.OnClickListener listener) {
+ View view = findViewById(resId);
+ if (view != null) {
+ view.setOnClickListener(listener);
+ } else {
+ LogUtils.e(TAG, "【绑定异常】未找到视图:" + resId);
+ }
+ }
+
+ // ====================== 按钮点击事件(按功能分类)======================
private View.OnClickListener onOriginNullClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】取消背景图片");
- mBgSourceUtils.getPreviewBackgroundBean().setIsUseBackgroundFile(false);
- mBgSourceUtils.saveSettings();
- doubleRefreshPreview();
- isPreviewBackgroundChanged = true;
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【操作异常】预览Bean为空");
+ return;
+ }
+ previewBean.setIsUseBackgroundFile(false);
+ mBgSourceUtils.saveSettings();
+ doubleRefreshPreview();
+ isPreviewBackgroundChanged = true;
}
};
@@ -227,7 +212,27 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】选择图片");
- launchImageSelector();
+ launchImageSelector();
+ }
+ };
+
+ private View.OnClickListener onNetworkBackgroundDialog = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ NetworkBackgroundDialog networkBackgroundDialog = new NetworkBackgroundDialog(BackgroundSettingsActivity.this, new NetworkBackgroundDialog.OnDialogClickListener(){
+ @Override
+ public void onConfirm(String szConfirmFilePath) {
+ // 拷贝文件到预览数据并启动裁剪
+ if (putUriFileToPreviewSource(new File(szConfirmFilePath))) {
+ startImageCrop(false);
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ }
+ });
+ networkBackgroundDialog.show();
}
};
@@ -235,13 +240,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】固定比例裁剪");
- ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
- mBgSourceUtils.getPreviewBackgroundBean(),
- mBackgroundView.getWidth(),
- mBackgroundView.getHeight(),
- false,
- REQUEST_CROP_IMAGE
- );
+ startImageCrop(false);
}
};
@@ -249,13 +248,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】自由裁剪");
- ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
- mBgSourceUtils.getPreviewBackgroundBean(),
- 0,
- 0,
- true,
- REQUEST_CROP_IMAGE
- );
+ startImageCrop(true);
}
};
@@ -263,50 +256,47 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】拍照");
- // 移除:旧文件删除逻辑
- try {
- boolean createSuccess = mfTakePhoto.createNewFile();
- LogUtils.d(TAG, "【拍照准备】创建新文件:" + (createSuccess ? "成功" : "失败"));
- if (!createSuccess) {
- ToastUtils.show("拍照文件创建失败");
- return;
- }
- } catch (IOException e) {
- LogUtils.e(TAG, "【拍照异常】" + e.getMessage());
- ToastUtils.show("拍照文件创建失败");
+ // 动态申请相机权限
+ if (ContextCompat.checkSelfPermission(BackgroundSettingsActivity.this, Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED) {
+ LogUtils.d(TAG, "【拍照准备】相机权限未授予,发起申请");
+ ActivityCompat.requestPermissions(
+ BackgroundSettingsActivity.this,
+ new String[]{Manifest.permission.CAMERA},
+ REQUEST_CAMERA_PERMISSION);
return;
}
-
- Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- try {
- Uri photoUri = getFileProviderUri(mfTakePhoto);
- takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
- startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
- LogUtils.d(TAG, "【拍照启动】Uri:" + photoUri.toString());
- } catch (Exception e) {
- String errMsg = "拍照启动异常:" + e.getMessage();
- ToastUtils.show(errMsg.substring(0, 20));
- LogUtils.e(TAG, "【拍照失败】" + e.getMessage());
- }
+ handleTakePhoto();
}
};
private View.OnClickListener onReceivedPictureClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
- mBgSourceUtils.getPreviewBackgroundBean().setIsUseBackgroundFile(true);
- mBgSourceUtils.saveSettings();
- doubleRefreshPreview();
- isPreviewBackgroundChanged = true;
+ LogUtils.d(TAG, "【按钮点击】恢复收到的图片");
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【操作异常】预览Bean为空");
+ return;
+ }
+ previewBean.setIsUseBackgroundFile(true);
+ mBgSourceUtils.saveSettings();
+ doubleRefreshPreview();
+ isPreviewBackgroundChanged = true;
}
};
private View.OnClickListener onPixelPickerClickListener = new View.OnClickListener() {
-
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】像素拾取");
- String targetImagePath = mBgSourceUtils.getPreviewBackgroundBean().getBackgroundFilePath();
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【操作异常】预览Bean为空");
+ ToastUtils.show("无有效图片可拾取像素");
+ return;
+ }
+ String targetImagePath = previewBean.getBackgroundFilePath();
File targetFile = new File(targetImagePath);
if (targetFile == null || !targetFile.exists() || targetFile.length() <= 0) {
ToastUtils.show("无有效图片可拾取像素");
@@ -324,48 +314,59 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】清空像素颜色");
- BackgroundBean bean = mBgSourceUtils.getPreviewBackgroundBean();
- int oldColor = bean.getPixelColor();
- bean.setPixelColor(0xFF000000);
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【操作异常】预览Bean为空");
+ return;
+ }
+ int oldColor = previewBean.getPixelColor();
+ previewBean.setPixelColor(0xFF000000);
mBgSourceUtils.saveSettings();
doubleRefreshPreview();
- isPreviewBackgroundChanged = true;
+ isPreviewBackgroundChanged = true;
ToastUtils.show("像素颜色已清空");
- LogUtils.d(TAG, "【像素清空】旧颜色:" + oldColor);
+ LogUtils.d(TAG, "【像素清空】旧颜色:" + String.format("#%08X", oldColor));
}
};
- private View.OnClickListener onColorPaletteClickListener = new View.OnClickListener() {
+ private View.OnClickListener onColorPaletteClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
LogUtils.d(TAG, "【按钮点击】调色板按钮");
-
- // 初始颜色(白色,含透明度)
- //int initialColor = 0xFFFFFFFF;
- int initialColor = mBgSourceUtils.getPreviewBackgroundBean().getPixelColor();
- // 显示对话框
- ColorPaletteDialog dialog = new ColorPaletteDialog(BackgroundSettingsActivity.this, initialColor, new ColorPaletteDialog.OnColorSelectedListener() {
+ final BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【操作异常】预览Bean为空");
+ return;
+ }
+ int initialColor = previewBean.getPixelColor();
+ LogUtils.d(TAG, "【调色板】初始颜色:" + String.format("#%08X", initialColor));
+ ColorPaletteDialog dialog = new ColorPaletteDialog(BackgroundSettingsActivity.this, initialColor, new ColorPaletteDialog.OnColorSelectedListener() {
@Override
public void onColorSelected(int color) {
- // 回调返回 0xAARRGGBB 格式颜色,直接使用
- mBgSourceUtils.getPreviewBackgroundBean().setPixelColor(color);
+ previewBean.setPixelColor(color);
mBgSourceUtils.saveSettings();
doubleRefreshPreview();
isPreviewBackgroundChanged = true;
- LogUtils.d("选择颜色", String.format("#%08X", color));
+ LogUtils.d(TAG, "【颜色选择】选中颜色:" + String.format("#%08X", color));
}
});
- dialog.show();
-
- LogUtils.d(TAG, "调色板按钮响应完成。");
+ dialog.show();
+ LogUtils.d(TAG, "【调色板】对话框已显示");
}
};
- // ====================== 工具方法 ======================
+ // ====================== 工具方法(通用工具 + 视图工具)======================
/**
* 生成 FileProvider Uri,适配 Android 7.0+
+ * @param file 目标文件
+ * @return 适配后的Uri,失败返回null
*/
public Uri getFileProviderUri(File file) {
+ LogUtils.d(TAG, "【工具方法】生成FileProvider Uri,文件路径:" + (file != null ? file.getAbsolutePath() : "null"));
+ if (file == null) {
+ LogUtils.e(TAG, "【工具异常】文件为空");
+ return null;
+ }
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String FILE_PROVIDER_AUTHORITY = getPackageName() + ".fileprovider";
@@ -374,24 +375,27 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
return Uri.fromFile(file);
}
} catch (Exception e) {
- LogUtils.e(TAG, "getFileProviderUri: 生成Uri失败:" + e.getMessage());
+ LogUtils.e(TAG, "【工具异常】生成Uri失败:" + e.getMessage());
return null;
}
}
/**
* 校验 Bitmap 是否有效(未被回收且不为空)
+ * @param bitmap 目标Bitmap
+ * @return 有效返回true,否则false
*/
private boolean isBitmapValid(Bitmap bitmap) {
- return bitmap != null && !bitmap.isRecycled();
+ boolean isValid = bitmap != null && !bitmap.isRecycled();
+ LogUtils.d(TAG, "【工具方法】Bitmap有效性校验:" + isValid);
+ return isValid;
}
/**
* 双重刷新预览,确保背景加载最新数据
- * 移除:缓存清空逻辑
*/
private void doubleRefreshPreview() {
- LogUtils.d(TAG, "【工具方法】doubleRefreshPreview 开始执行");
+ LogUtils.d(TAG, "【工具方法】开始双重刷新预览");
if (mBgSourceUtils == null || mBackgroundView == null || isFinishing()) {
LogUtils.w(TAG, "【双重刷新】跳过:对象为空或Activity已结束");
return;
@@ -400,8 +404,9 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
// 第一重刷新
try {
mBgSourceUtils.loadSettings();
- mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean(), true);
- mBackgroundView.setBackgroundColor(mBgSourceUtils.getPreviewBackgroundBean().getPixelColor());
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ mBackgroundView.loadBackgroundBean(previewBean, true);
+ mBackgroundView.setBackgroundColor(previewBean.getPixelColor());
LogUtils.d(TAG, "【双重刷新】第一重完成");
} catch (Exception e) {
LogUtils.e(TAG, "【双重刷新】第一重异常:" + e.getMessage());
@@ -415,8 +420,9 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
if (mBackgroundView != null && !isFinishing() && mBgSourceUtils != null) {
try {
mBgSourceUtils.loadSettings();
- mBackgroundView.loadBackgroundBean(mBgSourceUtils.getPreviewBackgroundBean(), true);
- mBackgroundView.setBackgroundColor(mBgSourceUtils.getPreviewBackgroundBean().getPixelColor());
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ mBackgroundView.loadBackgroundBean(previewBean, true);
+ mBackgroundView.setBackgroundColor(previewBean.getPixelColor());
LogUtils.d(TAG, "【双重刷新】第二重完成");
} catch (Exception e) {
LogUtils.e(TAG, "【双重刷新】第二重异常:" + e.getMessage());
@@ -428,26 +434,25 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
/**
* 解析裁剪临时文件为 Bitmap,带采样率优化
+ * @param cropTempFile 裁剪临时文件
+ * @return 解析后的Bitmap,失败返回null
*/
private Bitmap parseCropTempFileToBitmap(File cropTempFile) {
- LogUtils.d(TAG, "【工具方法】parseCropTempFileToBitmap 解析文件:" + (cropTempFile != null ? cropTempFile.getAbsolutePath() : "null"));
+ LogUtils.d(TAG, "【工具方法】解析裁剪文件:" + (cropTempFile != null ? cropTempFile.getAbsolutePath() : "null"));
if (cropTempFile == null || !cropTempFile.exists() || !cropTempFile.isFile() || cropTempFile.length() <= 100) {
LogUtils.e(TAG, "【Bitmap解析】文件无效");
return null;
}
+ // 计算采样率
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(cropTempFile.getAbsolutePath(), options);
- int maxSize = 2048;
- int sampleSize = 1;
- while (options.outWidth / sampleSize > maxSize || options.outHeight / sampleSize > maxSize) {
- sampleSize *= 2;
- }
- sampleSize = Math.min(sampleSize, 16);
+ int sampleSize = calculateSampleSize(options.outWidth, options.outHeight);
LogUtils.d(TAG, "【Bitmap解析】采样率:" + sampleSize);
+ // 解析Bitmap
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.RGB_565;
@@ -472,123 +477,69 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
}
/**
- * 调整 Bitmap 比例至目标比例
+ * 计算Bitmap采样率
+ * @param width 图片宽度
+ * @param height 图片高度
+ * @return 采样率
*/
- private Bitmap adjustBitmapToFinalRatio(Bitmap originalBitmap, float finalCropRatio) {
- LogUtils.d(TAG, "【工具方法】adjustBitmapToFinalRatio 调整比例,目标比例:" + finalCropRatio);
- if (!isBitmapValid(originalBitmap) || finalCropRatio <= 0) {
- LogUtils.e(TAG, "【比例调整】参数无效");
- return null;
+ private int calculateSampleSize(int width, int height) {
+ int sampleSize = 1;
+ while (width / sampleSize > BITMAP_MAX_SIZE || height / sampleSize > BITMAP_MAX_SIZE) {
+ sampleSize *= 2;
}
+ return Math.min(sampleSize, BITMAP_MAX_SAMPLE_SIZE);
+ }
- int originalWidth = originalBitmap.getWidth();
- int originalHeight = originalBitmap.getHeight();
- float originalRatio = (float) originalWidth / originalHeight;
-
- if (Math.abs(originalRatio - finalCropRatio) < 0.001f) {
- LogUtils.d(TAG, "【比例调整】比例一致,生成副本");
- return originalBitmap.copy(originalBitmap.getConfig(), false);
+ // ====================== 业务逻辑方法(按功能分类)======================
+ /**
+ * 初始化核心组件(工具类+视图)
+ */
+ private void initCoreComponents() {
+ // 初始化视图
+ mBackgroundView = findViewById(R.id.background_view);
+ if (mBackgroundView == null) {
+ LogUtils.e(TAG, "【初始化异常】BackgroundView未找到");
}
+ // 初始化工具类
+ mBgSourceUtils = BackgroundSourceUtils.getInstance(this);
+ mBgSourceUtils.loadSettings();
+ mBitmapCache = BitmapCacheUtils.getInstance();
+ LogUtils.d(TAG, "【初始化】视图与工具类加载完成");
+ }
- int targetWidth, targetHeight;
- targetHeight = originalHeight;
- targetWidth = Math.round(targetHeight * finalCropRatio);
- if (targetWidth > originalWidth) {
- targetWidth = originalWidth;
- targetHeight = Math.round(targetWidth / finalCropRatio);
- }
- targetWidth = Math.round(targetHeight * finalCropRatio);
- LogUtils.d(TAG, "【比例调整】调整前:" + originalWidth + "x" + originalHeight + ",调整后:" + targetWidth + "x" + targetHeight);
-
- try {
- Bitmap adjustedBitmap = Bitmap.createBitmap(
- originalBitmap,
- (originalWidth - targetWidth) / 2,
- (originalHeight - targetHeight) / 2,
- targetWidth,
- targetHeight
- );
- return adjustedBitmap;
- } catch (OutOfMemoryError e) {
- LogUtils.e(TAG, "【比例调整】OOM异常");
- return null;
+ /**
+ * 处理意图或初始化预览
+ */
+ private void handleIntentOrPreview() {
+ if (handleShareIntent()) {
+ ToastUtils.show("已接收分享图片");
+ } else {
+ mBgSourceUtils.setCurrentSourceToPreview();
+ LogUtils.d(TAG, "【预览初始化】加载当前背景配置");
}
}
/**
- * 保存 Bitmap 到目标文件
- * 移除:原文件删除逻辑
+ * 初始化预览环境
*/
- private void saveScaledBitmapToFile(Bitmap bitmap, File targetFile) {
- LogUtils.d(TAG, "【工具方法】saveScaledBitmapToFile 保存图片:" + targetFile.getAbsolutePath());
- if (!isBitmapValid(bitmap) || targetFile == null) {
- LogUtils.e(TAG, "【图片保存】参数无效");
- return;
- }
-
- OutputStream outputStream = null;
- try {
- outputStream = new BufferedOutputStream(new FileOutputStream(targetFile));
- bitmap.compress(CompressFormat.JPEG, 100, outputStream);
- outputStream.flush();
- LogUtils.d(TAG, "【图片保存】成功,文件大小:" + targetFile.length() + " bytes");
- } catch (IOException e) {
- LogUtils.e(TAG, "【图片保存】异常:" + e.getMessage());
- } finally {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException e) {
- LogUtils.e(TAG, "【图片保存】关闭流异常");
- }
- }
- }
+ private void initPreviewEnvironment() {
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ mBgSourceUtils.createAndUpdatePreviewEnvironmentForCropping(previewBean);
+ doubleRefreshPreview();
}
- /**
- * 从裁剪文件中读取比例
- */
- private float getRatioFromSystemCropFile(File systemCropFile) {
- LogUtils.d(TAG, "【工具方法】getRatioFromSystemCropFile 读取比例:" + systemCropFile.getAbsolutePath());
- if (systemCropFile == null || !systemCropFile.exists() || !systemCropFile.isFile()) {
- LogUtils.e(TAG, "【比例读取】文件无效");
- return -1;
- }
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(systemCropFile.getAbsolutePath(), options);
-
- int cropWidth = options.outWidth;
- int cropHeight = options.outHeight;
- if (cropWidth <= 0 || cropHeight <= 0) {
- LogUtils.e(TAG, "【比例读取】尺寸无效");
- return -1;
- }
-
- float systemRatio = (float) cropWidth / cropHeight;
- LogUtils.d(TAG, "【比例读取】成功,比例:" + systemRatio);
- return systemRatio;
- }
-
- // ====================== 业务逻辑方法 ======================
/**
* 处理分享意图
+ * @return 处理成功返回true,否则false
*/
private boolean handleShareIntent() {
Intent intent = getIntent();
if (intent != null) {
String action = intent.getAction();
String type = intent.getType();
+ LogUtils.d(TAG, "【分享处理】action:" + action + ",type:" + type);
if (Intent.ACTION_SEND.equals(action) && type != null && isImageType(type)) {
- BackgroundPicturePreviewDialog dlg = new BackgroundPicturePreviewDialog(this, new BackgroundPicturePreviewDialog.IOnRecivedPictureListener(){
- @Override
- public void onAcceptRecivedPicture(Uri uriRecivedPicture) {
- ToastUtils.show(String.format("uriRecivedPicture %s", uriRecivedPicture));
- }
- });
- dlg.show();
- LogUtils.d(TAG, "【分享处理】收到分享图片意图");
+ showSharePreviewDialog();
return true;
}
}
@@ -596,9 +547,30 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
}
/**
- * 判断是否为图片类型
+ * 显示分享图片预览对话框
*/
- boolean isImageType(String lowerMimeType) {
+ private void showSharePreviewDialog() {
+ BackgroundPicturePreviewDialog dlg = new BackgroundPicturePreviewDialog(this, new BackgroundPicturePreviewDialog.IOnRecivedPictureListener() {
+ @Override
+ public void onAcceptRecivedPicture(Uri uriRecivedPicture) {
+ ToastUtils.show("已接收图片:" + uriRecivedPicture);
+ LogUtils.d(TAG, "【分享处理】接收图片Uri:" + uriRecivedPicture);
+ }
+ });
+ dlg.show();
+ LogUtils.d(TAG, "【分享处理】显示图片预览对话框");
+ }
+
+ /**
+ * 判断是否为图片类型
+ * @param mimeType MIME类型
+ * @return 是图片返回true,否则false
+ */
+ private boolean isImageType(String mimeType) {
+ if (mimeType == null) {
+ return false;
+ }
+ String lowerMimeType = mimeType.toLowerCase();
return lowerMimeType.equals("image/jpeg")
|| lowerMimeType.equals("image/png")
|| lowerMimeType.equals("image/tiff")
@@ -610,19 +582,37 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
* 启动图片选择器
*/
private void launchImageSelector() {
- LogUtils.d(TAG, "【业务逻辑】launchImageSelector 启动选择器");
+ LogUtils.d(TAG, "【业务逻辑】启动图片选择器");
+ Intent[] intents = createImageSelectorIntents();
+ Intent validIntent = findValidIntent(intents);
+
+ if (validIntent != null) {
+ launchImageChooser(validIntent);
+ } else {
+ showNoGalleryDialog();
+ }
+ }
+
+ /**
+ * 创建图片选择器意图数组
+ * @return 意图数组
+ */
+ private Intent[] createImageSelectorIntents() {
Intent[] intents = new Intent[3];
+ // ACTION_GET_CONTENT
Intent getContentIntent = new Intent(Intent.ACTION_GET_CONTENT);
getContentIntent.setType("image/*");
getContentIntent.addCategory(Intent.CATEGORY_OPENABLE);
getContentIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intents[0] = getContentIntent;
+ // ACTION_PICK
Intent pickIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickIntent.setType("image/*");
pickIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intents[1] = pickIntent;
+ // ACTION_OPEN_DOCUMENT(API19+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Intent openDocIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
openDocIntent.setType("image/*");
@@ -630,58 +620,68 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
openDocIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intents[2] = openDocIntent;
}
-
- Intent validIntent = null;
- for (Intent intent : intents) {
- if (intent != null && intent.resolveActivity(getPackageManager()) != null) {
- validIntent = intent;
- break;
- }
- }
-
- if (validIntent != null) {
- Intent chooser = Intent.createChooser(validIntent, "选择图片");
- chooser.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
- startActivityForResult(chooser, REQUEST_SELECT_PICTURE);
- LogUtils.d(TAG, "【选图意图】启动图片选择");
- } else {
- LogUtils.d(TAG, "【选图意图】无相册应用");
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- ToastUtils.show("未找到相册应用,请安装后重试");
- new AlertDialog.Builder(BackgroundSettingsActivity.this)
- .setTitle("无图片选择应用")
- .setMessage("需要安装相册应用才能选择图片")
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent marketIntent = new Intent(Intent.ACTION_VIEW);
- marketIntent.setData(Uri.parse("market://details?id=com.android.gallery3d"));
- if (marketIntent.resolveActivity(getPackageManager()) != null) {
- startActivity(marketIntent);
- } else {
- ToastUtils.show("无法打开应用商店");
- }
- }
- })
- .setNegativeButton("取消", null)
- .show();
- }
- });
- }
+ return intents;
}
/**
- * 处理存储权限回调
+ * 查找有效的意图
+ * @param intents 意图数组
+ * @return 有效意图,无则返回null
*/
- private void handleStoragePermissionCallback() {
- if (Environment.isExternalStorageManager()) {
- LogUtils.d(TAG, "【权限回调】已授予");
- ToastUtils.show("存储权限已获取");
+ private Intent findValidIntent(Intent[] intents) {
+ for (Intent intent : intents) {
+ if (intent != null && intent.resolveActivity(getPackageManager()) != null) {
+ return intent;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 启动图片选择器
+ * @param validIntent 有效意图
+ */
+ private void launchImageChooser(Intent validIntent) {
+ Intent chooser = Intent.createChooser(validIntent, "选择图片");
+ chooser.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+ startActivityForResult(chooser, REQUEST_SELECT_PICTURE);
+ LogUtils.d(TAG, "【选图意图】启动图片选择");
+ }
+
+ /**
+ * 显示无相册应用提示对话框
+ */
+ private void showNoGalleryDialog() {
+ LogUtils.d(TAG, "【选图意图】无相册应用");
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ToastUtils.show("未找到相册应用,请安装后重试");
+ new AlertDialog.Builder(BackgroundSettingsActivity.this)
+ .setTitle("无图片选择应用")
+ .setMessage("需要安装相册应用才能选择图片")
+ .setPositiveButton("确定", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ launchGalleryMarket();
+ }
+ })
+ .setNegativeButton("取消", null)
+ .show();
+ }
+ });
+ }
+
+ /**
+ * 启动应用商店下载相册
+ */
+ private void launchGalleryMarket() {
+ Intent marketIntent = new Intent(Intent.ACTION_VIEW);
+ marketIntent.setData(Uri.parse("market://details?id=com.android.gallery3d"));
+ if (marketIntent.resolveActivity(getPackageManager()) != null) {
+ startActivity(marketIntent);
} else {
- LogUtils.d(TAG, "【权限回调】已拒绝");
- ToastUtils.show("存储权限不足");
+ ToastUtils.show("无法打开应用商店");
}
}
@@ -696,115 +696,112 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
}
/**
- * 处理拍照结果
+ * 处理拍照逻辑(权限通过后执行)
*/
- private void handleTakePhotoResult(int resultCode, Intent data) {
- LogUtils.d(TAG, "【业务逻辑】handleTakePhotoResult 处理拍照结果");
- if (resultCode != RESULT_OK || data == null) {
- handleOperationCancelOrFail();
+ void handleTakePhoto() {
+ LogUtils.d(TAG, "【业务逻辑】开始处理拍照");
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【拍照失败】预览Bean为空");
+ ToastUtils.show("拍照文件创建失败");
return;
}
- if (!mfTakePhoto.exists() || mfTakePhoto.length() <= 0) {
- ToastUtils.show("拍照文件无效");
+ File takePhotoFile = new File(previewBean.getBackgroundFilePath());
+ if (!takePhotoFile.exists()) {
+ ToastUtils.show("拍照文件创建失败");
+ LogUtils.e(TAG, "【拍照失败】文件不存在:" + takePhotoFile.getAbsolutePath());
return;
}
- Bitmap photoBitmap = getTakePhotoBitmap(data);
- if (isBitmapValid(photoBitmap)) {
- mBgSourceUtils.compressQualityToRecivedPicture(photoBitmap);
- } else {
- ToastUtils.show("拍照图片为空");
+ Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ try {
+ Uri photoUri = getFileProviderUri(takePhotoFile);
+ if (photoUri == null) {
+ throw new Exception("生成FileProvider Uri失败");
+ }
+ takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
+ startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
+ LogUtils.d(TAG, "【拍照启动】Uri:" + photoUri.toString());
+ } catch (Exception e) {
+ String errMsg = "拍照启动异常:" + e.getMessage();
+ ToastUtils.show(errMsg.substring(0, 20));
+ LogUtils.e(TAG, "【拍照失败】" + e.getMessage());
+ }
+ }
+
+ /**
+ * 处理ActivityResult分发
+ * @param requestCode 请求码
+ * @param data 回调数据
+ */
+ private void handleActivityResult(int requestCode, Intent data) {
+ switch (requestCode) {
+ case REQUEST_SELECT_PICTURE:
+ handleSelectPictureResult(data);
+ break;
+ case REQUEST_TAKE_PHOTO:
+ handleTakePhotoResult(data);
+ break;
+ case REQUEST_CROP_IMAGE:
+ handleCropImageResult(data);
+ break;
+ case REQUEST_PIXELPICKER:
+ handlePixelPickerResult();
+ break;
+ default:
+ LogUtils.d(TAG, "【回调忽略】未知requestCode:" + requestCode);
+ break;
+ }
+ }
+
+ /**
+ * 处理拍照结果
+ * @param data 回调数据
+ */
+ private void handleTakePhotoResult(Intent data) {
+ LogUtils.d(TAG, "【业务逻辑】处理拍照结果");
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【拍照结果处理】预览Bean为空");
return;
}
- mBgSourceUtils.saveFileToPreviewBean(mfTakePhoto, mfTakePhoto.getAbsolutePath());
+ previewBean.setIsUseBackgroundFile(true);
+ previewBean.setIsUseBackgroundScaledCompressFile(false);
+ mBgSourceUtils.saveSettings();
doubleRefreshPreview();
- ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
- mBgSourceUtils.getPreviewBackgroundBean(),
- mBackgroundView.getWidth(),
- mBackgroundView.getHeight(),
- false,
- REQUEST_CROP_IMAGE
- );
+ startImageCrop(false);
LogUtils.d(TAG, "【拍照完成】已启动裁剪");
}
- /**
- * 解析拍照返回的 Bitmap
- */
- private Bitmap getTakePhotoBitmap(Intent data) {
- LogUtils.d(TAG, "【业务逻辑】getTakePhotoBitmap 解析拍照Bitmap");
- if (mfTakePhoto != null && mfTakePhoto.exists()) {
- LogUtils.d(TAG, "【拍照Bitmap解析】从文件解析");
- Bitmap photoBitmap = parseCropTempFileToBitmap(mfTakePhoto);
- if (isBitmapValid(photoBitmap)) {
- LogUtils.d(TAG, "【拍照Bitmap解析】成功");
- return photoBitmap;
- } else {
- LogUtils.w(TAG, "【拍照Bitmap解析】文件解析失败,尝试Intent");
- }
- } else {
- LogUtils.w(TAG, "【拍照Bitmap解析】文件无效,尝试Intent");
- }
-
- if (data != null) {
- try {
- Bitmap thumbnailBitmap = data.getParcelableExtra("data");
- if (isBitmapValid(thumbnailBitmap)) {
- LogUtils.d(TAG, "【拍照Bitmap解析】从Intent获取成功");
- return thumbnailBitmap;
- } else {
- LogUtils.e(TAG, "【拍照Bitmap解析】Intent解析失败");
- }
- } catch (Exception e) {
- LogUtils.e(TAG, "【拍照Bitmap解析】Intent异常:" + e.getMessage());
- }
- } else {
- LogUtils.e(TAG, "【拍照Bitmap解析】Intent为空");
- }
-
- LogUtils.e(TAG, "【拍照Bitmap解析】失败");
- ToastUtils.show("拍照图片解析失败");
- return null;
- }
-
/**
* 处理选图结果
- * 移除:缓存清空逻辑
+ * @param data 回调数据
*/
- private void handleSelectPictureResult(int resultCode, Intent data) {
- LogUtils.d(TAG, "【业务逻辑】handleSelectPictureResult 处理选图结果");
- if (resultCode != RESULT_OK || data == null) {
- handleOperationCancelOrFail();
- return;
- }
-
+ private void handleSelectPictureResult(Intent data) {
+ LogUtils.d(TAG, "【业务逻辑】处理选图结果");
Uri selectedImage = data.getData();
if (selectedImage == null) {
ToastUtils.show("图片Uri为空");
+ LogUtils.e(TAG, "【选图结果】Uri为空");
return;
}
LogUtils.d(TAG, "【选图回调】系统返回Uri : " + selectedImage.toString());
+ // 申请持久化权限(API33+)
if (Build.VERSION.SDK_INT >= SDK_VERSION_TIRAMISU) {
getContentResolver().takePersistableUriPermission(
selectedImage,
- Intent.FLAG_GRANT_READ_URI_PERMISSION
- );
+ Intent.FLAG_GRANT_READ_URI_PERMISSION);
LogUtils.d(TAG, "【选图权限】已添加持久化权限");
}
+ // 同步文件并启动裁剪
if (putUriFileToPreviewSource(selectedImage)) {
LogUtils.d(TAG, "【选图同步】路径绑定完成");
- ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
- mBgSourceUtils.getPreviewBackgroundBean(),
- mBackgroundView.getWidth(),
- mBackgroundView.getHeight(),
- false,
- REQUEST_CROP_IMAGE
- );
+ startImageCrop(false);
} else {
ToastUtils.show("图片同步失败");
LogUtils.e(TAG, "【选图同步】文件复制失败");
@@ -813,11 +810,13 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
/**
* 将 Uri 文件同步到预览 Bean
+ * @param srcUriFile 源Uri
+ * @return 同步成功返回true,否则false
*/
- boolean putUriFileToPreviewSource(Uri srcUriFile) {
+ private boolean putUriFileToPreviewSource(Uri srcUriFile) {
String filePath = UriUtils.getFilePathFromUri(this, srcUriFile);
if (TextUtils.isEmpty(filePath)) {
- LogUtils.e(TAG, "putUriFileToPreviewSource: Uri解析路径为空");
+ LogUtils.e(TAG, "【选图同步】Uri解析路径为空");
return false;
}
File srcFile = new File(filePath);
@@ -826,74 +825,158 @@ public class BackgroundSettingsActivity extends WinBoLLActivity {
/**
* 将 File 同步到预览 Bean
- * 保留:核心修复逻辑(更新预览Bean路径)
+ * @param srcFile 源文件
+ * @return 同步成功返回true,否则false
*/
- boolean putUriFileToPreviewSource(File srcFile) {
- LogUtils.d(TAG, String.format("putUriFileToPreviewSource(File srcFile) srcFile %s", srcFile));
- mBgSourceUtils.loadSettings();
- BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
- File dstFile = new File(previewBean.getBackgroundFilePath());
- LogUtils.d(TAG, String.format("putUriFileToPreviewSource(File srcFile) dstFile %s", dstFile));
+ private boolean putUriFileToPreviewSource(File srcFile) {
+ LogUtils.d(TAG, "【选图同步】源文件:" + srcFile.getAbsolutePath());
+ mBgSourceUtils.loadSettings();
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ File dstFile = new File(previewBean.getBackgroundFilePath());
+ LogUtils.d(TAG, "【选图同步】目标文件:" + dstFile.getAbsolutePath());
if (FileUtils.copyFile(srcFile, dstFile)) {
- LogUtils.d(TAG, "putUriFileToPreviewSource(File srcFile) 文件拷贝成功。 ");
- return true;
- }
- LogUtils.d(TAG, "putUriFileToPreviewSource(File srcFile) 文件无法拷贝。 ");
- return false;
+ LogUtils.d(TAG, "【选图同步】文件拷贝成功");
+ return true;
+ }
+ LogUtils.d(TAG, "【选图同步】文件无法拷贝");
+ return false;
}
/**
* 处理裁剪结果
+ * @param data 回调数据
*/
- private void handleCropImageResult(int requestCode, int resultCode, Intent data) {
- LogUtils.d(TAG, "【业务逻辑】handleCropImageResult 处理裁剪结果");
- File cropTempFile = new File(mBgSourceUtils.getPreviewBackgroundBean().getBackgroundScaledCompressFilePath());
+ private void handleCropImageResult(Intent data) {
+ LogUtils.d(TAG, "【业务逻辑】处理裁剪结果");
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【裁剪结果处理】预览Bean为空");
+ handleOperationCancelOrFail();
+ return;
+ }
+
+ File cropTempFile = new File(previewBean.getBackgroundScaledCompressFilePath());
boolean isFileExist = cropTempFile.exists();
boolean isFileReadable = isFileExist ? cropTempFile.canRead() : false;
long fileSize = isFileExist ? cropTempFile.length() : 0;
- boolean isCropSuccess = (resultCode == RESULT_OK) && isFileExist && isFileReadable && fileSize > 100;
+ boolean isCropSuccess = isFileExist && isFileReadable && fileSize > 100;
if (isCropSuccess) {
- isPreviewBackgroundChanged = true;
- LogUtils.d(TAG, "【裁剪结果】裁剪成功");
- final BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
- previewBean.setIsUseBackgroundFile(true);
- previewBean.setIsUseBackgroundScaledCompressFile(true);
- mBgSourceUtils.saveSettings();
- doubleRefreshPreview();
-
-// float systemFileRatio = getRatioFromSystemCropFile(cropTempFile);
-// if (systemFileRatio > 0) {
-// Bitmap cropBitmap = parseCropTempFileToBitmap(cropTempFile);
-// if (isBitmapValid(cropBitmap)) {
-// Bitmap scaledCropBitmap = adjustBitmapToFinalRatio(cropBitmap, systemFileRatio);
-// if (isBitmapValid(scaledCropBitmap)) {
-// saveScaledBitmapToFile(scaledCropBitmap, cropTempFile);
-// scaledCropBitmap.recycle();
-// }
-// cropBitmap.recycle();
-// } else {
-// LogUtils.e(TAG, "【裁剪结果】裁剪Bitmap解析无效");
-// }
-// }
-//
-// new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
-// @Override
-// public void run() {
-// if (!isFinishing()) {
-// doubleRefreshPreview();
-// LogUtils.d(TAG, "【裁剪结果】触发双重刷新");
-// }
-// }
-// }, 300);
+ handleCropSuccess(previewBean, fileSize);
} else {
- handleOperationCancelOrFail();
+ handleCropFailure(isFileExist, isFileReadable, fileSize);
}
}
- private void handlePixelPickerResult(int requestCode, int resultCode, Intent data) {
- doubleRefreshPreview();
- isPreviewBackgroundChanged = true;
- }
+ /**
+ * 处理裁剪成功
+ * @param previewBean 预览Bean
+ * @param fileSize 文件大小
+ */
+ private void handleCropSuccess(BackgroundBean previewBean, long fileSize) {
+ isPreviewBackgroundChanged = true;
+ LogUtils.d(TAG, "【裁剪结果】裁剪成功,文件大小:" + fileSize);
+ previewBean.setIsUseBackgroundFile(true);
+ previewBean.setIsUseBackgroundScaledCompressFile(true);
+ mBgSourceUtils.saveSettings();
+ doubleRefreshPreview();
+ }
+
+ /**
+ * 处理裁剪失败
+ * @param isFileExist 文件是否存在
+ * @param isFileReadable 文件是否可读
+ * @param fileSize 文件大小
+ */
+ private void handleCropFailure(boolean isFileExist, boolean isFileReadable, long fileSize) {
+ handleOperationCancelOrFail();
+ LogUtils.e(TAG, "【裁剪结果】裁剪失败,文件状态:存在=" + isFileExist + ",可读=" + isFileReadable + ",大小=" + fileSize);
+ }
+
+ /**
+ * 处理像素拾取结果
+ */
+ private void handlePixelPickerResult() {
+ LogUtils.d(TAG, "【业务逻辑】处理像素拾取结果");
+ doubleRefreshPreview();
+ isPreviewBackgroundChanged = true;
+ }
+
+ /**
+ * 处理相机权限申请结果
+ * @param grantResults 权限结果数组
+ */
+ private void handleCameraPermissionResult(int[] grantResults) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ LogUtils.d(TAG, "【权限申请】相机权限授予成功");
+ handleTakePhoto();
+ } else {
+ LogUtils.d(TAG, "【权限申请】相机权限授予失败");
+ ToastUtils.show("相机权限被拒绝,无法拍照");
+ // 引导用户到设置页面开启权限(用户选择不再询问时)
+ if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
+ launchAppSettings();
+ }
+ }
+ }
+
+ /**
+ * 启动应用设置页面
+ */
+ private void launchAppSettings() {
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ Uri uri = Uri.fromParts("package", getPackageName(), null);
+ intent.setData(uri);
+ startActivity(intent);
+ ToastUtils.show("请在设置中开启相机权限");
+ LogUtils.d(TAG, "【权限引导】启动应用设置页面");
+ }
+
+ /**
+ * 处理Finish确认对话框
+ */
+ private void handleFinishConfirmation() {
+ if (isPreviewBackgroundChanged) {
+ YesNoAlertDialog.show(this, "背景更换问题", "是否确定背景图片设置?", new YesNoAlertDialog.OnDialogResultListener() {
+ @Override
+ public void onYes() {
+ mBgSourceUtils.commitPreviewSourceToCurrent();
+ isCommitSettings = true;
+ finish();
+ }
+
+ @Override
+ public void onNo() {
+ isCommitSettings = true;
+ finish();
+ }
+ });
+ } else {
+ isCommitSettings = true;
+ finish();
+ }
+ }
+
+ /**
+ * 启动图片裁剪
+ * @param isFreeCrop 是否自由裁剪
+ */
+ private void startImageCrop(boolean isFreeCrop) {
+ BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean();
+ if (previewBean == null) {
+ LogUtils.e(TAG, "【裁剪启动】预览Bean为空");
+ ToastUtils.show("裁剪失败:无有效图片");
+ return;
+ }
+ int width = isFreeCrop ? 0 : mBackgroundView.getWidth();
+ int height = isFreeCrop ? 0 : mBackgroundView.getHeight();
+ ImageCropUtils.startImageCrop(BackgroundSettingsActivity.this,
+ previewBean,
+ width,
+ height,
+ isFreeCrop,
+ REQUEST_CROP_IMAGE);
+ LogUtils.d(TAG, "【裁剪启动】是否自由裁剪:" + isFreeCrop + ",目标尺寸:" + width + "x" + height);
+ }
}
diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java
index 1627d0b..1bcbd33 100644
--- a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java
+++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import cc.winboll.studio.powerbell.utils.ImageDownloader;
import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils;
+import android.text.TextUtils;
/**
* @Author ZhanGSKen&豆包大模型
@@ -52,7 +53,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
// 按钮点击回调接口(Java7 接口实现)
public interface OnDialogClickListener {
- void onConfirm(String szConfirmFilePath, String previewFileUrl); // 确认按钮点击
+ void onConfirm(String szConfirmFilePath); // 确认按钮点击
void onCancel(); // 取消按钮点击
}
@@ -91,7 +92,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
case MSG_IMAGE_LOAD_SUCCESS:
// 图片加载成功,获取文件路径并设置背景
mDownloadSavedPath = (String) msg.obj;
- previewBackground(mDownloadSavedPath);
+ mBackgroundView.loadImage(mDownloadSavedPath);
break;
case MSG_IMAGE_LOAD_FAILED:
// 图片加载失败,设置默认背景
@@ -139,7 +140,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
etURL = (EditText) dialogView.findViewById(R.id.et_url);
mBackgroundView = (BackgroundView) dialogView.findViewById(R.id.bv_background_preview);
// 加载初始图片
- mBackgroundView.setBackgroundResource(R.drawable.ic_launcher);
+ mBackgroundView.setBackgroundResource(R.drawable.blank100x100);
// 设置按钮点击事件
setButtonClickListeners();
}
@@ -168,13 +169,13 @@ public class NetworkBackgroundDialog extends AlertDialog {
@Override
public void onClick(View v) {
LogUtils.d("NetworkBackgroundDialog", "确认按钮点击");
- // 确定预览背景资源
- BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext);
- utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl);
-
dismiss(); // 关闭对话框
+ if(TextUtils.isEmpty(mDownloadSavedPath)) {
+ ToastUtils.show("未下载图片。");
+ return;
+ }
if (listener != null) {
- listener.onConfirm(mPreviewFilePath, mPreviewFileUrl);
+ listener.onConfirm(mDownloadSavedPath);
}
}
});
@@ -258,6 +259,7 @@ public class NetworkBackgroundDialog extends AlertDialog {
// 发送消息到主线程,携带图片路径
Message successMsg = mUiHandler.obtainMessage(MSG_IMAGE_LOAD_SUCCESS, savePath);
mUiHandler.sendMessage(successMsg);
+
}
@Override
diff --git a/powerbell/src/main/res/drawable/blank100x100.png b/powerbell/src/main/res/drawable/blank100x100.png
new file mode 100644
index 0000000..84e1003
Binary files /dev/null and b/powerbell/src/main/res/drawable/blank100x100.png differ
diff --git a/powerbell/src/main/res/layout/activity_background_settings.xml b/powerbell/src/main/res/layout/activity_background_settings.xml
index e8096d1..74d18c9 100644
--- a/powerbell/src/main/res/layout/activity_background_settings.xml
+++ b/powerbell/src/main/res/layout/activity_background_settings.xml
@@ -40,17 +40,17 @@
android:layout_width="160dp"
android:layout_height="36dp"
android:text="Origin BG"
- android:id="@+id/activitybackgroundpictureAButton5"
android:layout_alignParentLeft="true"
- android:layout_margin="5dp"/>
+ android:layout_margin="5dp"
+ android:id="@+id/activitybackgroundsettingsAButton1"/>
+ android:layout_margin="5dp"
+ android:id="@+id/activitybackgroundsettingsAButton2"/>
@@ -66,7 +66,7 @@
android:text="◎"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
- android:id="@+id/activitybackgroundpictureAButton1"/>
+ android:id="@+id/activitybackgroundsettingsAButton3"/>
+ android:id="@+id/activitybackgroundsettingsAButton4"/>
+ android:id="@+id/activitybackgroundsettingsAButton5"/>
@@ -99,7 +98,7 @@
android:text="[+]"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
- android:id="@+id/activitybackgroundpictureAButton3"/>
+ android:id="@+id/activitybackgroundsettingsAButton6"/>
+ android:id="@+id/activitybackgroundsettingsAButton7"/>
+ android:id="@+id/activitybackgroundsettingsAButton8"/>
+ android:onClick="onColorPaletteDialog"
+ android:id="@+id/activitybackgroundsettingsAButton9"/>
+ android:id="@+id/activitybackgroundsettingsAButton10"/>
diff --git a/powerbell/src/main/res/layout/dialog_networkbackground.xml b/powerbell/src/main/res/layout/dialog_networkbackground.xml
index 34e7ea7..2b5cf40 100644
--- a/powerbell/src/main/res/layout/dialog_networkbackground.xml
+++ b/powerbell/src/main/res/layout/dialog_networkbackground.xml
@@ -13,11 +13,20 @@
android:id="@+id/tv_dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="网络后台提示"
+ android:text="网络图片资源下载"
android:textSize="18sp"
android:textColor="@android:color/black"
android:textStyle="bold"/>
+
+
-
-
@@ -83,7 +83,7 @@
android:id="@+id/btn_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="允许"
+ android:text="使用图片"
android:textSize="14sp"
android:background="@android:drawable/btn_default_small"/>