runningServices = manager
+ .getRunningServices(1000);
+ if (runningServices.size() <= 0) {
+ return false;
+ }
+ // 遍历,若存在名字和传入的serviceName的一致则说明存在
+ for (ActivityManager.RunningServiceInfo runningServiceInfo : runningServices) {
+ if (runningServiceInfo.service.getClassName().equals(szServiceName)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/libapputils/src/main/java/cc/winboll/studio/libapputils/utils/UriUtils.java b/libapputils/src/main/java/cc/winboll/studio/libapputils/utils/UriUtils.java
new file mode 100644
index 0000000..04b1d18
--- /dev/null
+++ b/libapputils/src/main/java/cc/winboll/studio/libapputils/utils/UriUtils.java
@@ -0,0 +1,130 @@
+package cc.winboll.studio.libapputils.utils;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Describe Uri 资源管理工具类
+ */
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class UriUtils {
+
+ public static final String TAG = "UriUtil";
+
+ //
+ // 获取真实路径
+ //
+ // @param context
+ //
+ public static String getFileFromUri(Context context, Uri uri) {
+ if (uri == null) {
+ return null;
+ }
+ switch (uri.getScheme()) {
+ case ContentResolver.SCHEME_CONTENT:
+ //Android7.0之后的uri content:// URI
+ return getFilePathFromContentUri(context, uri);
+ case ContentResolver.SCHEME_FILE:
+ default:
+ //Android7.0之前的uri file://
+ return new File(uri.getPath()).getAbsolutePath();
+ }
+ }
+
+ //
+ // 从uri获取path
+ //
+ // @param uri content://media/external/file/109009
+ //
+ // FileProvider适配
+ // content://com.tencent.mobileqq.fileprovider/external_files/storage/emulated/0/Tencent/QQfile_recv/
+ // content://com.tencent.mm.external.fileprovider/external/tencent/MicroMsg/Download/
+ //
+ private static String getFilePathFromContentUri(Context context, Uri uri) {
+ if (null == uri) return null;
+ String data = null;
+
+ String[] filePathColumn = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME};
+ Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
+ if (null != cursor) {
+ if (cursor.moveToFirst()) {
+ int index = cursor.getColumnIndex(MediaStore.MediaColumns.DATA);
+ if (index > -1) {
+ data = cursor.getString(index);
+ } else {
+ int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
+ String fileName = cursor.getString(nameIndex);
+ data = getPathFromInputStreamUri(context, uri, fileName);
+ }
+ }
+ cursor.close();
+ }
+ return data;
+ }
+
+ //
+ // 用流拷贝文件一份到自己APP私有目录下
+ //
+ // @param context
+ // @param uri
+ // @param fileName
+ //
+ private static String getPathFromInputStreamUri(Context context, Uri uri, String fileName) {
+ InputStream inputStream = null;
+ String filePath = null;
+
+ if (uri.getAuthority() != null) {
+ try {
+ inputStream = context.getContentResolver().openInputStream(uri);
+ File file = createTemporalFileFrom(context, inputStream, fileName);
+ filePath = file.getPath();
+
+ } catch (Exception e) {
+ } finally {
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ return filePath;
+ }
+
+ private static File createTemporalFileFrom(Context context, InputStream inputStream, String fileName)
+ throws IOException {
+ File targetFile = null;
+ if (inputStream != null) {
+ int read;
+ byte[] buffer = new byte[8 * 1024];
+ //自己定义拷贝文件路径
+ targetFile = new File(context.getExternalCacheDir(), fileName);
+ if (targetFile.exists()) {
+ targetFile.delete();
+ }
+ OutputStream outputStream = new FileOutputStream(targetFile);
+
+ while ((read = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, read);
+ }
+ outputStream.flush();
+
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return targetFile;
+ }
+}
diff --git a/libapputils/src/main/java/cc/winboll/studio/libapputils/views/SimpleWebView.java b/libapputils/src/main/java/cc/winboll/studio/libapputils/views/SimpleWebView.java
new file mode 100644
index 0000000..6765fa4
--- /dev/null
+++ b/libapputils/src/main/java/cc/winboll/studio/libapputils/views/SimpleWebView.java
@@ -0,0 +1,38 @@
+package cc.winboll.studio.libapputils.views;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/03 11:05:45
+ * @Describe 简单网页视图类
+ */
+import android.content.Context;
+import android.util.AttributeSet;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+
+public class SimpleWebView extends WebView {
+
+ public static final String TAG = "SimpleWebView";
+
+ public SimpleWebView(Context context) {
+ super(context);
+ initWebView();
+ }
+
+ public SimpleWebView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initWebView();
+ }
+
+ public SimpleWebView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initWebView();
+ }
+
+ private void initWebView() {
+ // 获取WebView的设置对象
+ WebSettings webSettings = getSettings();
+ // 启用JavaScript
+ webSettings.setJavaScriptEnabled(true);
+ }
+}
diff --git a/libapputils/src/main/java/cc/winboll/studio/libapputils/views/StringToQrCodeView.java b/libapputils/src/main/java/cc/winboll/studio/libapputils/views/StringToQrCodeView.java
new file mode 100644
index 0000000..40577eb
--- /dev/null
+++ b/libapputils/src/main/java/cc/winboll/studio/libapputils/views/StringToQrCodeView.java
@@ -0,0 +1,66 @@
+package cc.winboll.studio.libapputils.views;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/12/19 13:49:14
+ * @Describe 把字符串转化为二维码的视图
+ */
+import cc.winboll.studio.libapputils.R;
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import cc.winboll.studio.libapputils.utils.QRCodeGenerator;
+import com.journeyapps.barcodescanner.DecoratedBarcodeView;
+
+public class StringToQrCodeView extends LinearLayout {
+
+ static String TAG = "StringToQrCodeView";
+
+ Context mContext;
+ TextView mTextView;
+ ImageView mImageView;
+
+ private static final int REQUEST_CAMERA_PERMISSION = 1;
+ private DecoratedBarcodeView barcodeView;
+
+ public StringToQrCodeView(Context context) {
+ super(context);
+ initView(context);
+ }
+
+ public StringToQrCodeView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initView(context);
+ }
+
+ public StringToQrCodeView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initView(context);
+ }
+
+ public StringToQrCodeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ initView(context);
+ }
+
+ void initView(Context context) {
+ mContext = context;
+ View view = inflate(context, R.layout.view_string2qrcode, null);
+ mTextView = view.findViewById(R.id.viewstring2qrcodeTextView1);
+ mImageView = view.findViewById(R.id.viewstring2qrcodeImageView1);
+ addView(view);
+ stringToQrCode("Hello, World!");
+ }
+
+ public void stringToQrCode(String text) {
+ Drawable drawable = new BitmapDrawable(getResources(), QRCodeGenerator.generateQRCodeImage(text, 300, 300));
+ mTextView.setText(text);
+ mImageView.setBackground(drawable);
+ }
+
+}
diff --git a/libapputils/src/main/res/drawable/bg_shadow.xml b/libapputils/src/main/res/drawable/bg_shadow.xml
new file mode 100644
index 0000000..6d3d898
--- /dev/null
+++ b/libapputils/src/main/res/drawable/bg_shadow.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/ic_dev_connected.xml b/libapputils/src/main/res/drawable/ic_dev_connected.xml
new file mode 100644
index 0000000..1fb2f26
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_dev_connected.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/libapputils/src/main/res/drawable/ic_dev_disconnected.xml b/libapputils/src/main/res/drawable/ic_dev_disconnected.xml
new file mode 100644
index 0000000..4267975
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_dev_disconnected.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/libapputils/src/main/res/drawable/ic_email.xml b/libapputils/src/main/res/drawable/ic_email.xml
new file mode 100644
index 0000000..d526b26
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_email.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/ic_email_alert.xml b/libapputils/src/main/res/drawable/ic_email_alert.xml
new file mode 100644
index 0000000..f3ed613
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_email_alert.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/ic_launcher.xml b/libapputils/src/main/res/drawable/ic_launcher.xml
new file mode 100644
index 0000000..f269b7e
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_launcher.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
diff --git a/libapputils/src/main/res/drawable/ic_launcher_background.xml b/libapputils/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..9486190
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/ic_launcher_foreground.xml b/libapputils/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..872b04e
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/ic_winboll.xml b/libapputils/src/main/res/drawable/ic_winboll.xml
new file mode 100644
index 0000000..f269b7e
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_winboll.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
diff --git a/libapputils/src/main/res/drawable/ic_winbollbeta.xml b/libapputils/src/main/res/drawable/ic_winbollbeta.xml
new file mode 100644
index 0000000..f4876a0
--- /dev/null
+++ b/libapputils/src/main/res/drawable/ic_winbollbeta.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/shape_gradient.xml b/libapputils/src/main/res/drawable/shape_gradient.xml
new file mode 100644
index 0000000..c164fe9
--- /dev/null
+++ b/libapputils/src/main/res/drawable/shape_gradient.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/view_border.xml b/libapputils/src/main/res/drawable/view_border.xml
new file mode 100644
index 0000000..58b374a
--- /dev/null
+++ b/libapputils/src/main/res/drawable/view_border.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/winboll_help.xml b/libapputils/src/main/res/drawable/winboll_help.xml
new file mode 100644
index 0000000..564175f
--- /dev/null
+++ b/libapputils/src/main/res/drawable/winboll_help.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/winboll_logo.xml b/libapputils/src/main/res/drawable/winboll_logo.xml
new file mode 100644
index 0000000..ea28987
--- /dev/null
+++ b/libapputils/src/main/res/drawable/winboll_logo.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/drawable/winboll_point.xml b/libapputils/src/main/res/drawable/winboll_point.xml
new file mode 100644
index 0000000..48028cc
--- /dev/null
+++ b/libapputils/src/main/res/drawable/winboll_point.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/libapputils/src/main/res/layout/activity_library.xml b/libapputils/src/main/res/layout/activity_library.xml
new file mode 100644
index 0000000..b1d869f
--- /dev/null
+++ b/libapputils/src/main/res/layout/activity_library.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/layout/activity_log.xml b/libapputils/src/main/res/layout/activity_log.xml
new file mode 100644
index 0000000..80fe3fa
--- /dev/null
+++ b/libapputils/src/main/res/layout/activity_log.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/layout/activity_unittest.xml b/libapputils/src/main/res/layout/activity_unittest.xml
new file mode 100644
index 0000000..338b4b5
--- /dev/null
+++ b/libapputils/src/main/res/layout/activity_unittest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/layout/view_ads.xml b/libapputils/src/main/res/layout/view_ads.xml
new file mode 100644
index 0000000..d0cbbe4
--- /dev/null
+++ b/libapputils/src/main/res/layout/view_ads.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/layout/view_string2qrcode.xml b/libapputils/src/main/res/layout/view_string2qrcode.xml
new file mode 100644
index 0000000..420dcb5
--- /dev/null
+++ b/libapputils/src/main/res/layout/view_string2qrcode.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/menu/toolbar_studio_debug.xml b/libapputils/src/main/res/menu/toolbar_studio_debug.xml
new file mode 100644
index 0000000..15e95a2
--- /dev/null
+++ b/libapputils/src/main/res/menu/toolbar_studio_debug.xml
@@ -0,0 +1,35 @@
+
+
diff --git a/libapputils/src/main/res/menu/toolbar_winboll_shared_about.xml b/libapputils/src/main/res/menu/toolbar_winboll_shared_about.xml
new file mode 100644
index 0000000..b1e40c8
--- /dev/null
+++ b/libapputils/src/main/res/menu/toolbar_winboll_shared_about.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/libapputils/src/main/res/menu/toolbar_winboll_shared_main.xml b/libapputils/src/main/res/menu/toolbar_winboll_shared_main.xml
new file mode 100644
index 0000000..a6328f5
--- /dev/null
+++ b/libapputils/src/main/res/menu/toolbar_winboll_shared_main.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/libapputils/src/main/res/values-v21/styles.xml b/libapputils/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..a39bdd8
--- /dev/null
+++ b/libapputils/src/main/res/values-v21/styles.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/libapputils/src/main/res/values/array.xml b/libapputils/src/main/res/values/array.xml
new file mode 100644
index 0000000..fdb5cac
--- /dev/null
+++ b/libapputils/src/main/res/values/array.xml
@@ -0,0 +1,11 @@
+
+
+
+ - Off
+ - Error
+ - Warn
+ - Info
+ - Debug
+ - Verbose
+
+
diff --git a/libapputils/src/main/res/values/attrs.xml b/libapputils/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..6c985c2
--- /dev/null
+++ b/libapputils/src/main/res/values/attrs.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libapputils/src/main/res/values/colors.xml b/libapputils/src/main/res/values/colors.xml
new file mode 100644
index 0000000..d8b303c
--- /dev/null
+++ b/libapputils/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #FF196ABC
+ #FF002B57
+ #FF80BFFF
+
diff --git a/libapputils/src/main/res/values/strings.xml b/libapputils/src/main/res/values/strings.xml
new file mode 100644
index 0000000..932b20e
--- /dev/null
+++ b/libapputils/src/main/res/values/strings.xml
@@ -0,0 +1,11 @@
+
+
+
+ libapputils
+ Click here is switch to Normal APP
+ Click here is switch to APP DEBUG
+ GITEA HOME
+ APP UPDATE
+ Hello world!
+
+
diff --git a/libapputils/src/main/res/values/styles.xml b/libapputils/src/main/res/values/styles.xml
new file mode 100644
index 0000000..311bb71
--- /dev/null
+++ b/libapputils/src/main/res/values/styles.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/libapputils/src/main/res/xml/network_security_config.xml b/libapputils/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000..6879853
--- /dev/null
+++ b/libapputils/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,6 @@
+
+
+
+ 10.8.0.13
+
+
diff --git a/libjc/.classpath b/libjc/.classpath
new file mode 100644
index 0000000..f0eb145
--- /dev/null
+++ b/libjc/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/libjc/.gitignore b/libjc/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/libjc/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/libjc/.project b/libjc/.project
new file mode 100644
index 0000000..3019de5
--- /dev/null
+++ b/libjc/.project
@@ -0,0 +1,17 @@
+
+
+ $project_name$
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/libjc/README.md b/libjc/README.md
new file mode 100644
index 0000000..745acbb
--- /dev/null
+++ b/libjc/README.md
@@ -0,0 +1,4 @@
+## LIBJC
+### Java console Library
+### It design JC,JCNDK project.
+### And the Unit Test Console is jcc project which is place in libjc.
diff --git a/libjc/build.gradle b/libjc/build.gradle
new file mode 100644
index 0000000..01e5d44
--- /dev/null
+++ b/libjc/build.gradle
@@ -0,0 +1,33 @@
+apply plugin: 'com.android.library'
+
+android {
+ //compileSdkVersion 21
+ //buildToolsVersion "21.1.0"
+ compileSdkVersion 32
+ buildToolsVersion "33.0.3"
+
+ defaultConfig {
+ //applicationId "cc.winboll.studio.libjc"
+ //minSdkVersion 14
+ //targetSdkVersion 21
+ minSdkVersion 24
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
+ //implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
+ implementation 'org.bouncycastle:bcprov-jdk15to18:1.69'
+ implementation 'org.bouncycastle:bcpkix-jdk15to18:1.69'
+
+ api fileTree(dir: 'libs', include: ['*.jar'])
+}
diff --git a/libjc/build.properties b/libjc/build.properties
new file mode 100644
index 0000000..1be8de6
--- /dev/null
+++ b/libjc/build.properties
@@ -0,0 +1,8 @@
+#Created by .winboll/winboll_app_build.gradle
+#Fri Jan 10 22:03:57 GMT 2025
+stageCount=0
+libraryProject=libjc
+baseVersion=1.0
+publishVersion=1.0.0
+buildCount=133
+baseBetaVersion=1.0.1
diff --git a/libjc/jcc/.classpath b/libjc/jcc/.classpath
new file mode 100644
index 0000000..49328e7
--- /dev/null
+++ b/libjc/jcc/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/libjc/jcc/.gitignore b/libjc/jcc/.gitignore
new file mode 100644
index 0000000..191883d
--- /dev/null
+++ b/libjc/jcc/.gitignore
@@ -0,0 +1 @@
+/output_jars
diff --git a/libjc/jcc/.project b/libjc/jcc/.project
new file mode 100644
index 0000000..3019de5
--- /dev/null
+++ b/libjc/jcc/.project
@@ -0,0 +1,17 @@
+
+
+ $project_name$
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/libjc/jcc/MANIFEST.MF b/libjc/jcc/MANIFEST.MF
new file mode 100644
index 0000000..0ae48ae
--- /dev/null
+++ b/libjc/jcc/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: .
+Main-Class: cc.winboll.studio.libjc.Main
diff --git a/libjc/jcc/bash_build_jar.sh b/libjc/jcc/bash_build_jar.sh
new file mode 100644
index 0000000..487922a
--- /dev/null
+++ b/libjc/jcc/bash_build_jar.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/bash
+## 跳转到 libjc 项目目录查找源码文件夹 src 和编译环境目录 jcc 目录,如果两个目录其中一个不存在就退出
+cd ..
+
+## 记录当前工作目录
+workpath=$(pwd)
+
+## 检查源码目录与 jcc 工作目录
+srcdir="src"
+if [ -d "${srcdir}" ]; then
+ echo "Src dir ${srcdir} found."
+else
+ echo "Src dir ${srcdir} not exist."
+ exit 1
+fi
+jccdir="jcc"
+if [ -d "${jccdir}" ]; then
+ echo "Jcc dir ${jccdir} found."
+else
+ echo "Jcc dir ${jccdir} not exist."
+ exit 1
+fi
+
+jarversion="1.0.1"
+jarname="libjc-"${jarversion}".jar"
+classespath="${workpath}/${jccdir}/classes"
+jarspath="${workpath}/${jccdir}/output_jars"
+srcpath="${workpath}/${srcdir}/main/java"
+libspath="${workpath}/${jccdir}/libs"
+
+echo "Gen class to "${classespath}" :"
+cd ${srcpath}
+javac -cp ".:${libspath}/android-29.jar" -d ${classespath} $(find . -name "*.java")
+echo "Build "${jarname}" :"
+cd ${classespath};
+jar -cvfm ${jarspath}/${jarname} ${workpath}/${jccdir}/MANIFEST.MF cc
+echo "Jar Build OK."
+
+cd ..
+bash test_jar.sh ${jarversion}
diff --git a/libjc/jcc/src/Main.java b/libjc/jcc/src/Main.java
new file mode 100644
index 0000000..5f8cbf4
--- /dev/null
+++ b/libjc/jcc/src/Main.java
@@ -0,0 +1,10 @@
+//import java.util.*;
+//
+//public class Main {
+//
+// public static void main(String[] args) {
+// System.out.println("Hello World!");
+//
+// }
+//
+//}
diff --git a/libjc/jcc/test_jar.sh b/libjc/jcc/test_jar.sh
new file mode 100644
index 0000000..e5c96fe
--- /dev/null
+++ b/libjc/jcc/test_jar.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/bash
+jarversion=$1
+jarname="libjc-"${jarversion}".jar"
+
+cd output_jars
+
+echo -e "\nTest "${jarname}" Main :"
+java -jar ${jarname} "UnitTest"
+
+testclass="TestClassA"
+echo -e "\nTest "${jarname}" ${testclass} :"
+echo -e "Test 1 :"
+java -cp ${jarname} cc.winboll.studio.libjc.${testclass}
+echo -e "Test 2 :"
+java -cp ${jarname} cc.winboll.studio.libjc.${testclass} "Test"
+echo -e "Test 3 :"
+java -cp ${jarname} cc.winboll.studio.libjc.${testclass} "UnitTest"
+
+testclass="TestClassB"
+echo -e "\nTest "${jarname}" ${testclass} :"
+echo "Test 1 :"
+java -cp ${jarname} cc.winboll.studio.libjc.${testclass}
+echo -e "Test 2 :"
+java -cp ${jarname} cc.winboll.studio.libjc.${testclass} "Test"
+echo -e "Test 3 :"
+java -cp ${jarname} cc.winboll.studio.libjc.${testclass} "UnitTest"
diff --git a/libjc/proguard-rules.pro b/libjc/proguard-rules.pro
new file mode 100644
index 0000000..536058a
--- /dev/null
+++ b/libjc/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:/tools/adt-bundle-windows-x86_64-20131030/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/libjc/src/main/AndroidManifest.xml b/libjc/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b51a4cc
--- /dev/null
+++ b/libjc/src/main/AndroidManifest.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/JCCommandThread.java b/libjc/src/main/java/cc/winboll/studio/libjc/JCCommandThread.java
new file mode 100644
index 0000000..50a1e0d
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/JCCommandThread.java
@@ -0,0 +1,160 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/07 17:34:56
+ * @Describe JC命令行执行类
+ */
+import cc.winboll.studio.libjc.util.LogUtils;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+
+public class JCCommandThread extends Thread {
+ //static volatile JCCommandThread _JCCommandThread;
+ public JCCommandThread() {}
+// public static synchronized JCCommandThread getInstance() {
+// if(_JCCommandThread == null) {
+// _JCCommandThreadRunning = false;
+// _JCCommandThread = new JCCommandThread();
+// }
+// return _JCCommandThread;
+// }
+//
+ static volatile String _CMD;
+ static volatile boolean _Exit;
+ static volatile boolean _JCCommandThreadRunning;
+ static Process _Process;
+
+ public static final String TAG = "JCCommand";
+
+ public synchronized void exec(String cmd) {
+ if (cmd.equals("/bye")) {
+ _Exit = true;
+ return;
+ } else if (_CMD.equals("") && !cmd.equals("")) {
+ _CMD = cmd + "\n";
+ OutputStream outputStream = _Process.getOutputStream();
+ try {
+ System.out.println("$ " + _CMD);
+ //Log.d(TAG, "_CMD : " + _CMD);
+ outputStream.write(_CMD.getBytes());
+ outputStream.flush();
+ _CMD = "";
+ //Log.d(TAG, "OutputStream done.");
+ } catch (IOException e) {
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ if(!_JCCommandThreadRunning) {
+ _JCCommandThreadRunning = true;
+ init();
+ }
+ }
+
+ public void init() {
+ _Exit = false;
+ _CMD = "";
+ try {
+ LogUtils.d(TAG, "start()");
+ _Process = Runtime.getRuntime().exec("/system/xbin/busybox ash");
+
+ // 创建线程读取标准输出流
+ OutputThread outputThread = new OutputThread();
+ //outputThread.initProcess(_Process);
+
+ // 创建线程读取标准错误流(通常命令执行出错的信息会在这里输出)
+ ErrorThread errorThread = new ErrorThread();
+ //outputThread.initProcess(_Process);
+
+ LogUtils.d(TAG, "Process init ok.");
+ outputThread.start();
+ errorThread.start();
+ LogUtils.d(TAG, "Thread start.");
+
+// while (!_Exit) {
+// exec();
+// }
+
+ // 等待线程执行完毕
+// try {
+// outputThread.join();
+// errorThread.join();
+// Log.d(TAG, "Thread join.");
+// } catch (InterruptedException e) {
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+
+ // 等待命令执行结束并获取退出值
+ LogUtils.d(TAG, "_Process.waitFor()");
+ int exitValue = _Process.waitFor();
+ LogUtils.d(TAG, "Process exited with value: " + exitValue);
+
+ _Exit = true;
+
+ } catch (IOException | InterruptedException e) {
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+
+ public static class OutputThread extends Thread {
+// java.lang.Process mProcess;
+// public void initProcess(java.lang.Process process) {
+// mProcess = process;
+// }
+ @Override
+ public void run() {
+ super.run();
+ try {
+ InputStream inputStream = _Process.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ System.out.println(line);
+ //Log.d(TAG, line);
+ }
+ reader.close();
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+
+ }
+
+ public static class ErrorThread extends Thread {
+// java.lang.Process mProcess;
+// public void initProcess(java.lang.Process process) {
+// mProcess = process;
+// }
+
+ @Override
+ public void run() {
+ super.run();
+ try {
+ InputStream errorStream = _Process.getErrorStream();
+ BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream));
+ String line;
+ while ((line = errorReader.readLine()) != null) {
+ System.out.println("Error: " + line);
+ //Log.d(TAG, "Error: " + line);
+ }
+ errorReader.close();
+ errorStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+
+ }
+}
+
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/JCErrorStream.java b/libjc/src/main/java/cc/winboll/studio/libjc/JCErrorStream.java
new file mode 100644
index 0000000..33b9188
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/JCErrorStream.java
@@ -0,0 +1,84 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/07 13:46:40
+ * @Describe JC 错误输出流
+ */
+import cc.winboll.studio.libjc.util.LogUtils;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public class JCErrorStream extends OutputStream {
+
+ public static final String TAG = "JCErrorStream";
+ private StringBuilder buffer = new StringBuilder();
+
+ static volatile JCErrorStream _JCErrorStream;
+ static volatile boolean _IsInitOK;
+ JCMainThread.OnMessageListener mOnMessageListener;
+
+ @Override
+ public void write(int b) {
+ buffer.append((char) b);
+ err(String.format("%i", b));
+ }
+
+ void err(String message) {
+ mOnMessageListener.errPrint(message);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) {
+ buffer.append(new String(b, off, len));
+ err(new String(b, off, len));
+ }
+
+ public String getOutput() {
+ return buffer.toString();
+ }
+ JCErrorStream(JCMainThread.OnMessageListener listener) {
+ mOnMessageListener = listener;
+ }
+
+ public static void start(JCMainThread.OnMessageListener listener) {
+ LogUtils.d(TAG, String.format("%s init()\n", TAG));
+
+ if (_JCErrorStream == null) {
+ _JCErrorStream = new JCErrorStream(listener);
+ _IsInitOK = false;
+
+ // 保存原始的System.out
+ PrintStream originalOut = System.err;
+ try {
+ // 创建自定义输出流实例并将System.out重定向到它
+ //JCOutputStream jcOutputStream = new JCOutputStream();
+ System.setErr(new PrintStream(_JCErrorStream));
+ System.err.println("Test err stream.\n");
+ while (!JCMainThread._Exit) {
+
+ }
+ // 这里原本输出到控制台的内容会被重定向到自定义输出流
+ System.out.println("这是被接管后输出的内容");
+ System.out.println("另一行内容");
+
+ // 获取自定义输出流收集到的内容
+ String output = _JCErrorStream.getOutput();
+ System.out.println("收集到的内容: " + output);
+
+ // 恢复System.out为原始的输出流
+ System.setOut(originalOut);
+
+
+ } finally {
+ try {
+ _JCErrorStream.close();
+ } catch (IOException e) {
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+ }
+}
+
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/JCErrorThread.java b/libjc/src/main/java/cc/winboll/studio/libjc/JCErrorThread.java
new file mode 100644
index 0000000..d00102a
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/JCErrorThread.java
@@ -0,0 +1,22 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/07 13:51:14
+ * @Describe 错误输出流进程
+ */
+public class JCErrorThread extends Thread {
+
+ public static final String TAG = "JCErrorThread";
+
+ JCMainThread.OnMessageListener mOnMessageListener;
+
+ public JCErrorThread(JCMainThread.OnMessageListener listener) {
+ mOnMessageListener = listener;
+ }
+ @Override
+ public void run() {
+ super.run();
+ JCErrorStream.start(mOnMessageListener);
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/JCMainThread.java b/libjc/src/main/java/cc/winboll/studio/libjc/JCMainThread.java
new file mode 100644
index 0000000..9570427
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/JCMainThread.java
@@ -0,0 +1,101 @@
+package cc.winboll.studio.libjc;
+
+import cc.winboll.studio.libjc.JCMainThread;
+import cc.winboll.studio.libjc.util.ConsoleUtils;
+import cc.winboll.studio.libjc.util.LogUtils;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class JCMainThread extends Thread {
+
+ public static String TAG = "JCMainThread";
+
+ static volatile JCMainThread _JCMainThread;
+ static volatile boolean _Exit;
+ static OnMessageListener _OnLogListener;
+ JCCommandThread mJCCommand;
+
+ JCMainThread(String logName) {
+ ConsoleUtils.Debug.printFuncInfo(TAG);
+
+ _Exit = false;
+ _OnLogListener = null;
+
+ LogUtils.init((logName == null || logName.equals("")) ?JCMainThread.class.getName(): logName);
+ System.out.println("JCMainThread()");
+ LogUtils.d(TAG, "JCMainThread()");
+
+ Main.setRunningMode(Main.JAR_RUNNING_MODE.CONSOLE);
+ }
+
+ public static synchronized JCMainThread getInstance(String logName) {
+ if (_JCMainThread == null) {
+ _JCMainThread = new JCMainThread(logName);
+ }
+ return _JCMainThread;
+ }
+
+
+
+ public void exeInit(String cmd) {
+ //System.out.println("cmd " + cmd);
+ mJCCommand.exec(cmd);
+ }
+
+ public void exeBashCommand(String cmd) {
+ //System.out.println("cmd " + cmd);
+ mJCCommand.exec(cmd);
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ System.out.println("JCMainThread run()");
+ LogUtils.d(TAG, "run()");
+ if (_OnLogListener != null) {
+ (new JCErrorThread(_OnLogListener)).start();
+ (new JCOutputThread(_OnLogListener)).start();
+ }
+ mJCCommand = new JCCommandThread();
+ mJCCommand.start();
+
+ while (!_Exit) {
+
+ //Log.d(TAG, "!_Exit");
+ Date date = new Date();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ String formattedDate = sdf.format(date);
+ String msg = String.format("run() %s", formattedDate);
+ //System.out.println(msg);
+ //System.err.println("err : " + msg);
+ try {
+ Thread.sleep(5 * 1000);
+
+ // 这里模拟一下运行出错
+// String[] as = new String[2];
+// String b = as[3];
+// System.out.println(b);
+//
+ } catch (Exception e) {
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ System.out.println("JCMainThread run()");
+ // 内存清理
+ _OnLogListener = null;
+ }
+
+ public static OnMessageListener getOnLogListener() {
+ return _OnLogListener;
+ }
+
+ public static void setOnLogListener(OnMessageListener listener) {
+ _OnLogListener = listener;
+ }
+
+ public interface OnMessageListener {
+ //void log(String message);
+ void outPrint(String message);
+ void errPrint(String message);
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/JCOutputStream.java b/libjc/src/main/java/cc/winboll/studio/libjc/JCOutputStream.java
new file mode 100644
index 0000000..b55d263
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/JCOutputStream.java
@@ -0,0 +1,84 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/07 12:32:19
+ * @Describe 控制台输出流接口类
+ */
+import cc.winboll.studio.libjc.util.LogUtils;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public class JCOutputStream extends OutputStream {
+
+ public static final String TAG = "JCOutputStream";
+ private StringBuilder buffer = new StringBuilder();
+
+ static volatile JCOutputStream _JCOutputStream;
+ static volatile boolean _IsInitOK;
+ JCMainThread.OnMessageListener mOnMessageListener;
+
+ @Override
+ public void write(int b) {
+ buffer.append((char) b);
+ print(String.format("%i", b));
+ }
+
+ void print(String message) {
+ mOnMessageListener.outPrint(message);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) {
+ buffer.append(new String(b, off, len));
+ print(new String(b, off, len));
+ }
+
+ public String getOutput() {
+ return buffer.toString();
+ }
+ JCOutputStream(JCMainThread.OnMessageListener listener) {
+ mOnMessageListener = listener;
+ }
+
+ public static void start(JCMainThread.OnMessageListener listener) {
+ LogUtils.d(TAG, String.format("%s init()\n", TAG));
+
+ if (_JCOutputStream == null) {
+ _JCOutputStream = new JCOutputStream(listener);
+ _IsInitOK = false;
+
+ // 保存原始的System.out
+ PrintStream originalOut = System.out;
+ try {
+ // 创建自定义输出流实例并将System.out重定向到它
+ //JCOutputStream jcOutputStream = new JCOutputStream();
+ System.setOut(new PrintStream(_JCOutputStream));
+ System.out.println("Test out stream.\n");
+ while (!JCMainThread._Exit) {
+
+ }
+ // 这里原本输出到控制台的内容会被重定向到自定义输出流
+ System.out.println("这是被接管后输出的内容");
+ System.out.println("另一行内容");
+
+ // 获取自定义输出流收集到的内容
+ String output = _JCOutputStream.getOutput();
+ System.out.println("收集到的内容: " + output);
+
+ // 恢复System.out为原始的输出流
+ System.setOut(originalOut);
+
+
+ } finally {
+ try {
+ _JCOutputStream.close();
+ } catch (IOException e) {
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+ }
+}
+
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/JCOutputThread.java b/libjc/src/main/java/cc/winboll/studio/libjc/JCOutputThread.java
new file mode 100644
index 0000000..5579b59
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/JCOutputThread.java
@@ -0,0 +1,22 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/07 13:27:26
+ * @Describe JC输出流进程
+ */
+public class JCOutputThread extends Thread {
+
+ public static final String TAG = "JCOutputThread";
+
+ JCMainThread.OnMessageListener mOnMessageListener;
+
+ public JCOutputThread(JCMainThread.OnMessageListener listener) {
+ mOnMessageListener = listener;
+ }
+ @Override
+ public void run() {
+ super.run();
+ JCOutputStream.start(mOnMessageListener);
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/Main.java b/libjc/src/main/java/cc/winboll/studio/libjc/Main.java
new file mode 100644
index 0000000..22dd372
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/Main.java
@@ -0,0 +1,136 @@
+package cc.winboll.studio.libjc;
+
+import cc.winboll.studio.libjc.Main;
+import cc.winboll.studio.libjc.cmd.ListJarClassHasMain;
+import cc.winboll.studio.libjc.net.JCSocketServer;
+import java.util.Scanner;
+
+public class Main {
+
+ public final static String TAG = "Main";
+
+ /**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/09 17:03:50
+ * @Describe 当前源码实例的运行模式。
+ */
+ public final static int JAR_RUNNING_MODE_UNKNOWN = 0;
+ public final static int JAR_RUNNING_MODE_CONSOLE = 1;
+ public final static int JAR_RUNNING_MODE_CONSOLE_DEBUG = 2;
+ public final static int JAR_RUNNING_MODE_JCNDK = 3;
+ public final static int JAR_RUNNING_MODE_JCNDK_DEBUG = 4;
+ public final static int JAR_RUNNING_MODE_JC = 5;
+ public final static int JAR_RUNNING_MODE_JC_DEBUG = 6;
+ public enum JAR_RUNNING_MODE {
+ UNKNOWN(JAR_RUNNING_MODE_UNKNOWN),
+ CONSOLE(JAR_RUNNING_MODE_CONSOLE),
+ CONSOLE_DEBUG(JAR_RUNNING_MODE_CONSOLE_DEBUG),
+ JCNDK(JAR_RUNNING_MODE_JCNDK),
+ JCNDK_DEBUG(JAR_RUNNING_MODE_JCNDK_DEBUG),
+ JC(JAR_RUNNING_MODE_JC),
+ JC_DEBUG(JAR_RUNNING_MODE_JC_DEBUG);
+ static String[] _mlistName = {
+ "未知模式",
+ "控制台",
+ "控制台调试",
+ "JCNDK",
+ "JCNDK_DEBUG",
+ "JC",
+ "JC_DEBUG"};
+ private int value = 0;
+ private JAR_RUNNING_MODE(int value) { //必须是private的,否则编译错误
+ this.value = value;
+ }
+ }
+
+ public static volatile boolean _DEBUG = true; //调试标志
+ static volatile JAR_RUNNING_MODE _JAR_RUNNING_MODE = JAR_RUNNING_MODE.UNKNOWN;
+
+ static UserInputThread _UserInputThread;
+ static JCMainThread _JCMainThread;
+
+ static JCSocketServer _SocketServer;
+
+ public static void setDebug(boolean isDebug) {
+ _DEBUG = isDebug;
+ }
+
+ public static boolean isDebug() {
+ return _DEBUG;
+ }
+
+ public static void setRunningMode(JAR_RUNNING_MODE mode) {
+ _JAR_RUNNING_MODE = mode;
+ switch (_JAR_RUNNING_MODE.ordinal()) {
+ case JAR_RUNNING_MODE_CONSOLE_DEBUG:
+ case JAR_RUNNING_MODE_JCNDK_DEBUG:
+ case JAR_RUNNING_MODE_JC_DEBUG: {
+ setDebug(true);
+ break;
+ }
+ default : {
+ setDebug(false);
+ break;
+ }
+ }
+ }
+
+ public static JAR_RUNNING_MODE getRunningMode() {
+ return _JAR_RUNNING_MODE;
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ System.out.println(String.format("%s Start", TAG));
+
+ Scanner scanner = new Scanner(System.in);
+ System.out.println("是否进入调试状态?(请输入yes或其他内容)");
+ String input = scanner.nextLine();
+ if ("yes".equalsIgnoreCase(input)) {
+ //System.out.println("OK");
+ Main.setRunningMode(Main.JAR_RUNNING_MODE.CONSOLE_DEBUG);
+ } else {
+ Main.setRunningMode(Main.JAR_RUNNING_MODE.CONSOLE);
+ }
+ scanner.close();
+
+ //Main.setRunningMode(Main.JAR_RUNNING_MODE.CONSOLE);
+ //Main.setRunningMode(Main.JAR_RUNNING_MODE.CONSOLE_DEBUG);
+
+ try {
+ if (args.length > 0 && args[0].equals("UnitTest")) {
+ System.out.println(TestClassA.hello());
+ System.out.println(TestClassB.hello());
+ } else {
+ _JCMainThread = JCMainThread.getInstance(Main.class.getName());
+ _JCMainThread.start();
+
+ _SocketServer = JCSocketServer.getInstance();
+ _SocketServer.main(null);
+
+ _UserInputThread = new UserInputThread();
+ _UserInputThread.start();
+
+ ListJarClassHasMain.main(null);
+ }
+ } catch (Exception e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ }
+ }
+
+ static class UserInputThread extends Thread {
+
+ @Override
+ public void run() {
+ super.run();
+ Scanner scanner;
+ scanner = new Scanner(System.in);
+ while (scanner.hasNextLine()) {
+ String input = scanner.nextLine();
+ //System.out.println(String.format("User Input : %s", input));
+
+ _SocketServer.sendMessage(input);
+ }
+ }
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/TestClassA.java b/libjc/src/main/java/cc/winboll/studio/libjc/TestClassA.java
new file mode 100644
index 0000000..84670e0
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/TestClassA.java
@@ -0,0 +1,35 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/06 11:14:19
+ * @Describe 测试类A
+ */
+public class TestClassA {
+
+ public static final String TAG = "TestClassA";
+
+ //
+ // 当前类入口
+ //
+ // @args[0] 为 "UnitTest" 时就进行单元测试输出
+ //
+ public static void main(String[] args) {
+ if (args.length == 1 && args[0].equals("UnitTest")) {
+ //System.out.println("main : ");
+ System.out.println("args[0] " + args[0]);
+ //System.out.println("args[1]" + args[1]);
+ System.out.println(hello(args[0]));
+ } else {
+ System.out.println(hello());
+ }
+ }
+
+ public static String hello() {
+ return String.format("Hello, World! %s works well.", TAG);
+ }
+
+ public static String hello(String name) {
+ return String.format("Hello, %s! %s works well.", name, TAG);
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/TestClassB.java b/libjc/src/main/java/cc/winboll/studio/libjc/TestClassB.java
new file mode 100644
index 0000000..22c25ee
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/TestClassB.java
@@ -0,0 +1,37 @@
+package cc.winboll.studio.libjc;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/09 08:49:08
+ * @Describe 测试类B
+ */
+public class TestClassB {
+
+ public static final String TAG = "TestClassB";
+
+
+ //
+ // 当前类入口
+ //
+ // @args[0] 为 "UnitTest" 时就进行单元测试输出
+ //
+ public static void main(String[] args) {
+ if (args.length == 1 && args[0].equals("UnitTest")) {
+ //System.out.println("main : ");
+ System.out.println("args[0] " + args[0]);
+ //System.out.println("args[1]" + args[1]);
+ System.out.println(hello(args[0]));
+ } else {
+ System.out.println(hello());
+ }
+ }
+
+ public static String hello() {
+ return String.format("Hello, World! %s works well.", TAG);
+ }
+
+ public static String hello(String name) {
+ return String.format("Hello, %s! %s works well.", name, TAG);
+ }
+
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/bean/BaseBean.java b/libjc/src/main/java/cc/winboll/studio/libjc/bean/BaseBean.java
new file mode 100644
index 0000000..73146dd
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/bean/BaseBean.java
@@ -0,0 +1,278 @@
+package main.java.cc.winboll.studio.libjc.bean;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/23 15:40:30
+ * @Describe Json Bean 基础类。
+ */
+import android.content.Context;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import cc.winboll.studio.libjc.util.FileUtils;
+import cc.winboll.studio.libjc.util.LogUtils;
+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 | IllegalAccessException | IOException e) {
+ sbResult.append(szErrorInfo);
+ sbResult.append(e);
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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 | IllegalAccessException | IOException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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);
+ //Log.d(TAG, "beanList.add(bean)");
+ }
+ }
+ jsonReader.endArray();
+ return true;
+ //Log.d(TAG, "beanList.size() is " + Integer.toString(beanList.size()));
+ } catch (InstantiationException | IllegalAccessException | IOException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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 | IllegalAccessException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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 | IllegalAccessException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+
+ } catch (IOException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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 | IllegalAccessException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, 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 | IllegalAccessException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+
+ public static boolean saveBeanListToFile(String szFilePath, ArrayList beanList) {
+ try {
+ String szJson = toStringByBeanList(beanList);
+ FileUtils.writeStringToFile(szFilePath, szJson);
+ //Log.d(TAG, "FileUtil.writeFile beanList.size() is " + Integer.toString(beanList.size()));
+ return true;
+ } catch (IOException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ return false;
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/cmd/ListJarClassHasMain.java b/libjc/src/main/java/cc/winboll/studio/libjc/cmd/ListJarClassHasMain.java
new file mode 100644
index 0000000..5be74e2
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/cmd/ListJarClassHasMain.java
@@ -0,0 +1,75 @@
+package cc.winboll.studio.libjc.cmd;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/11 12:43:29
+ * @Describe 列举定义了main函数的所有类。
+ */
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+public class ListJarClassHasMain {
+
+ public static final String TAG = "ListJarClassHasMain";
+
+ public static void main(String[] args) {
+ System.out.println("ListJarClassHasMain main");
+ try {
+ String jarFileName = getCurrentClassJarFileName();
+ System.out.println(String.format("\nCurrent Class Jar File Name : %s", jarFileName));
+
+ File fJarFolder = new File("/sdcard/WinBollStudio/DEV/jars/");
+ System.out.println(String.format("\nJars Folder : %s", fJarFolder.getPath()));
+ for (File fJarFile : fJarFolder.listFiles()) {
+ if (fJarFile.getName().endsWith(".jar")) {
+ System.out.println(String.format("\nJar File Name : %s", fJarFile.getName()));
+ listJarFileMainClass(new JarFile(fJarFile.getPath()));
+ }
+ }
+
+ } catch (Exception e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ }
+ }
+
+ static void listJarFileMainClass(JarFile jarFile) {
+ System.out.println("\nMain Functions Class : ");
+ //JarFile jarFile = new JarFile("yourJarFile.jar");
+ java.util.Enumeration entries = jarFile.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = entries.nextElement();
+ if (entry.getName().endsWith(".class")) {
+ String className = entry.getName().replace('/', '.').substring(0, entry.getName().length() - 6);
+ try {
+ Class> clazz = Class.forName(className);
+ Method method = clazz.getMethod("main", String[].class);
+ if (method != null) {
+ System.out.println(className);
+ }
+ } catch (Exception e) {
+ // 没有main方法或者加载类出错,忽略
+ }
+ }
+ }
+ }
+
+
+
+
+ public static String getCurrentClassJarFileName() {
+ String jarFileName = "";
+ try {
+ String classPath = ListJarClassHasMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
+ jarFileName = new java.io.File(classPath).getName();
+ } catch (NullPointerException e) {
+ // 忽略读取Jar文件失败问题,返回空数据
+ return "";
+ } catch (Exception e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ }
+ return jarFileName;
+ }
+}
+
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/net/JCSocketClient.java b/libjc/src/main/java/cc/winboll/studio/libjc/net/JCSocketClient.java
new file mode 100644
index 0000000..db0fa41
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/net/JCSocketClient.java
@@ -0,0 +1,196 @@
+package cc.winboll.studio.libjc.net;
+
+import cc.winboll.studio.libjc.JCMainThread;
+import cc.winboll.studio.libjc.util.LogUtils;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.util.Scanner;
+import cc.winboll.studio.libjc.Main;
+
+public class JCSocketClient {
+
+ public final static String TAG = "JCSocketClient";
+
+ public final static String DEFAULT_SERVER = "127.0.0.1";
+
+ volatile static JCSocketClient _JCSocketClient;
+ String mszServer = "";
+ Socket socket;
+ Scanner in_socket;
+ PrintWriter out_socket;
+ Scanner userInput;
+ public volatile boolean isMessage2Server;
+ public volatile String szMessage2Server;
+ ClientMessageSendThread mClientMessageSendThread;
+ //SyncMesaageThread mSyncMesaageThread;
+ ConsoleMessageSendThread mConsoleMessageSendThread;
+
+ JCSocketClient() {
+ LogUtils.d(TAG, "JCSocketClient()");
+ isMessage2Server = false;
+ szMessage2Server = "";
+ }
+
+ public static JCSocketClient getInstance() {
+ if (_JCSocketClient == null) {
+ _JCSocketClient = new JCSocketClient();
+ }
+ return _JCSocketClient;
+ }
+
+ public static void main(String[] args) {
+ System.out.println("JCSocketClient main :");
+
+ JCSocketClient jcSocketClient = JCSocketClient.getInstance();
+ if (args != null && args.length == 1 && !args.equals("")) {
+ jcSocketClient.mszServer = args[0];
+ } else {
+ jcSocketClient.mszServer = DEFAULT_SERVER;
+ }
+ jcSocketClient.start();
+ }
+
+ public void start(String server) {
+ mszServer = server;
+ start();
+ }
+
+ void start() {
+ System.out.println("JCSocketClient start()");
+ // 连接服务器
+ try {
+ System.out.println(String.format("Connect to %s", mszServer));
+ socket = new Socket(mszServer, 8888);
+ System.out.println("已连接到服务器");
+ // 获取输出流
+ out_socket = new PrintWriter(socket.getOutputStream(), true);
+ // 获取输入流
+ in_socket = new Scanner(socket.getInputStream());
+ //userInput = new Scanner(System.in);
+
+ mClientMessageSendThread = new ClientMessageSendThread();
+ mClientMessageSendThread.start();
+// mSyncMesaageThread = new SyncMesaageThread();
+// mSyncMesaageThread.start();
+ if (Main.getRunningMode() == Main.JAR_RUNNING_MODE.CONSOLE
+ || Main.getRunningMode() == Main.JAR_RUNNING_MODE.JC) {
+ mConsoleMessageSendThread = new ConsoleMessageSendThread();
+ mConsoleMessageSendThread.start();
+ }
+ // 开始发送消息
+ //sendMessage(String.format("%s OK", TAG));
+
+ } catch (IOException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+
+ }
+
+ public void sendMessage(String message) {
+ //Log.d(TAG, String.format("sendMessage : %s", message));
+ szMessage2Server = message;
+ isMessage2Server = true;
+ }
+
+// public synchronized void syncClientMessage() {
+// //Log.d(TAG, "syncClientMessage()");
+// //System.out.println("syncClientMessage()");
+// if (isClientMessageReady) {
+// isClientMessageReady = false;
+// //System.out.println(String.format("Client : %s", szClientMessage));
+// //Log.d(TAG, String.format("Send %s", szClientMessage));
+// //out_socket.println(szClientMessage);
+// out_socket.println(szClientMessage);
+// System.out.println(String.format("out_socket->%s", szClientMessage));
+// szClientMessage = "";
+// }
+// }
+
+ public synchronized void scan_in_socket() {
+ //Log.d(TAG, "scan_in_socket()");
+ //System.out.println("scan_in_socket");
+
+ if (in_socket.hasNextLine()) {
+ //Log.d(TAG, "Reciving System Input Message...");
+ String response = in_socket.nextLine();
+ System.out.println(String.format("%s :%s", JCSocketServer.TAG, response));
+ }
+ }
+
+ class ClientMessageSendThread extends Thread {
+
+ @Override
+ public void run() {
+ super.run();
+ try {
+ // 向服务器发送消息
+ while (true) {
+ if (isMessage2Server) {
+ isMessage2Server = false;
+ //System.out.println(String.format("Client : %s", szClientMessage));
+ //Log.d(TAG, String.format("Send %s", szClientMessage));
+ //out_socket.println(szClientMessage);
+ out_socket.println(szMessage2Server);
+ System.out.println(String.format("%s : %s", TAG, szMessage2Server));
+ szMessage2Server = "";
+ }
+// syncClientMessage();
+// try {
+// //syncClientMessage();
+// Thread.sleep(1000);
+// } catch (InterruptedException e) {
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+ }
+ } catch (Exception e) {
+ System.err.println(String.format("%s ClientMessageSendThread : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+
+ }
+
+// class SyncMesaageThread extends Thread {
+//
+// @Override
+// public void run() {
+// super.run();
+// while (true) {
+// sendMessage(String.format("%s OK", TAG));
+// try {
+// Thread.sleep(5000);
+// } catch (InterruptedException e) {
+// System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+// }
+// }
+// }
+
+ class ConsoleMessageSendThread extends Thread {
+
+ @Override
+ public void run() {
+ super.run();
+ try {
+ System.out.println("ConsoleMessageSendThread run()");
+
+ // 读取服务器响应
+ while (true) {
+ scan_in_socket();
+// try {
+// syncSystemInMessage();
+// Thread.sleep(3000);
+// } catch (InterruptedException e) {
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+ }
+ } catch (Exception e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/net/JCSocketServer.java b/libjc/src/main/java/cc/winboll/studio/libjc/net/JCSocketServer.java
new file mode 100644
index 0000000..cb98c05
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/net/JCSocketServer.java
@@ -0,0 +1,204 @@
+package cc.winboll.studio.libjc.net;
+
+import cc.winboll.studio.libjc.JCMainThread;
+import cc.winboll.studio.libjc.Main;
+import cc.winboll.studio.libjc.util.ConsoleUtils;
+import cc.winboll.studio.libjc.util.LogUtils;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Scanner;
+
+public class JCSocketServer {
+
+ public final static String TAG = "JCSocketServer";
+
+ volatile static JCSocketServer _JCSocketServer;
+ ServerSocket serverSocket;
+ Socket clientSocket;
+ Scanner in_socket;
+ PrintWriter out_socket;
+ public volatile boolean isServerMessageReady;
+ public volatile String szServerMessage;
+ ServerMessageSendThread mServerMessageSendThread;
+ //SyncMesaageThread mSyncMesaageThread;
+ ConsoleMessageSendThread mConsoleMessageSendThread;
+
+
+ JCSocketServer() {
+ ConsoleUtils.Debug.printFuncInfo(TAG);
+ //Log.d(TAG, "JCSocketClient()");
+ isServerMessageReady = false;
+ szServerMessage = "";
+ }
+
+ public static JCSocketServer getInstance() {
+ if (_JCSocketServer == null) {
+ _JCSocketServer = new JCSocketServer();
+ }
+ return _JCSocketServer;
+ }
+
+ public static void main(String[] args) {
+ System.out.println("JCSocketServer main :");
+ JCSocketServer.getInstance().start();
+ }
+
+
+
+ void start() {
+ System.out.println("JCSocketServer start :");
+ // 连接服务器
+ try {
+ // 创建一个ServerSocket,监听端口8888
+ serverSocket = new ServerSocket(8888);
+ System.out.println("服务器已启动,等待客户端连接...");
+ // 等待客户端连接
+ clientSocket = serverSocket.accept();
+ LogUtils.d(TAG, "客户端已连接");
+ System.out.println("客户端已连接");
+ out_socket = new PrintWriter(clientSocket.getOutputStream(), true);
+ in_socket = new Scanner(clientSocket.getInputStream());
+
+
+ mServerMessageSendThread = new ServerMessageSendThread();
+ mServerMessageSendThread.start();
+// mSyncMesaageThread = new SyncMesaageThread();
+// mSyncMesaageThread.start();
+ if (Main.getRunningMode() == Main.JAR_RUNNING_MODE.CONSOLE
+ || Main.getRunningMode() == Main.JAR_RUNNING_MODE.JCNDK) {
+ mConsoleMessageSendThread = new ConsoleMessageSendThread();
+ mConsoleMessageSendThread.start();
+ }
+ System.out.println("JCSocketServer start() end.");
+
+ } catch (IOException e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+
+ }
+
+ public void sendMessage(String message) {
+ //Log.d(TAG, String.format("sendMessage : %s", message));
+ szServerMessage = message;
+ isServerMessageReady = true;
+ }
+
+// public synchronized void syncServerMessage() {
+// //Log.d(TAG, "syncServerMessage()");
+// //System.out.println("syncServerMessage()");
+//// if (isServerMessageReady) {
+//// isServerMessageReady = false;
+//// //System.out.println(String.format("JCSocketServer : %s", szServerMessage));
+//// //Log.d(TAG, String.format("Send %s", szClientMessage));
+//// out.println(szServerMessage);
+//// szServerMessage = "";
+//// }
+// }
+
+// public synchronized void syncSystemInMessage() {
+// //Log.d(TAG, "syncSystemInMessage()");
+// //System.out.println("syncSystemInMessage");
+//
+// if (in_socket.hasNextLine()) {
+// //Log.d(TAG, "Reciving System Input Message...");
+// String response = in_socket.nextLine();
+// System.out.println("Recived :" + response);
+//
+// // 发送一个消息回去给客户端
+// out_socket.println(String.format("%s : Recived [%s]", TAG, response));
+// }
+// }
+
+ class ServerMessageSendThread extends Thread {
+
+ @Override
+ public void run() {
+ super.run();// 获取输入输出流
+ try {
+ // 向客户端发送消息
+ while (true) {
+
+// if(userInput.hasNextLine()) {
+// String szServerMessage = userInput.nextLine();
+// System.out.println(String.format("Send [%s] to client.", szServerMessage));
+// out_socket.println(szServerMessage);
+// }
+ if (isServerMessageReady) {
+ isServerMessageReady = false;
+ //System.out.println(String.format("JCSocketServer : %s", szServerMessage));
+ //Log.d(TAG, String.format("Send %s", szClientMessage));
+ System.out.println(String.format("%s : %s", TAG, szServerMessage));
+ out_socket.println(szServerMessage);
+ szServerMessage = "";
+ }
+ //syncServerMessage();
+// try {
+// syncServerMessage();
+// Thread.sleep(500);
+// } catch (Exception e) {
+// System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+ }
+ } catch (Exception e) {
+ System.err.println(String.format("%s ServerMessageSendThread : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+
+ }
+
+// class SyncMesaageThread extends Thread {
+//
+// @Override
+// public void run() {
+// super.run();
+// while (true) {
+// sendMessage(String.format("%s OK", TAG));
+// try {
+// Thread.sleep(5000);
+// } catch (InterruptedException e) {
+// System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+// }
+// }
+// }
+
+ class ConsoleMessageSendThread extends Thread {
+
+ @Override
+ public void run() {
+ super.run();
+ // 获取输入输出流
+ try {
+ System.out.println("ConsoleMessageSendThread run()");
+
+ // 读取服务器响应
+ while (true) {
+ if (in_socket.hasNextLine()) {
+ //Log.d(TAG, "Reciving System Input Message...");
+ String response = in_socket.nextLine();
+ System.out.println(String.format("%s :%s", JCSocketClient.TAG, response));
+
+ // 发送一个消息回去给客户端
+ //out_socket.println(String.format("%s : Recived [%s]", TAG, response));
+ }
+ //syncSystemInMessage();
+// try {
+// //syncSystemInMessage();
+// Thread.sleep(1000);
+// } catch (InterruptedException e) {
+// Log.e(TAG, e, Thread.currentThread().getStackTrace());
+// }
+ }
+ } catch (Exception e) {
+ System.err.println(String.format("%s ConsoleMessageSendThread : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/net/MesaageBean.java b/libjc/src/main/java/cc/winboll/studio/libjc/net/MesaageBean.java
new file mode 100644
index 0000000..4e860e6
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/net/MesaageBean.java
@@ -0,0 +1,88 @@
+package cc.winboll.studio.libjc.net;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import java.io.IOException;
+import main.java.cc.winboll.studio.libjc.bean.BaseBean;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/09 20:07:06
+ * @Describe 消息类
+ */
+public class MesaageBean extends BaseBean {
+
+ public static final String TAG = "MesaageBean";
+
+ public static enum MESAAGE_TYPE {
+ UNKNOWN,
+ CONNECTION_STATUS,
+ MESSAGE
+ ;
+ }
+
+ MESAAGE_TYPE mMESAAGE_TYPE = MESAAGE_TYPE.UNKNOWN;
+ String messageContents;
+
+
+ public void setMESAAGE_TYPE(MESAAGE_TYPE type) {
+ this.mMESAAGE_TYPE = type;
+ }
+
+ public MESAAGE_TYPE getMESAAGE_TYPE() {
+ return mMESAAGE_TYPE;
+ }
+
+ public void setMessageContents(String messageContents) {
+ this.messageContents = messageContents;
+ }
+
+ public String getMessageContents() {
+ return messageContents;
+ }
+
+ @Override
+ public String getName() {
+ return MesaageBean.class.getName();
+ }
+
+ @Override
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ super.writeThisToJsonWriter(jsonWriter);
+ MesaageBean bean = this;
+ jsonWriter.name("MESAAGE_TYPE").value(bean.mMESAAGE_TYPE.ordinal());
+ jsonWriter.name("messageContents").value(bean.getMessageContents());
+
+ }
+
+ @Override
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
+ if (name.equals("MESAAGE_TYPE")) {
+ setMESAAGE_TYPE(MESAAGE_TYPE.values()[jsonReader.nextInt()]);
+ } else if (name.equals("messageContents")) {
+ setMessageContents(jsonReader.nextString());
+ } 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;
+ }
+
+ public MesaageBean parseString() {
+ return null;
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/task/TermuxUniteTask.java b/libjc/src/main/java/cc/winboll/studio/libjc/task/TermuxUniteTask.java
new file mode 100644
index 0000000..0f82da4
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/task/TermuxUniteTask.java
@@ -0,0 +1,5 @@
+package main.java.cc.winboll.studio.libjc.task;
+
+public class TermuxUniteTask
+{
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/util/ConsoleUtils.java b/libjc/src/main/java/cc/winboll/studio/libjc/util/ConsoleUtils.java
new file mode 100644
index 0000000..66a1b9d
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/util/ConsoleUtils.java
@@ -0,0 +1,36 @@
+package cc.winboll.studio.libjc.util;
+
+import cc.winboll.studio.libjc.Main;
+
+public class ConsoleUtils {
+
+ public static String TAG = "ConsoleUtils";
+
+ public static class Debug {
+
+
+ public static void printFuncInfo(String tag) {
+ if (Main._DEBUG) {
+ String methodName = "";
+ int lineNumber = 0;
+ try {
+ // 获取当前正在执行的栈帧
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ // 一般取第2个元素(索引为1)对应的就是当前调用的方法,可根据实际情况调整
+ methodName = stackTrace[3].getMethodName();
+ lineNumber = stackTrace[3].getLineNumber();
+ System.out.println(String.format("[ Class=>%s ] [ Line=>(%d) ] [ Func=>%s ]: ", tag, lineNumber, methodName));
+ } catch (Exception e) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ }
+ }
+ }
+
+ public static void printObjectInfo(String objName, Object obj) {
+ if (Main._DEBUG) {
+ System.out.println(String.format("[ %s : %s ]", objName, obj.toString()));
+ }
+ }
+ }
+
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/util/FileUtils.java b/libjc/src/main/java/cc/winboll/studio/libjc/util/FileUtils.java
new file mode 100644
index 0000000..183d2a6
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/util/FileUtils.java
@@ -0,0 +1,81 @@
+package cc.winboll.studio.libjc.util;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/08/12 13:46:32
+ * @Describe 文件处理工具
+ */
+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.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";
+
+ //
+ // 把字符串写入文件,指定 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) {
+ System.err.println(String.format("%s Exception : %s", TAG, e.getMessage()));
+ LogUtils.e(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ return false;
+ }
+}
diff --git a/libjc/src/main/java/cc/winboll/studio/libjc/util/LogUtils.java b/libjc/src/main/java/cc/winboll/studio/libjc/util/LogUtils.java
new file mode 100644
index 0000000..9724f54
--- /dev/null
+++ b/libjc/src/main/java/cc/winboll/studio/libjc/util/LogUtils.java
@@ -0,0 +1,93 @@
+package cc.winboll.studio.libjc.util;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2025/01/06 18:47:05
+ * @Describe 日志类
+ */
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class LogUtils {
+
+ public static final String TAG = "Log";
+
+ static SimpleDateFormat _SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ static File _fLog;
+ static volatile LogUtils _Log;
+ static volatile boolean _LogInitOK = false;
+
+ public synchronized static void init(String logName) {
+ ConsoleUtils.Debug.printFuncInfo(TAG);
+
+ if (_Log == null) {
+ _LogInitOK = false;
+ _Log = new LogUtils();
+ File fLogDir = new File("/sdcard/WinBollStudio/Logs");
+ if (!fLogDir.exists()) {
+ System.out.println("Log dir not exist : /sdcard/WinBollStudio/Logs");
+ return;
+ }
+ _fLog = new File(fLogDir, ((logName == null || logName.equals("")) ?TAG: logName) + ".txt");
+ ConsoleUtils.Debug.printObjectInfo("_LogInitOK", _LogInitOK);
+ //System.out.println("Log Init OK!");
+ _LogInitOK = true;
+ ConsoleUtils.Debug.printObjectInfo("_LogInitOK", _LogInitOK);
+ }
+ }
+
+ public static void d(String tag, String msg) {
+ if (!_LogInitOK) {
+ return;
+ }
+
+ try {
+ Date date = new Date();
+ String formattedDate = _SimpleDateFormat.format(date);
+ FileOutputStream fos = new FileOutputStream(_fLog, true);
+ fos.write(String.format("[ %s ]<%s> :\n%s\n", formattedDate, tag, msg).getBytes());
+ fos.close();
+
+// JCMainThread.OnMessageListener listener = JCMainThread.getOnLogListener();
+// if (listener != null) {
+// listener.log(msg);
+// }
+ } catch (IOException e) {
+ System.err.println(String.format("%s Exception : %s", LogUtils.class.getName(), e.getMessage()));
+ }
+ }
+
+ public static void e(String tag, Exception e, StackTraceElement[] listStackTrace) {
+ if (!_LogInitOK) {
+ return;
+ }
+
+ try {
+ Date date = new Date();
+ String formattedDate = _SimpleDateFormat.format(date);
+ StringBuilder sbMessage = new StringBuilder(String.format("[ %s ]<%s> :\n%s -> \n", formattedDate, tag, e.getClass().getName()));
+ FileOutputStream fos = new FileOutputStream(_fLog, true);
+ sbMessage.append("At [ function : ");
+ sbMessage.append(listStackTrace[2].getMethodName());
+ sbMessage.append(" ]( ");
+ sbMessage.append(listStackTrace[2].getFileName());
+ sbMessage.append(" : ");
+ sbMessage.append(listStackTrace[2].getLineNumber());
+ sbMessage.append(" )");
+ fos.write(sbMessage.toString().getBytes());
+ fos.close();
+
+ //System.err.println(sbMessage.toString());
+
+// JCMainThread.OnMessageListener listener = JCMainThread.getOnLogListener();
+// if (listener != null) {
+// listener.log(sbMessage.toString());
+// }
+ } catch (IOException ex) {
+ System.err.println(String.format("%s Exception : %s", LogUtils.class.getName(), ex.getMessage()));
+ }
+ }
+}
diff --git a/libjc/src/main/res/drawable-hdpi/ic_launcher.png b/libjc/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
Binary files /dev/null and b/libjc/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/libjc/src/main/res/drawable-mdpi/ic_launcher.png b/libjc/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
Binary files /dev/null and b/libjc/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/libjc/src/main/res/drawable-xhdpi/ic_launcher.png b/libjc/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
Binary files /dev/null and b/libjc/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/libjc/src/main/res/drawable-xxhdpi/ic_launcher.png b/libjc/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4df1894
Binary files /dev/null and b/libjc/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/libjc/src/main/res/layout/library.xml b/libjc/src/main/res/layout/library.xml
new file mode 100644
index 0000000..b1d869f
--- /dev/null
+++ b/libjc/src/main/res/layout/library.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libjc/src/main/res/values-v21/styles.xml b/libjc/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..0948fdc
--- /dev/null
+++ b/libjc/src/main/res/values-v21/styles.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/libjc/src/main/res/values/strings.xml b/libjc/src/main/res/values/strings.xml
new file mode 100644
index 0000000..66a0b8b
--- /dev/null
+++ b/libjc/src/main/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+
+
+ libjc
+ Hello world!
+
+
diff --git a/libjc/src/main/res/values/styles.xml b/libjc/src/main/res/values/styles.xml
new file mode 100644
index 0000000..8d78246
--- /dev/null
+++ b/libjc/src/main/res/values/styles.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/local.properties-demo b/local.properties-demo
new file mode 100644
index 0000000..1fc1081
--- /dev/null
+++ b/local.properties-demo
@@ -0,0 +1,8 @@
+## This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+#Sat Apr 27 01:35:26 CST 2024
+#sdk.dir=
diff --git a/mj/app_update_description.txt b/mj/app_update_description.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/mj/app_update_description.txt
@@ -0,0 +1 @@
+
diff --git a/mj/build.gradle b/mj/build.gradle
new file mode 100644
index 0000000..6838909
--- /dev/null
+++ b/mj/build.gradle
@@ -0,0 +1,64 @@
+apply plugin: 'com.android.application'
+apply from: '../.winboll/winboll_app_build.gradle'
+apply from: '../.winboll/winboll_lint_build.gradle'
+
+def genVersionName(def versionName){
+ // 检查编译标志位配置
+ assert (winbollBuildProps['stageCount'] != null)
+ assert (winbollBuildProps['baseVersion'] != null)
+ // 保存基础版本号
+ winbollBuildProps.setProperty("baseVersion", "${versionName}");
+ //保存编译标志配置
+ FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile)
+ winbollBuildProps.store(fos, "${winbollBuildPropsDesc}");
+ fos.close();
+
+ // 返回编译版本号
+ return "${versionName}." + winbollBuildProps['stageCount']
+}
+
+android {
+ compileSdkVersion 32
+ buildToolsVersion "33.0.3"
+
+ defaultConfig {
+ applicationId "cc.winboll.studio.mj"
+ minSdkVersion 24
+ targetSdkVersion 30
+ versionCode 1
+ // versionName 更新后需要手动设置
+ // .winboll/winbollBuildProps.properties 文件的 stageCount=0
+ // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
+ versionName "1.0"
+ if(true) {
+ versionName = genVersionName("${versionName}")
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+}
+
+dependencies {
+ api 'cc.winboll.studio:winboll-shared:1.6.4'
+ api 'io.github.medyo:android-about-page:2.0.0'
+ api 'com.github.getActivity:ToastUtils:10.5'
+ api 'com.jcraft:jsch:0.1.55'
+ api 'org.jsoup:jsoup:1.13.1'
+ api 'com.squareup.okhttp3:okhttp:4.4.1'
+
+ api 'androidx.appcompat:appcompat:1.0.0'
+ api 'androidx.fragment:fragment:1.0.0'
+ api 'com.google.android.material:material:1.0.0'
+
+ api fileTree(dir: 'libs', include: ['*.jar'])
+}
diff --git a/mj/build.properties b/mj/build.properties
new file mode 100644
index 0000000..0694b08
--- /dev/null
+++ b/mj/build.properties
@@ -0,0 +1,8 @@
+#Created by .winboll/winboll_app_build.gradle
+#Wed Jan 01 11:08:15 GMT 2025
+stageCount=8
+libraryProject=
+baseVersion=1.0
+publishVersion=1.0.7
+buildCount=4
+baseBetaVersion=1.0.8
diff --git a/mj/proguard-rules.pro b/mj/proguard-rules.pro
new file mode 100644
index 0000000..233bad2
--- /dev/null
+++ b/mj/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/mj/src/beta/AndroidManifest.xml b/mj/src/beta/AndroidManifest.xml
new file mode 100644
index 0000000..f8a9dd2
--- /dev/null
+++ b/mj/src/beta/AndroidManifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/beta/res/values/strings.xml b/mj/src/beta/res/values/strings.xml
new file mode 100644
index 0000000..3fef0aa
--- /dev/null
+++ b/mj/src/beta/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ MJ♢
+
+
diff --git a/mj/src/main/AndroidManifest.xml b/mj/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..0ad7391
--- /dev/null
+++ b/mj/src/main/AndroidManifest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/main/java/cc/winboll/studio/mj/App.java b/mj/src/main/java/cc/winboll/studio/mj/App.java
new file mode 100644
index 0000000..eaea7d3
--- /dev/null
+++ b/mj/src/main/java/cc/winboll/studio/mj/App.java
@@ -0,0 +1,19 @@
+package cc.winboll.studio.mj;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/11/28 15:42:47
+ * @Describe 全局应用类
+ */
+ import cc.winboll.studio.shared.app.WinBollApplication;
+
+public class App extends WinBollApplication {
+
+ public static final String TAG = "App";
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ setIsDebug(BuildConfig.DEBUG);
+ }
+}
diff --git a/mj/src/main/java/cc/winboll/studio/mj/MainActivity.java b/mj/src/main/java/cc/winboll/studio/mj/MainActivity.java
new file mode 100644
index 0000000..a0c5f5d
--- /dev/null
+++ b/mj/src/main/java/cc/winboll/studio/mj/MainActivity.java
@@ -0,0 +1,87 @@
+package cc.winboll.studio.mj;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.mj.activities.AboutActivity;
+import cc.winboll.studio.shared.app.WinBollActivity;
+import cc.winboll.studio.shared.app.WinBollApplication;
+import cc.winboll.studio.shared.log.LogUtils;
+
+final public class MainActivity extends WinBollActivity {
+
+ public static final String TAG = "MainActivity";
+
+ public static final int REQUEST_HOME_ACTIVITY = 0;
+ public static final int REQUEST_ABOUT_ACTIVITY = 1;
+
+ @Override
+ protected boolean isEnableDisplayHomeAsUp() {
+ return false;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ // 设置 WinBoll 应用 UI 类型
+ WinBollApplication.setWinBollUI_TYPE(WinBollApplication.WinBollUI_TYPE.Aplication);
+ //ToastUtils.show("WinBollUI_TYPE " + WinBollApplication.getWinBollUI_TYPE());
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+
+ @Override
+ protected boolean isAddWinBollToolBar() {
+ return true;
+ }
+
+ @Override
+ protected Toolbar initToolBar() {
+ return findViewById(R.id.activitymainToolbar1);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.toolbar_main, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.item_about) {
+ try {
+ WinBollActivity clazzActivity = AboutActivity.class.newInstance();
+ String tag = clazzActivity.getTag();
+ LogUtils.d(TAG, "String tag = clazzActivity.getTag(); tag " + tag);
+ Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
+ startWinBollActivity(intent, tag);
+ } catch (IllegalAccessException e) {} catch (InstantiationException e) {}
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (resultCode) {
+ case REQUEST_HOME_ACTIVITY : {
+ LogUtils.d(TAG, "REQUEST_HOME_ACTIVITY");
+ break;
+ }
+ case REQUEST_ABOUT_ACTIVITY : {
+ LogUtils.d(TAG, "REQUEST_ABOUT_ACTIVITY");
+ break;
+ }
+ default : {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+ }
+}
diff --git a/mj/src/main/java/cc/winboll/studio/mj/activities/AboutActivity.java b/mj/src/main/java/cc/winboll/studio/mj/activities/AboutActivity.java
new file mode 100644
index 0000000..cb46aa9
--- /dev/null
+++ b/mj/src/main/java/cc/winboll/studio/mj/activities/AboutActivity.java
@@ -0,0 +1,62 @@
+package cc.winboll.studio.mj.activities;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/07/14 13:20:33
+ * @Describe 应用关于对话窗口
+ */
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.mj.R;
+import cc.winboll.studio.shared.app.WinBollActivity;
+import cc.winboll.studio.shared.app.WinBollActivityManager;
+import com.hjq.toast.ToastUtils;
+
+final public class AboutActivity extends WinBollActivity {
+
+ public static final String TAG = "AboutActivity";
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ protected boolean isEnableDisplayHomeAsUp() {
+ return true;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_about);
+ }
+
+ @Override
+ protected boolean isAddWinBollToolBar() {
+ return true;
+ }
+
+ @Override
+ protected Toolbar initToolBar() {
+ return findViewById(R.id.activityaboutToolbar1);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.toolbar_about, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.item_help) {
+ ToastUtils.show("R.id.item_help");
+ } else if (item.getItemId() == android.R.id.home) {
+ WinBollActivityManager.getInstance(getApplicationContext()).finish(this);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/mj/src/main/res/drawable/ic_launcher.xml b/mj/src/main/res/drawable/ic_launcher.xml
new file mode 100644
index 0000000..d4d1eaf
--- /dev/null
+++ b/mj/src/main/res/drawable/ic_launcher.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/mj/src/main/res/drawable/ic_launcher_background.xml b/mj/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..9486190
--- /dev/null
+++ b/mj/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/main/res/drawable/ic_launcher_foreground.xml b/mj/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..872b04e
--- /dev/null
+++ b/mj/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/mj/src/main/res/drawable/shape_gradient.xml b/mj/src/main/res/drawable/shape_gradient.xml
new file mode 100644
index 0000000..c164fe9
--- /dev/null
+++ b/mj/src/main/res/drawable/shape_gradient.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/mj/src/main/res/layout/activity_about.xml b/mj/src/main/res/layout/activity_about.xml
new file mode 100644
index 0000000..cf2acdd
--- /dev/null
+++ b/mj/src/main/res/layout/activity_about.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/main/res/layout/activity_main.xml b/mj/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..1f05c49
--- /dev/null
+++ b/mj/src/main/res/layout/activity_main.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/main/res/layout/view_toast.xml b/mj/src/main/res/layout/view_toast.xml
new file mode 100644
index 0000000..d6a9915
--- /dev/null
+++ b/mj/src/main/res/layout/view_toast.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/main/res/menu/toolbar_about.xml b/mj/src/main/res/menu/toolbar_about.xml
new file mode 100644
index 0000000..1a827f5
--- /dev/null
+++ b/mj/src/main/res/menu/toolbar_about.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/mj/src/main/res/menu/toolbar_main.xml b/mj/src/main/res/menu/toolbar_main.xml
new file mode 100644
index 0000000..e992ee9
--- /dev/null
+++ b/mj/src/main/res/menu/toolbar_main.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/mj/src/main/res/values/colors.xml b/mj/src/main/res/values/colors.xml
new file mode 100644
index 0000000..6be8764
--- /dev/null
+++ b/mj/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+
+ #FF196ABC
+ #FF002B57
+ #FF80BFFF
+ #FFA9A9A9
+ #FF000000
+ #FFFFFFFF
+
diff --git a/mj/src/main/res/values/strings.xml b/mj/src/main/res/values/strings.xml
new file mode 100644
index 0000000..26d02a0
--- /dev/null
+++ b/mj/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ MJ
+
+
diff --git a/mj/src/main/res/values/styles.xml b/mj/src/main/res/values/styles.xml
new file mode 100644
index 0000000..045e125
--- /dev/null
+++ b/mj/src/main/res/values/styles.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/mj/src/stage/AndroidManifest.xml b/mj/src/stage/AndroidManifest.xml
new file mode 100644
index 0000000..ee78d9f
--- /dev/null
+++ b/mj/src/stage/AndroidManifest.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mj/src/stage/res/values/strings.xml b/mj/src/stage/res/values/strings.xml
new file mode 100644
index 0000000..ace0c41
--- /dev/null
+++ b/mj/src/stage/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/mymessagemanager/.gitignore b/mymessagemanager/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/mymessagemanager/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/mymessagemanager/README.md b/mymessagemanager/README.md
new file mode 100644
index 0000000..75856f4
--- /dev/null
+++ b/mymessagemanager/README.md
@@ -0,0 +1,45 @@
+# MyMessageManager
+
+#### 介绍
+用正则表达式方法自定义短信过滤和语音播报的短信应用。
+
+#### 软件架构
+软件架构说明
+
+
+#### 安装教程
+
+1. xxxx
+2. xxxx
+3. xxxx
+
+#### 使用说明
+
+1. xxxx
+2. xxxx
+3. xxxx
+
+#### 参与贡献
+
+1. Fork 本仓库
+2. 新建 Feat_xxx 分支
+3. 提交代码:ZhanGSKen(ZhanGSKen@QQ.COM)
+4. 新建 Pull Request
+
+
+#### 特技
+
+1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
+2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
+3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
+4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
+5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
+6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+
+#### 参考文档
+
+使用GitHub Actions实现Android自动打包apk
+https://blog.csdn.net/ZZL23333/article/details/115798615?app_version=6.0.0&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22115798615%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app
+
+Android中assets的使用(用于读取内容)
+https://blog.csdn.net/qq_27664947/article/details/103924058?app_version=6.0.0&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22103924058%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app
diff --git a/mymessagemanager/app_update_description.txt b/mymessagemanager/app_update_description.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/mymessagemanager/app_update_description.txt
@@ -0,0 +1 @@
+
diff --git a/mymessagemanager/build.gradle b/mymessagemanager/build.gradle
new file mode 100644
index 0000000..7f9a2d1
--- /dev/null
+++ b/mymessagemanager/build.gradle
@@ -0,0 +1,69 @@
+apply plugin: 'com.android.application'
+apply from: '../.winboll/winboll_app_build.gradle'
+apply from: '../.winboll/winboll_lint_build.gradle'
+
+def genVersionName(def versionName){
+ // 检查编译标志位配置
+ assert (winbollBuildProps['stageCount'] != null)
+ assert (winbollBuildProps['baseVersion'] != null)
+ // 保存基础版本号
+ winbollBuildProps.setProperty("baseVersion", "${versionName}");
+ //保存编译标志配置
+ FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile)
+ winbollBuildProps.store(fos, "${winbollBuildPropsDesc}");
+ fos.close();
+
+ // 返回编译版本号
+ return "${versionName}." + winbollBuildProps['stageCount']
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "cc.winboll.studio.mymessagemanager"
+ minSdkVersion 26
+ targetSdkVersion 29
+ versionCode 8
+ // versionName 更新后需要手动设置
+ // .winboll/winbollBuildProps.properties 文件的 stageCount=0
+ // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
+ versionName "4.1"
+ if(true) {
+ versionName = genVersionName("${versionName}")
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ api 'cc.winboll.studio:winboll-shared:1.6.4'
+ api 'io.github.medyo:android-about-page:2.0.0'
+ api 'com.github.getActivity:ToastUtils:10.5'
+ api 'com.jcraft:jsch:0.1.55'
+ api 'org.jsoup:jsoup:1.13.1'
+ api 'com.squareup.okhttp3:okhttp:4.4.1'
+
+ api 'androidx.appcompat:appcompat:1.0.0'
+ api 'androidx.fragment:fragment:1.0.0'
+ api 'com.google.android.material:material:1.0.0'
+
+ // 权限请求框架:https://github.com/getActivity/XXPermissions
+ api 'com.github.getActivity:XXPermissions:18.63'
+ api 'com.baoyz.pullrefreshlayout:library:1.2.0'
+
+ api 'androidx.appcompat:appcompat:1.0.0'
+ api 'androidx.fragment:fragment:1.0.0'
+ api 'com.google.android.material:material:1.0.0'
+
+ api 'cc.winboll.studio:libaes:7.6.0'
+
+ api fileTree(dir: 'libs', include: ['*.jar'])
+}
diff --git a/mymessagemanager/build.properties b/mymessagemanager/build.properties
new file mode 100644
index 0000000..2414519
--- /dev/null
+++ b/mymessagemanager/build.properties
@@ -0,0 +1,8 @@
+#Created by .winboll/winboll_app_build.gradle
+#Tue Feb 25 10:52:41 GMT 2025
+stageCount=14
+libraryProject=
+baseVersion=4.1
+publishVersion=4.1.13
+buildCount=5
+baseBetaVersion=4.1.14
diff --git a/mymessagemanager/proguard-rules.pro b/mymessagemanager/proguard-rules.pro
new file mode 100644
index 0000000..233bad2
--- /dev/null
+++ b/mymessagemanager/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/mymessagemanager/src/beta/AndroidManifest.xml b/mymessagemanager/src/beta/AndroidManifest.xml
new file mode 100644
index 0000000..522ecec
--- /dev/null
+++ b/mymessagemanager/src/beta/AndroidManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mymessagemanager/src/beta/res/values-zh/strings.xml b/mymessagemanager/src/beta/res/values-zh/strings.xml
new file mode 100644
index 0000000..ffbc3e5
--- /dev/null
+++ b/mymessagemanager/src/beta/res/values-zh/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ 我的短信管家 ☆
+
+
diff --git a/mymessagemanager/src/beta/res/values/strings.xml b/mymessagemanager/src/beta/res/values/strings.xml
new file mode 100644
index 0000000..085d3ca
--- /dev/null
+++ b/mymessagemanager/src/beta/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ My Message Manager +
+
+
diff --git a/mymessagemanager/src/main/AndroidManifest.xml b/mymessagemanager/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c1e89fa
--- /dev/null
+++ b/mymessagemanager/src/main/AndroidManifest.xml
@@ -0,0 +1,231 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mymessagemanager/src/main/assets/GlobalApplication/SMSAcceptRuleBean_List.json b/mymessagemanager/src/main/assets/GlobalApplication/SMSAcceptRuleBean_List.json
new file mode 100644
index 0000000..b7fdefe
--- /dev/null
+++ b/mymessagemanager/src/main/assets/GlobalApplication/SMSAcceptRuleBean_List.json
@@ -0,0 +1,7 @@
+[
+ {
+ "userId": -1,
+ "ruleData": ".*",
+ "isEnable": true
+ }
+]
\ No newline at end of file
diff --git a/mymessagemanager/src/main/assets/GlobalApplication/TTSPlayRuleBean_List.json b/mymessagemanager/src/main/assets/GlobalApplication/TTSPlayRuleBean_List.json
new file mode 100644
index 0000000..8c9f761
--- /dev/null
+++ b/mymessagemanager/src/main/assets/GlobalApplication/TTSPlayRuleBean_List.json
@@ -0,0 +1,38 @@
+[
+ {
+ "userId": 1,
+ "ruleName": "规则1",
+ "demoSMSText": "【短信应用A】验证码123456",
+ "patternText": "^(【.*】)验证码(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)$",
+ "ttdRuleText": "$1验证码是($2)($3)($4)($5)($6)($7)。",
+ "isSimpleView": false,
+ "isEnable": true
+ },
+ {
+ "userId": 1,
+ "ruleName": "规则2",
+ "demoSMSText": "[短信应用A]验证码123456",
+ "patternText": "^(\\[.*\\])验证码(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)$",
+ "ttdRuleText": "$1验证码是($2)($3)($4)($5)($6)($7)。",
+ "isSimpleView": false,
+ "isEnable": true
+ },
+ {
+ "userId": 1,
+ "ruleName": "规则3",
+ "demoSMSText": "【短信应用A】验证码123456",
+ "patternText": ".*(【.+】).*",
+ "ttdRuleText": "短信来自$1。",
+ "isSimpleView": false,
+ "isEnable": true
+ },
+ {
+ "userId": 1,
+ "ruleName": "规则4",
+ "demoSMSText": "[短信应用A]验证码123456",
+ "patternText": ".*(\\[.*\\]).*",
+ "ttdRuleText": "短信来自$1。",
+ "isSimpleView": false,
+ "isEnable": true
+ }
+]
\ No newline at end of file
diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/GlobalApplication.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/GlobalApplication.java
new file mode 100644
index 0000000..a14351e
--- /dev/null
+++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/GlobalApplication.java
@@ -0,0 +1,52 @@
+package cc.winboll.studio.mymessagemanager;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2023/07/24 01:46:59
+ * @Describe 全局应用类
+ */
+import android.view.Gravity;
+import cc.winboll.studio.mymessagemanager.R;
+import cc.winboll.studio.shared.app.WinBollApplication;
+import cc.winboll.studio.shared.log.LogUtils;
+import com.hjq.toast.ToastUtils;
+import java.io.File;
+
+public class GlobalApplication extends WinBollApplication {
+
+ public static final String TAG = "GlobalApplication";
+
+ static String _mszAppExternalFilesDir;
+ static String _mszConfigUtilFileName = "ConfigUtil.json";
+ static String _mszConfigUtilPath;
+ static String _mszSMSReceiveRuleUtilFileName = "SMSReceiveRuleUtil.json";
+ static String _mszSMSReceiveRuleUtilPath;
+
+ public static final int USER_ID = -1;
+ Long mszVersionName = 1L;
+ Long mszDataVersionName = 1L;
+
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ //setIsDebug(cc.winboll.studio.mymessagemanager.BuildConfig.DEBUG);
+
+ // 初始化 Toast 框架
+ ToastUtils.init(this);
+ // 设置 Toast 布局样式
+ ToastUtils.setView(R.layout.toast_custom_view);
+ //ToastUtils.setStyle(new WhiteToastStyle());
+ ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
+
+ //LogUtils.d(TAG, "BuildConfig.DEBUG " + Boolean.toString(BuildConfig.DEBUG));
+
+ _mszAppExternalFilesDir = getExternalFilesDir(TAG).toString();
+ _mszConfigUtilPath = _mszAppExternalFilesDir + File.separator + _mszConfigUtilFileName;
+ _mszSMSReceiveRuleUtilPath = _mszAppExternalFilesDir + File.separator + _mszSMSReceiveRuleUtilFileName;
+ }
+
+ public static void showApplicationMessage(String szMessage) {
+ LogUtils.i(TAG, szMessage);
+ }
+}
diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/AboutActivity.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/AboutActivity.java
new file mode 100644
index 0000000..51750d6
--- /dev/null
+++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/AboutActivity.java
@@ -0,0 +1,74 @@
+package cc.winboll.studio.mymessagemanager.activitys;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/07/14 13:20:33
+ * @Describe 应用关于对话窗口
+ */
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.mymessagemanager.R;
+import cc.winboll.studio.shared.app.WinBollActivity;
+import cc.winboll.studio.shared.app.WinBollActivityManager;
+import com.hjq.toast.ToastUtils;
+import cc.winboll.studio.libaes.utils.AESThemeUtil;
+import android.content.Context;
+
+final public class AboutActivity extends WinBollActivity {
+
+ public static final String TAG = "AboutActivity";
+
+ Context mContext;
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ protected boolean isEnableDisplayHomeAsUp() {
+ return false;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_about);
+ mContext = getApplicationContext();
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ setTitle(mContext.getString(R.string.text_about) + mContext.getString(R.string.app_name));
+ }
+
+ @Override
+ protected boolean isAddWinBollToolBar() {
+ return false;
+ }
+
+ @Override
+ protected Toolbar initToolBar() {
+ return findViewById(R.id.activityaboutASupportToolbar1);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.toolbar_about, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ /*if (item.getItemId() == R.id.item_help) {
+ ToastUtils.show("R.id.item_help");
+ } else */if (item.getItemId() == android.R.id.home) {
+ WinBollActivityManager.getInstance(getApplicationContext()).finish(this);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/AppSettingsActivity.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/AppSettingsActivity.java
new file mode 100644
index 0000000..2704fe6
--- /dev/null
+++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/AppSettingsActivity.java
@@ -0,0 +1,99 @@
+package cc.winboll.studio.mymessagemanager.activitys;
+
+/**
+ * @Author ZhanGSKen@QQ.COM
+ * @Date 2024/05/12 20:03:42
+ * @Describe 应用设置窗口
+ */
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.Switch;
+import android.widget.Toast;
+import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
+import cc.winboll.studio.libaes.views.AToolbar;
+import cc.winboll.studio.mymessagemanager.R;
+import cc.winboll.studio.mymessagemanager.utils.AppConfigUtil;
+import cc.winboll.studio.mymessagemanager.utils.PermissionUtil;
+
+public class AppSettingsActivity extends BaseActivity {
+
+ public static final String TAG = "AppSettingsActivity";
+
+ AppConfigUtil mAppConfigUtil;
+ AToolbar mAToolbar;
+ AOHPCTCSeekBar mAOHPCTCSeekBar;
+ EditText metTTSPlayDelayTimes;
+ EditText metPhoneMergePrefix;
+ Switch mswMergePrefixPhone;
+ Switch mswSMSRecycleProtectMode;
+ EditText metProtectModerRefuseChars;
+ EditText metProtectModerReplaceChars;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_appsettings);
+
+ // 初始化属性
+ mAppConfigUtil = AppConfigUtil.getInstance(this);
+ int nTtsPlayDelayTimes = mAppConfigUtil.mAppConfigBean.getTtsPlayDelayTimes();
+ metTTSPlayDelayTimes = findViewById(R.id.activityappsettingsEditText1);
+ metTTSPlayDelayTimes.setText(Integer.toString(nTtsPlayDelayTimes / 1000));
+
+ // 初始化标题栏
+ mAToolbar = findViewById(R.id.activityappsettingsAToolbar1);
+ mAToolbar.setSubtitle(getString(R.string.activity_name_appsettings));
+ setActionBar(mAToolbar);
+
+ metPhoneMergePrefix = findViewById(R.id.activityappsettingsEditText2);
+ metPhoneMergePrefix.setText(mAppConfigUtil.mAppConfigBean.getCountryCode());
+
+ mswMergePrefixPhone = findViewById(R.id.activityappsettingsSwitch1);
+ mswMergePrefixPhone.setChecked(mAppConfigUtil.mAppConfigBean.isMergeCountryCodePrefix());
+
+ mswSMSRecycleProtectMode = findViewById(R.id.activityappsettingsSwitch3);
+ mswSMSRecycleProtectMode.setChecked(mAppConfigUtil.mAppConfigBean.isSMSRecycleProtectMode());
+
+ metProtectModerRefuseChars = findViewById(R.id.activityappsettingsEditText3);
+ metProtectModerRefuseChars.setText(mAppConfigUtil.mAppConfigBean.getProtectModerRefuseChars());
+
+ metProtectModerReplaceChars = findViewById(R.id.activityappsettingsEditText4);
+ metProtectModerReplaceChars.setText(mAppConfigUtil.mAppConfigBean.getProtectModerReplaceChars());
+
+ mAOHPCTCSeekBar = findViewById(R.id.activityappsettingsAOHPCTCSeekBar1);
+ mAOHPCTCSeekBar.setThumb(getDrawable(R.drawable.cursor_pointer));
+ mAOHPCTCSeekBar.setThumbOffset(0);
+ mAOHPCTCSeekBar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener(){
+
+ @Override
+ public void onOHPCommit() {
+ mAppConfigUtil.reLoadConfig();
+ mAppConfigUtil.mAppConfigBean.setIsSMSRecycleProtectMode(mswSMSRecycleProtectMode.isChecked());
+ mAppConfigUtil.mAppConfigBean.setProtectModerRefuseChars(metProtectModerRefuseChars.getText().toString());
+ mAppConfigUtil.mAppConfigBean.setProtectModerReplaceChars(metProtectModerReplaceChars.getText().toString());
+ mAppConfigUtil.mAppConfigBean.setCountryCode(metPhoneMergePrefix.getText().toString());
+ mAppConfigUtil.mAppConfigBean.setIsMergeCountryCodePrefix(mswMergePrefixPhone.isChecked());
+ int nTtsPlayDelayTimes = 1000 * Integer.parseInt(metTTSPlayDelayTimes.getText().toString());
+ mAppConfigUtil.mAppConfigBean.setTtsPlayDelayTimes(nTtsPlayDelayTimes);
+ mAppConfigUtil.saveConfig();
+ Toast.makeText(getApplication(), "App config data is saved.", Toast.LENGTH_SHORT).show();
+ //LogUtils.d(TAG, "TTS Play Delay Times is setting to : " + Integer.toString(mAppConfigData.getTtsPlayDelayTimes()));Toast.makeText(getApplication(), "onOHPCommit", Toast.LENGTH_SHORT).show();
+ }
+ });
+ };
+
+ public void onOpenSystemDefaultAppSettings(View view) {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
+ startActivity(intent);
+ }
+
+ public void onCheckAndGetAppPermission(View view) {
+ //LogUtils.d(TAG, "onCheckAndGetAppPermission");
+ if (PermissionUtil.checkAndGetAppPermission(this)) {
+ Toast.makeText(getApplication(), "应用已获得所需权限。", Toast.LENGTH_SHORT).show();
+ }
+ }
+}
diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/BaseActivity.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/BaseActivity.java
new file mode 100644
index 0000000..233f18a
--- /dev/null
+++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/BaseActivity.java
@@ -0,0 +1,113 @@
+package cc.winboll.studio.mymessagemanager.activitys;
+
+import cc.winboll.studio.mymessagemanager.R;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Menu;
+import android.view.MenuItem;
+import androidx.appcompat.app.AppCompatActivity;
+import cc.winboll.studio.libaes.utils.AESThemeUtil;
+import cc.winboll.studio.shared.log.LogUtils;
+import com.hjq.toast.ToastUtils;
+import cc.winboll.studio.libaes.beans.AESThemeBean;
+
+abstract public class BaseActivity extends AppCompatActivity {
+
+ public static final String TAG = "BaseActivity";
+
+ IOnActivityMessageReceived mIOnActivityMessageReceived;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ //AppConfigUtil configUtil = AppConfigUtil.getInstance(this);
+ //setTheme(configUtil.mAppConfigBean.getAppThemeID());
+ LogUtils.d(TAG, "AESThemeUtil.getThemeTypeID(this) is : " + Integer.toString(AESThemeUtil.getThemeTypeID(this)));
+ setTheme(AESThemeUtil.getThemeTypeID(this));
+ super.onCreate(savedInstanceState);
+ }
+
+ public void sendActivityMessage(Message msg) {
+ mHandler.sendMessage(msg);
+ }
+
+ protected void setOnActivityMessageReceived(IOnActivityMessageReceived iOnActivityMessageReceived) {
+ mIOnActivityMessageReceived = iOnActivityMessageReceived;
+ }
+
+ Handler mHandler = new Handler(){
+
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ if (mIOnActivityMessageReceived != null) {
+ mIOnActivityMessageReceived.onActivityMessageReceived(msg);
+ }
+ }
+ };
+
+ protected interface IOnActivityMessageReceived {
+ void onActivityMessageReceived(Message msg);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ AESThemeUtil.inflateMenu(this, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ /*if (AESThemeUtil.onAppCompatThemeItemSelected(this, item)) {
+ ToastUtils.show("onAppCompatThemeItemSelected");
+ recreate();
+ }*/
+
+ /*int nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT);
+ if (R.id.item_depththeme == item.getItemId()) {
+ nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH);
+ AESThemeUtil.saveThemeStyleID(this, nThemeStyleID);
+ recreate();
+ } else if (R.id.item_skytheme == item.getItemId()) {
+ nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.SKY);
+ AESThemeUtil.saveThemeStyleID(this, nThemeStyleID);
+ recreate();
+ } else if (R.id.item_goldentheme == item.getItemId()) {
+ nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.GOLDEN);
+ AESThemeUtil.saveThemeStyleID(this, nThemeStyleID);
+ recreate();
+ } else if (R.id.item_taotheme == item.getItemId()) {
+ nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.TAO);
+ AESThemeUtil.saveThemeStyleID(this, nThemeStyleID);
+ recreate();
+ } else if (R.id.item_defaulttheme == item.getItemId()) {
+ nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT);
+ AESThemeUtil.saveThemeStyleID(this, nThemeStyleID);
+ recreate();
+ }*/
+
+ //int nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEFAULT);
+ if (R.id.item_depththeme == item.getItemId()) {
+ AESThemeUtil.saveThemeStyleID(this, R.style.MyDepthAESTheme);
+ recreate();
+ } else if (R.id.item_skytheme == item.getItemId()) {
+ AESThemeUtil.saveThemeStyleID(this, R.style.MySkyAESTheme);
+ recreate();
+ } else if (R.id.item_goldentheme == item.getItemId()) {
+ AESThemeUtil.saveThemeStyleID(this, R.style.MyGoldenAESTheme);
+ recreate();
+ } else if (R.id.item_memortheme == item.getItemId()) {
+ AESThemeUtil.saveThemeStyleID(this, R.style.MyMemorAESTheme);
+ recreate();
+ } else if (R.id.item_taotheme == item.getItemId()) {
+ AESThemeUtil.saveThemeStyleID(this, R.style.MyTaoAESTheme);
+ recreate();
+ } else if (R.id.item_defaulttheme == item.getItemId()) {
+ AESThemeUtil.saveThemeStyleID(this, R.style.MyDefaultAESTheme);
+ recreate();
+ }
+ //ToastUtils.show("nThemeStyleID " + Integer.toString(nThemeStyleID));
+
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/ComposeSMSActivity.java b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/ComposeSMSActivity.java
new file mode 100644
index 0000000..03a7a3c
--- /dev/null
+++ b/mymessagemanager/src/main/java/cc/winboll/studio/mymessagemanager/activitys/ComposeSMSActivity.java
@@ -0,0 +1,192 @@
+package cc.winboll.studio.mymessagemanager.activitys;
+
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.Toolbar;
+import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
+import cc.winboll.studio.mymessagemanager.R;
+import cc.winboll.studio.mymessagemanager.activitys.ComposeSMSActivity;
+import cc.winboll.studio.mymessagemanager.beans.PhoneBean;
+import cc.winboll.studio.mymessagemanager.utils.PhoneUtil;
+import cc.winboll.studio.mymessagemanager.utils.SMSUtil;
+import com.hjq.toast.ToastUtils;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ComposeSMSActivity extends BaseActivity {
+
+ public static String TAG = "ComposeSMSActivity";
+
+ public static String EXTRA_SMSBODY = "sms_body";
+
+ static String MAP_NAME = "NAME";
+ static String MAP_PHONE = "PHONE";
+
+ String mszSMSBody;
+ String mszScheme;
+ String mszPhoneTo;
+ EditText metTO;
+ EditText metSMSBody;
+ SimpleAdapter mSimpleAdapter;
+ List