diff --git a/aes/build.gradle b/aes/build.gradle
index d022e95..3bfd561 100644
--- a/aes/build.gradle
+++ b/aes/build.gradle
@@ -23,7 +23,7 @@ android {
defaultConfig {
applicationId "cc.winboll.studio.aes"
- minSdkVersion 26
+ minSdkVersion 24
targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
diff --git a/aes/build.properties b/aes/build.properties
index 650a078..83da101 100644
--- a/aes/build.properties
+++ b/aes/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Mon Mar 24 19:50:52 GMT 2025
+#Sat Mar 29 00:26:50 GMT 2025
stageCount=8
libraryProject=libaes
baseVersion=15.0
publishVersion=15.0.7
-buildCount=6
+buildCount=23
baseBetaVersion=15.0.8
diff --git a/aes/src/main/AndroidManifest.xml b/aes/src/main/AndroidManifest.xml
index 2f397f0..bbd1308 100644
--- a/aes/src/main/AndroidManifest.xml
+++ b/aes/src/main/AndroidManifest.xml
@@ -34,4 +34,4 @@
-
\ No newline at end of file
+
diff --git a/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java
index d8b297c..80fc544 100644
--- a/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java
+++ b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java
@@ -5,26 +5,38 @@ package cc.winboll.studio.aes;
* @Date 2025/03/24 23:52:29
* @Describe AES应用介绍窗口
*/
-import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.LinearLayout;
+import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.winboll.APPInfo;
import cc.winboll.studio.libaes.winboll.AboutView;
+import cc.winboll.studio.libappbase.GlobalApplication;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
+import android.app.Activity;
-public class AboutActivity extends Activity {
+public class AboutActivity extends AppCompatActivity implements IWinBollActivity {
+
+ public static final String TAG = "AboutActivity";
Context mContext;
-
- public static final String TAG = "AboutActivity";
+
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
-
+
AboutView aboutView = CreateAboutView();
// 在 Activity 的 onCreate 或其他生命周期方法中调用
LinearLayout layout = new LinearLayout(this);
@@ -35,7 +47,14 @@ public class AboutActivity extends Activity {
ViewGroup.LayoutParams.MATCH_PARENT
);
addContentView(aboutView, params);
-
+
+ GlobalApplication.getWinBollActivityManager().add(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ GlobalApplication.getWinBollActivityManager().registeRemove(this);
}
public AboutView CreateAboutView() {
diff --git a/aes/src/main/java/cc/winboll/studio/aes/App.java b/aes/src/main/java/cc/winboll/studio/aes/App.java
index df1a0a2..b8723d9 100644
--- a/aes/src/main/java/cc/winboll/studio/aes/App.java
+++ b/aes/src/main/java/cc/winboll/studio/aes/App.java
@@ -6,6 +6,8 @@ package cc.winboll.studio.aes;
* @Describe AES应用类
*/
import cc.winboll.studio.libappbase.GlobalApplication;
+import com.hjq.toast.ToastUtils;
+
public class App extends GlobalApplication {
@@ -14,6 +16,8 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
+ ToastUtils.init(this);
+ ToastUtils.show("App onCreate");
}
}
diff --git a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
index 61ce96e..06ef438 100644
--- a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
+++ b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
@@ -5,6 +5,7 @@ package cc.winboll.studio.aes;
* @Date 2024/06/13 19:05:52
* @Describe 应用主窗口
*/
+import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
@@ -12,8 +13,6 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
-import android.widget.Toolbar;
-import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.aes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
@@ -25,9 +24,10 @@ import cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestAToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity;
import cc.winboll.studio.libaes.unittests.TestViewPageFragment;
-import cc.winboll.studio.libaes.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import com.a4455jkjh.colorpicker.ColorPickerDialog;
+import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
public class MainActivity extends DrawerFragmentActivity implements IWinBollActivity {
@@ -39,7 +39,7 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBollActi
TestViewPageFragment mTestViewPageFragment;
@Override
- public AppCompatActivity getActivity() {
+ public Activity getActivity() {
return this;
}
@@ -48,21 +48,6 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBollActi
return TAG;
}
- @Override
- public Toolbar initToolBar() {
- return null;
- }
-
- @Override
- public boolean isAddWinBollToolBar() {
- return false;
- }
-
- @Override
- public boolean isEnableDisplayHomeAsUp() {
- return false;
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -72,6 +57,7 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBollActi
}
showFragment(mTestAButtonFragment);
//setSubtitle(TAG);
+ ToastUtils.show("onCreate");
}
@Override
diff --git a/libaes/build.gradle b/libaes/build.gradle
index f994f15..0f46395 100644
--- a/libaes/build.gradle
+++ b/libaes/build.gradle
@@ -8,7 +8,7 @@ android {
buildToolsVersion "32.0.0"
defaultConfig {
- minSdkVersion 26
+ minSdkVersion 24
targetSdkVersion 29
}
buildTypes {
@@ -22,6 +22,9 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
+ // 吐司类库
+ api 'com.github.getActivity:ToastUtils:10.5'
+
// 权限请求框架:https://github.com/getActivity/XXPermissions
api 'com.github.getActivity:XXPermissions:18.63'
// 下拉控件
@@ -48,6 +51,6 @@ dependencies {
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0'
- api 'cc.winboll.studio:libappbase:15.0.10'
- api 'cc.winboll.studio:libapputils:15.0.17'
+ api 'cc.winboll.studio:libappbase:15.1.4'
+ api 'cc.winboll.studio:libapputils:15.0.19'
}
diff --git a/libaes/build.properties b/libaes/build.properties
index 650a078..83da101 100644
--- a/libaes/build.properties
+++ b/libaes/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Mon Mar 24 19:50:52 GMT 2025
+#Sat Mar 29 00:26:50 GMT 2025
stageCount=8
libraryProject=libaes
baseVersion=15.0
publishVersion=15.0.7
-buildCount=6
+buildCount=23
baseBetaVersion=15.0.8
diff --git a/libaes/src/main/AndroidManifest.xml b/libaes/src/main/AndroidManifest.xml
index 7e9ecb7..a1257eb 100644
--- a/libaes/src/main/AndroidManifest.xml
+++ b/libaes/src/main/AndroidManifest.xml
@@ -13,6 +13,12 @@
+
+
+
+
+
+
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java
index 058a22f..c2e6c56 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java
@@ -16,6 +16,7 @@ import android.view.View;
import android.widget.AdapterView;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -27,10 +28,9 @@ import cc.winboll.studio.libaes.beans.DrawerMenuBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libaes.views.ADrawerMenuListView;
import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import com.baoyz.widget.PullRefreshLayout;
import java.util.ArrayList;
-import cc.winboll.studio.libaes.winboll.IWinBollActivity;
-import androidx.appcompat.widget.Toolbar;
public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBollActivity,AdapterView.OnItemClickListener {
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java
index a4d4f8e..42cdef8 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java
@@ -1,15 +1,13 @@
package cc.winboll.studio.libaes.unittests;
+import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
-import android.widget.Toolbar;
-import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
-import cc.winboll.studio.libaes.winboll.APPInfo;
-import cc.winboll.studio.libaes.winboll.IWinBollActivity;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
/**
* @Author ZhanGSKen@QQ.COM
@@ -23,7 +21,7 @@ public class SecondaryLibraryActivity extends DrawerFragmentActivity implements
SecondaryLibraryFragment mSecondaryLibraryFragment;
@Override
- public AppCompatActivity getActivity() {
+ public Activity getActivity() {
return this;
}
@@ -32,21 +30,6 @@ public class SecondaryLibraryActivity extends DrawerFragmentActivity implements
return null;
}
- @Override
- public Toolbar initToolBar() {
- return null;
- }
-
- @Override
- public boolean isAddWinBollToolBar() {
- return false;
- }
-
- @Override
- public boolean isEnableDisplayHomeAsUp() {
- return false;
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java
index d79c186..6dcf11d 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java
@@ -13,7 +13,7 @@ import androidx.fragment.app.Fragment;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.views.AButton;
import cc.winboll.studio.libappbase.LogUtils;
-import cc.winboll.studio.libappbase.utils.ToastUtils;
+import com.hjq.toast.ToastUtils;
public class TestAButtonFragment extends Fragment {
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java
index c570bf6..1ba071d 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java
@@ -5,19 +5,27 @@ package cc.winboll.studio.libaes.unittests;
* @Date 2024/07/16 01:14:00
* @Describe TestASupportToolbarActivity
*/
-import android.content.Context;
-import android.content.SharedPreferences;
+import android.app.Activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libaes.R;
-import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
-public class TestASupportToolbarActivity extends AppCompatActivity {
+public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "TestASupportToolbarActivity";
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java
index bdd401c..2aa4f4d 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java
@@ -10,11 +10,22 @@ import android.os.Bundle;
import android.widget.Toolbar;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.utils.AESThemeUtil;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
-public class TestAToolbarActivity extends Activity {
+public class TestAToolbarActivity extends Activity implements IWinBollActivity {
public static final String TAG = "TestAToolbarActivity";
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
AESThemeUtil.applyAppTheme(this);
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java
index 469b047..2646e1c 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java
@@ -4,6 +4,7 @@ package cc.winboll.studio.libaes.unittests;
* @Author ZhanGSKen@QQ.COM
* @Date 2024/06/30 15:00:51
*/
+import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -11,19 +12,18 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.DrawerMenuBean;
-import cc.winboll.studio.libaes.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import java.util.ArrayList;
public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBollActivity {
@Override
- public AppCompatActivity getActivity() {
+ public Activity getActivity() {
return this;
}
@@ -32,22 +32,6 @@ public class TestDrawerFragmentActivity extends DrawerFragmentActivity implement
return null;
}
- @Override
- public Toolbar initToolBar() {
- return null;
- }
-
- @Override
- public boolean isAddWinBollToolBar() {
- return false;
- }
-
- @Override
- public boolean isEnableDisplayHomeAsUp() {
- return false;
- }
-
-
public static final String TAG = "TestDrawerFragmentActivity";
TestFragment1 mTestFragment1;
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java
index 6f17661..a7253c8 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java
@@ -19,7 +19,7 @@ import cc.winboll.studio.libaes.ImagePagerAdapter;
import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.views.AOHPCTCSeekBar;
import cc.winboll.studio.libappbase.LogView;
-import cc.winboll.studio.libappbase.utils.ToastUtils;
+import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
import java.util.List;
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java
new file mode 100644
index 0000000..f684626
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java
@@ -0,0 +1,162 @@
+package cc.winboll.studio.libaes.utils;
+
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2024/08/12 14:45:35
+ * @Describe 应用版本工具集
+ */
+import cc.winboll.studio.libappbase.LogUtils;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AppVersionUtils {
+
+ public static final String TAG = "AppVersionUtils";
+
+ //
+ // 检查新版本是否成立
+ // szCurrentCode : 当前版本应用包名
+ // szNextCode : 新版本应用包名
+ // 返回 :情况1:当前版本是发布版
+ // 返回 true (新版本 > 当前版本)
+ // 情况1:当前版本是Beta版
+ // true 新版本 == 当前版本
+ //
+ public static boolean isHasNewVersion2(String szCurrentName, String szNextName) {
+ LogUtils.d(TAG, String.format("isHasNewVersion2\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
+ //szCurrentName = "AES_6.2.0-beta0_3234.apk";
+ //szNextName = "AES_6.1.12.apk";
+ //szCurrentName = "AES_6.2.0-beta0_3234.apk";
+ //szNextName = "AES_6.2.0.apk";
+ //szCurrentName = "AES_6.2.0-beta0_3234.apk";
+ //szNextName = "AES_6.2.2.apk";
+ //szCurrentName = "AES_6.2.0-beta0_3234.apk";
+ //szNextName = "AES_6.2.0.apk";
+ //szCurrentName = "AES_6.1.0.apk";
+ //szNextName = "AES_6.2.0.apk";
+ //LogUtils.d(TAG, "szCurrentName : " + szCurrentName);
+ //LogUtils.d(TAG, "szNextName : " + szNextName);
+
+ //boolean isVersionNewer = false;
+ //if(szCurrentName.equals(szNextName)) {
+ // isVersionNewer = false;
+ //} else {
+ //ToastUtils.show("szCurrent : " + szCurrent + "\nszNext : " + szNext);
+ //int nApk = szNextName.lastIndexOf(".apk");
+ //ToastUtils.show("nApk : " + Integer.toString(nApk));
+ //String szNextNoApkName = szNextName.substring(0, nApk);
+ //ToastUtils.show("szNextNoApkName : " + szNextNoApkName);
+ //String szCurrentNoApkName = szCurrentName.substring(0, szNextNoApkName.length());
+ //ToastUtils.show("szCurrentNoApkName : " + szCurrentNoApkName);
+ //String str1 = "3.4.50";
+ //String str2 = "3.3.60";
+ //String str1 = getCodeInPackageName(szCurrentName);
+ //String str2 = getCodeInPackageName(szNextName);
+ //String str1 = getCodeInPackageName(szNextName);
+ //String str2 = getCodeInPackageName(szCurrentName);
+ //Boolean isVersionNewer2 = checkNewVersion(str1,str2);
+ //ToastUtils.show("isVersionNewer2 : " + Boolean.toString(isVersionNewer2));
+ //ToastUtils.show(checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName)));
+ //return checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName));
+ //}
+ //return isVersionNewer;
+ if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
+ // 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。
+ // 比 AES_6.2.0-beta0_3234.apk 大,如 AES_6.2.1.apk。
+ //LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName);
+ return true;
+ }
+ if (szCurrentName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) {
+ String szCurrentReleasePackageName = getReleasePackageName(szCurrentName);
+ //LogUtils.d(TAG, "szCurrentReleasePackageName : " + szCurrentReleasePackageName);
+ if (szCurrentReleasePackageName.equals(szNextName)) {
+ // 与 AES_6.2.0-beta0_3234.apk 版本相同,如 AES_6.2.0.apk。
+ //LogUtils.d(TAG, "App stage version is released. Release name : " + szNextName);
+ return true;
+ }
+ }
+ //LogUtils.d(TAG, "App version is the newest. ");
+ return false;
+ }
+
+ public static boolean isHasNewStageReleaseVersion(String szCurrentName, String szNextName) {
+ LogUtils.d(TAG, String.format("isHasNewStageReleaseVersion\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName));
+ //szCurrentName = "AES_6.2.12.apk";
+ //szNextName = "AES_6.3.12.apk";
+ if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) {
+ // 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。
+ //LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName);
+ return true;
+ }
+ return false;
+ }
+
+ //
+ // 检查新版本是否成立
+ // szCurrentCode : 当前版本
+ // szNextCode : 新版本
+ // 返回 :true 新版本 > 当前版本
+ //
+ public static Boolean checkNewVersion(String szCurrentCode, String szNextCode) {
+ if (szCurrentCode == null || szCurrentCode.equals("") || szNextCode == null || szNextCode.equals("")) {
+ LogUtils.d(TAG, String.format("checkNewVersion unexpected parameters:\nszCurrentCode : %s\nszNextCode : %s", szCurrentCode, szNextCode));
+ return false;
+ }
+ boolean isNew = false;
+ String[] appVersionCurrent = szCurrentCode.split("\\.");
+ String[] appVersionNext = szNextCode.split("\\.");
+ //根据位数最短的判断
+ int lim = appVersionCurrent.length > appVersionNext.length ? appVersionNext.length : appVersionCurrent.length;
+ //根据位数循环判断各个版本
+ for (int i = 0; i < lim; i++) {
+ if (Integer.parseInt(appVersionNext[i]) > Integer.parseInt(appVersionCurrent[i])) {
+ isNew = true;
+ return isNew;
+ } else if (Integer.parseInt(appVersionNext[i]) == Integer.parseInt(appVersionCurrent[i])) {
+ continue ;
+ } else {
+ isNew = false;
+ return isNew;
+ }
+ }
+ return isNew;
+ }
+
+ //
+ // 截取应用包名称版本号信息
+ // 如 :AppUtils_7.0.4-beta1_0120.apk 版本号为 7.0.4
+ // 如 :AppUtils_7.0.4.apk 版本号为 7.0.4
+ //
+ public static String getCodeInPackageName(String apkName) {
+ LogUtils.d(TAG, String.format("getCodeInPackageName apkName : %s", apkName));
+ //String apkName = "AppUtils_7.0.0.apk";
+ Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+");
+ Matcher matcher = pattern.matcher(apkName);
+ if (matcher.find()) {
+ String version = matcher.group();
+ LogUtils.d(TAG, String.format("version is %s", version));
+ return version;
+ //System.out.println("Version number: " + version); // 输出:7.0.0
+ }
+ LogUtils.d(TAG, String.format("No result."));
+ return "";
+ }
+
+ //
+ // 根据Beta版名称生成发布版应用包名称
+ // 如 AppUtils_7.0.4-beta1_0120.apk
+ // 发布版名称就为AppUtils_7.0.4.apk
+ //
+ public static String getReleasePackageName(String szBetaPackageName) {
+ //String szBetaPackageName = "AppUtils_7.0.4-beta1_0120.apk";
+ Pattern pattern = Pattern.compile(".*\\d+\\.\\d+\\.\\d+");
+ Matcher matcher = pattern.matcher(szBetaPackageName);
+ if (matcher.find()) {
+ String szReleasePackageName = matcher.group();
+ return szReleasePackageName + ".apk";
+ //System.out.println("Version number: " + version); // 输出:7.0.0
+ }
+ return "";
+ }
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java
index ad894b9..3628113 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java
@@ -17,13 +17,12 @@ import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import cc.winboll.studio.libaes.R;
+import cc.winboll.studio.libaes.utils.AppVersionUtils;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
-import cc.winboll.studio.libappbase.utils.ToastUtils;
-import cc.winboll.studio.libapputils.app.AppVersionUtils;
-import cc.winboll.studio.libapputils.util.PrefUtils;
-import cc.winboll.studio.libapputils.view.WinBollServiceStatusView;
-import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
+import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
+import cc.winboll.studio.libapputils.utils.PrefUtils;
+import com.hjq.toast.ToastUtils;
import java.io.IOException;
import mehdi.sakout.aboutpage.AboutPage;
import mehdi.sakout.aboutpage.Element;
@@ -284,7 +283,7 @@ public class AboutView extends LinearLayout {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
GlobalApplication.setIsDebuging(true);
- WinBollActivityManager.getInstance(context).finishAll();
+ GlobalApplication.getWinBollActivityManager().finishAll();
context.startActivity(intent);
}
}
@@ -295,7 +294,7 @@ public class AboutView extends LinearLayout {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
GlobalApplication.setIsDebuging(false);
- WinBollActivityManager.getInstance(context).finishAll();
+ GlobalApplication.getWinBollActivityManager().finishAll();
context.startActivity(intent);
}
}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AssistantService.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AssistantService.java
new file mode 100644
index 0000000..9f1e48a
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AssistantService.java
@@ -0,0 +1,96 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 19:12:12
+ * @Describe 应用主要服务组件类守护进程服务组件类
+ */
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import cc.winboll.studio.libaes.winboll.WinBollClientService;
+import cc.winboll.studio.libappbase.utils.ServiceUtils;
+
+public class AssistantService extends Service {
+
+ public final static String TAG = "AssistantService";
+
+ WinBollClientServiceBean mWinBollServiceBean;
+ MyServiceConnection mMyServiceConnection;
+ volatile boolean mIsServiceRunning;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
+ if (mMyServiceConnection == null) {
+ mMyServiceConnection = new MyServiceConnection();
+ }
+ // 设置运行参数
+ mIsServiceRunning = false;
+ run();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ run();
+ return START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ mIsServiceRunning = false;
+ super.onDestroy();
+ }
+
+ //
+ // 运行服务内容
+ //
+ void run() {
+ mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
+ if (mWinBollServiceBean.isEnable()) {
+ if (mIsServiceRunning == false) {
+ // 设置运行状态
+ mIsServiceRunning = true;
+ // 唤醒和绑定主进程
+ wakeupAndBindMain();
+ }
+ }
+ }
+
+ //
+ // 唤醒和绑定主进程
+ //
+ void wakeupAndBindMain() {
+ if (ServiceUtils.isServiceRunning(getApplicationContext(), WinBollClientService.class.getName()) == false) {
+ startForegroundService(new Intent(AssistantService.this, WinBollClientService.class));
+ }
+
+ bindService(new Intent(AssistantService.this, WinBollClientService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
+ }
+
+ //
+ // 主进程与守护进程连接时需要用到此类
+ //
+ class MyServiceConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(AssistantService.this);
+ if (mWinBollServiceBean.isEnable()) {
+ wakeupAndBindMain();
+ }
+ }
+ }
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/EWUIStatusIconDrawable.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/EWUIStatusIconDrawable.java
new file mode 100644
index 0000000..3d66468
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/EWUIStatusIconDrawable.java
@@ -0,0 +1,35 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 19:11:27
+ * @Describe WinBoll UI 状态图标枚举
+ */
+import cc.winboll.studio.libaes.R;
+
+public enum EWUIStatusIconDrawable {
+ NORMAL(0),
+ NEWS(1)
+ ;
+
+ static final String TAG = "WUIStatusIconDrawable";
+
+ static String[] _mlistCNName = { "正常", "新的消息" };
+
+ private int value = 0;
+ private EWUIStatusIconDrawable(int value) { //必须是private的,否则编译错误
+ this.value = value;
+ }
+
+ public static int getIconDrawableId(EWUIStatusIconDrawable drawableId) {
+ int res;
+ switch(drawableId){
+ case NEWS :
+ res = R.drawable.ic_winbollbeta;
+ break;
+ default :
+ res = R.drawable.ic_winboll;
+ }
+ return res;
+ }
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollActivity.java
deleted file mode 100644
index d4cb61c..0000000
--- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollActivity.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package cc.winboll.studio.libaes.winboll;
-
-/**
- * @Author ZhanGSKen@AliYun.Com
- * @Date 2025/03/24 08:23:40
- * @Describe WinBoll 活动窗口通用接口
- */
-import android.widget.Toolbar;
-import androidx.appcompat.app.AppCompatActivity;
-
-public interface IWinBollActivity {
-
- public static final String TAG = "IWinBollActivity";
-
- // 获取应用资源上下文
- abstract public AppCompatActivity getActivity();
- abstract public String getTag();
- abstract public Toolbar initToolBar();
- abstract public boolean isEnableDisplayHomeAsUp();
- abstract public boolean isAddWinBollToolBar();
-}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollClientServiceBinder.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollClientServiceBinder.java
new file mode 100644
index 0000000..eaf40d5
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollClientServiceBinder.java
@@ -0,0 +1,17 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 19:08:45
+ * @Describe WinBollService 服务 Binder。
+ */
+import android.graphics.drawable.Drawable;
+
+public interface IWinBollClientServiceBinder {
+
+ public static final String TAG = "IWinBollClientServiceBinder";
+
+ public WinBollClientService getService();
+
+ public Drawable getCurrentStatusIconDrawable();
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/MyActivityLifecycleCallbacks.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/MyActivityLifecycleCallbacks.java
deleted file mode 100644
index 5e928a8..0000000
--- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/MyActivityLifecycleCallbacks.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package cc.winboll.studio.libaes.winboll;
-
-/**
- * @Author ZhanGSKen@AliYun.Com
- * @Date 2025/03/24 08:24:52
- */
-import android.app.Activity;
-import android.app.Application;
-import android.content.Intent;
-import android.os.Bundle;
-import cc.winboll.studio.libappbase.LogUtils;
-import cc.winboll.studio.libappbase.utils.ToastUtils;
-
-public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
-
- public static final String TAG = "MyActivityLifecycleCallbacks";
-
- public String mInfo = "";
-
- public MyActivityLifecycleCallbacks() {
- }
-
- void createActivityeInfo(Activity activity) {
- StringBuilder sb = new StringBuilder();
- Intent receivedIntent = activity.getIntent();
- sb.append("\nCallingActivity : \n");
- if (activity.getCallingActivity() != null) {
- sb.append(activity.getCallingActivity().getPackageName());
- }
- sb.append("\nReceived Intent Package : \n");
- sb.append(receivedIntent.getPackage());
-
- Bundle extras = receivedIntent.getExtras();
- if (extras != null) {
- for (String key : extras.keySet()) {
- sb.append("\nIntentInfo");
- sb.append("\n键: ");
- sb.append(key);
- sb.append(", 值: ");
- sb.append(extras.get(key));
- //Log.d("IntentInfo", "键: " + key + ", 值: " + extras.get(key));
- }
- }
- mInfo = sb.toString();
- //Log.d("IntentInfo", "发送Intent的应用包名: " + senderPackage);
- }
-
- public void showActivityeInfo() {
- ToastUtils.show("ActivityeInfo : " + mInfo);
- LogUtils.d(TAG, "ActivityeInfo : " + mInfo);
- }
-
- @Override
- public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
- // 在这里可以做一些初始化相关的操作,例如记录Activity的创建时间等
- //System.out.println(activity.getLocalClassName() + " was created");
- LogUtils.d(TAG, activity.getLocalClassName() + " was created");
- createActivityeInfo(activity);
- }
-
- @Override
- public void onActivityStarted(Activity activity) {
- //System.out.println(activity.getLocalClassName() + " was started");
- LogUtils.d(TAG, activity.getLocalClassName() + " was started");
- //createActivityeInfo(activity);
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
- //System.out.println(activity.getLocalClassName() + " was resumed");
- LogUtils.d(TAG, activity.getLocalClassName() + " was resumed");
- //createActivityeInfo(activity);
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
- //System.out.println(activity.getLocalClassName() + " was paused");
- LogUtils.d(TAG, activity.getLocalClassName() + " was paused");
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
- //System.out.println(activity.getLocalClassName() + " was stopped");
- LogUtils.d(TAG, activity.getLocalClassName() + " was stopped");
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
- // 可以在这里添加保存状态的自定义逻辑
- }
-
- @Override
- public void onActivityDestroyed(Activity activity) {
- //System.out.println(activity.getLocalClassName() + " was destroyed");
- LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed");
- }
-}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollActivityManager.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollActivityManager.java
deleted file mode 100644
index a975aed..0000000
--- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollActivityManager.java
+++ /dev/null
@@ -1,318 +0,0 @@
-package cc.winboll.studio.libaes.winboll;
-
-/**
- * @Author ZhanGSKen@AliYun.Com
- * @Date 2025/03/24 08:25:43
- * @Describe 应用活动窗口管理器
- * 参考 :
- * android 类似微信小程序多任务窗口 及 设置 TaskDescription 修改 icon 和 label
- * https://blog.csdn.net/qq_29364417/article/details/109379915?app_version=6.4.2&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22109379915%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app
- */
-import android.app.ActivityManager;
-import android.app.TaskStackBuilder;
-import android.content.Context;
-import android.content.Intent;
-import cc.winboll.studio.libappbase.LogUtils;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-public class WinBollActivityManager {
-
- public static final String TAG = "WinBollActivityManager";
- public static final String EXTRA_TAG = "EXTRA_TAG";
-
- public static enum WinBollUI_TYPE {
- Aplication, // 退出应用后,保持最近任务栏任务记录主窗口
- Service // 退出应用后,清理所有最近任务栏任务记录窗口
- };
-
- // 应用类型标志
- volatile static WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
-
- Context mContext;
- MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
- static WinBollActivityManager _mWinBollActivityManager;
- static Map _mapIWinBollList;
- IWinBollActivity firstIWinBollActivity;
-
- public WinBollActivityManager(Context context) {
- mContext = context;
- LogUtils.d(TAG, "WinBollActivityManager()");
- _mapIWinBollList = new HashMap();
- }
-
- public static synchronized WinBollActivityManager getInstance(Context context) {
- LogUtils.d(TAG, "getInstance");
- if (_mWinBollActivityManager == null) {
- LogUtils.d(TAG, "_mWinBollActivityManager == null");
- _mWinBollActivityManager = new WinBollActivityManager(context);
- }
- return _mWinBollActivityManager;
- }
-
- //
- // 设置 WinBoll 应用 UI 类型
- //
- public synchronized static void setWinBollUI_TYPE(WinBollUI_TYPE mWinBollUI_TYPE) {
- _mWinBollUI_TYPE = mWinBollUI_TYPE;
- }
-
- //
- // 获取 WinBoll 应用 UI 类型
- //
- public synchronized static WinBollUI_TYPE getWinBollUI_TYPE() {
- return _mWinBollUI_TYPE;
- }
-
- //
- // 把Activity添加到管理中
- //
- public void add(T iWinBoll) {
- if (isActive(iWinBoll.getTag())) {
- LogUtils.d(TAG, String.format("add(...) %s is active.", iWinBoll.getTag()));
- } else {
- // 设置起始活动窗口,以便最后退出时提问
- if (firstIWinBollActivity == null && _mapIWinBollList.size() == 0) {
- firstIWinBollActivity = iWinBoll;
- }
-
- // 添加到活动窗口列表
- _mapIWinBollList.put(iWinBoll.getTag(), iWinBoll);
- LogUtils.d(TAG, String.format("Add activity : %s\n_mapActivityList.size() : %d", iWinBoll.getTag(), _mapIWinBollList.size()));
- }
- }
-
-
- //
- // activity: 为 null 时,
- // intent.putExtra 函数 EXTRA_TAG 参数为 tag
- // activity: 不为 null 时,
- // intent.putExtra 函数 "tag" 参数为 activity.getTag()
- //
- public void startWinBollActivity(Context context, Class clazz) {
- try {
- // 如果窗口已存在就重启窗口
- String tag = clazz.newInstance().getTag();
- if (isActive(tag)) {
- resumeActivity(context, tag);
- return;
- }
-
- // 新建一个任务窗口
- Intent intent = new Intent(context, clazz);
- //打开多任务窗口 flags
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(EXTRA_TAG, tag);
- mContext.startActivity(intent);
- } catch (InstantiationException | IllegalAccessException e) {
- LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
- }
- }
-
- public void startWinBollActivity(Context context, Intent intent, Class clazz) {
- try {
- // 如果窗口已存在就重启窗口
- String tag = clazz.newInstance().getTag();
- if (isActive(tag)) {
- resumeActivity(context, tag);
- return;
- }
-
- // 新建一个任务窗口
- //Intent intent = new Intent(context, clazz);
- //打开多任务窗口 flags
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(EXTRA_TAG, tag);
- mContext.startActivity(intent);
- } catch (InstantiationException | IllegalAccessException e) {
- LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
- }
- }
-
- public boolean isFirstIWinBollActivity(IWinBollActivity iWinBollActivity) {
- return firstIWinBollActivity != null && firstIWinBollActivity == iWinBollActivity;
- }
-
- //
- // 判断 tag绑定的 MyActivity是否存在
- //
- public boolean isActive(String tag) {
- //printAvtivityListInfo();
- IWinBollActivity iWinBoll = getIWinBoll(tag);
- if (iWinBoll != null) {
- LogUtils.d(TAG, "isActive(...) activity != null tag " + tag);
- //ToastUtils.show("activity != null tag " + tag);
- //判断是否为 BaseActivity,如果已经销毁,则移除
- if (iWinBoll.getActivity().isFinishing() || iWinBoll.getActivity().isDestroyed()) {
- _mapIWinBollList.remove(iWinBoll.getTag());
- //_mWinBollActivityList.remove(activity);
- LogUtils.d(TAG, String.format("isActive(...) remove activity.\ntag : %s", tag));
- return false;
- } else {
- LogUtils.d(TAG, String.format("isActive(...) activity is exist.\ntag : %s", tag));
- return true;
- }
- } else {
- LogUtils.d(TAG, String.format("isActive(...) activity == null\ntag : %s", tag));
- return false;
- }
- }
-
- static IWinBollActivity getIWinBoll(String tag) {
- return _mapIWinBollList.get(tag);
- }
-
- //
- // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
- //
- public void resumeActivity(Context context, String tag) {
- LogUtils.d(TAG, "resumeActivty");
- T iWinBoll = (T)getIWinBoll(tag);
- //LogUtils.d(TAG, "activity " + activity.getTag());
- if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
- resumeActivity(context, iWinBoll);
- }
- }
-
- //
- // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
- //
- public void resumeActivity(Context context, T iWinBoll) {
- ActivityManager am = (ActivityManager) iWinBoll.getActivity().getSystemService(Context.ACTIVITY_SERVICE);
- //返回启动它的根任务(home 或者 MainActivity)
- Intent intent = new Intent(context, iWinBoll.getClass());
- TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
- stackBuilder.addNextIntentWithParentStack(intent);
- stackBuilder.startActivities();
- //moveTaskToFront(YourTaskId, 0);
- LogUtils.d(TAG, "am.moveTaskToFront");
- //ToastUtils.show("resumeActivity am.moveTaskToFront");
- am.moveTaskToFront(iWinBoll.getActivity().getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
- }
-
-
- //
- // 结束所有 Activity
- //
- public void finishAll() {
- try {
- for (String key : _mapIWinBollList.keySet()) {
- //System.out.println("Key: " + key + ", Value: " + _mapActivityList.get(key));
- IWinBollActivity iWinBoll = _mapIWinBollList.get(key);
- //ToastUtils.show("finishAll() activity");
- if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
- //ToastUtils.show("activity != null ...");
- if (getWinBollUI_TYPE() == WinBollUI_TYPE.Service) {
- // 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。
- iWinBoll.getActivity().finishAndRemoveTask();
- //ToastUtils.show("finishAll() activity.finishAndRemoveTask();");
- } else if (getWinBollUI_TYPE() == WinBollUI_TYPE.Aplication) {
- // 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。
- iWinBoll.getActivity().finish();
- //ToastUtils.show("finishAll() activity.finish();");
- } else {
- LogUtils.d(TAG, "WinBollApplication.WinBollUI_TYPE error.");
- //ToastUtils.show("WinBollApplication.WinBollUI_TYPE error.");
- }
- }
- }
- } catch (Exception e) {
- LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
- }
- }
-
- //
- // 结束指定Activity
- //
- public void finish(T iWinBoll) {
- try {
- if (iWinBoll != null && !iWinBoll.getActivity().isFinishing() && !iWinBoll.getActivity().isDestroyed()) {
- //根据tag 移除 MyActivity
- //String tag= activity.getTag();
- //_mWinBollActivityList.remove(tag);
- //ToastUtils.show("remove");
- //ToastUtils.show("_mWinBollActivityArrayMap.size() " + Integer.toString(_mWinBollActivityArrayMap.size()));
-
- // 窗口回调规则:
- // [] 当前窗口位置 >> 调度出的窗口位置
- // ★:[0] 1 2 3 4 >> 1
- // ★:0 1 [2] 3 4 >> 1
- // ★:0 1 2 [3] 4 >> 2
- // ★:0 1 2 3 [4] >> 3
- // ★:[0] >> 直接关闭当前窗口
- LogUtils.d(TAG, "finish no yet.");
- IWinBollActivity preIWinBoll = getPreIWinBoll(iWinBoll);
- iWinBoll.getActivity().finish();
- if (preIWinBoll != null) {
- resumeActivity(mContext, preIWinBoll);
- }
- }
-
- } catch (Exception e) {
- LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
- }
- }
-
- //
- // 获取窗口队列中的前一个窗口
- //
- IWinBollActivity getPreIWinBoll(IWinBollActivity iWinBoll) {
- try {
- boolean bingo = false;
- IWinBollActivity preIWinBoll = null;
- for (Map.Entry entity : _mapIWinBollList.entrySet()) {
- if (entity.getKey().equals(iWinBoll.getTag())) {
- bingo = true;
- LogUtils.d(TAG, "bingo");
- break;
- }
- preIWinBoll = entity.getValue();
- }
-
- if (bingo) {
- return preIWinBoll;
- }
- } catch (Exception e) {
- LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
- }
-
- return null;
- }
-
- //
- // 从管理列表中移除管理项
- //
- public boolean registeRemove(T activity) {
- IWinBollActivity iWinBollTest = _mapIWinBollList.get(activity.getTag());
- if (iWinBollTest != null) {
- _mapIWinBollList.remove(activity.getTag());
- return true;
- }
- return false;
- }
-
- //
- // 打印管理列表项列表里的信息
- //
- public static void printIWinBollListInfo() {
- //LogUtils.d(TAG, "printAvtivityListInfo");
- if (!_mapIWinBollList.isEmpty()) {
- StringBuilder sb = new StringBuilder("Map entries : " + Integer.toString(_mapIWinBollList.size()));
- Iterator> iterator = _mapIWinBollList.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry entry = iterator.next();
- sb.append("\nKey: " + entry.getKey() + ", \nValue: " + entry.getValue().getTag());
- //ToastUtils.show("\nKey: " + entry.getKey() + ", Value: " + entry.getValue().getTag());
- }
- sb.append("\nMap entries end.");
- LogUtils.d(TAG, sb.toString());
- } else {
- LogUtils.d(TAG, "The map is empty.");
- }
- }
-}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollClientService.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollClientService.java
new file mode 100644
index 0000000..54192ca
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollClientService.java
@@ -0,0 +1,190 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 19:06:54
+ * @Describe WinBoll 客户端服务
+ */
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import cc.winboll.studio.libaes.winboll.AssistantService;
+import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.utils.ServiceUtils;
+import com.hjq.toast.ToastUtils;
+
+public class WinBollClientService extends Service implements IWinBollClientServiceBinder {
+
+ public static final String TAG = "WinBollClientService";
+
+ WinBollClientServiceBean mWinBollClientServiceBean;
+ MyServiceConnection mMyServiceConnection;
+ volatile boolean mIsWinBollClientThreadRunning;
+ volatile boolean mIsEnableService;
+ WinBollClientThread mWinBollClientThread;
+
+ public boolean isWinBollClientThreadRunning() {
+ return mIsWinBollClientThreadRunning;
+ }
+
+ @Override
+ public WinBollClientService getService() {
+ return WinBollClientService.this;
+ }
+
+ @Override
+ public Drawable getCurrentStatusIconDrawable() {
+ return mIsWinBollClientThreadRunning ?
+ getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NORMAL))
+ : getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NEWS));
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ ToastUtils.show("onCreate");
+ super.onCreate();
+ mWinBollClientThread = null;
+ mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
+ mIsEnableService = mWinBollClientServiceBean.isEnable();
+
+ if (mMyServiceConnection == null) {
+ mMyServiceConnection = new MyServiceConnection();
+ }
+
+ // 由系统启动时,应用可以通过下面函数实例化实际服务进程。
+ runMainThread();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ ToastUtils.show("onStartCommand");
+ // 由应用 Intent 启动时,应用可以通过下面函数实例化实际服务进程。
+ runMainThread();
+
+ // 返回运行参数持久化存储后,服务状态控制参数
+ // 无论 Intent 传入如何,服务状态一直以持久化存储后的参数控制,
+ // PS: 另外当然可以通过 Intent 传入的指标来修改 mWinBollServiceBean,
+ // 不过本服务的应用方向会变得繁琐,
+ // 现阶段只要满足手机端启动与停止本服务,WinBoll 客户端实例运行在手机端就可以了。
+ return mIsEnableService ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
+ }
+
+ void runMainThread() {
+ if (mWinBollClientThread == null) {
+ ToastUtils.show("runMainThread()");
+ mWinBollClientThread = new WinBollClientThread();
+ mWinBollClientThread.start();
+ }
+ }
+
+ void syncWinBollClientThreadStatus() {
+ mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
+ mIsEnableService = mWinBollClientServiceBean.isEnable();
+ }
+
+
+ // 唤醒和绑定守护进程
+ //
+ void wakeupAndBindAssistant() {
+ if (ServiceUtils.isServiceRunning(getApplicationContext(), AssistantService.class.getName()) == false) {
+ startService(new Intent(WinBollClientService.this, AssistantService.class));
+ //LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService");
+ bindService(new Intent(WinBollClientService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
+ }
+ }
+
+ // 主进程与守护进程连接时需要用到此类
+ //
+ private class MyServiceConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(WinBollClientService.this);
+ if (mWinBollClientServiceBean.isEnable()) {
+ // 唤醒守护进程
+ wakeupAndBindAssistant();
+ }
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ ToastUtils.show("onDestroy");
+ }
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ super.onStart(intent, startId);
+ }
+
+ void setWinBollServiceEnableStatus(boolean isEnable) {
+ WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(this);
+ bean.setIsEnable(isEnable);
+ WinBollClientServiceBean.saveWinBollServiceBean(this, bean);
+ }
+
+ boolean getWinBollServiceEnableStatus(Context context) {
+ mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(context);
+ return mWinBollClientServiceBean.isEnable();
+ }
+
+ /*public interface OnServiceStatusChangeListener {
+ void onServerStatusChange(boolean isServiceAlive);
+ }
+
+ public void setOnServerStatusChangeListener(OnServiceStatusChangeListener l) {
+ mOnServerStatusChangeListener = l;
+ }*/
+
+ class WinBollClientThread extends Thread {
+ @Override
+ public void run() {
+ //ToastUtils.show("WinBollClientThread");
+ super.run();
+ syncWinBollClientThreadStatus();
+ if (mIsEnableService) {
+ if (mIsWinBollClientThreadRunning == false) {
+ // 设置运行状态
+ mIsWinBollClientThreadRunning = true;
+
+ //ToastUtils.show("run()");
+
+ // 唤醒守护进程
+ //wakeupAndBindAssistant();
+
+ while (mIsEnableService) {
+ // 显示运行状态
+ ToastUtils.show(TAG + " is running.");
+ try {
+ Thread.sleep(2 * 1000);
+ } catch (InterruptedException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ syncWinBollClientThreadStatus();
+ //ToastUtils.show("syncServiceThreadStatus OK.");
+ //ToastUtils.show("mIsExist : " + Boolean.toString(!mIsEnableService));
+ //break;
+ }
+
+ // 服务进程退出, 重置进程运行状态
+ mIsWinBollClientThreadRunning = false;
+ mWinBollClientThread = null;
+ }
+ }
+ }
+ }
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollClientServiceBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollClientServiceBean.java
new file mode 100644
index 0000000..271f1e0
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollClientServiceBean.java
@@ -0,0 +1,78 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 19:05:15
+ * @Describe WinBollService 运行参数配置
+ */
+import android.content.Context;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import cc.winboll.studio.libappbase.BaseBean;
+import java.io.IOException;
+
+public class WinBollClientServiceBean extends BaseBean {
+
+ public static final String TAG = "WinBollClientServiceBean";
+
+ volatile boolean isEnable;
+
+ public WinBollClientServiceBean() {
+ isEnable = false;
+ }
+
+ public void setIsEnable(boolean isEnable) {
+ this.isEnable = isEnable;
+ }
+
+ public boolean isEnable() {
+ return isEnable;
+ }
+
+ @Override
+ public String getName() {
+ return WinBollClientServiceBean.class.getName();
+ }
+
+ @Override
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ super.writeThisToJsonWriter(jsonWriter);
+ WinBollClientServiceBean bean = this;
+ jsonWriter.name("isEnable").value(bean.isEnable());
+ }
+
+ @Override
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
+ if (name.equals("isEnable")) {
+ setIsEnable(jsonReader.nextBoolean());
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
+ jsonReader.beginObject();
+ while (jsonReader.hasNext()) {
+ String name = jsonReader.nextName();
+ if (!initObjectsFromJsonReader(jsonReader, name)) {
+ jsonReader.skipValue();
+ }
+ }
+ // 结束 JSON 对象
+ jsonReader.endObject();
+ return this;
+ }
+
+ public static WinBollClientServiceBean loadWinBollClientServiceBean(Context context) {
+ WinBollClientServiceBean bean = WinBollClientServiceBean.loadBean(context, WinBollClientServiceBean.class);
+ return bean == null ? new WinBollClientServiceBean() : bean;
+ }
+
+ public static boolean saveWinBollServiceBean(WinBollClientService service, WinBollClientServiceBean bean) {
+ return WinBollClientServiceBean.saveBean(service, bean);
+ }
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollMail.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollMail.java
new file mode 100644
index 0000000..3806106
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollMail.java
@@ -0,0 +1,22 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 19:13:20
+ * @Describe WinBoll 邮件服务
+ */
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class WinBollMail extends Service {
+
+ public static final String TAG = "WinBollMail";
+
+ @Override
+ public IBinder onBind(Intent intent) {
+
+ return null;
+ }
+
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollServiceStatusView.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollServiceStatusView.java
new file mode 100644
index 0000000..9ec3bf2
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollServiceStatusView.java
@@ -0,0 +1,340 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 17:41:55
+ * @Describe WinBoll 服务主机连接状态视图
+ */
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import cc.winboll.studio.libappbase.LogUtils;
+import com.hjq.toast.ToastUtils;
+import cc.winboll.studio.libapputils.R;
+//import okhttp3.Authenticator;
+//import okhttp3.Credentials;
+//import okhttp3.OkHttpClient;
+//import okhttp3.Request;
+//import okhttp3.Response;
+//import okhttp3.Route;
+
+public class WinBollServiceStatusView extends LinearLayout {
+
+ public static final String TAG = "WinBollServiceStatusView";
+
+ public static final int MSG_CONNECTION_INFO = 0;
+ public static final int MSG_UPDATE_CONNECTION_STATUS = 1;
+
+ Context mContext;
+ //boolean mIsConnected;
+ ConnectionThread mConnectionThread;
+
+ String mszServerHost;
+ WinBollClientService mWinBollService;
+ ImageView mImageView;
+ TextView mTextView;
+ WinBollServiceViewHandler mWinBollServiceViewHandler;
+ //WebView mWebView;
+ static volatile ConnectionStatus mConnectionStatus;
+ View.OnClickListener mViewOnClickListener;
+ static String _mUserName;
+ static String _mPassword;
+
+ static enum ConnectionStatus {
+ DISCONNECTED,
+ START_CONNECT,
+ CONNECTING,
+ CONNECTED;
+ };
+
+ boolean isBound = false;
+ ServiceConnection connection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ IWinBollClientServiceBinder binder = (IWinBollClientServiceBinder) service;
+ mWinBollService = binder.getService();
+ isBound = true;
+ // 可以在这里调用Service的方法进行通信,比如获取数据
+ mImageView.setBackgroundDrawable(mWinBollService.getCurrentStatusIconDrawable());
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ isBound = false;
+ }
+ };
+
+ public WinBollServiceStatusView(Context context) {
+ super(context);
+ mContext = context;
+ initView();
+ }
+
+ public WinBollServiceStatusView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ initView();
+ }
+
+ public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mContext = context;
+ initView();
+ }
+
+ public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mContext = context;
+ initView();
+ }
+
+ ConnectionStatus getConnectionStatus() {
+ return false ?
+ ConnectionStatus.CONNECTED
+ : ConnectionStatus.DISCONNECTED;
+ }
+
+ void initView() {
+ mImageView = new ImageView(mContext);
+ setImageViewByConnection(mImageView, false);
+ mConnectionStatus = getConnectionStatus();
+ //mIsConnected = false;
+ //mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.DISCONNECTED;
+ //ToastUtils.show("initView()");
+
+ mViewOnClickListener = new View.OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ //ToastUtils.show("onClick()");
+ //ToastUtils.show("mWinBollServerHostConnectionStatus : " + mWinBollServerHostConnectionStatus);
+ //isConnected = !isConnected;
+ if (mConnectionStatus == ConnectionStatus.CONNECTED) {
+ ToastUtils.show("Click to stop service.");
+ WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext);
+ bean.setIsEnable(false);
+ WinBollClientServiceBean.saveBean(mContext, bean);
+ Intent intent = new Intent(mContext, WinBollClientService.class);
+ mContext.stopService(intent);
+ mConnectionStatus = ConnectionStatus.DISCONNECTED;
+//
+ /*//ToastUtils.show("CONNECTED");
+ setConnectionStatusView(false);
+ mWinBollServerHostConnectionStatusViewHandler.postMessageText("");
+ if (mConnectionThread != null) {
+ mConnectionThread.mIsExist = true;
+ mConnectionThread = null;
+ mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.DISCONNECTED;
+ ToastUtils.show("WinBoll Server Disconnected.");
+ }*/
+ } else if (mConnectionStatus == ConnectionStatus.DISCONNECTED) {
+ ToastUtils.show("Click to start service.");
+ WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext);
+ bean.setIsEnable(true);
+ WinBollClientServiceBean.saveBean(mContext, bean);
+ Intent intent = new Intent(mContext, WinBollClientService.class);
+ mContext.startService(intent);
+ mConnectionStatus = ConnectionStatus.CONNECTED;
+ ToastUtils.show("startService");
+ /*//ToastUtils.show("DISCONNECTED");
+ setConnectionStatusView(true);
+
+ if (mConnectionThread == null) {
+ ToastUtils.show("mConnectionThread == null");
+ mConnectionThread = new ConnectionThread();
+ mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.START_CONNECT;
+ mConnectionThread.start();
+ }*/
+ } else {
+ ToastUtils.show("Other Click condition.");
+ }
+
+ /*if (isConnected) {
+ mWebView.loadUrl("https://dev.winboll.cc");
+ } else {
+ mWebView.stopLoading();
+ }*/
+ //ToastUtils.show(mDevelopHostConnectionStatus);
+ //LogUtils.d(TAG, "mDevelopHostConnectionStatus : " + mWinBollServerHostConnectionStatus);
+ }
+ };
+ setOnClickListener(mViewOnClickListener);
+ addView(mImageView);
+ mTextView = new TextView(mContext);
+ mWinBollServiceViewHandler = new WinBollServiceViewHandler(this);
+ addView(mTextView);
+ /*mWebView = new WebView(mContext);
+ mWebView.setWebViewClient(new WebViewClient() {
+ @Override
+ public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
+ // 弹出系统基本HTTP验证窗口
+ handler.proceed("username", "password");
+ }
+ });
+ addView(mWebView);*/
+ }
+
+ void checkWinBollServerStatusAndUpdateCurrentView() {
+ LogUtils.d(TAG, "checkWinBollServerStatusAndUpdateCurrentView()");
+ /*if (getConnectionStatus() == ConnectionStatus.CONNECTED) {
+ mConnectionStatus = ConnectionStatus.CONNECTED;
+ } else {
+ mConnectionStatus = ConnectionStatus.DISCONNECTED;
+ }*/
+ }
+
+ public void setServerHost(String szWinBollServerHost) {
+ mszServerHost = szWinBollServerHost;
+ }
+
+ public void setAuthInfo(String username, String password) {
+ _mUserName = username;
+ _mPassword = password;
+ }
+
+ void setImageViewByConnection(ImageView imageView, boolean isConnected) {
+ //mIsConnected = isConnected;
+ // 获取vector drawable
+ Drawable drawable = mContext.getDrawable(isConnected ? R.drawable.ic_dev_connected : R.drawable.ic_dev_disconnected);
+ if (drawable != null) {
+ imageView.setImageDrawable(drawable);
+ }
+ }
+
+ void requestWithBasicAuth(WinBollServiceViewHandler textViewHandler, String targetUrl, final String username, final String password) {
+ // 用户名和密码,替换为实际的认证信息
+ //String username = "your_username";
+ //String password = "your_password";
+
+// OkHttpClient client = new OkHttpClient.Builder()
+// .authenticator(new Authenticator() {
+// @Override
+// public Request authenticate(Route route, Response response) throws IOException {
+// String credential = Credentials.basic(username, password);
+// return response.request().newBuilder()
+// .header("Authorization", credential)
+// .build();
+// }
+// })
+// .build();
+//
+// Request request = new Request.Builder()
+// .url(targetUrl) // 替换为实际要请求的网页地址
+// .build();
+//
+// try {
+// Response response = client.newCall(request).execute();
+// if (response.isSuccessful()) {
+// //System.out.println(response.body().string());
+// //ToastUtils.show("Develop Host Connection IP is : " + response.body().string());
+// // 获取当前时间
+// LocalDateTime now = LocalDateTime.now();
+//
+// // 定义时间格式
+// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
+// // 按照指定格式格式化时间并输出
+// String formattedDateTime = now.format(formatter);
+// //System.out.println(formattedDateTime);
+// textViewHandler.postMessageText("ClientIP<" + formattedDateTime + ">: " + response.body().string());
+// textViewHandler.postMessageConnectionStatus(true);
+// } else {
+// String sz = "请求失败,状态码: " + response.code();
+// setImageViewByConnection(mImageView, false);
+// textViewHandler.postMessageText(sz);
+// textViewHandler.postMessageConnectionStatus(false);
+// LogUtils.d(TAG, sz);
+// }
+// } catch (IOException e) {
+// textViewHandler.postMessageText(e.getMessage());
+// textViewHandler.postMessageConnectionStatus(false);
+// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+// }
+ }
+
+ class WinBollServiceViewHandler extends Handler {
+ WinBollServiceStatusView mDevelopHostConnectionStatusView;
+
+ public WinBollServiceViewHandler(WinBollServiceStatusView view) {
+ mDevelopHostConnectionStatusView = view;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_CONNECTION_INFO) {
+ mDevelopHostConnectionStatusView.mTextView.setText((String)msg.obj);
+ } else if (msg.what == MSG_UPDATE_CONNECTION_STATUS) {
+ mDevelopHostConnectionStatusView.setImageViewByConnection(mImageView, (boolean)msg.obj);
+ mDevelopHostConnectionStatusView.mConnectionStatus = ((boolean)msg.obj) ? ConnectionStatus.CONNECTED : ConnectionStatus.DISCONNECTED;
+ }
+ super.handleMessage(msg);
+ }
+
+ void postMessageText(String szMSG) {
+ Message msg = new Message();
+ msg.what = MSG_CONNECTION_INFO;
+ msg.obj = szMSG;
+ sendMessage(msg);
+ }
+
+ void postMessageConnectionStatus(boolean isConnected) {
+ Message msg = new Message();
+ msg.what = MSG_UPDATE_CONNECTION_STATUS;
+ msg.obj = isConnected;
+ sendMessage(msg);
+ }
+ }
+
+ class ConnectionThread extends Thread {
+
+ public volatile boolean mIsExist;
+
+ //DevelopHostConnectionStatusViewHandler mDevelopHostConnectionStatusViewHandler;
+
+ //public ConnectionThread(DevelopHostConnectionStatusViewHandler developHostConnectionStatusViewHandler) {
+ //mDevelopHostConnectionStatusViewHandler = developHostConnectionStatusViewHandler;
+ //}
+ public ConnectionThread() {
+ mIsExist = false;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ while (mIsExist == false) {
+ if (mConnectionStatus == ConnectionStatus.START_CONNECT) {
+ mConnectionStatus = ConnectionStatus.CONNECTING;
+ ToastUtils.show("WinBoll Server Connection Start.");
+ //LogUtils.d(TAG, "Develop Host Connection Start.");
+ String targetUrl = "https://" + mszServerHost + "/cip/?simple=true"; // 这里替换成你实际要访问的网址
+ requestWithBasicAuth(mWinBollServiceViewHandler, targetUrl, _mUserName, _mPassword);
+ } else if (mConnectionStatus == ConnectionStatus.CONNECTED
+ && mConnectionStatus == ConnectionStatus.DISCONNECTED) {
+ ToastUtils.show("mWinBollServerHostConnectionStatus " + mConnectionStatus);
+ }
+
+ try {
+ Thread.sleep(5 * 1000);
+ } catch (InterruptedException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ //ToastUtils.show("ConnectionThread exit.");
+ LogUtils.d(TAG, "ConnectionThread exit.");
+ }
+ }
+
+ /*WinBollService.OnServiceStatusChangeListener mOnServerStatusChangeListener = new WinBollService.OnServiceStatusChangeListener(){
+ @Override
+ public void onServerStatusChange(boolean isServiceAlive) {
+ }
+ };*/
+}
diff --git a/libaes/src/main/res/layout/view_about_dev.xml b/libaes/src/main/res/layout/view_about_dev.xml
index 1f19c03..629585f 100644
--- a/libaes/src/main/res/layout/view_about_dev.xml
+++ b/libaes/src/main/res/layout/view_about_dev.xml
@@ -53,7 +53,7 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal">
-
diff --git a/libaes/src/main/res/layout/view_about_www.xml b/libaes/src/main/res/layout/view_about_www.xml
index 69c02d9..6cd4e5c 100644
--- a/libaes/src/main/res/layout/view_about_www.xml
+++ b/libaes/src/main/res/layout/view_about_www.xml
@@ -12,7 +12,7 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal">
-