diff --git a/appbase/build.properties b/appbase/build.properties
index 47d6f2f..162c3eb 100644
--- a/appbase/build.properties
+++ b/appbase/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Wed Feb 12 18:04:02 HKT 2025
+#Wed Feb 12 19:45:53 GMT 2025
stageCount=2
libraryProject=libappbase
baseVersion=1.4
publishVersion=1.4.1
-buildCount=0
+buildCount=22
baseBetaVersion=1.4.2
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 d83a39e..84d0424 100644
--- a/appbase/src/main/java/cc/winboll/studio/appbase/App.java
+++ b/appbase/src/main/java/cc/winboll/studio/appbase/App.java
@@ -6,18 +6,22 @@ package cc.winboll.studio.appbase;
* @Describe APPbase 应用类
*/
import cc.winboll.studio.libappbase.GlobalApplication;
-import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.SOSCSBroadcastReceiver;
+import android.content.IntentFilter;
public class App extends GlobalApplication {
public static final String TAG = "App";
-
+
+ SOSCSBroadcastReceiver mSOSCSBroadcastReceiver;
+
@Override
public void onCreate() {
- GlobalApplication.setIsDebuging(this, BuildConfig.DEBUG);
super.onCreate();
- LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug);
- LogUtils.setALlTAGListEnable(true);
- LogUtils.d(TAG, "LogUtils init");
+ GlobalApplication.setIsDebuging(this, BuildConfig.DEBUG);
+ mSOSCSBroadcastReceiver = new SOSCSBroadcastReceiver();
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(SOSCSBroadcastReceiver.ACTION_SOS);
+ registerReceiver(mSOSCSBroadcastReceiver, intentFilter);
}
}
diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java b/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java
index 66709bd..12d578c 100644
--- a/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java
+++ b/appbase/src/main/java/cc/winboll/studio/appbase/MainActivity.java
@@ -1,15 +1,23 @@
package cc.winboll.studio.appbase;
+import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import androidx.appcompat.app.AppCompatActivity;
-import cc.winboll.studio.libappbase.GlobalApplication;
import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.appbase.R;
+import cc.winboll.studio.libappbase.GlobalApplication;
+import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.LogView;
import com.hjq.toast.ToastUtils;
public class MainActivity extends AppCompatActivity {
+ public static final String TAG = "MainActivity";
+
+ LogView mLogView;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -18,13 +26,32 @@ public class MainActivity extends AppCompatActivity {
Toolbar toolbar = findViewById(R.id.activitymainToolbar1);
setSupportActionBar(toolbar);
-
+
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
-
+ mLogView = findViewById(R.id.activitymainLogView1);
+
+ if (GlobalApplication.isDebuging()) { mLogView.start(); }
+ }
+
+ @Override
+ protected void onResume() {
+ LogUtils.d(TAG, "onResume");
+ super.onResume();
+ mLogView.start();
}
public void onSwitchDebugMode(View view) {
GlobalApplication.setIsDebuging(this, ((CheckBox)view).isChecked());
}
+
+ public void onSOS(View view) {
+ // 创建Intent对象,指定广播的action
+ Intent intent = new Intent("cc.winboll.studio.libappbase.SOSCSBroadcastReceiver.ACTION_SOS");
+ // 可以添加额外的数据
+ intent.putExtra("data", "这是广播携带的数据");
+ // 发送广播
+ sendBroadcast(intent);
+ LogUtils.d(TAG, "onSOS");
+ }
}
diff --git a/appbase/src/main/res/layout/activity_main.xml b/appbase/src/main/res/layout/activity_main.xml
index 42c38fa..2a3329d 100644
--- a/appbase/src/main/res/layout/activity_main.xml
+++ b/appbase/src/main/res/layout/activity_main.xml
@@ -47,6 +47,26 @@
+
+
+
+
+
+
+
+
diff --git a/libappbase/build.gradle b/libappbase/build.gradle
index 2e50a7a..15ccce1 100644
--- a/libappbase/build.gradle
+++ b/libappbase/build.gradle
@@ -29,8 +29,10 @@ dependencies {
api 'com.github.getActivity:ToastUtils:10.5'
api 'androidx.appcompat:appcompat:1.3.1'
- //api 'androidx.vectordrawable:vectordrawable:1.1.0'
- //api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
+ api 'androidx.vectordrawable:vectordrawable:1.1.0'
+ api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
+ api 'androidx.fragment:fragment:1.1.0'
+ api 'com.google.android.material:material:1.1.0'
api fileTree(dir: 'libs', include: ['*.jar'])
}
diff --git a/libappbase/build.properties b/libappbase/build.properties
index b249df5..162c3eb 100644
--- a/libappbase/build.properties
+++ b/libappbase/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Wed Feb 12 18:03:55 HKT 2025
+#Wed Feb 12 19:45:53 GMT 2025
stageCount=2
libraryProject=libappbase
baseVersion=1.4
publishVersion=1.4.1
-buildCount=0
+buildCount=22
baseBetaVersion=1.4.2
diff --git a/libappbase/src/main/AndroidManifest.xml b/libappbase/src/main/AndroidManifest.xml
index 28eb2a2..744fdf1 100644
--- a/libappbase/src/main/AndroidManifest.xml
+++ b/libappbase/src/main/AndroidManifest.xml
@@ -20,6 +20,8 @@
+
+
-
\ No newline at end of file
+
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/IWinBollActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/IWinBollActivity.java
new file mode 100644
index 0000000..fe51ef8
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/IWinBollActivity.java
@@ -0,0 +1,24 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/02/04 10:20:16
+ * @Describe WinBoll Activity 接口
+ */
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.libappbase.bean.APPInfo;
+
+public interface IWinBollActivity {
+
+ public static final String TAG = "IWinBollActivity";
+
+ // 获取当前具有 IWinBoll 特征的 AppCompatActivity 活动窗口
+ AppCompatActivity getActivity();
+
+ abstract public APPInfo getAppInfo();
+ abstract public String getTag();
+ abstract Toolbar initToolBar();
+ abstract boolean isEnableDisplayHomeAsUp();
+ abstract boolean isAddWinBollToolBar();
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java
new file mode 100644
index 0000000..f20061a
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java
@@ -0,0 +1,68 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/12 15:07:58
+ * @Describe WinBoll 应用日志窗口
+ */
+import android.os.Bundle;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.libappbase.GlobalApplication;
+import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.bean.APPInfo;
+import cc.winboll.studio.libappbase.R;
+
+public class LogActivity extends AppCompatActivity implements IWinBollActivity {
+
+ public static final String TAG = "LogActivity";
+
+ LogView mLogView;
+
+ @Override
+ public AppCompatActivity getActivity() {
+ return this;
+ }
+
+ @Override
+ public APPInfo getAppInfo() {
+ return null;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ public Toolbar initToolBar() {
+ return null;
+ }
+
+ @Override
+ public boolean isEnableDisplayHomeAsUp() {
+ return false;
+ }
+
+ @Override
+ public boolean isAddWinBollToolBar() {
+ return false;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ LogUtils.d(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_log);
+ mLogView = findViewById(R.id.logview);
+
+ if (GlobalApplication.isDebuging()) { mLogView.start(); }
+ }
+
+ @Override
+ protected void onResume() {
+ LogUtils.d(TAG, "onResume");
+ super.onResume();
+ mLogView.start();
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java
new file mode 100644
index 0000000..ec71977
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java
@@ -0,0 +1,387 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/12 14:36:18
+ * @Describe 日志视图类,继承 RelativeLayout 类。
+ */
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.R;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+public class LogView extends RelativeLayout {
+
+ public static final String TAG = "LogView";
+
+ public volatile boolean mIsHandling;
+ public volatile boolean mIsAddNewLog;
+
+ Context mContext;
+ ScrollView mScrollView;
+ TextView mTextView;
+ CheckBox mSelectableCheckBox;
+ CheckBox mSelectAllTAGCheckBox;
+ TAGListAdapter mTAGListAdapter;
+ LogViewThread mLogViewThread;
+ LogViewHandler mLogViewHandler;
+ Spinner mLogLevelSpinner;
+ ArrayAdapter mLogLevelSpinnerAdapter;
+ // 标签列表
+ RecyclerView recyclerView;
+
+ public LogView(Context context) {
+ super(context);
+ initView(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initView(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initView(context);
+ }
+
+ public LogView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ initView(context);
+ }
+
+ public void start() {
+ mLogViewThread = new LogViewThread(LogView.this);
+ mLogViewThread.start();
+ // 显示日志
+ showAndScrollLogView();
+ }
+
+ public void scrollLogUp() {
+ mScrollView.post(new Runnable() {
+ @Override
+ public void run() {
+ mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
+ // 日志显示结束
+ mLogViewHandler.setIsHandling(false);
+ // 检查是否添加了新日志
+ if (mLogViewHandler.isAddNewLog()) {
+ // 有新日志添加,先更改新日志标志
+ mLogViewHandler.setIsAddNewLog(false);
+ // 再次发送显示日志的显示
+ Message message = mLogViewHandler.obtainMessage(LogViewHandler.MSG_LOGVIEW_UPDATE);
+ mLogViewHandler.sendMessage(message);
+ }
+ }
+ });
+ }
+
+ void initView(Context context) {
+ mContext = context;
+ mLogViewHandler = new LogViewHandler();
+ // 加载视图布局
+ addView(inflate(mContext, cc.winboll.studio.libappbase.R.layout.view_log, null));
+ // 初始化日志子控件视图
+ //
+ mScrollView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogScrollViewLog);
+ mTextView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogTextViewLog);
+ // 获取Log Level spinner实例
+ mLogLevelSpinner = findViewById(cc.winboll.studio.libappbase.R.id.viewlogSpinner1);
+
+ (findViewById(cc.winboll.studio.libappbase.R.id.viewlogButtonClean)).setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+ LogUtils.cleanLog();
+ LogUtils.d(TAG, "Log is cleaned.");
+ }
+ });
+ (findViewById(cc.winboll.studio.libappbase.R.id.viewlogButtonCopy)).setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+
+ ClipboardManager cm = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(ClipData.newPlainText(mContext.getPackageName(), LogUtils.loadLog()));
+ LogUtils.d(TAG, "Log is copied.");
+ }
+ });
+ mSelectableCheckBox = findViewById(cc.winboll.studio.libappbase.R.id.viewlogCheckBoxSelectable);
+ mSelectableCheckBox.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ if (mSelectableCheckBox.isChecked()) {
+ setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+ } else {
+ setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ }
+ }
+ });
+
+ // 设置日志级别列表
+ ArrayList adapterItems = new ArrayList<>();
+ for (LogUtils.LOG_LEVEL e : LogUtils.LOG_LEVEL.values()) {
+ adapterItems.add(e.name());
+ }
+ // 假设你有一个字符串数组作为选项列表
+ //String[] options = {"Option 1", "Option 2", "Option 3"};
+ // 创建一个ArrayAdapter来绑定数据到spinner
+ mLogLevelSpinnerAdapter = ArrayAdapter.createFromResource(
+ context, cc.winboll.studio.libappbase.R.array.enum_loglevel_array, android.R.layout.simple_spinner_item);
+ mLogLevelSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+ // 设置适配器并将它应用到spinner上
+ mLogLevelSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // 设置下拉视图样式
+ mLogLevelSpinner.setAdapter(mLogLevelSpinnerAdapter);
+ // 为Spinner添加监听器
+ mLogLevelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ //String selectedOption = mLogLevelSpinnerAdapter.getItem(position);
+ // 处理选中的选项...
+ LogUtils.setLogLevel(LogUtils.LOG_LEVEL.values()[position]);
+ }
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ // 如果没有选择,则执行此操作...
+ }
+ });
+ // 获取默认值的索引
+ int defaultValueIndex = LogUtils.getLogLevel().ordinal();
+
+ if (defaultValueIndex != -1) {
+ // 如果找到了默认值,设置默认选项
+ mLogLevelSpinner.setSelection(defaultValueIndex);
+ }
+
+ // 加载标签列表
+ Map mapTAGList = LogUtils.getMapTAGList();
+ boolean isAllSelect = true;
+ for (Map.Entry entry : mapTAGList.entrySet()) {
+ if (entry.getValue() == false) {
+ isAllSelect = false;
+ break;
+ }
+ }
+ CheckBox cbALLTAG = findViewById(cc.winboll.studio.libappbase.R.id.viewlogCheckBox1);
+ cbALLTAG.setChecked(isAllSelect);
+
+ // 加载标签表
+ recyclerView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogRecyclerView1);
+ LinearLayoutManager layoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false);
+ recyclerView.setLayoutManager(layoutManager);
+ mTAGListAdapter = new TAGListAdapter(mapTAGList);
+ recyclerView.setAdapter(mTAGListAdapter);
+
+ // 可以添加点击监听器来处理勾选框状态变化后的逻辑,比如获取当前勾选情况等
+ mTAGListAdapter.notifyDataSetChanged();
+
+ mSelectAllTAGCheckBox = findViewById(cc.winboll.studio.libappbase.R.id.viewlogCheckBox1);
+ mSelectAllTAGCheckBox.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ LogUtils.setALlTAGListEnable(mSelectAllTAGCheckBox.isChecked());
+ //LogUtils.setALlTAGListEnable(false);
+ //mTAGListAdapter.notifyDataSetChanged();
+ mTAGListAdapter.reload();
+ //ToastUtils.show(String.format("onClick\nmSelectAllTAGCheckBox.isChecked() : %s", mSelectAllTAGCheckBox.isChecked()));
+ }
+ });
+
+
+ // 设置滚动时不聚焦日志
+ setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ }
+
+ public void updateLogView() {
+ if (mLogViewHandler.isHandling() == true) {
+ // 正在处理日志显示,
+ // 就先设置一个新日志标志位
+ // 以便日志显示完后,再次显示新日志内容
+ mLogViewHandler.setIsAddNewLog(true);
+ } else {
+ //LogUtils.d(TAG, "LogListener showLog(String path)");
+ Message message = mLogViewHandler.obtainMessage(LogViewHandler.MSG_LOGVIEW_UPDATE);
+ mLogViewHandler.sendMessage(message);
+ mLogViewHandler.setIsAddNewLog(false);
+ }
+ }
+
+ void showAndScrollLogView() {
+ mTextView.setText(LogUtils.loadLog());
+ scrollLogUp();
+ }
+
+ class LogViewHandler extends Handler {
+
+ final static int MSG_LOGVIEW_UPDATE = 0;
+ volatile boolean isHandling;
+ volatile boolean isAddNewLog;
+
+ public LogViewHandler() {
+ setIsHandling(false);
+ setIsAddNewLog(false);
+ }
+
+ public void setIsHandling(boolean isHandling) {
+ this.isHandling = isHandling;
+ }
+
+ public boolean isHandling() {
+ return isHandling;
+ }
+
+ public void setIsAddNewLog(boolean isAddNewLog) {
+ this.isAddNewLog = isAddNewLog;
+ }
+
+ public boolean isAddNewLog() {
+ return isAddNewLog;
+ }
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_LOGVIEW_UPDATE:{
+ if (isHandling() == false) {
+ setIsHandling(true);
+ showAndScrollLogView();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ }
+
+ public class TAGItemModel {
+ private String tag;
+ private boolean isChecked;
+
+ public TAGItemModel(String tag, boolean isChecked) {
+ this.tag = tag;
+ this.isChecked = isChecked;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ public boolean isChecked() {
+ return isChecked;
+ }
+
+ public void setChecked(boolean checked) {
+ isChecked = checked;
+ }
+ }
+
+
+ public class TAGListAdapter extends RecyclerView.Adapter {
+
+ private Map mapOrigin;
+ private List itemList;
+
+ public TAGListAdapter(Map map) {
+ mapOrigin = map;
+ loadMap(mapOrigin);
+ }
+
+ void loadMap(Map map) {
+ itemList = new ArrayList();
+ for (Map.Entry entry : map.entrySet()) {
+ itemList.add(new TAGItemModel(entry.getKey(), entry.getValue()));
+ }
+ // 添加排序功能,按照tag进行升序排序
+ Collections.sort(itemList, new SortMapEntryByKeyString(true));
+ //Collections.sort(itemList, new SortMapEntryByKeyString(false));
+ }
+
+ public void reload() {
+ loadMap(mapOrigin);
+ super.notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_logtag, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ final TAGItemModel item = itemList.get(position);
+ holder.tvText.setText(item.getTag());
+ holder.cbChecked.setChecked(item.isChecked());
+ holder.cbChecked.setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+ LogUtils.setTAGListEnable(item.getTag(), ((CheckBox)v).isChecked());
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return itemList.size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ TextView tvText;
+ CheckBox cbChecked;
+
+ public ViewHolder(@NonNull View itemView) {
+ super(itemView);
+ tvText = itemView.findViewById(R.id.viewlogtagTextView1);
+ cbChecked = itemView.findViewById(R.id.viewlogtagCheckBox1);
+ }
+ }
+ }
+
+ class SortMapEntryByKeyString implements Comparator {
+ private boolean mIsDesc = true;
+ // isDesc 是否降序排列
+ public SortMapEntryByKeyString(boolean isDesc) {
+ mIsDesc = isDesc;
+ }
+ Collator cmp = Collator.getInstance(java.util.Locale.CHINA);
+ @Override
+ public int compare(TAGItemModel o1, TAGItemModel o2) {
+ if (mIsDesc) {
+ return o1.getTag().compareTo(o2.getTag());
+ } else {
+ return o2.getTag().compareTo(o1.getTag());
+ }
+ }
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java
new file mode 100644
index 0000000..00d06b2
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java
@@ -0,0 +1,80 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/12 14:43:50
+ * @Describe 日志视图线程类
+ */
+import android.os.FileObserver;
+import cc.winboll.studio.libappbase.LogUtils;
+import java.lang.ref.WeakReference;
+
+public class LogViewThread extends Thread {
+
+ public static final String TAG = "LogViewThread";
+
+ // 线程退出标志
+ volatile boolean isExist = false;
+ // 应用日志文件监听实例
+ LogListener mLogListener;
+ // 日志视图弱引用
+ WeakReference mwrLogView;
+
+ //
+ // 构造函数
+ // @logView : 日志显示输出视图类
+ public LogViewThread(LogView logView) {
+ mwrLogView = new WeakReference(logView);
+
+ }
+
+ public void setIsExist(boolean isExist) {
+ this.isExist = isExist;
+ }
+
+ public boolean isExist() {
+ return isExist;
+ }
+
+ @Override
+ public void run() {
+ String szLogDir = LogUtils.getLogCacheDir().getPath();
+ mLogListener = new LogListener(szLogDir);
+ mLogListener.startWatching();
+ while (isExist() == false) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {}
+ }
+ mLogListener.stopWatching();
+ }
+
+
+ //
+ // 日志文件监听类
+ //
+ class LogListener extends FileObserver {
+ public LogListener(String path) {
+ super(path);
+ }
+
+ @Override
+ public void onEvent(int event, String path) {
+ int e = event & FileObserver.ALL_EVENTS;
+ switch (e) {
+ case FileObserver.CLOSE_WRITE:{
+ if (mwrLogView.get() != null) {
+ mwrLogView.get().updateLogView();
+ }
+ break;
+ }
+ case FileObserver.DELETE:{
+ if (mwrLogView.get() != null) {
+ mwrLogView.get().updateLogView();
+ }
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/SOSCSBroadcastReceiver.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/SOSCSBroadcastReceiver.java
new file mode 100644
index 0000000..6de76ee
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/SOSCSBroadcastReceiver.java
@@ -0,0 +1,27 @@
+package cc.winboll.studio.libappbase;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/02/12 23:44:57
+ * @Describe 简单信号通信中心接收器
+ */
+public class SOSCSBroadcastReceiver extends BroadcastReceiver {
+
+ public static final String TAG = "SOSCSBroadcastReceiver";
+ public static final String ACTION_SOS = SOSCSBroadcastReceiver.class.getName() + ".ACTION_SOS";
+
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if(action.equals(context.getString(R.string.action_sos))) {
+ LogUtils.d(TAG, "action_sos");
+ } else {
+ LogUtils.d(TAG, String.format("action %s", action));
+ }
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/SimpleOperateSignalCenterService.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/SimpleOperateSignalCenterService.java
index 2b18fab..17e9663 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/SimpleOperateSignalCenterService.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/SimpleOperateSignalCenterService.java
@@ -11,12 +11,21 @@ import android.content.Intent;
import android.os.IBinder;
public class SimpleOperateSignalCenterService extends Service {
-
+
public static final String TAG = "SimpleOperateSignalCenterService";
-
+
@Override
public IBinder onBind(Intent intent) {
return null;
}
-
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return super.onStartCommand(intent, flags, startId);
+ }
}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/APPInfo.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/APPInfo.java
new file mode 100644
index 0000000..ef4c3a8
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/bean/APPInfo.java
@@ -0,0 +1,142 @@
+package cc.winboll.studio.libappbase.bean;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/20 14:19:02
+ * @Describe 应用信息类
+ */
+import cc.winboll.studio.libappbase.R;
+import java.io.Serializable;
+
+public class APPInfo implements Serializable {
+
+ public static final String TAG = "APPInfo";
+
+ // 应用名称
+ String appName;
+ // 应用图标
+ int appIcon;
+ // 应用描述
+ String appDescription;
+ // 应用Git仓库地址
+ String appGitName;
+ // 应用Git仓库拥有者
+ String appGitOwner;
+ // 应用Git仓库分支
+ String appGitAPPBranch;
+ // 应用Git仓库子项目文件夹
+ String appGitAPPSubProjectFolder;
+ // 应用主页
+ String appHomePage;
+ // 应用包名称
+ String appAPKName;
+ // 应用包存储文件夹名称
+ String appAPKFolderName;
+
+ public APPInfo(String appName, int appIcon, String appDescription, String appGitName, String appGitOwner, String appGitAPPBranch, String appGitAPPSubProjectFolder, String appHomePage, String appAPKName, String appAPKFolderName) {
+ this.appName = appName;
+ this.appIcon = appIcon;
+ this.appDescription = appDescription;
+ this.appGitName = appGitName;
+ this.appGitOwner = appGitOwner;
+ this.appGitAPPBranch = appGitAPPBranch;
+ this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
+ this.appHomePage = appHomePage;
+ this.appAPKName = appAPKName;
+ this.appAPKFolderName = appAPKFolderName;
+ }
+
+ public APPInfo() {
+ this.appName = "WinBoll-APP";
+ this.appIcon = R.drawable.ic_launcher;
+ this.appDescription = "WinBoll APP";
+ this.appGitName = "APP";
+ this.appGitOwner = "Studio";
+ this.appGitAPPBranch = "app";
+ this.appGitAPPSubProjectFolder = "app";
+ this.appHomePage = "https://www.winboll.cc/studio/details.php?app=APP";
+ this.appAPKName = "APP";
+ this.appAPKFolderName = "APP";
+ }
+
+ public void setAppGitOwner(String appGitOwner) {
+ this.appGitOwner = appGitOwner;
+ }
+
+ public String getAppGitOwner() {
+ return appGitOwner;
+ }
+
+ public void setAppGitAPPBranch(String appGitAPPBranch) {
+ this.appGitAPPBranch = appGitAPPBranch;
+ }
+
+ public String getAppGitAPPBranch() {
+ return appGitAPPBranch;
+ }
+
+ public void setAppGitAPPSubProjectFolder(String appGitAPPSubProjectFolder) {
+ this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
+ }
+
+ public String getAppGitAPPSubProjectFolder() {
+ return appGitAPPSubProjectFolder;
+ }
+
+ public void setAppIcon(int appIcon) {
+ this.appIcon = appIcon;
+ }
+
+ public int getAppIcon() {
+ return appIcon;
+ }
+
+ public void setAppDescription(String appDescription) {
+ this.appDescription = appDescription;
+ }
+
+ public String getAppDescription() {
+ return appDescription;
+ }
+
+ public void setAppAPKFolderName(String appAPKFolderName) {
+ this.appAPKFolderName = appAPKFolderName;
+ }
+
+ public String getAppAPKFolderName() {
+ return appAPKFolderName;
+ }
+
+ public void setAppName(String appName) {
+ this.appName = appName;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public void setAppGitName(String appGitName) {
+ this.appGitName = appGitName;
+ }
+
+ public String getAppGitName() {
+ return appGitName;
+ }
+
+ public void setAppHomePage(String appHomePage) {
+ this.appHomePage = appHomePage;
+ }
+
+ public String getAppHomePage() {
+ return appHomePage;
+ }
+
+ public void setAppAPKName(String appAPKName) {
+ this.appAPKName = appAPKName;
+ }
+
+ public String getAppAPKName() {
+ return appAPKName;
+ }
+}
+
diff --git a/libappbase/src/main/res/drawable-hdpi/ic_launcher.png b/libappbase/src/main/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 96a442e..0000000
Binary files a/libappbase/src/main/res/drawable-hdpi/ic_launcher.png and /dev/null differ
diff --git a/libappbase/src/main/res/drawable-mdpi/ic_launcher.png b/libappbase/src/main/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index 359047d..0000000
Binary files a/libappbase/src/main/res/drawable-mdpi/ic_launcher.png and /dev/null differ
diff --git a/libappbase/src/main/res/drawable-xhdpi/ic_launcher.png b/libappbase/src/main/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 71c6d76..0000000
Binary files a/libappbase/src/main/res/drawable-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/libappbase/src/main/res/drawable-xxhdpi/ic_launcher.png b/libappbase/src/main/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 4df1894..0000000
Binary files a/libappbase/src/main/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/libappbase/src/main/res/drawable/bg_shadow.xml b/libappbase/src/main/res/drawable/bg_shadow.xml
new file mode 100644
index 0000000..6d3d898
--- /dev/null
+++ b/libappbase/src/main/res/drawable/bg_shadow.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_launcher.xml b/libappbase/src/main/res/drawable/ic_launcher.xml
new file mode 100644
index 0000000..0380101
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_launcher.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/libappbase/src/main/res/drawable/view_border.xml b/libappbase/src/main/res/drawable/view_border.xml
new file mode 100644
index 0000000..58b374a
--- /dev/null
+++ b/libappbase/src/main/res/drawable/view_border.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/libappbase/src/main/res/layout/activity_log.xml b/libappbase/src/main/res/layout/activity_log.xml
new file mode 100644
index 0000000..dfcde4f
--- /dev/null
+++ b/libappbase/src/main/res/layout/activity_log.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/layout/view_log.xml b/libappbase/src/main/res/layout/view_log.xml
new file mode 100644
index 0000000..1b98af1
--- /dev/null
+++ b/libappbase/src/main/res/layout/view_log.xml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/layout/view_logtag.xml b/libappbase/src/main/res/layout/view_logtag.xml
new file mode 100644
index 0000000..17e36f8
--- /dev/null
+++ b/libappbase/src/main/res/layout/view_logtag.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/values/array.xml b/libappbase/src/main/res/values/array.xml
new file mode 100644
index 0000000..fdb5cac
--- /dev/null
+++ b/libappbase/src/main/res/values/array.xml
@@ -0,0 +1,11 @@
+
+
+
+ - Off
+ - Error
+ - Warn
+ - Info
+ - Debug
+ - Verbose
+
+
diff --git a/libappbase/src/main/res/values/strings.xml b/libappbase/src/main/res/values/strings.xml
index 87eff22..1774a62 100644
--- a/libappbase/src/main/res/values/strings.xml
+++ b/libappbase/src/main/res/values/strings.xml
@@ -3,5 +3,6 @@
libappbase
Hello world!
-
+ cc.winboll.studio.libappbase.SOSCSBroadcastReceiver.ACTION_SOS
+