From 6635358ec5d4a1f57462f5364cf570c123dac57f Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 19 Jun 2025 10:19:10 +0800 Subject: [PATCH 01/20] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E4=B8=B4=E6=97=B6=E5=89=AA=E8=A3=81=E8=B7=AF=E5=BE=84=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8Pictures=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.properties | 4 +- .../java/cc/winboll/studio/powerbell/App.java | 28 +- .../activities/BackgroundPictureActivity.java | 447 ++++++++++++------ 3 files changed, 321 insertions(+), 158 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index f3ffbfa..4921bc3 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu May 29 09:43:37 HKT 2025 +#Thu Jun 19 02:15:49 GMT 2025 stageCount=2 libraryProject= baseVersion=15.4 publishVersion=15.4.1 -buildCount=0 +buildCount=7 baseBetaVersion=15.4.2 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java index 6e2c6a9..bb5b2c2 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/App.java @@ -1,6 +1,7 @@ package cc.winboll.studio.powerbell; import android.content.Context; +import android.os.Environment; import android.view.Gravity; import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.powerbell.receivers.GlobalApplicationReceiver; @@ -18,7 +19,7 @@ public class App extends GlobalApplication { static AppCacheUtils _mAppCacheUtils; GlobalApplicationReceiver mReceiver; static String szTempDir = ""; - + public static String getTempDirPath() { return szTempDir; } @@ -26,15 +27,24 @@ public class App extends GlobalApplication { @Override public void onCreate() { super.onCreate(); + + // 临时文件夹方案1 + // 获取Pictures文件夹路径(Android 10及以上推荐使用MediaStore,此处为传统方式) + File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); + // 定义目标文件路径(在Pictures目录下创建"PowerBell"子文件夹及文件) + File powerBellDir = new File(picturesDir, "PowerBell"); - // 初始化临时文件夹目录 - File fTempDir = new File(getExternalCacheDir(), "TempDir"); - if(!fTempDir.exists()) { - fTempDir.mkdirs(); + // 临时文件夹方案2 <图片保存失败> + // 获取Pictures文件夹路径(Android 10及以上推荐使用MediaStore,此处为传统方式) + //File powerBellDir = getExternalFilesDir("TempDir"); + + // 先创建文件夹(如果不存在) + if (!powerBellDir.exists()) { + powerBellDir.mkdirs(); } - szTempDir = fTempDir.getAbsolutePath(); - - + szTempDir = powerBellDir.getAbsolutePath(); + + // 初始化 Toast 框架 ToastUtils.init(this); // 设置 Toast 布局样式 @@ -45,7 +55,7 @@ public class App extends GlobalApplication { // 设置数据配置存储工具 _mAppConfigUtils = getAppConfigUtils(this); _mAppCacheUtils = getAppCacheUtils(this); - + mReceiver = new GlobalApplicationReceiver(this); mReceiver.registerAction(); } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java index 2ddca5f..0aa5766 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java @@ -1,22 +1,26 @@ package cc.winboll.studio.powerbell.activities; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.ImageView; -import android.widget.Toast; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import cc.winboll.studio.libaes.views.AToolbar; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.utils.ToastUtils; import cc.winboll.studio.powerbell.App; import cc.winboll.studio.powerbell.R; -import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; import cc.winboll.studio.powerbell.beans.BackgroundPictureBean; import cc.winboll.studio.powerbell.dialogs.BackgroundPicturePreviewDialog; import cc.winboll.studio.powerbell.utils.BackgroundPictureUtils; @@ -24,42 +28,35 @@ import cc.winboll.studio.powerbell.utils.FileUtils; import cc.winboll.studio.powerbell.utils.UriUtil; import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -public class BackgroundPictureActivity extends Activity -implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { +public class BackgroundPictureActivity extends Activity implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { public static final String TAG = "BackgroundPictureActivity"; - public BackgroundPictureUtils mBackgroundPictureUtils; - // 图片选择请求 + // 图片选择请求码 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 STORAGE_PERMISSION_REQUEST = 100; - AToolbar mAToolbar; - // 所有图片存储的文件夹 - File mfBackgroundDir; - // 拍照与剪裁的文件夹 - File mfPictureDir; - // 拍照文件类 - File mfTakePhoto; - // 接收到的图片文件类 - public File mfRecivedPicture; - // 剪裁文件类 - File mfTempCropPicture; - // 剪裁接收后的文件的文件名 + private AToolbar mAToolbar; + private File mfBackgroundDir; // 背景图片存储文件夹 + private File mfPictureDir; // 拍照与剪裁临时文件夹 + private File mfTakePhoto; // 拍照文件 + private File mfRecivedPicture; // 接收的图片文件 + private File mfTempCropPicture; // 剪裁临时文件 + private File mfRecivedCropPicture; // 剪裁后的目标文件 + + // 静态变量 public static String _mszRecivedCropPicture = "RecivedCrop.jpg"; - File mfRecivedCropPicture; - static String _mszCommonFileType = "jpeg"; - // 背景图片的压缩比 - int mnPictureCompress = 100; - static String _RecivedPictureFileName; + private static String _mszCommonFileType = "jpeg"; + private int mnPictureCompress = 100; + private static String _RecivedPictureFileName; @Override protected void onCreate(Bundle savedInstanceState) { @@ -67,30 +64,29 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { setContentView(R.layout.activity_backgroundpicture); initEnv(); + // 初始化工具类和文件夹 mBackgroundPictureUtils = BackgroundPictureUtils.getInstance(this); mfBackgroundDir = new File(mBackgroundPictureUtils.getBackgroundDir()); if (!mfBackgroundDir.exists()) { mfBackgroundDir.mkdirs(); } - //mfPictureDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), getString(R.string.app_projectname)); + mfPictureDir = new File(App.getTempDirPath()); if (!mfPictureDir.exists()) { mfPictureDir.mkdirs(); } + + // 初始化文件对象 mfTakePhoto = new File(mfPictureDir, "TakePhoto.jpg"); mfTempCropPicture = new File(mfPictureDir, "TempCrop.jpg"); + mfRecivedPicture = getRecivedPictureFile(this); mfRecivedCropPicture = new File(mfBackgroundDir, _mszRecivedCropPicture); // 初始化工具栏 mAToolbar = (AToolbar) findViewById(R.id.toolbar); setActionBar(mAToolbar); - //mAToolbar.setTitle(getTitle() + "-" + getString(R.string.subtitle_activity_backgroundpicture)); mAToolbar.setSubtitle(R.string.subtitle_activity_backgroundpicture); - //mAToolbar.setTitleTextAppearance(this, R.style.Toolbar_TitleText); - //mAToolbar.setSubtitleTextAppearance(this, R.style.Toolbar_SubTitleText); - //mAToolbar.setBackgroundColor(getColor(R.color.colorPrimary)); - setActionBar(mAToolbar); getActionBar().setDisplayHomeAsUpEnabled(true); mAToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override @@ -99,7 +95,7 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { } }); - //给按钮设置点击事件 + // 设置按钮点击事件 findViewById(R.id.activitybackgroundpictureAButton5).setOnClickListener(onOriginNullClickListener); findViewById(R.id.activitybackgroundpictureAButton4).setOnClickListener(onReceivedPictureClickListener); findViewById(R.id.activitybackgroundpictureAButton1).setOnClickListener(onTakePhotoClickListener); @@ -109,31 +105,18 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { updatePreviewBackground(); - - - // 判断并且处理应用分享到的文件 - // - //ToastUtils.show("Activity Opened."); - - // 预备接收参数 + // 处理分享的图片 Intent intent = getIntent(); String action = intent.getAction(); String type = intent.getType(); - //LogUtils.d(TAG, "action : " + action); - //LogUtils.d(TAG, "type : " + type); - - // 判断是否进入图片分享状态 - if (Intent.ACTION_SEND.equals(action) - && type != null - && ("image/*".equals(type) || "image/jpeg".equals(type) || "image/jpg".equals(type) || "image/png".equals(type) || "image/webp".equals(type))) { - // 预览图片 - BackgroundPicturePreviewDialog dlg= new BackgroundPicturePreviewDialog(this); + if (Intent.ACTION_SEND.equals(action) && type != null && isImageType(type)) { + BackgroundPicturePreviewDialog dlg = new BackgroundPicturePreviewDialog(this); dlg.show(); } } - void initEnv() { + private void initEnv() { LogUtils.d(TAG, "initEnv()"); _RecivedPictureFileName = "Recived.data"; } @@ -144,47 +127,55 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { @Override public void onAcceptRecivedPicture(String szPreRecivedPictureName) { - //ToastUtils.show("onAcceptRecivedPicture"); BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(this); utils.getBackgroundPictureBean().setIsUseBackgroundFile(true); utils.saveData(); - File fPreRecivedPictureName = new File(utils.getBackgroundDir(), szPreRecivedPictureName); - FileUtils.copyFile(fPreRecivedPictureName, mfRecivedPicture); - // 加载背景 - startCropImageActivity(false); - } - // - // 更新预览背景 - // - public void updatePreviewBackground() { - LogUtils.d(TAG, "updatePreviewBackground"); - ImageView ivPreviewBackground = findViewById(R.id.activitybackgroundpictureImageView1); - BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(this); - utils.loadBackgroundPictureBean(); - boolean isUseBackgroundFile = utils.getBackgroundPictureBean().isUseBackgroundFile(); - if (isUseBackgroundFile && mfRecivedCropPicture.exists()) { - try { - String szBackgroundFilePath = utils.getBackgroundDir() + getBackgroundFileName(); - Drawable drawableBackground = FileUtils.getImageDrawable(szBackgroundFilePath); - drawableBackground.setAlpha(120); - ivPreviewBackground.setImageDrawable(drawableBackground); - ToastUtils.show("Use acceptRecived background."); - } catch (IOException e) { - LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); - } + File sourceFile = new File(utils.getBackgroundDir(), szPreRecivedPictureName); + if (FileUtils.copyFile(sourceFile, mfRecivedPicture)) { + startCropImageActivity(false); } else { - ToastUtils.show(" No background."); - Drawable drawableBackground = getDrawable(R.drawable.blank10x10); - drawableBackground.setAlpha(120); - ivPreviewBackground.setImageDrawable(drawableBackground); + ToastUtils.show("图片复制失败,请重试"); } } + /** + * 更新背景图片预览 + */ + public void updatePreviewBackground() { + LogUtils.d(TAG, "updatePreviewBackground"); + ImageView ivPreviewBackground = (ImageView) findViewById(R.id.activitybackgroundpictureImageView1); + BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(this); + utils.loadBackgroundPictureBean(); + + boolean isUseBackgroundFile = utils.getBackgroundPictureBean().isUseBackgroundFile(); + if (isUseBackgroundFile && mfRecivedCropPicture.exists()) { + try { + String filePath = utils.getBackgroundDir() + getBackgroundFileName(); + Drawable drawable = FileUtils.getImageDrawable(filePath); + if (drawable != null) { + drawable.setAlpha(120); + ivPreviewBackground.setImageDrawable(drawable); + } + ToastUtils.show("背景图片已更新"); + } catch (IOException e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + ToastUtils.show("背景图片加载失败"); + } + } else { + ToastUtils.show("未使用背景图片"); + Drawable drawable = getResources().getDrawable(R.drawable.blank10x10); + if (drawable != null) { + drawable.setAlpha(120); + ivPreviewBackground.setImageDrawable(drawable); + } + } + } + + // 点击事件监听器 private View.OnClickListener onOriginNullClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - // 选择原始空白背景 BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(BackgroundPictureActivity.this); BackgroundPictureBean bean = utils.getBackgroundPictureBean(); bean.setIsUseBackgroundFile(false); @@ -196,11 +187,10 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { private View.OnClickListener onSelectPictureClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - // 导入外部图片 - Intent intent = new Intent( - Intent.ACTION_PICK, - android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); - startActivityForResult(intent, REQUEST_SELECT_PICTURE); + if (checkAndRequestStoragePermission()) { + Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); + startActivityForResult(intent, REQUEST_SELECT_PICTURE); + } } }; @@ -211,7 +201,7 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { if (fCheck.exists()) { startCropImageActivity(false); } else { - ToastUtils.show("There is not any picture to crop."); + ToastUtils.show("没有可剪裁的图片"); } } }; @@ -223,7 +213,7 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { if (fCheck.exists()) { startCropImageActivity(true); } else { - ToastUtils.show("There is not any picture to crop."); + ToastUtils.show("没有可剪裁的图片"); } } }; @@ -233,6 +223,7 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { public void onClick(View v) { LogUtils.d(TAG, "onTakePhotoClickListener"); LogUtils.d(TAG, "mfTakePhoto : " + mfTakePhoto.getPath()); + if (mfTakePhoto.exists()) { mfTakePhoto.delete(); } @@ -240,56 +231,70 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { mfTakePhoto.createNewFile(); } catch (IOException e) { LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + ToastUtils.show("拍照文件创建失败"); + return; + } + + if (checkAndRequestStoragePermission()) { + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); } - Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); } }; private View.OnClickListener onReceivedPictureClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - // 选择接收到的背景图片 BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(BackgroundPictureActivity.this); - utils.getBackgroundPictureBean().setIsUseBackgroundFile(true); + utils.getBackgroundPictureBean().setIsUseBackgroundFile(true); utils.saveData(); updatePreviewBackground(); } }; + /** + * 压缩图片并保存到接收文件 + */ void compressQualityToRecivedPicture(Bitmap bitmap) { - // 设置输出流 OutputStream outStream = null; try { - // 创建输出流对象,准备写入压缩后的图片文件 mfRecivedPicture = getRecivedPictureFile(this); - // 创建新的接收文件 if (!mfRecivedPicture.exists()) { mfRecivedPicture.createNewFile(); } FileOutputStream fos = new FileOutputStream(mfRecivedPicture); - - // 获取输出流对象 outStream = new BufferedOutputStream(fos); - - // 使用默认的质量参数压缩图片 - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream); // 70% 的质量 - - // 关闭输出流以完成文件操作 + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream); outStream.flush(); - outStream.close(); } catch (IOException e) { LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + ToastUtils.show("图片压缩失败"); + } finally { + if (outStream != null) { + try { + outStream.close(); + } catch (IOException e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + } + if (bitmap != null && !bitmap.isRecycled()) { + bitmap.recycle(); + } } } + /** + * 启动图片裁剪活动 + * @param isCropFree 是否自由裁剪 + */ public void startCropImageActivity(boolean isCropFree) { LogUtils.d(TAG, "startCropImageActivity"); BackgroundPictureBean bean = mBackgroundPictureUtils.loadBackgroundPictureBean(); mfRecivedPicture = getRecivedPictureFile(this); Uri uri = UriUtil.getUriForFile(this, mfRecivedPicture); LogUtils.d(TAG, "uri : " + uri.toString()); + if (mfTempCropPicture.exists()) { mfTempCropPicture.delete(); } @@ -297,27 +302,24 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { mfTempCropPicture.createNewFile(); } catch (IOException e) { LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + ToastUtils.show("剪裁临时文件创建失败"); + return; } - // 使用正确的文件路径构建 Uri + Uri cropOutPutUri = Uri.fromFile(mfTempCropPicture); LogUtils.d(TAG, "mfTempCropPicture : " + mfTempCropPicture.getPath()); + Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/" + _mszCommonFileType); - // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪 intent.putExtra("crop", "true"); intent.putExtra("noFaceDetection", true); + if (!isCropFree) { - // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", bean.getBackgroundWidth()); intent.putExtra("aspectY", bean.getBackgroundHeight()); } - // outputX outputY 是裁剪图片宽高 - //intent.putExtra("outputX", 100); - //intent.putExtra("outputY", 100); - //return-data =false 意味着裁剪成功后不能在onActivityResult 的intent 中获得图片 - //intent.putExtra("return-data", false); + intent.putExtra("return-data", true); - //裁剪后的图片输出至 cropOutPutUri intent.putExtra(MediaStore.EXTRA_OUTPUT, cropOutPutUri); intent.putExtra("scale", true); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); @@ -325,13 +327,102 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { startActivityForResult(intent, REQUEST_CROP_IMAGE); } - // 启动裁剪窗口,裁剪操作文件为 uirImage - // + /** + * 保存剪裁后的Bitmap(优化版) + */ + private void saveCropBitmap(Bitmap bitmap) { + if (bitmap == null) { + ToastUtils.show("剪裁图片为空"); + return; + } + + // 内存优化:大图片自动缩放 + Bitmap scaledBitmap = bitmap; + if (bitmap.getByteCount() > 10 * 1024 * 1024) { // 超过10MB + float scale = 1.0f; + while (scaledBitmap.getByteCount() > 5 * 1024 * 1024) { + scale -= 0.2f; // 每次缩小20% + if (scale < 0.2f) break; // 最小缩放到20% + scaledBitmap = scaleBitmap(scaledBitmap, scale); + } + if (scaledBitmap != bitmap) { + bitmap.recycle(); // 回收原Bitmap + } + } + + // 优化:创建保存目录 + File backgroundDir = new File(mBackgroundPictureUtils.getBackgroundDir()); + if (!backgroundDir.exists()) { + if (!backgroundDir.mkdirs()) { + ToastUtils.show("无法创建保存目录"); + if (scaledBitmap != bitmap) scaledBitmap.recycle(); + return; + } + } + + File saveFile = new File(backgroundDir, getBackgroundFileName()); + + // 优化:检查文件是否可写 + if (saveFile.exists() && !saveFile.canWrite()) { + if (!saveFile.delete()) { + ToastUtils.show("无法删除旧文件"); + if (scaledBitmap != bitmap) scaledBitmap.recycle(); + return; + } + } + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(saveFile); + boolean success = scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos); + fos.flush(); + if (success) { + ToastUtils.show("保存成功"); + // 更新数据 + mBackgroundPictureUtils.getBackgroundPictureBean().setIsUseBackgroundFile(true); + updatePreviewBackground(); + } else { + ToastUtils.show("图片压缩保存失败"); + } + } catch (FileNotFoundException e) { + LogUtils.e(TAG, "文件未找到" + e); + ToastUtils.show("保存失败:文件路径错误"); + } catch (IOException e) { + LogUtils.e(TAG, "写入异常" + e); + ToastUtils.show("保存失败:磁盘可能已满或路径错误"); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + LogUtils.e(TAG, "流关闭异常" + e); + } + } + if (scaledBitmap != null && !scaledBitmap.isRecycled()) { + scaledBitmap.recycle(); + } + } + } + + /** + * 缩放Bitmap + */ + private Bitmap scaleBitmap(Bitmap original, float scale) { + if (original == null) { + return null; + } + int width = (int) (original.getWidth() * scale); + int height = (int) (original.getHeight() * scale); + return Bitmap.createScaledBitmap(original, width, height, true); + } + + /** + * 分享图片 + */ void sharePicture() { Uri uri = UriUtil.getUriForFile(this, mfRecivedPicture); - Intent shareIntent = new Intent(); - shareIntent.setAction(Intent.ACTION_SEND); - shareIntent.putExtra(Intent.EXTRA_STREAM, uri); + Intent shareIntent = new Intent(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_STREAM, uri); shareIntent.setType("image/" + _mszCommonFileType); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(Intent.createChooser(shareIntent, "Share Image")); @@ -345,45 +436,107 @@ implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_SELECT_PICTURE) { - // 处理选择后图片 - if (resultCode == RESULT_OK) { - try { - Uri selectedImage = data.getData(); - LogUtils.d(TAG, "Uri is : " + selectedImage.toString()); - File fSrcImage = new File(UriUtil.getFilePathFromUri(this, selectedImage)); - mfRecivedPicture = getRecivedPictureFile(this); - - FileUtils.copyFile(fSrcImage, mfRecivedPicture); - // 启动剪裁文件窗口 + if (requestCode == REQUEST_SELECT_PICTURE && resultCode == RESULT_OK) { + try { + Uri selectedImage = data.getData(); + LogUtils.d(TAG, "Uri is : " + selectedImage.toString()); + File fSrcImage = new File(UriUtil.getFilePathFromUri(this, selectedImage)); + mfRecivedPicture = getRecivedPictureFile(this); + if (FileUtils.copyFile(fSrcImage, mfRecivedPicture)) { startCropImageActivity(false); - } catch (Exception e) { - LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } else { + ToastUtils.show("图片复制失败,请重试"); } + } catch (Exception e) { + LogUtils.e(TAG, "选择图片异常" + e); + ToastUtils.show("选择图片失败:" + e.getMessage()); } - } else if (requestCode == REQUEST_TAKE_PHOTO) { - if (resultCode == RESULT_OK) { - LogUtils.d(TAG, "REQUEST_TAKE_PHOTO"); - Bundle extras = data.getExtras(); + } else if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) { + LogUtils.d(TAG, "REQUEST_TAKE_PHOTO"); + Bundle extras = data.getExtras(); + if (extras != null) { Bitmap imageBitmap = (Bitmap) extras.get("data"); - compressQualityToRecivedPicture(imageBitmap); - startCropImageActivity(false); - } - } else if (requestCode == REQUEST_CROP_IMAGE) { - if (resultCode == RESULT_OK) { - LogUtils.d(TAG, "CROP_IMAGE_REQUEST_CODE"); - FileUtils.copyFile(mfTempCropPicture, mfRecivedCropPicture); - mfTempCropPicture.delete(); - mBackgroundPictureUtils.getBackgroundPictureBean().setIsUseBackgroundFile(true); - updatePreviewBackground(); + if (imageBitmap != null) { + compressQualityToRecivedPicture(imageBitmap); + startCropImageActivity(false); + } else { + ToastUtils.show("拍照图片为空"); + } + } else { + ToastUtils.show("拍照数据获取失败"); } + } else if (requestCode == REQUEST_CROP_IMAGE && resultCode == RESULT_OK) { + LogUtils.d(TAG, "CROP_IMAGE_REQUEST_CODE"); + try { + Bitmap cropBitmap = null; + // 方案1:通过Intent获取剪裁后的Bitmap + if (data != null && data.hasExtra("data")) { + cropBitmap = data.getParcelableExtra("data"); + } else if (mfTempCropPicture.exists()) { + cropBitmap = BitmapFactory.decodeFile(mfTempCropPicture.getPath()); + } else { + ToastUtils.show("剪裁文件不存在"); + return; + } - } else { - String sz = "Unsolved requestCode = " + Integer.toString(requestCode); - Toast.makeText(getApplication(), sz, Toast.LENGTH_SHORT).show(); - LogUtils.d(TAG, sz); + if (cropBitmap != null) { + saveCropBitmap(cropBitmap); + } else { + ToastUtils.show("获取剪裁图片失败"); + } + } catch (OutOfMemoryError e) { + LogUtils.e(TAG, "内存溢出" + e); + ToastUtils.show("保存失败:内存不足,请尝试裁剪更小的图片"); + } catch (Exception e) { + LogUtils.e(TAG, "剪裁保存异常" + e); + ToastUtils.show("保存失败:" + e.getMessage()); + }/* finally { + // 安全删除临时文件 + if (mfTempCropPicture.exists()) { + mfTempCropPicture.delete(); + } + }*/ + } else if (resultCode != RESULT_OK) { + LogUtils.d(TAG, "操作取消或失败,requestCode: " + requestCode); + ToastUtils.show("操作已取消"); + } + } + + /** + * 检查类型是否为图片 + */ + private boolean isImageType(String type) { + return type.startsWith("image/") || "image/jpeg".equals(type) || + "image/jpg".equals(type) || "image/png".equals(type) || + "image/webp".equals(type); + } + + /** + * 检查并申请存储权限 + */ + private boolean checkAndRequestStoragePermission() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + STORAGE_PERMISSION_REQUEST); + return false; + } + } + return true; + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == STORAGE_PERMISSION_REQUEST) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + ToastUtils.show("存储权限已获取"); + } else { + ToastUtils.show("需要存储权限才能保存图片"); + } } } } + From 2a819e94e49fbc58967a43ac07898ca60358a4bd Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 19 Jun 2025 10:22:12 +0800 Subject: [PATCH 02/20] APK 15.4.2 release Publish. --- powerbell/build.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index 4921bc3..0bfc721 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Jun 19 02:15:49 GMT 2025 -stageCount=2 +#Thu Jun 19 10:22:12 HKT 2025 +stageCount=3 libraryProject= baseVersion=15.4 -publishVersion=15.4.1 -buildCount=7 -baseBetaVersion=15.4.2 +publishVersion=15.4.2 +buildCount=0 +baseBetaVersion=15.4.3 From ccdb9c5abdf7e1f5b4615149f7762983d52eb70a Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 19 Jun 2025 21:14:22 +0800 Subject: [PATCH 03/20] =?UTF-8?q?UI=E7=BE=8E=E5=8C=96=EF=BC=8C=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E8=A7=86=E5=9B=BE=E5=B8=83=E5=B1=80=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.gradle | 6 ++-- powerbell/build.properties | 4 +-- .../studio/powerbell/MainActivity.java | 29 ++++++++++++++----- .../powerbell/activities/WinBoLLActivity.java | 20 +++++++++++++ .../src/main/res/layout/activity_main.xml | 6 ---- .../src/main/res/layout/fragment_mainview.xml | 24 +++++++++------ powerbell/src/main/res/menu/toolbar_main.xml | 3 ++ 7 files changed, 64 insertions(+), 28 deletions(-) create mode 100644 powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java diff --git a/powerbell/build.gradle b/powerbell/build.gradle index 22d7603..9e8f4f3 100644 --- a/powerbell/build.gradle +++ b/powerbell/build.gradle @@ -45,9 +45,9 @@ android { dependencies { api fileTree(dir: 'libs', include: ['*.jar']) - api 'cc.winboll.studio:libaes:15.6.0' - api 'cc.winboll.studio:libapputils:15.3.4' - api 'cc.winboll.studio:libappbase:15.7.6' + api 'cc.winboll.studio:libaes:15.8.0' + api 'cc.winboll.studio:libapputils:15.8.2' + api 'cc.winboll.studio:libappbase:15.8.2' // 吐司提示库 api 'com.github.getActivity:ToastUtils:10.5' diff --git a/powerbell/build.properties b/powerbell/build.properties index 0bfc721..b1c694e 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Jun 19 10:22:12 HKT 2025 +#Thu Jun 19 13:11:30 GMT 2025 stageCount=3 libraryProject= baseVersion=15.4 publishVersion=15.4.2 -buildCount=0 +buildCount=5 baseBetaVersion=15.4.3 diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 3e7527b..faa9c5d 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -1,6 +1,5 @@ package cc.winboll.studio.powerbell; -import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; @@ -13,20 +12,22 @@ import android.view.MenuItem; import android.widget.Toast; import cc.winboll.studio.libaes.views.AToolbar; import cc.winboll.studio.libappbase.LogUtils; -import cc.winboll.studio.libappbase.LogView; import cc.winboll.studio.powerbell.MainActivity; import cc.winboll.studio.powerbell.activities.AboutActivity; import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; import cc.winboll.studio.powerbell.activities.BatteryReporterActivity; import cc.winboll.studio.powerbell.activities.ClearRecordActivity; +import cc.winboll.studio.powerbell.activities.WinBoLLActivity; import cc.winboll.studio.powerbell.fragments.MainViewFragment; +import android.app.Activity; -public class MainActivity extends Activity { +public class MainActivity extends WinBoLLActivity { + public static final String TAG = "MainActivity"; public static final int BACKGROUND_PICTURE_REQUEST_CODE = 0; public static MainActivity _mMainActivity; - LogView mLogView; + //LogView mLogView; //ArrayList mlistFragment; App mApplication; //AppConfigUtils mAppConfigUtils; @@ -35,6 +36,16 @@ public class MainActivity extends Activity { MainViewFragment mMainViewFragment; AToolbar mAToolbar; + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + @Override protected void onCreate(Bundle savedInstanceState) { //LogUtils.d(TAG, "onCreate(...)"); @@ -42,10 +53,10 @@ public class MainActivity extends Activity { setContentView(R.layout.activity_main); // 设置调试日志 - mLogView = findViewById(R.id.logview); - mLogView.start(); - //LogUtils.d(TAG, "LogView Start."); - mLogView.updateLogView(); +// mLogView = findViewById(R.id.logview); +// mLogView.start(); +// //LogUtils.d(TAG, "LogView Start."); +// mLogView.updateLogView(); _mMainActivity = MainActivity.this; mApplication = (App) getApplication(); @@ -157,6 +168,8 @@ public class MainActivity extends Activity { Intent intent = new Intent(); intent.setClass(this, BackgroundPictureActivity.class); startActivity(intent); + } else if (menuItemId == R.id.action_log) { + App.getWinBoLLActivityManager().startLogActivity(this); } return true; diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java new file mode 100644 index 0000000..bb422cc --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/WinBoLLActivity.java @@ -0,0 +1,20 @@ +package cc.winboll.studio.powerbell.activities; + +import android.app.Activity; +import android.os.Bundle; +import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; + +/** + * @Author ZhanGSKen + * @Date 2025/06/19 20:35 + * @Describe 应用窗口基类 + */ +public abstract class WinBoLLActivity extends Activity implements IWinBoLLActivity { + + public static final String TAG = "WinBoLLActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } +} diff --git a/powerbell/src/main/res/layout/activity_main.xml b/powerbell/src/main/res/layout/activity_main.xml index 874c31a..213ee82 100644 --- a/powerbell/src/main/res/layout/activity_main.xml +++ b/powerbell/src/main/res/layout/activity_main.xml @@ -33,11 +33,5 @@ - - diff --git a/powerbell/src/main/res/layout/fragment_mainview.xml b/powerbell/src/main/res/layout/fragment_mainview.xml index 7d530e1..1c5b33c 100644 --- a/powerbell/src/main/res/layout/fragment_mainview.xml +++ b/powerbell/src/main/res/layout/fragment_mainview.xml @@ -43,15 +43,6 @@ - - + + + + + + diff --git a/powerbell/src/main/res/menu/toolbar_main.xml b/powerbell/src/main/res/menu/toolbar_main.xml index dce9de9..77ba849 100644 --- a/powerbell/src/main/res/menu/toolbar_main.xml +++ b/powerbell/src/main/res/menu/toolbar_main.xml @@ -9,6 +9,9 @@ + From df10306059907f968b16d8aa9303eaec6bac6010 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 19 Jun 2025 21:16:18 +0800 Subject: [PATCH 04/20] APK 15.4.3 release Publish. --- powerbell/build.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/powerbell/build.properties b/powerbell/build.properties index b1c694e..3ab111d 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Jun 19 13:11:30 GMT 2025 -stageCount=3 +#Thu Jun 19 21:16:18 HKT 2025 +stageCount=4 libraryProject= baseVersion=15.4 -publishVersion=15.4.2 -buildCount=5 -baseBetaVersion=15.4.3 +publishVersion=15.4.3 +buildCount=0 +baseBetaVersion=15.4.4 From 3071d186ec430939efb8698f6ad6eb11440c321c Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Sun, 22 Jun 2025 16:19:24 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E5=83=8F=E7=B4=A0=E6=8B=BE=E5=8F=96=E5=B9=B6=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=83=8F=E7=B4=A0=E4=B8=BA=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E8=83=8C=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.gradle | 6 +- powerbell/build.properties | 4 +- powerbell/src/main/AndroidManifest.xml | 4 +- .../studio/powerbell/MainActivity.java | 19 +- .../activities/BackgroundPictureActivity.java | 46 +++- .../activities/PixelPickerActivity.java | 203 ++++++++++++++++++ .../beans/BackgroundPictureBean.java | 13 ++ .../powerbell/fragments/MainViewFragment.java | 4 +- .../res/layout/activity_backgroundpicture.xml | 155 +++++++------ .../src/main/res/layout/activity_main.xml | 32 ++- .../main/res/layout/activity_pixelpicker.xml | 31 +++ .../src/main/res/layout/dialog_pixel.xml | 32 +++ 12 files changed, 454 insertions(+), 95 deletions(-) create mode 100644 powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java create mode 100644 powerbell/src/main/res/layout/activity_pixelpicker.xml create mode 100644 powerbell/src/main/res/layout/dialog_pixel.xml diff --git a/powerbell/build.gradle b/powerbell/build.gradle index 9e8f4f3..28c9e16 100644 --- a/powerbell/build.gradle +++ b/powerbell/build.gradle @@ -45,9 +45,9 @@ android { dependencies { api fileTree(dir: 'libs', include: ['*.jar']) - api 'cc.winboll.studio:libaes:15.8.0' - api 'cc.winboll.studio:libapputils:15.8.2' - api 'cc.winboll.studio:libappbase:15.8.2' + api 'cc.winboll.studio:libaes:15.9.1' + api 'cc.winboll.studio:libapputils:15.8.4' + api 'cc.winboll.studio:libappbase:15.8.4' // 吐司提示库 api 'com.github.getActivity:ToastUtils:10.5' diff --git a/powerbell/build.properties b/powerbell/build.properties index 3ab111d..c8b7d3f 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Thu Jun 19 21:16:18 HKT 2025 +#Sun Jun 22 08:17:22 GMT 2025 stageCount=4 libraryProject= baseVersion=15.4 publishVersion=15.4.3 -buildCount=0 +buildCount=22 baseBetaVersion=15.4.4 diff --git a/powerbell/src/main/AndroidManifest.xml b/powerbell/src/main/AndroidManifest.xml index 93ad2bc..1bfaabd 100644 --- a/powerbell/src/main/AndroidManifest.xml +++ b/powerbell/src/main/AndroidManifest.xml @@ -121,6 +121,8 @@ + + - + \ No newline at end of file diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index faa9c5d..b0cce7c 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -1,5 +1,6 @@ package cc.winboll.studio.powerbell; +import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; @@ -9,6 +10,7 @@ import android.os.Bundle; import android.provider.MediaStore; import android.view.Menu; import android.view.MenuItem; +import android.widget.RelativeLayout; import android.widget.Toast; import cc.winboll.studio.libaes.views.AToolbar; import cc.winboll.studio.libappbase.LogUtils; @@ -18,11 +20,12 @@ import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; import cc.winboll.studio.powerbell.activities.BatteryReporterActivity; import cc.winboll.studio.powerbell.activities.ClearRecordActivity; import cc.winboll.studio.powerbell.activities.WinBoLLActivity; +import cc.winboll.studio.powerbell.beans.BackgroundPictureBean; import cc.winboll.studio.powerbell.fragments.MainViewFragment; -import android.app.Activity; +import cc.winboll.studio.powerbell.utils.BackgroundPictureUtils; public class MainActivity extends WinBoLLActivity { - + public static final String TAG = "MainActivity"; public static final int BACKGROUND_PICTURE_REQUEST_CODE = 0; @@ -45,7 +48,7 @@ public class MainActivity extends WinBoLLActivity { public String getTag() { return TAG; } - + @Override protected void onCreate(Bundle savedInstanceState) { //LogUtils.d(TAG, "onCreate(...)"); @@ -128,8 +131,8 @@ public class MainActivity extends WinBoLLActivity { super.onResume(); // 回到窗口自动取消提醒消息 //NotificationHelper.cancelRemindNotification(this); - reloadBackground(); + setBackgroundColor(); } // Menu icons are inflated just as they were with actionbar @@ -206,4 +209,12 @@ public class MainActivity extends WinBoLLActivity { moveTaskToBack(true); } } + + void setBackgroundColor() { + BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(MainActivity.this); + BackgroundPictureBean bean = utils.getBackgroundPictureBean(); + int nPixelColor = bean.getPixelColor(); + RelativeLayout mainLayout = findViewById(R.id.activitymainRelativeLayout1); + mainLayout.setBackgroundColor(nPixelColor); + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java index 0aa5766..ba7e79b 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundPictureActivity.java @@ -32,6 +32,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import android.service.quickaccesswallet.GetWalletCardsError; +import android.widget.RelativeLayout; public class BackgroundPictureActivity extends Activity implements BackgroundPicturePreviewDialog.IOnRecivedPictureListener { @@ -102,7 +104,9 @@ public class BackgroundPictureActivity extends Activity implements BackgroundPic 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); + updatePreviewBackground(); // 处理分享的图片 @@ -154,7 +158,7 @@ public class BackgroundPictureActivity extends Activity implements BackgroundPic String filePath = utils.getBackgroundDir() + getBackgroundFileName(); Drawable drawable = FileUtils.getImageDrawable(filePath); if (drawable != null) { - drawable.setAlpha(120); + //drawable.setAlpha(120); ivPreviewBackground.setImageDrawable(drawable); } ToastUtils.show("背景图片已更新"); @@ -251,6 +255,30 @@ public class BackgroundPictureActivity extends Activity implements BackgroundPic updatePreviewBackground(); } }; + + private View.OnClickListener onPixelPickerClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + // 从文件路径启动像素拾取活动 + //String imagePath = "/storage/emulated/0/DCIM/Camera/sample.jpg"; + String imagePath = mfRecivedCropPicture.toString(); + Intent intent = new Intent(getApplicationContext(), PixelPickerActivity.class); + intent.putExtra("imagePath", imagePath); + //startActivity(intent); + App.getWinBoLLActivityManager().startWinBoLLActivity(getApplicationContext(), intent, PixelPickerActivity.class); + } + }; + + private View.OnClickListener onCleanPixelClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(BackgroundPictureActivity.this); + BackgroundPictureBean bean = utils.getBackgroundPictureBean(); + bean.setPixelColor(0); + utils.saveData(); + setBackgroundColor(); + } + }; /** * 压缩图片并保存到接收文件 @@ -538,5 +566,19 @@ public class BackgroundPictureActivity extends Activity implements BackgroundPic } } } + + void setBackgroundColor() { + BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(BackgroundPictureActivity.this); + BackgroundPictureBean bean = utils.getBackgroundPictureBean(); + int nPixelColor = bean.getPixelColor(); + RelativeLayout mainLayout = findViewById(R.id.activitybackgroundpictureRelativeLayout1); + mainLayout.setBackgroundColor(nPixelColor); + } + + @Override + protected void onResume() { + super.onResume(); + setBackgroundColor(); + } } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java new file mode 100644 index 0000000..be5cc1d --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/PixelPickerActivity.java @@ -0,0 +1,203 @@ +package cc.winboll.studio.powerbell.activities; + +/** + * @Author ZhanGSKen + * @Date 2025/06/22 14:15 + */ +import android.app.Activity; +import android.app.Dialog; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; +import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; +import cc.winboll.studio.powerbell.R; +import cc.winboll.studio.powerbell.activities.BackgroundPictureActivity; +import cc.winboll.studio.powerbell.activities.PixelPickerActivity; +import cc.winboll.studio.powerbell.beans.BackgroundPictureBean; +import cc.winboll.studio.powerbell.utils.BackgroundPictureUtils; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; + +public class PixelPickerActivity extends WinBoLLActivity implements IWinBoLLActivity { + + public static final String TAG = "PixelPickerActivity"; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + + + + + private ImageView imageView; + private Bitmap originalBitmap; + private TextView infoText; + private ViewGroup imageContainer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_pixelpicker); + + imageView = findViewById(R.id.imageView); + infoText = findViewById(R.id.infoText); + imageContainer = findViewById(R.id.imageContainer); + + // 从Intent获取图片路径并加载 + String imagePath = getIntent().getStringExtra("imagePath"); + if (imagePath != null) { + loadImage(imagePath); + } else { + infoText.setText("未找到图片路径"); + } + + // 设置图片点击事件 + imageContainer.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN && originalBitmap != null) { + // 计算点击位置在图片上的实际坐标 + float touchX = event.getX(); + float touchY = event.getY(); + + int pixelX = -1, pixelY = -1; + try { + // 获取图片在容器中的实际位置和尺寸 + int[] imageLocation = new int[2]; + imageView.getLocationInWindow(imageLocation); + int imageWidth = imageView.getWidth(); + int imageHeight = imageView.getHeight(); + + // 计算缩放比例 + float scaleX = (float) originalBitmap.getWidth() / imageWidth; + float scaleY = (float) originalBitmap.getHeight() / imageHeight; + + // 调整触摸坐标到图片坐标系 + float adjustedX = touchX - imageLocation[0]; + float adjustedY = touchY - imageLocation[1]; + + // 检查是否在图片范围内 + if (adjustedX >= 0 && adjustedX <= imageWidth && adjustedY >= 0 && adjustedY <= imageHeight) { + // 计算实际像素坐标 + pixelX = (int) (adjustedX * scaleX); + pixelY = (int) (adjustedY * scaleY); + + // 再次检查像素坐标是否在有效范围内 + if (pixelX >= 0 && pixelX < originalBitmap.getWidth() && + pixelY >= 0 && pixelY < originalBitmap.getHeight()) { + int pixelColor = originalBitmap.getPixel(pixelX, pixelY); + showPixelDialog(pixelColor, pixelX, pixelY); + } else { + Toast.makeText(PixelPickerActivity.this, "像素坐标超出范围", Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(PixelPickerActivity.this, "点击位置超出图片显示范围", Toast.LENGTH_SHORT).show(); + } + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(PixelPickerActivity.this, "计算像素位置失败", Toast.LENGTH_SHORT).show(); + } + } + return true; + } + }); + } + + /** + * 加载图片 + */ + private void loadImage(String imagePath) { + try { + File file = new File(imagePath); + if (file.exists()) { + // 解码图片 + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = 1; // 加载原图 + originalBitmap = BitmapFactory.decodeStream(new FileInputStream(file), null, options); + + if (originalBitmap != null) { + imageView.setImageBitmap(originalBitmap); + infoText.setText("图片已加载,点击获取像素值"); + } else { + infoText.setText("图片加载失败"); + } + } else { + infoText.setText("图片文件不存在"); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + infoText.setText("图片文件未找到"); + } + } + + /** + * 显示像素对话框 + */ + private void showPixelDialog(final int pixelColor, int x, int y) { + Dialog dialog = new Dialog(this); + dialog.setContentView(R.layout.dialog_pixel); + dialog.setCancelable(true); + + // 设置像素颜色视图背景 + TextView colorView = dialog.findViewById(R.id.pixelColorView); + colorView.setBackgroundColor(pixelColor); + + // 显示颜色信息 + TextView infoText = dialog.findViewById(R.id.colorInfoText); + String colorInfo = String.format( + "RGB: (%d, %d, %d)\n" + + "ARGB: #%08X\n" + + "实际像素位置: (%d, %d)", + Color.red(pixelColor), + Color.green(pixelColor), + Color.blue(pixelColor), + pixelColor, + x, y); + infoText.setText(colorInfo); + + // 设置确定按钮点击事件 + Button confirmButton = dialog.findViewById(R.id.confirmButton); + confirmButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + // 可以在这里添加确定后的回调逻辑 + BackgroundPictureUtils utils = BackgroundPictureUtils.getInstance(PixelPickerActivity.this); + BackgroundPictureBean bean = utils.getBackgroundPictureBean(); + bean.setPixelColor(pixelColor); + utils.saveData(); + Toast.makeText(PixelPickerActivity.this, "已记录像素值", Toast.LENGTH_SHORT).show(); + } + }); + + dialog.show(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + // 回收Bitmap资源 + if (originalBitmap != null && !originalBitmap.isRecycled()) { + originalBitmap.recycle(); + originalBitmap = null; + } + } +} + + + diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/beans/BackgroundPictureBean.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/beans/BackgroundPictureBean.java index ae818a8..b2eb8f4 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/beans/BackgroundPictureBean.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/beans/BackgroundPictureBean.java @@ -17,6 +17,8 @@ public class BackgroundPictureBean extends BaseBean { int backgroundWidth = 100; int backgroundHeight = 100; boolean isUseBackgroundFile = false; + // 图片拾取像素颜色 + int pixelColor = 0; public BackgroundPictureBean() { } @@ -25,6 +27,14 @@ public class BackgroundPictureBean extends BaseBean { this.isUseBackgroundFile = isUseBackgroundFile; } + public void setPixelColor(int pixelColor) { + this.pixelColor = pixelColor; + } + + public int getPixelColor() { + return pixelColor; + } + public void setBackgroundWidth(int backgroundWidth) { this.backgroundWidth = backgroundWidth; } @@ -61,6 +71,7 @@ public class BackgroundPictureBean extends BaseBean { jsonWriter.name("backgroundWidth").value(bean.getBackgroundWidth()); jsonWriter.name("backgroundHeight").value(bean.getBackgroundHeight()); jsonWriter.name("isUseBackgroundFile").value(bean.isUseBackgroundFile()); + jsonWriter.name("pixelColor").value(bean.getPixelColor()); } @Override @@ -75,6 +86,8 @@ public class BackgroundPictureBean extends BaseBean { bean.setBackgroundHeight(jsonReader.nextInt()); } else if (name.equals("isUseBackgroundFile")) { bean.setIsUseBackgroundFile(jsonReader.nextBoolean()); + } else if (name.equals("pixelColor")) { + bean.setPixelColor(jsonReader.nextInt()); } else { jsonReader.skipValue(); } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/fragments/MainViewFragment.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/fragments/MainViewFragment.java index 0e63a91..6819a65 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/fragments/MainViewFragment.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/fragments/MainViewFragment.java @@ -311,11 +311,11 @@ public class MainViewFragment extends Fragment { LogUtils.d(TAG, String.format("fBackgroundFilePath.exists() %s", fBackgroundFilePath.exists())); if (bean.isUseBackgroundFile() && fBackgroundFilePath.exists()) { Drawable drawableBackground = Drawable.createFromPath(szBackgroundFilePath); - drawableBackground.setAlpha(120); + //drawableBackground.setAlpha(120); imageView.setImageDrawable(drawableBackground); } else { Drawable drawableBackground = getActivity().getDrawable(R.drawable.blank10x10); - drawableBackground.setAlpha(120); + //drawableBackground.setAlpha(120); imageView.setImageDrawable(drawableBackground); } } diff --git a/powerbell/src/main/res/layout/activity_backgroundpicture.xml b/powerbell/src/main/res/layout/activity_backgroundpicture.xml index 32197b4..d3f329a 100644 --- a/powerbell/src/main/res/layout/activity_backgroundpicture.xml +++ b/powerbell/src/main/res/layout/activity_backgroundpicture.xml @@ -1,5 +1,5 @@ - - - - - - + + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/activitybackgroundpictureRelativeLayout1"/> - - + - + + android:layout_below="@id/toolbar"> - + - + - + - + + + + + + + + + + + + + + + + + - - - + + diff --git a/powerbell/src/main/res/layout/activity_main.xml b/powerbell/src/main/res/layout/activity_main.xml index 213ee82..54bf752 100644 --- a/powerbell/src/main/res/layout/activity_main.xml +++ b/powerbell/src/main/res/layout/activity_main.xml @@ -2,36 +2,34 @@ - + android:layout_height="@dimen/toolbar_height" + android:id="@+id/toolbar" + android:gravity="center_vertical" + style="@style/DefaultAToolbar"/> - - - - - + + - + diff --git a/powerbell/src/main/res/layout/activity_pixelpicker.xml b/powerbell/src/main/res/layout/activity_pixelpicker.xml new file mode 100644 index 0000000..4bce86b --- /dev/null +++ b/powerbell/src/main/res/layout/activity_pixelpicker.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/powerbell/src/main/res/layout/dialog_pixel.xml b/powerbell/src/main/res/layout/dialog_pixel.xml new file mode 100644 index 0000000..182ee4a --- /dev/null +++ b/powerbell/src/main/res/layout/dialog_pixel.xml @@ -0,0 +1,32 @@ + + + + + + + +