diff --git a/appbase/build.properties b/appbase/build.properties
index b02ade7..93f41e8 100644
--- a/appbase/build.properties
+++ b/appbase/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Thu Feb 06 07:12:44 HKT 2025
+#Fri Feb 07 09:04:42 GMT 2025
stageCount=1
libraryProject=libappbase
baseVersion=1.2
publishVersion=1.2.0
-buildCount=0
+buildCount=172
baseBetaVersion=1.2.1
diff --git a/libappbase/build.properties b/libappbase/build.properties
index bebcdb7..93f41e8 100644
--- a/libappbase/build.properties
+++ b/libappbase/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Thu Feb 06 07:12:30 HKT 2025
+#Fri Feb 07 09:04:42 GMT 2025
stageCount=1
libraryProject=libappbase
baseVersion=1.2
publishVersion=1.2.0
-buildCount=0
+buildCount=172
baseBetaVersion=1.2.1
diff --git a/libappbase/src/main/AndroidManifest.xml b/libappbase/src/main/AndroidManifest.xml
index 7293655..8a9e6cf 100644
--- a/libappbase/src/main/AndroidManifest.xml
+++ b/libappbase/src/main/AndroidManifest.xml
@@ -7,6 +7,10 @@
android:name=".CrashHandler$CrashActiviy"
android:label="CrashActiviy"
android:launchMode="standard"/>
+
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/BaseBean.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/BaseBean.java
new file mode 100644
index 0000000..230a02a
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/BaseBean.java
@@ -0,0 +1,283 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/15 11:11:52
+ * @Describe Json Bean 基础类。
+ */
+import android.content.Context;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+public abstract class BaseBean {
+
+ public static final String TAG = "BaseBean";
+ static final String BEAN_NAME = "BeanName";
+
+ public BaseBean() {}
+
+ public abstract String getName();
+
+ public String getBeanJsonFilePath(Context context) {
+
+ return context.getExternalFilesDir(TAG) + "/" + getName() + ".json";
+ }
+
+ public String getBeanListJsonFilePath(Context context) {
+
+ return context.getExternalFilesDir(TAG) + "/" + getName() + "_List.json";
+ }
+
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ jsonWriter.name(BEAN_NAME).value(getName());
+ }
+
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ return false;
+ }
+
+ abstract public T readBeanFromJsonReader(JsonReader jsonReader) throws IOException;
+
+ public static String checkIsTheSameBeanListAndFile(String szFilePath, Class clazz) {
+ StringBuilder sbResult = new StringBuilder();
+ String szErrorInfo = "Check Is The Same Bean List And File Error : ";
+
+ try {
+ int nSameCount = 0;
+ int nBeanListCout = 0;
+
+ T beanTemp = clazz.newInstance();
+ String szBeanSimpleName = beanTemp.getName();
+ String szListJson = FileUtils.readStringFromFile(szFilePath);
+ StringReader stringReader = new StringReader(szListJson);
+ JsonReader jsonReader = new JsonReader(stringReader);
+ jsonReader.beginArray();
+ while (jsonReader.hasNext()) {
+ nBeanListCout++;
+ jsonReader.beginObject();
+ while (jsonReader.hasNext()) {
+ String name = jsonReader.nextName();
+ if (name.equals(BEAN_NAME)) {
+ if (szBeanSimpleName.equals(jsonReader.nextString())) {
+ nSameCount++;
+ }
+ } else {
+ jsonReader.skipValue();
+ }
+ }
+ jsonReader.endObject();
+ }
+ jsonReader.endArray();
+
+ // 返回检查结果
+ if (nSameCount == nBeanListCout) {
+ // 检查一致直接返回空串
+ return "";
+ } else {
+ // 检查不一致返回对比信息
+ sbResult.append("Total : ");
+ sbResult.append(nBeanListCout);
+ sbResult.append(" Diff : ");
+ sbResult.append(nBeanListCout - nSameCount);
+ }
+ } catch (InstantiationException e) {
+ sbResult.append(szErrorInfo);
+ sbResult.append(e);
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IllegalAccessException e) {
+ sbResult.append(szErrorInfo);
+ sbResult.append(e);
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IOException e) {
+ sbResult.append(szErrorInfo);
+ sbResult.append(e);
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return sbResult.toString();
+ }
+
+ public static T parseStringToBean(String szBean, Class clazz) throws IOException {
+ // 创建 JsonWriter 对象
+ StringReader stringReader = new StringReader(szBean);
+ JsonReader jsonReader = new JsonReader(stringReader);
+ try {
+ T beanTemp = clazz.newInstance();
+ return (T)beanTemp.readBeanFromJsonReader(jsonReader);
+ } catch (InstantiationException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return null;
+ }
+
+ public static boolean parseStringToBeanList(String szBeanList, ArrayList beanList, Class clazz) {
+ try {
+ beanList.clear();
+ StringReader stringReader = new StringReader(szBeanList);
+ JsonReader jsonReader = new JsonReader(stringReader);
+ jsonReader.beginArray();
+ while (jsonReader.hasNext()) {
+ T beanTemp = clazz.newInstance();
+ T bean = (T)beanTemp.readBeanFromJsonReader(jsonReader);
+ if (bean != null) {
+ beanList.add(bean);
+ //LogUtils.d(TAG, "beanList.add(bean)");
+ }
+ }
+ jsonReader.endArray();
+ return true;
+ //LogUtils.d(TAG, "beanList.size() is " + Integer.toString(beanList.size()));
+ } catch (InstantiationException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ // 创建 JsonWriter 对象
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ jsonWriter.setIndent(" ");
+ try {// 开始 JSON 对象
+ jsonWriter.beginObject();
+ // 写入键值对
+ writeThisToJsonWriter(jsonWriter);
+ // 结束 JSON 对象
+ jsonWriter.endObject();
+ return stringWriter.toString();
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ // 获取 JSON 字符串
+ return "";
+ }
+
+ public static String toStringByBeanList(ArrayList beanList) {
+ try {
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ jsonWriter.setIndent(" ");
+ jsonWriter.beginArray();
+ for (int i = 0; i < beanList.size(); i++) {
+ // 开始 JSON 对象
+ jsonWriter.beginObject();
+ // 写入键值对
+ beanList.get(i).writeThisToJsonWriter(jsonWriter);
+ // 结束 JSON 对象
+ jsonWriter.endObject();
+ }
+ jsonWriter.endArray();
+ jsonWriter.close();
+ return stringWriter.toString();
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return "";
+ }
+
+
+ public static T loadBean(Context context, Class clazz) {
+ try {
+ T beanTemp = clazz.newInstance();
+ return loadBeanFromFile(beanTemp.getBeanJsonFilePath(context), clazz);
+ } catch (InstantiationException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return null;
+ }
+
+ public static T loadBeanFromFile(String szFilePath, Class clazz) {
+ try {
+ try {
+ File fTemp = new File(szFilePath);
+ if (fTemp.exists()) {
+ T beanTemp = clazz.newInstance();String szJson = FileUtils.readStringFromFile(szFilePath);
+ return beanTemp.parseStringToBean(szJson, clazz);
+ }
+ } catch (InstantiationException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return null;
+ }
+
+ public static boolean saveBean(Context context, T bean) {
+ return saveBeanToFile(bean.getBeanJsonFilePath(context), bean);
+ }
+
+ public static boolean saveBeanToFile(String szFilePath, T bean) {
+ try {
+ String szJson = bean.toString();
+ FileUtils.writeStringToFile(szFilePath, szJson);
+ return true;
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+
+ public static boolean loadBeanList(Context context, ArrayList beanListDst, Class clazz) {
+ try {
+ T beanTemp = clazz.newInstance();
+ return loadBeanListFromFile(beanTemp.getBeanListJsonFilePath(context), beanListDst, clazz);
+ } catch (InstantiationException e) {} catch (IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+
+ public static boolean loadBeanListFromFile(String szFilePath, ArrayList beanList, Class clazz) {
+ try {
+ File fTemp = new File(szFilePath);
+ if (fTemp.exists()) {
+ String szListJson = FileUtils.readStringFromFile(szFilePath);
+ return parseStringToBeanList(szListJson, beanList, clazz);
+ }
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+
+ public static boolean saveBeanList(Context context, ArrayList beanList, Class clazz) {
+ try {
+ T beanTemp = clazz.newInstance();
+ return saveBeanListToFile(beanTemp.getBeanListJsonFilePath(context), beanList);
+ } catch (InstantiationException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } catch (IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+
+ public static boolean saveBeanListToFile(String szFilePath, ArrayList beanList) {
+ try {
+ String szJson = toStringByBeanList(beanList);
+ FileUtils.writeStringToFile(szFilePath, szJson);
+ //LogUtils.d(TAG, "FileUtil.writeFile beanList.size() is " + Integer.toString(beanList.size()));
+ return true;
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+}
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 2fce15d..7257c05 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java
@@ -18,17 +18,24 @@ import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
+import cc.winboll.studio.libappbase.GlobalApplication;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
@@ -37,11 +44,22 @@ import java.util.Date;
import java.util.Locale;
public final class CrashHandler {
+ public static final String TAG = "CrashHandler";
+
+ final static String PREFS = CrashHandler.class.getName() + "PREFS";
+ final static String PREFS_CRASHHANDLER_ISCRASHHAPPEN = "PREFS_CRASHHANDLER_ISCRASHHAPPEN";
+
+ public static String _CrashCountFilePath;
public static final UncaughtExceptionHandler DEFAULT_UNCAUGHT_EXCEPTION_HANDLER = Thread.getDefaultUncaughtExceptionHandler();
+
+
+
public static void init(Application app) {
+ _CrashCountFilePath = app.getExternalFilesDir("CrashHandler") + "/IsCrashHandlerCrashHappen.dat";
init(app, null);
+ LogUtils.d(TAG, "init");
}
public static void init(final Application app, final String crashDir) {
@@ -90,6 +108,7 @@ public final class CrashHandler {
sb.append("App VersionName : ").append(versionName).append("\n");
sb.append("App VersionCode : ").append(versionCode).append("\n");
sb.append("AppBase GlobalApplication Debug Mode : ").append(GlobalApplication.isDebuging).append("\n");
+ sb.append("CrashHandler CurrentSafeLevel : ").append(String.format("%d", AppCrashSafetyWire.getInstance().getCurrentSafetyLevel())).append("\n");
sb.append("************* Crash Head ****************\n");
sb.append("\n").append(fullStackTrace);
@@ -100,12 +119,31 @@ public final class CrashHandler {
} catch (IOException ignored) {}
gotoCrashActiviy: {
- Intent intent = new Intent(app, CrashActiviy.class);
+ Intent intent = new Intent();
+
+ if (AppCrashSafetyWire.getInstance().isAppCrashSafetyWireOK() && AppCrashSafetyWire.getInstance().postCrashSafetyWire(app)) {
+ AppCrashSafetyWire.getInstance().reset();
+ intent.setClass(app, GlobalCrashActiviy.class);
+ intent.putExtra(GlobalCrashActiviy.EXTRA_CRASH_INFO, errorLog);
+ // 如果发生了 CrashHandler 内部崩溃, 就调用基础的应用崩溃显示类
+// intent.setClass(app, GlobalCrashActiviy.class);
+// intent.putExtra(GlobalCrashActiviy.EXTRA_CRASH_INFO, errorLog);
+ } else {
+ AppCrashSafetyWire.getInstance().reset();
+ // 正常状态调用进阶的应用崩溃显示页
+ intent.setClass(app, CrashActiviy.class);
+ intent.putExtra(CrashActiviy.EXTRA_CRASH_INFO, errorLog);
+ }
+
+// intent.setClass(app, CrashActiviy.class);
+// intent.putExtra(CrashActiviy.EXTRA_CRASH_INFO, errorLog);
+
+
intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
);
- intent.putExtra(CrashActiviy.EXTRA_CRASH_INFO, errorLog);
+
try {
app.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
@@ -114,6 +152,10 @@ public final class CrashHandler {
e.printStackTrace();
if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (DEFAULT_UNCAUGHT_EXCEPTION_HANDLER != null)
+ DEFAULT_UNCAUGHT_EXCEPTION_HANDLER.uncaughtException(thread, throwable);
}
}
@@ -135,6 +177,113 @@ public final class CrashHandler {
});
}
+ //
+ // 应用崩溃保险丝
+ //
+ public static final class AppCrashSafetyWire {
+
+ volatile static AppCrashSafetyWire _AppCrashSafetyWire;
+
+ volatile int currentSafetyLevel; // 熔断值,为 0 表示熔断了。
+ private static final int _MINI = 1;
+ private static final int _MAX = 5;
+
+ AppCrashSafetyWire() {
+ currentSafetyLevel = loadCurrentSafetyLevel();
+ }
+
+ public static synchronized AppCrashSafetyWire getInstance() {
+ if (_AppCrashSafetyWire == null) {
+ _AppCrashSafetyWire = new AppCrashSafetyWire();
+ }
+ return _AppCrashSafetyWire;
+ }
+
+ public void setCurrentSafetyLevel(int currentSafetyLevel) {
+ this.currentSafetyLevel = currentSafetyLevel;
+ }
+
+ public int getCurrentSafetyLevel() {
+ return currentSafetyLevel;
+ }
+
+ public void saveCurrentSafetyLevel(int currentSafetyLevel) {
+ this.currentSafetyLevel = currentSafetyLevel;
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(_CrashCountFilePath));
+ oos.writeInt(currentSafetyLevel);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public int loadCurrentSafetyLevel() {
+ try {
+ File f = new File(_CrashCountFilePath);
+ if (f.exists()) {
+ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(_CrashCountFilePath));
+ currentSafetyLevel = ois.readInt();
+ } else {
+ currentSafetyLevel = _MAX;
+ saveCurrentSafetyLevel(currentSafetyLevel);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return currentSafetyLevel;
+ }
+
+ boolean putOnSafetyWire() {
+ // 崩溃计数进入崩溃保险值
+ int safeLevel = loadCurrentSafetyLevel();
+ if (isSafetyWireOK(safeLevel)) {
+ // 如果保险丝未熔断, 就减少一次熔断值
+ saveCurrentSafetyLevel(safeLevel - 1);
+ return true;
+ }
+
+
+ return false;
+ }
+
+ boolean isSafetyWireOK(int safetyLevel) {
+ if (safetyLevel >= _MINI && safetyLevel <= _MAX) {
+ // 如果在保险值之内
+ return true;
+ }
+ return false;
+ }
+
+ void reset() {
+ saveCurrentSafetyLevel(_MAX);
+ }
+
+ void off() {
+ saveCurrentSafetyLevel(_MINI);
+ }
+
+ boolean isAppCrashSafetyWireOK() {
+ return false;
+ }
+
+ // 调用函数以启用持续崩溃保险,从而调用 CrashHandler 内部崩溃处理窗口
+ boolean postCrashSafetyWire(final Context context) {
+ if (AppCrashSafetyWire.getInstance().putOnSafetyWire()) {
+ // 设置内部崩溃处理模块失效
+ new Handler(Looper.getMainLooper()).postDelayed(new Runnable(){
+ @Override
+ public void run() {
+ // 进程持续运行时重置保险丝
+ //AppCrashSafetyWire.getInstance().reset();
+ }
+ }, 1000);
+ return true;
+ }
+ return false;
+ }
+
+ }
+
public static final class CrashActiviy extends Activity implements MenuItem.OnMenuItemClickListener {
private static final String EXTRA_CRASH_INFO = "crashInfo";
@@ -147,11 +296,13 @@ public final class CrashHandler {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
mLog = getIntent().getStringExtra(EXTRA_CRASH_INFO);
setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
setContentView: {
ScrollView contentView = new ScrollView(this);
contentView.setFillViewport(true);
+
HorizontalScrollView hw = new HorizontalScrollView(this);
hw.setBackgroundColor(Color.GRAY);
TextView message = new TextView(this); {
@@ -161,6 +312,7 @@ public final class CrashHandler {
message.setTextIsSelectable(true);
}
hw.addView(message);
+
contentView.addView(hw, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
setContentView(contentView);
}
@@ -215,5 +367,99 @@ public final class CrashHandler {
return true;
}
}
+
+ public static final class GlobalCrashActiviy extends Activity implements MenuItem.OnMenuItemClickListener {
+
+ private static final String EXTRA_CRASH_INFO = "crashInfo";
+
+ private static final int MENUITEM_COPY = 0;
+ private static final int MENUITEM_RESTART = 1;
+
+ private String mLog;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLog = getIntent().getStringExtra(EXTRA_CRASH_INFO);
+ setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
+ setContentView: {
+ ScrollView contentView = new ScrollView(this);
+ contentView.setFillViewport(true);
+
+ LinearLayout llTitle = new LinearLayout(this);
+ TextView title = new TextView(this); {
+ int padding = dp2px(16);
+ title.setPadding(padding, padding, padding, padding);
+ title.setText("GlobalCrashActiviy");
+ }
+ llTitle.addView(title, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ contentView.addView(llTitle, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
+ HorizontalScrollView hw = new HorizontalScrollView(this);
+ hw.setBackgroundColor(Color.GRAY);
+ TextView message = new TextView(this); {
+ int padding = dp2px(16);
+ message.setPadding(padding, padding, padding, padding);
+ message.setText(mLog);
+ message.setTextIsSelectable(true);
+ }
+ hw.addView(message);
+
+ contentView.addView(hw, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
+ setContentView(contentView);
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ restart();
+ }
+
+ private void restart() {
+ PackageManager pm = getPackageManager();
+ Intent intent = pm.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 onMenuItemClick(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:
+ restart();
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(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;
+ }
+ }
+
+
}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/FileUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/FileUtils.java
new file mode 100644
index 0000000..bbf4003
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/FileUtils.java
@@ -0,0 +1,120 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/07/19 14:30:57
+ * @Describe 文件工具类
+ */
+import android.content.Context;
+import android.content.res.AssetManager;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class FileUtils {
+
+ public static final String TAG = "FileUtils";
+
+ public static void copyAssetsToSD(Context context, String szSrcAssets, String szDstSD) {
+ LogUtils.d(TAG, "copyAssetsToSD [" + szSrcAssets + "] to [" + szDstSD + "]");
+ AssetManager assetManager = context.getAssets();
+ InputStream inputStream = null;
+ OutputStream outputStream = null;
+ try {
+ inputStream = assetManager.open(szSrcAssets);
+ File outputFile = new File(szDstSD);
+ outputStream = new FileOutputStream(outputFile);
+ byte[] buffer = new byte[1024];
+ int length = 0;
+ while ((length = inputStream.read(buffer)) > 0) {
+ outputStream.write(buffer, 0, length);
+ }
+ outputStream.flush();
+ LogUtils.d(TAG, "copyAssetsToSD done.");
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ }
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+ }
+
+ //
+ // 把字符串写入文件,指定 UTF-8 编码
+ //
+ public static void writeStringToFile(String szFilePath, String szContent) throws IOException {
+ File file = new File(szFilePath);
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+ FileOutputStream outputStream = new FileOutputStream(file);
+ OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
+ writer.write(szContent);
+ writer.close();
+ }
+
+ //
+ // 读取文件到字符串,指定 UTF-8 编码
+ //
+ public static String readStringFromFile(String szFilePath) throws IOException {
+ File file = new File(szFilePath);
+ FileInputStream inputStream = new FileInputStream(file);
+ InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
+ StringBuilder content = new StringBuilder();
+ int character;
+ while ((character = reader.read()) != -1) {
+ content.append((char) character);
+ }
+ reader.close();
+ return content.toString();
+ }
+
+ public static boolean copyFile(File srcFile, File dstFile) {
+ if (!srcFile.exists()) {
+ LogUtils.d(TAG, "The original file does not exist.");
+ } else {
+ try {
+ // 源文件路径
+ Path sourcePath = Paths.get(srcFile.getPath());
+ // 目标文件路径
+ Path destPath = Paths.get(dstFile.getPath());
+ // 建立目标父级文件夹
+ if (!dstFile.getParentFile().exists()) {
+ dstFile.getParentFile().mkdirs();
+ }
+ // 删除旧的目标文件
+ if (dstFile.exists()) {
+ dstFile.delete();
+ }
+ // 拷贝文件
+ Files.copy(sourcePath, destPath);
+ LogUtils.d(TAG, "File copy successfully.");
+ return true;
+ } catch (Exception e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ return false;
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java
index 38c9da4..d48a3f7 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java
@@ -20,10 +20,13 @@ import java.io.InputStream;
import java.io.OutputStream;
public class GlobalApplication extends Application {
-
+
+ public static final String TAG = "GlobalApplication";
+
final static String PREFS = GlobalApplication.class.getName() + "PREFS";
final static String PREFS_ISDEBUGING = "PREFS_ISDEBUGING";
+
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
// 是否处于调试状态
@@ -57,13 +60,15 @@ public class GlobalApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
-
// 设置应用异常处理窗口
CrashHandler.init(this);
-
+
// 设置应用调试状态
SharedPreferences sharedPreferences = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
GlobalApplication.isDebuging = sharedPreferences.getBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
+
+ LogUtils.init(this);
+ LogUtils.d(TAG, "onCreate");
}
public static void write(InputStream input, OutputStream output) throws IOException {
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java
new file mode 100644
index 0000000..94b7827
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java
@@ -0,0 +1,369 @@
+package cc.winboll.studio.libappbase;
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/12 13:44:06
+ * @Describe LogUtils
+ * @Describe 应用日志类
+ */
+import android.content.Context;
+import cc.winboll.studio.libappbase.GlobalApplication;
+import dalvik.system.DexFile;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+
+public class LogUtils {
+
+ public static final String TAG = "LogUtils";
+
+ public static enum LOG_LEVEL { Off, Error, Warn, Info, Debug, Verbose }
+
+ static volatile boolean _IsInited = false;
+ static Context _mContext;
+ // 日志显示时间格式
+ static SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("[yyyyMMdd_HHmmSS]", Locale.getDefault());
+ // 应用日志文件夹
+ static File _mfLogCacheDir;
+ static File _mfLogDataDir;
+ // 应用日志文件
+ static File _mfLogCatchFile;
+ static File _mfLogUtilsBeanFile;
+ static LogUtilsBean _mLogUtilsBean;
+ public static Map mapTAGList = new HashMap();
+
+ //
+ // 初始化函数
+ //
+ public static void init(Context context) {
+ _mContext = context;
+ init(context, LOG_LEVEL.Off);
+ }
+
+ //
+ // 初始化函数
+ //
+ public static void init(Context context, LOG_LEVEL logLevel) {
+ if (GlobalApplication.isDebuging()) {
+ // 初始化日志缓存文件路径
+ _mfLogCacheDir = new File(context.getApplicationContext().getExternalCacheDir(), TAG);
+ if (!_mfLogCacheDir.exists()) {
+ _mfLogCacheDir.mkdirs();
+ }
+ _mfLogCatchFile = new File(_mfLogCacheDir, "log.txt");
+
+ // 初始化日志配置文件路径
+ _mfLogDataDir = context.getApplicationContext().getExternalFilesDir(TAG);
+ if (!_mfLogDataDir.exists()) {
+ _mfLogDataDir.mkdirs();
+ }
+ _mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json");
+ } else {
+ // 初始化日志缓存文件路径
+ _mfLogCacheDir = new File(context.getApplicationContext().getCacheDir(), TAG);
+ if (!_mfLogCacheDir.exists()) {
+ _mfLogCacheDir.mkdirs();
+ }
+ _mfLogCatchFile = new File(_mfLogCacheDir, "log.txt");
+
+ // 初始化日志配置文件路径
+ _mfLogDataDir = new File(context.getApplicationContext().getFilesDir(), TAG);
+ if (!_mfLogDataDir.exists()) {
+ _mfLogDataDir.mkdirs();
+ }
+ _mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json");
+ }
+
+// Toast.makeText(context,
+// "_mfLogUtilsBeanFile : " + _mfLogUtilsBeanFile
+// + "\n_mfLogCatchFile : " + _mfLogCatchFile,
+// Toast.LENGTH_SHORT).show();
+//
+ _mLogUtilsBean = LogUtilsBean.loadBeanFromFile(_mfLogUtilsBeanFile.getPath(), LogUtilsBean.class);
+ if (_mLogUtilsBean == null) {
+ _mLogUtilsBean = new LogUtilsBean();
+ _mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean);
+ }
+
+ // 加载当前应用下的所有类的 TAG
+ addClassTAGList();
+ loadTAGBeanSettings();
+ _IsInited = true;
+ LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
+ }
+
+ public static Map getMapTAGList() {
+ return mapTAGList;
+ }
+
+ static void loadTAGBeanSettings() {
+ ArrayList list = new ArrayList();
+ LogUtilsClassTAGBean.loadBeanList(_mContext, list, LogUtilsClassTAGBean.class);
+ for (int i = 0; i < list.size(); i++) {
+ LogUtilsClassTAGBean beanSetting = list.get(i);
+ for (Map.Entry entry : mapTAGList.entrySet()) {
+ if (entry.getKey().equals(beanSetting.getTag())) {
+ entry.setValue(beanSetting.getEnable());
+ }
+ }
+
+ }
+ }
+
+ static void saveTAGBeanSettings() {
+ ArrayList list = new ArrayList();
+ for (Map.Entry entry : mapTAGList.entrySet()) {
+ list.add(new LogUtilsClassTAGBean(entry.getKey(), entry.getValue()));
+ }
+ LogUtilsClassTAGBean.saveBeanList(_mContext, list, LogUtilsClassTAGBean.class);
+ }
+
+ static void addClassTAGList() {
+ //ClassLoader classLoader = getClass().getClassLoader();
+ try {
+ //String packageName = context.getPackageName();
+ String packageNamePrefix = "cc.winboll.studio";
+ List classNames = new ArrayList<>();
+ String apkPath = _mContext.getPackageCodePath();
+ //Log.d("APK_PATH", "The APK path is: " + apkPath);
+ LogUtils.d(TAG, String.format("apkPath : %s", apkPath));
+ //String apkPath = "/data/app/" + packageName + "-";
+
+ //DexFile dexfile = new DexFile(apkPath + "1/base.apk");
+ DexFile dexfile = new DexFile(apkPath);
+
+ int countTemp = 0;
+ Enumeration entries = dexfile.entries();
+ while (entries.hasMoreElements()) {
+ countTemp++;
+ String className = entries.nextElement();
+ if (className.startsWith(packageNamePrefix)) {
+ classNames.add(className);
+ }
+ }
+
+ LogUtils.d(TAG, String.format("countTemp : %d\nClassNames size : %d", countTemp, classNames.size()));
+
+ for (String className : classNames) {
+ try {
+ Class> clazz = Class.forName(className);
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ if (Modifier.isStatic(field.getModifiers()) && Modifier.isPublic(field.getModifiers()) && field.getType() == String.class && "TAG".equals(field.getName())) {
+ String tagValue = (String) field.get(null);
+ //Log.d("TAG_INFO", "Class: " + className + ", TAG value: " + tagValue);
+ //LogUtils.d(TAG, String.format("Tag Value : %s", tagValue));
+ //mapTAGList.put(tagValue, true);
+ mapTAGList.put(tagValue, false);
+ }
+ }
+ } catch (NoClassDefFoundError | ClassNotFoundException | IllegalAccessException e) {
+ LogUtils.d(TAG, e.getMessage(), Thread.currentThread().getStackTrace());
+ //LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ //Toast.makeText(context, TAG + " : " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ }
+ } catch (IOException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ //Toast.makeText(context, TAG + " : " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ public static void setTAGListEnable(String tag, boolean isEnable) {
+ Iterator> iterator = mapTAGList.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = iterator.next();
+ if (tag.equals(entry.getKey())) {
+ entry.setValue(isEnable);
+ //System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
+ break;
+ }
+ }
+ saveTAGBeanSettings();
+ LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
+ }
+
+ public static void setALlTAGListEnable(boolean isEnable) {
+ Iterator> iterator = mapTAGList.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = iterator.next();
+ entry.setValue(isEnable);
+ //System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
+ }
+ saveTAGBeanSettings();
+ LogUtils.d(TAG, String.format("mapTAGList : %s", mapTAGList.toString()));
+ }
+
+ public static void setLogLevel(LOG_LEVEL logLevel) {
+ LogUtils._mLogUtilsBean.setLogLevel(logLevel);
+ _mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean);
+ }
+
+ public static LOG_LEVEL getLogLevel() {
+ return LogUtils._mLogUtilsBean.getLogLevel();
+ }
+
+ static boolean isLoggable(String tag, LOG_LEVEL logLevel) {
+ return _IsInited && mapTAGList.get(tag) && isInTheLevel(logLevel);
+ }
+
+ static boolean isInTheLevel(LOG_LEVEL logLevel) {
+ return (LogUtils._mLogUtilsBean.getLogLevel().ordinal() == logLevel.ordinal()
+ || LogUtils._mLogUtilsBean.getLogLevel().ordinal() > logLevel.ordinal());
+ }
+
+ //
+ // 获取应用日志文件夹
+ //
+ public static File getLogCacheDir() {
+ return _mfLogCacheDir;
+ }
+
+ //
+ // 调试日志写入函数
+ //
+ public static void e(String szTAG, String szMessage) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Error)) {
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Error, szMessage);
+ }
+ }
+
+ //
+ // 调试日志写入函数
+ //
+ public static void w(String szTAG, String szMessage) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Warn)) {
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Warn, szMessage);
+ }
+ }
+
+ //
+ // 调试日志写入函数
+ //
+ public static void i(String szTAG, String szMessage) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Info)) {
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Info, szMessage);
+ }
+ }
+
+ //
+ // 调试日志写入函数
+ //
+ public static void d(String szTAG, String szMessage) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, szMessage);
+ }
+ }
+
+ //
+ // 调试日志写入函数
+ // 包含线程调试堆栈信息
+ //
+ public static void d(String szTAG, String szMessage, StackTraceElement[] listStackTrace) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
+ StringBuilder sbMessage = new StringBuilder(szMessage);
+ sbMessage.append(" \nAt ");
+ sbMessage.append(listStackTrace[2].getMethodName());
+ sbMessage.append(" (");
+ sbMessage.append(listStackTrace[2].getFileName());
+ sbMessage.append(":");
+ sbMessage.append(listStackTrace[2].getLineNumber());
+ sbMessage.append(")");
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sbMessage.toString());
+ }
+ }
+
+ //
+ // 调试日志写入函数
+ // 包含异常信息和线程调试堆栈信息
+ //
+ public static void d(String szTAG, Exception e, StackTraceElement[] listStackTrace) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Debug)) {
+ StringBuilder sbMessage = new StringBuilder(e.getClass().toGenericString());
+ sbMessage.append(" : ");
+ sbMessage.append(e.getMessage());
+ sbMessage.append(" \nAt ");
+ sbMessage.append(listStackTrace[2].getMethodName());
+ sbMessage.append(" (");
+ sbMessage.append(listStackTrace[2].getFileName());
+ sbMessage.append(":");
+ sbMessage.append(listStackTrace[2].getLineNumber());
+ sbMessage.append(")");
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Debug, sbMessage.toString());
+ }
+ }
+
+ //
+ // 调试日志写入函数
+ //
+ public static void v(String szTAG, String szMessage) {
+ if (isLoggable(szTAG, LogUtils.LOG_LEVEL.Verbose)) {
+ saveLog(szTAG, LogUtils.LOG_LEVEL.Verbose, szMessage);
+ }
+ }
+
+ //
+ // 日志文件保存函数
+ //
+ static void saveLog(String szTAG, LogUtils.LOG_LEVEL logLevel, String szMessage) {
+ try {
+ BufferedWriter out = null;
+ out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(_mfLogCatchFile, true), "UTF-8"));
+ out.write("[" + logLevel + "] " + mSimpleDateFormat.format(System.currentTimeMillis()) + " [" + szTAG + "]\n" + szMessage + "\n");
+ out.close();
+ } catch (IOException e) {
+ LogUtils.d(TAG, "IOException : " + e.getMessage());
+ }
+ }
+
+ //
+ // 历史日志加载函数
+ //
+ public static String loadLog() {
+ if (_mfLogCatchFile.exists()) {
+ StringBuffer sb = new StringBuffer();
+ try {
+ BufferedReader in = null;
+ in = new BufferedReader(new InputStreamReader(new FileInputStream(_mfLogCatchFile), "UTF-8"));
+ String line = "";
+ while ((line = in.readLine()) != null) {
+ sb.append(line);
+ sb.append("\n");
+ }
+ } catch (IOException e) {
+ LogUtils.d(TAG, "IOException : " + e.getMessage());
+ }
+ return sb.toString();
+ }
+ return "";
+ }
+
+ //
+ // 清理日志函数
+ //
+ public static void cleanLog() {
+ if (_mfLogCatchFile.exists()) {
+ try {
+ FileUtils.writeStringToFile(_mfLogCatchFile.getPath(), "");
+ //LogUtils.d(TAG, "cleanLog");
+ } catch (IOException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java
new file mode 100644
index 0000000..6cc415d
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java
@@ -0,0 +1,70 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/23 15:39:07
+ * @Describe LogUtils 数据配置类。
+ */
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import java.io.IOException;
+public class LogUtilsBean extends BaseBean {
+
+ public static final String TAG = "LogUtilsBean";
+
+ LogUtils.LOG_LEVEL logLevel;
+
+ public LogUtilsBean() {
+ this.logLevel = LogUtils.LOG_LEVEL.Off;
+ }
+
+ public LogUtilsBean(LogUtils.LOG_LEVEL logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ public void setLogLevel(LogUtils.LOG_LEVEL logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ public LogUtils.LOG_LEVEL getLogLevel() {
+ return logLevel;
+ }
+
+ @Override
+ public String getName() {
+ return LogUtilsBean.class.getName();
+ }
+
+ @Override
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ super.writeThisToJsonWriter(jsonWriter);
+ LogUtilsBean bean = this;
+ jsonWriter.name("logLevel").value(bean.getLogLevel().ordinal());
+ }
+
+ @Override
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
+ if (name.equals("logLevel")) {
+ setLogLevel(LogUtils.LOG_LEVEL.values()[jsonReader.nextInt()]);
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
+ jsonReader.beginObject();
+ while (jsonReader.hasNext()) {
+ String name = jsonReader.nextName();
+ if (!initObjectsFromJsonReader(jsonReader, name)) {
+ jsonReader.skipValue();
+ }
+ }
+ // 结束 JSON 对象
+ jsonReader.endObject();
+ return this;
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java
new file mode 100644
index 0000000..d3d4505
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java
@@ -0,0 +1,87 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/04 14:17:02
+ * @Describe 日志类class TAG 标签数据类
+ */
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import java.io.IOException;
+
+public class LogUtilsClassTAGBean extends BaseBean {
+
+ public static final String TAG = "LogUtilsClassTAGBean";
+
+ // 标签名
+ String tag;
+ // 是否启用
+ Boolean enable;
+
+ public LogUtilsClassTAGBean() {
+ this.tag = TAG;
+ this.enable = true;
+ }
+
+ public LogUtilsClassTAGBean(String tag, Boolean enable) {
+ this.tag = tag;
+ this.enable = enable;
+ }
+
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public void setEnable(Boolean enable) {
+ this.enable = enable;
+ }
+
+ public Boolean getEnable() {
+ return enable;
+ }
+
+ @Override
+ public String getName() {
+ return LogUtilsClassTAGBean.class.getName();
+ }
+
+ @Override
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ super.writeThisToJsonWriter(jsonWriter);
+ LogUtilsClassTAGBean bean = this;
+ jsonWriter.name("tag").value(bean.getTag());
+ jsonWriter.name("enable").value(bean.getEnable());
+ }
+
+ @Override
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
+ if (name.equals("tag")) {
+ setTag(jsonReader.nextString());
+ } else if (name.equals("enable")) {
+ setEnable(jsonReader.nextBoolean());
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
+ jsonReader.beginObject();
+ while (jsonReader.hasNext()) {
+ String name = jsonReader.nextName();
+ if (!initObjectsFromJsonReader(jsonReader, name)) {
+ jsonReader.skipValue();
+ }
+ }
+ // 结束 JSON 对象
+ jsonReader.endObject();
+ return this;
+ }
+}