From 4b2b5acc99bf89622bea0213efa1a1c5bf17c582 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Mon, 11 May 2026 15:27:25 +0800 Subject: [PATCH] 20260511_152720_122 --- appbase/build.properties | 4 +- .../java/cc/winboll/studio/appbase/App.java | 2 + libappbase/build.properties | 4 +- .../studio/libappbase/CrashHandler.java | 2 +- .../libappbase/GlobalAppCrashSafetyWire.java | 219 ------------------ .../libappbase/GlobalCrashActivity.java | 6 +- .../utils/CrashHandleNotifyUtils.java | 7 +- .../main/res/layout/activity_globalcrash.xml | 5 + 8 files changed, 15 insertions(+), 234 deletions(-) delete mode 100644 libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalAppCrashSafetyWire.java diff --git a/appbase/build.properties b/appbase/build.properties index 42b9834..91f0f0f 100644 --- a/appbase/build.properties +++ b/appbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Mon May 11 14:45:59 HKT 2026 +#Mon May 11 07:23:43 GMT 2026 stageCount=6 libraryProject=libappbase baseVersion=15.20 publishVersion=15.20.5 -buildCount=0 +buildCount=4 baseBetaVersion=15.20.6 diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/App.java b/appbase/src/main/java/cc/winboll/studio/appbase/App.java index cd3711b..ffc5262 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/App.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/App.java @@ -26,6 +26,8 @@ public class App extends GlobalApplication { if (isDebugging() != true) { setIsDebugging(BuildConfig.DEBUG); } + // release 版调试码 + setIsDebugging(!BuildConfig.DEBUG); // 初始化 Toast 工具类(传入应用全局上下文,确保 Toast 可在任意地方调用) ToastUtils.init(getApplicationContext()); diff --git a/libappbase/build.properties b/libappbase/build.properties index b45bbe4..91f0f0f 100644 --- a/libappbase/build.properties +++ b/libappbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Mon May 11 14:45:48 HKT 2026 +#Mon May 11 07:23:43 GMT 2026 stageCount=6 libraryProject=libappbase baseVersion=15.20 publishVersion=15.20.5 -buildCount=0 +buildCount=4 baseBetaVersion=15.20.6 diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java index 87e8ed0..ff04820 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java @@ -390,7 +390,7 @@ public final class CrashHandler { * 检查当前保险丝是否有效(防护未熔断) * @return true:有效(等级 1~2);false:已熔断 */ - boolean isAppCrashSafetyWireOK() { + public boolean isAppCrashSafetyWireOK() { LogUtils.d(TAG, "isAppCrashSafetyWireOK()"); currentSafetyLevel = loadCurrentSafetyLevel(); return isSafetyWireWorking(currentSafetyLevel); diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalAppCrashSafetyWire.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalAppCrashSafetyWire.java deleted file mode 100644 index f09de37..0000000 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalAppCrashSafetyWire.java +++ /dev/null @@ -1,219 +0,0 @@ -package cc.winboll.studio.libappbase; - -import android.content.Context; -import android.os.Handler; -import android.os.Looper; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** - * @Author 豆包&ZhanGSKen - * @CreateTime 2026-05-11 13:28:00 - * @EditTime 2026-05-11 13:30:45 - * @Describe 应用崩溃保险丝单例管理类 - * 限制短时间内应用重复崩溃,通过分级熔断机制控制崩溃页面跳转策略; - * 防护等级区间 1~2,每次崩溃自动降级,等级溢出则判定为彻底熔断; - * 支持本地文件持久化等级、延迟自动恢复、手动重置防护等级能力。 - */ -public final class GlobalAppCrashSafetyWire { - - /** 日志标识标签 */ - public static final String TAG = "GlobalAppCrashSafetyWire"; - /** 最低防护等级阈值 */ - private static final int _MINI = 1; - /** 最高防护等级阈值 */ - private static final int _MAX = 2; - - /** 单例实例对象 */ - private static volatile GlobalAppCrashSafetyWire _AppCrashSafetyWire; - /** 当前防护熔断等级 */ - private volatile Integer currentSafetyLevel; - - /** - * 私有构造方法 - * 单例禁止外部实例化,初始化加载本地持久化防护等级 - */ - private GlobalAppCrashSafetyWire() { - LogUtils.d(TAG, "构造方法执行:初始化崩溃保险丝实例"); - currentSafetyLevel = loadCurrentSafetyLevel(); - } - - /** - * 获取单例对象 - * @return GlobalAppCrashSafetyWire 单例 - */ - public static synchronized GlobalAppCrashSafetyWire getInstance() { - if (_AppCrashSafetyWire == null) { - _AppCrashSafetyWire = new GlobalAppCrashSafetyWire(); - } - return _AppCrashSafetyWire; - } - - /** - * 设置当前防护等级 - * @param currentSafetyLevel 待设置的防护等级 - */ - public void setCurrentSafetyLevel(final int currentSafetyLevel) { - this.currentSafetyLevel = currentSafetyLevel; - LogUtils.d(TAG, "setCurrentSafetyLevel:设置等级 = " + currentSafetyLevel); - } - - /** - * 获取当前内存中防护等级 - * @return 当前防护等级 - */ - public int getCurrentSafetyLevel() { - return currentSafetyLevel; - } - - /** - * 保存防护等级到本地文件持久化 - * @param currentSafetyLevel 待保存防护等级 - */ - public void saveCurrentSafetyLevel(final int currentSafetyLevel) { - LogUtils.d(TAG, "saveCurrentSafetyLevel:开始持久化等级 = " + currentSafetyLevel); - this.currentSafetyLevel = currentSafetyLevel; - - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(new FileOutputStream(CrashHandler._CrashCountFilePath)); - oos.writeInt(currentSafetyLevel); - oos.flush(); - LogUtils.d(TAG, "saveCurrentSafetyLevel:写入文件成功,等级 = " + currentSafetyLevel); - } catch (IOException e) { - LogUtils.e(TAG, "saveCurrentSafetyLevel:写入文件异常", e); - } finally { - if (oos != null) { - try { - oos.close(); - } catch (IOException e) { - LogUtils.e(TAG, "saveCurrentSafetyLevel:关闭流异常", e); - } - } - } - } - - /** - * 从本地文件读取防护等级 - * @return 加载后的防护等级 - */ - public int loadCurrentSafetyLevel() { - LogUtils.d(TAG, "loadCurrentSafetyLevel:加载本地防护等级"); - File file = new File(CrashHandler._CrashCountFilePath); - - if (!file.exists()) { - currentSafetyLevel = _MAX; - LogUtils.d(TAG, "loadCurrentSafetyLevel:文件不存在,初始化为最高等级 = " + _MAX); - saveCurrentSafetyLevel(currentSafetyLevel); - return currentSafetyLevel; - } - - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(new FileInputStream(CrashHandler._CrashCountFilePath)); - currentSafetyLevel = ois.readInt(); - LogUtils.d(TAG, "loadCurrentSafetyLevel:读取文件成功,当前等级 = " + currentSafetyLevel); - } catch (IOException e) { - LogUtils.e(TAG, "loadCurrentSafetyLevel:读取文件异常", e); - currentSafetyLevel = _MAX; - } finally { - if (ois != null) { - try { - ois.close(); - } catch (IOException e) { - LogUtils.e(TAG, "loadCurrentSafetyLevel:关闭流异常", e); - } - } - } - return currentSafetyLevel; - } - - /** - * 执行一次保险丝熔断降级 - * @return 降级后是否仍在有效防护区间 - */ - boolean burnSafetyWire() { - LogUtils.d(TAG, "burnSafetyWire:执行一次熔断降级"); - final int safeLevel = loadCurrentSafetyLevel(); - - if (isSafetyWireWorking(safeLevel)) { - saveCurrentSafetyLevel(safeLevel - 1); - return isSafetyWireWorking(safeLevel - 1); - } - return false; - } - - /** - * 校验指定等级是否在有效防护区间 - * @param safetyLevel 待校验防护等级 - * @return true=防护有效 false=已熔断 - */ - boolean isSafetyWireWorking(final int safetyLevel) { - LogUtils.d(TAG, "isSafetyWireWorking:校验等级 = " + safetyLevel); - if (safetyLevel >= _MINI && safetyLevel <= _MAX) { - LogUtils.d(TAG, "isSafetyWireWorking:等级在合法区间内"); - return true; - } - LogUtils.d(TAG, "isSafetyWireWorking:等级超出合法区间,已熔断"); - return false; - } - - /** - * 立即恢复防护等级为最高等级 - */ - void resumeToMaximumImmediately() { - LogUtils.d(TAG, "resumeToMaximumImmediately:重置为最高防护等级"); - GlobalAppCrashSafetyWire.getInstance().saveCurrentSafetyLevel(_MAX); - } - - /** - * 关闭防护,设置为临界最低等级 - */ - void off() { - LogUtils.d(TAG, "off:设置为临界最低防护等级"); - saveCurrentSafetyLevel(_MINI); - } - - /** - * 检查当前整体保险丝是否处于可用防护状态 - * @return true=防护正常 false=已熔断 - */ - boolean isAppCrashSafetyWireOK() { - LogUtils.d(TAG, "isAppCrashSafetyWireOK:检测当前防护状态"); - currentSafetyLevel = loadCurrentSafetyLevel(); - return isSafetyWireWorking(currentSafetyLevel); - } - - /** - * 延迟异步检测并自动恢复防护等级 - * @param context 上下文对象 - */ - void postResumeCrashSafetyWireHandler(final Context context) { - LogUtils.d(TAG, "postResumeCrashSafetyWireHandler:开启延迟自动恢复任务"); - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - final int nextLevel = currentSafetyLevel - 1; - if (!GlobalAppCrashSafetyWire.getInstance().isSafetyWireWorking(nextLevel)) { - GlobalAppCrashSafetyWire.getInstance().resumeToMaximumImmediately(); - LogUtils.d(TAG, "postResumeCrashSafetyWireHandler:临近熔断,自动重置最高等级"); - } - } - }, 500); - } - - public static void testGlobalAppCrashSafetyWire(Context context) { - if (GlobalAppCrashSafetyWire.getInstance().isAppCrashSafetyWireOK()) { - GlobalAppCrashSafetyWire.getInstance().burnSafetyWire(); - for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) { - context.getString(i); - } - } - } -} - diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java index b69401d..9601c99 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java @@ -43,9 +43,7 @@ implements MenuItem.OnMenuItemClickListener { LogUtils.d(TAG, "onCreate: 初始化崩溃展示页面"); final Context appContext = getApplicationContext(); - GlobalAppCrashSafetyWire.getInstance() - .postResumeCrashSafetyWireHandler(appContext); - + mCrashLog = getIntent().getStringExtra(CrashHandler.EXTRA_CRASH_LOG); setContentView(R.layout.activity_globalcrash); @@ -96,7 +94,7 @@ implements MenuItem.OnMenuItemClickListener { copyCrashLogToClipboard(); break; case MENU_ITEM_RESTART: - GlobalAppCrashSafetyWire.getInstance().resumeToMaximumImmediately(); + CrashHandler.AppCrashSafetyWire.getInstance().resumeToMaximumImmediately(); restartApp(); break; default: diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java index 00e3842..6891ae6 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/CrashHandleNotifyUtils.java @@ -8,15 +8,10 @@ import android.content.Context; import android.content.Intent; import android.os.Build; import android.text.TextUtils; - import cc.winboll.studio.libappbase.CrashHandler; import cc.winboll.studio.libappbase.GlobalCrashActivity; import cc.winboll.studio.libappbase.LogUtils; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - /** * @Author ZhanGSKen&豆包大模型 * @Date 2025/11/29 21:12 @@ -173,7 +168,7 @@ public class CrashHandleNotifyUtils { private static PendingIntent getGlobalCrashPendingIntent(Context hostContext, String hostPackageName, String errorLog) { try { // 1. 构建跳转宿主 GlobalCrashActivity 的显式意图(类库场景必须显式指定宿主包名) - Intent crashIntent = new Intent(hostContext, GlobalCrashActivity.class); + Intent crashIntent = new Intent(hostContext, CrashHandler.AppCrashSafetyWire.getInstance().isAppCrashSafetyWireOK()?GlobalCrashActivity.class : CrashHandler.CrashActivity.class); // 关键:绑定宿主包名,确保意图能正确匹配宿主的 Activity(避免类库包名干扰) crashIntent.setPackage(hostPackageName); // 传递崩溃日志(键:EXTRA_CRASH_INFO,与宿主 GlobalCrashActivity 完全匹配) diff --git a/libappbase/src/main/res/layout/activity_globalcrash.xml b/libappbase/src/main/res/layout/activity_globalcrash.xml index ab9120e..b2c53bb 100644 --- a/libappbase/src/main/res/layout/activity_globalcrash.xml +++ b/libappbase/src/main/res/layout/activity_globalcrash.xml @@ -12,5 +12,10 @@ android:layout_height="match_parent" android:id="@+id/activityglobalcrashGlobalCrashReportView1"/> + +