合并 APPBase 项目

This commit is contained in:
qinglong
2026-06-03 22:00:09 +08:00
parent 7a1a591233
commit c3ce6d7980
8 changed files with 171 additions and 147 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Wed May 27 14:51:40 HKT 2026 #Wed Jun 03 20:17:17 HKT 2026
stageCount=23 stageCount=27
libraryProject=libappbase libraryProject=libappbase
baseVersion=15.20 baseVersion=15.20
publishVersion=15.20.22 publishVersion=15.20.26
buildCount=0 buildCount=0
baseBetaVersion=15.20.23 baseBetaVersion=15.20.27

View File

@@ -1,8 +1,11 @@
package cc.winboll.studio.appbase; package cc.winboll.studio.appbase;
import cc.winboll.studio.libappbase.CrashActivity;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.ToastUtils; import cc.winboll.studio.libappbase.ToastUtils;
import cc.winboll.studio.libappbase.BuildConfig; import cc.winboll.studio.libappbase.utils.CrashHandleNotifyUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
/** /**
* @Author ZhanGSKen<zhangsken@qq.com> * @Author ZhanGSKen<zhangsken@qq.com>
@@ -21,10 +24,24 @@ public class App extends GlobalApplication {
*/ */
@Override @Override
public void onCreate() { public void onCreate() {
try {
super.onCreate(); super.onCreate();
// 初始化 Toast 工具类(传入应用全局上下文,确保 Toast 可在任意地方调用) // 初始化 Toast 工具类(传入应用全局上下文,确保 Toast 可在任意地方调用)
ToastUtils.init(getApplicationContext()); ToastUtils.init(getApplicationContext());
} catch (Throwable e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.close();
String stackTraceStr = sw.toString();
CrashHandleNotifyUtils.handleUncaughtException(
this,
getPackageName(),
stackTraceStr,
CrashActivity.class
);
}
} }
/** /**

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Wed May 27 14:51:29 HKT 2026 #Wed Jun 03 20:17:02 HKT 2026
stageCount=23 stageCount=27
libraryProject=libappbase libraryProject=libappbase
baseVersion=15.20 baseVersion=15.20
publishVersion=15.20.22 publishVersion=15.20.26
buildCount=0 buildCount=0
baseBetaVersion=15.20.23 baseBetaVersion=15.20.27

View File

@@ -8,7 +8,7 @@
android:networkSecurityConfig="@xml/network_security_config"> android:networkSecurityConfig="@xml/network_security_config">
<activity <activity
android:name=".CrashHandler$CrashActivity" android:name=".CrashActivity"
android:label="CrashActivity" android:label="CrashActivity"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:process=":CrashActivity"/> android:process=":CrashActivity"/>

View File

@@ -0,0 +1,109 @@
package cc.winboll.studio.libappbase;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
public final class CrashActivity extends Activity implements MenuItem.OnMenuItemClickListener {
private static final int MENUITEM_COPY = 0;
private static final int MENUITEM_RESTART = 1;
private String mLog;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCrashSafetyWire.getInstance().postResumeCrashSafetyWireHandler(getApplicationContext());
mLog = getIntent().getStringExtra(CrashHandler.EXTRA_CRASH_LOG);
setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
initLayout();
}
private void initLayout() {
ScrollView contentView = new ScrollView(this);
contentView.setFillViewport(true);
HorizontalScrollView hw = new HorizontalScrollView(this);
hw.setBackgroundColor(0xFFF5F5F5);
TextView message = new TextView(this);
final int padding = dp2px(16);
message.setPadding(padding, padding, padding, padding);
message.setText(mLog);
message.setTextColor(0xFF000000);
message.setTextIsSelectable(true);
hw.addView(message);
contentView.addView(hw, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setContentView(contentView);
getActionBar().setTitle(CrashHandler.TITTLE);
getActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()) + " Error");
}
@Override
public void onBackPressed() {
restartApp();
}
private void restartApp() {
final Intent intent = getPackageManager()
.getLaunchIntentForPackage(getPackageName());
if (intent != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
private int dp2px(final float dpValue) {
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
menu.add(0, MENUITEM_COPY, 0, "Copy")
.setOnMenuItemClickListener(this)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, MENUITEM_RESTART, 0, "Restart")
.setOnMenuItemClickListener(this)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}
@Override
public boolean onMenuItemClick(final MenuItem item) {
switch (item.getItemId()) {
case MENUITEM_COPY:
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
Toast.makeText(getApplication(), "The text is copied.", Toast.LENGTH_SHORT).show();
break;
case MENUITEM_RESTART:
AppCrashSafetyWire.getInstance().resumeToMaximumImmediately();
restartApp();
break;
default:
break;
}
return false;
}
}

View File

@@ -1,27 +1,13 @@
package cc.winboll.studio.libappbase; package cc.winboll.studio.libappbase;
import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.libappbase.utils.CrashHandleNotifyUtils; import cc.winboll.studio.libappbase.utils.CrashHandleNotifyUtils;
@@ -220,111 +206,5 @@ public final class CrashHandler {
} }
} }
// ====================== 内部Activity页面 ======================
/**
* 基础极简崩溃页面
* 保险丝熔断时启动,避免复杂布局二次崩溃
*/
public static final class CrashActivity extends Activity implements MenuItem.OnMenuItemClickListener {
private static final int MENUITEM_COPY = 0;
private static final int MENUITEM_RESTART = 1;
private String mLog;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCrashSafetyWire.getInstance().postResumeCrashSafetyWireHandler(getApplicationContext());
mLog = getIntent().getStringExtra(EXTRA_CRASH_LOG);
setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
initLayout();
}
/**
* 动态初始化布局
*/
private void initLayout() {
ScrollView contentView = new ScrollView(this);
contentView.setFillViewport(true);
HorizontalScrollView hw = new HorizontalScrollView(this);
hw.setBackgroundColor(0xFFF5F5F5);
TextView message = new TextView(this);
final int padding = dp2px(16);
message.setPadding(padding, padding, padding, padding);
message.setText(mLog);
message.setTextColor(0xFF000000);
message.setTextIsSelectable(true);
hw.addView(message);
contentView.addView(hw, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setContentView(contentView);
getActionBar().setTitle(TITTLE);
getActionBar().setSubtitle(GlobalApplication.class.getSimpleName() + " Error");
}
@Override
public void onBackPressed() {
restartApp();
}
/**
* 重启应用
*/
private void restartApp() {
final Intent intent = getPackageManager()
.getLaunchIntentForPackage(getPackageName());
if (intent != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
/**
* dp转px
*/
private int dp2px(final float dpValue) {
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
menu.add(0, MENUITEM_COPY, 0, "Copy")
.setOnMenuItemClickListener(this)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add(0, MENUITEM_RESTART, 0, "Restart")
.setOnMenuItemClickListener(this)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}
@Override
public boolean onMenuItemClick(final MenuItem item) {
switch (item.getItemId()) {
case MENUITEM_COPY:
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(ClipData.newPlainText(getPackageName(), mLog));
Toast.makeText(getApplication(), "The text is copied.", Toast.LENGTH_SHORT).show();
break;
case MENUITEM_RESTART:
AppCrashSafetyWire.getInstance().resumeToMaximumImmediately();
restartApp();
break;
default:
break;
}
return false;
}
}
} }

View File

@@ -6,6 +6,10 @@ import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
import cc.winboll.studio.libappbase.utils.CrashHandleNotifyUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
/** /**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
@@ -125,7 +129,9 @@ public class GlobalApplication extends Application {
*/ */
@Override @Override
public void onCreate() { public void onCreate() {
try {
super.onCreate(); super.onCreate();
// 初始化单例实例(确保在所有初始化操作前完成) // 初始化单例实例(确保在所有初始化操作前完成)
sInstance = this; sInstance = this;
@@ -136,6 +142,19 @@ public class GlobalApplication extends Application {
initWinbollHost(); initWinbollHost();
LogUtils.d(TAG, "GlobalApplication 初始化完成,单例实例已创建"); LogUtils.d(TAG, "GlobalApplication 初始化完成,单例实例已创建");
} catch (Throwable e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.close();
String stackTraceStr = sw.toString();
CrashHandleNotifyUtils.handleUncaughtException(
this,
getPackageName(),
stackTraceStr,
CrashActivity.class
);
}
} }
/** /**
@@ -190,7 +209,7 @@ public class GlobalApplication extends Application {
*/ */
public static String getAppName(Context context) { public static String getAppName(Context context) {
if (context == null) { if (context == null) {
LogUtils.w(TAG, "getAppName: 上下文为空,返回 null"); Log.w(TAG, "getAppName: 上下文为空,返回 null");
return null; return null;
} }
PackageManager packageManager = context.getPackageManager(); PackageManager packageManager = context.getPackageManager();
@@ -206,8 +225,7 @@ public class GlobalApplication extends Application {
return appName; return appName;
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
// 包名不存在(理论上不会发生,捕获异常避免崩溃) // 包名不存在(理论上不会发生,捕获异常避免崩溃)
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); Log.e(TAG, "获取应用名称失败:包名不存在", e);
//LogUtils.e(TAG, "获取应用名称失败:包名不存在", e);
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;

View File

@@ -66,7 +66,7 @@ public final class GlobalCrashActivity extends Activity implements MenuItem.OnMe
mCrashLog = getIntent().getStringExtra(CrashHandler.EXTRA_CRASH_LOG); mCrashLog = getIntent().getStringExtra(CrashHandler.EXTRA_CRASH_LOG);
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.putExtra(CrashHandler.EXTRA_CRASH_LOG, mCrashLog); intent.putExtra(CrashHandler.EXTRA_CRASH_LOG, mCrashLog);
CrashHandleNotifyUtils.handleUncaughtException(GlobalApplication.getInstance(), intent, CrashHandler.CrashActivity.class); CrashHandleNotifyUtils.handleUncaughtException(GlobalApplication.getInstance(), intent, CrashActivity.class);
StackTraceElement[] stackElements = Thread.currentThread().getStackTrace(); StackTraceElement[] stackElements = Thread.currentThread().getStackTrace();
StringBuilder sb = new StringBuilder("GlobalCrashActivity onCreate StackTrace"); StringBuilder sb = new StringBuilder("GlobalCrashActivity onCreate StackTrace");