diff --git a/aes/build.properties b/aes/build.properties
index c46a2df..0169943 100644
--- a/aes/build.properties
+++ b/aes/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Mon Mar 24 15:00:52 HKT 2025
+#Mon Mar 24 09:20:58 GMT 2025
stageCount=4
libraryProject=libaes
baseVersion=15.0
publishVersion=15.0.3
-buildCount=0
+buildCount=11
baseBetaVersion=15.0.4
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 578f72d..9a764e2 100644
--- a/aes/src/main/java/cc/winboll/studio/aes/App.java
+++ b/aes/src/main/java/cc/winboll/studio/aes/App.java
@@ -14,7 +14,7 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
- //setIsDebug(BuildConfig.DEBUG);
+ setIsDebuging(BuildConfig.DEBUG);
}
}
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 592e2ef..1438eae 100644
--- a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
+++ b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
@@ -25,37 +25,25 @@ 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.APPInfo;
+import cc.winboll.studio.libaes.winboll.AboutActivityFactory;
import cc.winboll.studio.libaes.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.LogUtils;
-import cc.winboll.studio.libapputils.app.AboutActivityFactory;
-import cc.winboll.studio.libapputils.bean.APPInfo;
import com.a4455jkjh.colorpicker.ColorPickerDialog;
+import com.hjq.toast.ToastUtils;
import java.util.ArrayList;
public class MainActivity extends DrawerFragmentActivity implements IWinBollActivity {
+
public static final String TAG = "MainActivity";
TestAButtonFragment mTestAButtonFragment;
TestViewPageFragment mTestViewPageFragment;
-
+
@Override
- public APPInfo getAppInfo() {
- String szBranchName = "aes";
-
- APPInfo appInfo = AboutActivityFactory.buildDefaultAPPInfo();
- appInfo.setAppName("AES");
- appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
- appInfo.setAppDescription("AES Description");
- appInfo.setAppGitName("APP");
- appInfo.setAppGitOwner("Studio");
- appInfo.setAppGitAPPBranch(szBranchName);
- appInfo.setAppGitAPPSubProjectFolder(szBranchName);
- appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=AES");
- appInfo.setAppAPKName("AES");
- appInfo.setAppAPKFolderName("AES");
- return appInfo;
- //return null;
+ public AppCompatActivity getActivity() {
+ return this;
}
@Override
@@ -214,10 +202,28 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBollActi
startActivity(intent);
}
else if (nItemId == R.id.item_about) {
- AboutActivityFactory.showAboutActivity(this, getAppInfo());
+ onAbout();
return true;
}
return super.onOptionsItemSelected(item);
}
+
+ public void onAbout() {
+ String szBranchName = "aes";
+
+ APPInfo appInfo = AboutActivityFactory.buildDefaultAPPInfo();
+ appInfo.setAppName("AES");
+ appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
+ appInfo.setAppDescription("AES Description");
+ appInfo.setAppGitName("APP");
+ appInfo.setAppGitOwner("Studio");
+ appInfo.setAppGitAPPBranch(szBranchName);
+ appInfo.setAppGitAPPSubProjectFolder(szBranchName);
+ appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=AES");
+ appInfo.setAppAPKName("AES");
+ appInfo.setAppAPKFolderName("AES");
+ AboutActivityFactory.showAboutActivity(this, appInfo);
+ ToastUtils.show("onAbout");
+ }
}
diff --git a/libaes/build.gradle b/libaes/build.gradle
index 39fee28..9be2d4c 100644
--- a/libaes/build.gradle
+++ b/libaes/build.gradle
@@ -43,7 +43,7 @@ dependencies {
// 网络连接类库
api 'com.squareup.okhttp3:okhttp:4.4.1'
// AndroidX 类库
- api 'androidx.appcompat:appcompat:1.0.0'
+ api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0'
@@ -51,5 +51,5 @@ dependencies {
//api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libappbase:15.0.9'
- api 'cc.winboll.studio:libapputils:15.0.12'
+ api 'cc.winboll.studio:libapputils:15.0.15'
}
diff --git a/libaes/build.properties b/libaes/build.properties
index 80f8a87..70bdd0b 100644
--- a/libaes/build.properties
+++ b/libaes/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Mon Mar 24 15:00:41 HKT 2025
+#Mon Mar 24 09:19:18 GMT 2025
stageCount=4
libraryProject=libaes
baseVersion=15.0
publishVersion=15.0.3
-buildCount=0
+buildCount=11
baseBetaVersion=15.0.4
diff --git a/libaes/src/main/AndroidManifest.xml b/libaes/src/main/AndroidManifest.xml
index 74ac142..2d3330c 100644
--- a/libaes/src/main/AndroidManifest.xml
+++ b/libaes/src/main/AndroidManifest.xml
@@ -7,14 +7,14 @@
-
-
-
+
-
+
+
+
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/beans/AESModel.java b/libaes/src/main/java/cc/winboll/studio/libaes/beans/AESModel.java
new file mode 100644
index 0000000..330538e
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/beans/AESModel.java
@@ -0,0 +1,71 @@
+package cc.winboll.studio.libaes.beans;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/24 15:27:16
+ * @Describe AES数据实例化模型
+ */
+import cc.winboll.studio.libappbase.BaseBean;
+import android.util.JsonWriter;
+import java.io.IOException;
+import android.util.JsonReader;
+
+public class AESModel extends BaseBean {
+
+ public static final String TAG = "AESModel";
+
+ boolean isInDebugMode;
+
+ public AESModel() {
+ this.isInDebugMode = false;
+ }
+
+ public AESModel(boolean isInDebugMode) {
+ this.isInDebugMode = isInDebugMode;
+ }
+
+ public void setIsInDebugMode(boolean isInDebugMode) {
+ this.isInDebugMode = isInDebugMode;
+ }
+
+ public boolean isInDebugMode() {
+ return isInDebugMode;
+ }
+
+ @Override
+ public String getName() {
+ return AESModel.class.getName();
+ }
+
+ @Override
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ super.writeThisToJsonWriter(jsonWriter);
+ jsonWriter.name("isInDebugMode").value(isInDebugMode());
+ }
+
+ @Override
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
+ if (name.equals("isInDebugMode")) {
+ setIsInDebugMode(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;
+ }
+}
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 f2fd465..a4d4f8e 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
@@ -4,11 +4,11 @@ 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.libapputils.bean.APPInfo;
-import androidx.appcompat.app.AppCompatActivity;
-import android.widget.Toolbar;
+import cc.winboll.studio.libaes.winboll.APPInfo;
import cc.winboll.studio.libaes.winboll.IWinBollActivity;
/**
@@ -23,8 +23,8 @@ public class SecondaryLibraryActivity extends DrawerFragmentActivity implements
SecondaryLibraryFragment mSecondaryLibraryFragment;
@Override
- public APPInfo getAppInfo() {
- return null;
+ public AppCompatActivity getActivity() {
+ return this;
}
@Override
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 5bc35ad..469b047 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,7 +4,6 @@ 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;
@@ -12,20 +11,20 @@ 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.libapputils.bean.APPInfo;
import java.util.ArrayList;
public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBollActivity {
@Override
- public APPInfo getAppInfo() {
- return null;
+ public AppCompatActivity getActivity() {
+ return this;
}
@Override
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/APPInfo.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/APPInfo.java
new file mode 100644
index 0000000..73c4328
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/APPInfo.java
@@ -0,0 +1,142 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/01/20 14:19:02
+ * @Describe 应用信息类
+ */
+import cc.winboll.studio.libapputils.R;
+import java.io.Serializable;
+
+public class APPInfo implements Serializable {
+
+ public static final String TAG = "APPInfo";
+
+ // 应用名称
+ String appName;
+ // 应用图标
+ int appIcon;
+ // 应用描述
+ String appDescription;
+ // 应用Git仓库地址
+ String appGitName;
+ // 应用Git仓库拥有者
+ String appGitOwner;
+ // 应用Git仓库分支
+ String appGitAPPBranch;
+ // 应用Git仓库子项目文件夹
+ String appGitAPPSubProjectFolder;
+ // 应用主页
+ String appHomePage;
+ // 应用包名称
+ String appAPKName;
+ // 应用包存储文件夹名称
+ String appAPKFolderName;
+
+ public APPInfo(String appName, int appIcon, String appDescription, String appGitName, String appGitOwner, String appGitAPPBranch, String appGitAPPSubProjectFolder, String appHomePage, String appAPKName, String appAPKFolderName) {
+ this.appName = appName;
+ this.appIcon = appIcon;
+ this.appDescription = appDescription;
+ this.appGitName = appGitName;
+ this.appGitOwner = appGitOwner;
+ this.appGitAPPBranch = appGitAPPBranch;
+ this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
+ this.appHomePage = appHomePage;
+ this.appAPKName = appAPKName;
+ this.appAPKFolderName = appAPKFolderName;
+ }
+
+ public APPInfo() {
+ this.appName = "WinBoll-APP";
+ this.appIcon = R.drawable.ic_launcher;
+ this.appDescription = "WinBoll APP";
+ this.appGitName = "APP";
+ this.appGitOwner = "Studio";
+ this.appGitAPPBranch = "app";
+ this.appGitAPPSubProjectFolder = "app";
+ this.appHomePage = "https://www.winboll.cc/studio/details.php?app=APP";
+ this.appAPKName = "APP";
+ this.appAPKFolderName = "APP";
+ }
+
+ public void setAppGitOwner(String appGitOwner) {
+ this.appGitOwner = appGitOwner;
+ }
+
+ public String getAppGitOwner() {
+ return appGitOwner;
+ }
+
+ public void setAppGitAPPBranch(String appGitAPPBranch) {
+ this.appGitAPPBranch = appGitAPPBranch;
+ }
+
+ public String getAppGitAPPBranch() {
+ return appGitAPPBranch;
+ }
+
+ public void setAppGitAPPSubProjectFolder(String appGitAPPSubProjectFolder) {
+ this.appGitAPPSubProjectFolder = appGitAPPSubProjectFolder;
+ }
+
+ public String getAppGitAPPSubProjectFolder() {
+ return appGitAPPSubProjectFolder;
+ }
+
+ public void setAppIcon(int appIcon) {
+ this.appIcon = appIcon;
+ }
+
+ public int getAppIcon() {
+ return appIcon;
+ }
+
+ public void setAppDescription(String appDescription) {
+ this.appDescription = appDescription;
+ }
+
+ public String getAppDescription() {
+ return appDescription;
+ }
+
+ public void setAppAPKFolderName(String appAPKFolderName) {
+ this.appAPKFolderName = appAPKFolderName;
+ }
+
+ public String getAppAPKFolderName() {
+ return appAPKFolderName;
+ }
+
+ public void setAppName(String appName) {
+ this.appName = appName;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public void setAppGitName(String appGitName) {
+ this.appGitName = appGitName;
+ }
+
+ public String getAppGitName() {
+ return appGitName;
+ }
+
+ public void setAppHomePage(String appHomePage) {
+ this.appHomePage = appHomePage;
+ }
+
+ public String getAppHomePage() {
+ return appHomePage;
+ }
+
+ public void setAppAPKName(String appAPKName) {
+ this.appAPKName = appAPKName;
+ }
+
+ public String getAppAPKName() {
+ return appAPKName;
+ }
+}
+
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutActivity.java
new file mode 100644
index 0000000..c245544
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutActivity.java
@@ -0,0 +1,62 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/24 16:39:29
+ * @Describe WinBoll Android 应用介绍窗口
+ */
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.LinearLayout;
+import cc.winboll.studio.libaes.R;
+
+final public class AboutActivity extends Activity {
+
+ public static final String TAG = "AboutActivity";
+
+ public static final String EXTRA_APPINFO = "EXTRA_APPINFO";
+
+ APPInfo mAPPInfo;
+
+ @Override
+ public Context getApplicationContext() {
+ return this;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_about);
+ Intent intent = getIntent();
+ if (intent != null) {
+ mAPPInfo = (APPInfo)intent.getSerializableExtra(EXTRA_APPINFO);
+ }
+ if (mAPPInfo == null) {
+ mAPPInfo = new APPInfo();
+ }
+
+ AboutView aboutView = new AboutView(this, mAPPInfo);
+ LinearLayout llMain = findViewById(R.id.aboutroot_ll);
+ llMain.addView(aboutView);
+
+ //ToastUtils.show(TAG);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.toolbar_winboll_shared_about, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+// if (item.getItemId() == R.id.item_help) {
+// WinBollActivityManager.getInstance(this).startWinBollActivity(this, AssetsHtmlActivity.class);
+// }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutActivityFactory.java b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutActivityFactory.java
new file mode 100644
index 0000000..10b21f5
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutActivityFactory.java
@@ -0,0 +1,54 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/02/06 08:45:23
+ * @Describe 关于活动窗口的介绍窗口工厂
+ */
+
+import android.content.Context;
+import android.content.Intent;
+import cc.winboll.studio.libaes.winboll.AboutActivityFactory;
+
+public class AboutActivityFactory {
+
+ public static final String TAG = "AboutActivityFactory";
+
+ public static APPInfo buildDefaultAPPInfo() {
+ String szBranchName = "";
+
+ APPInfo appInfo = new APPInfo();
+ appInfo.setAppName("APP");
+ appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
+ appInfo.setAppDescription("APP Description");
+ appInfo.setAppGitName("APP");
+ appInfo.setAppGitOwner("Studio");
+ appInfo.setAppGitAPPBranch(szBranchName);
+ appInfo.setAppGitAPPSubProjectFolder(szBranchName);
+ appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=APP");
+ appInfo.setAppAPKName("APP");
+ appInfo.setAppAPKFolderName("APP");
+ return appInfo;
+ }
+
+ public static void showAboutActivity(Context context, APPInfo appInfo) {
+ /*String szPN = ((IWinBollActivity)context).getActivityPackageName();
+ //String szPN = context.getPackageName();
+ String szBranchName = "";
+ if (szPN != null) {
+ //String szPN = "cc.winboll.studio.apputils.beta";
+ String regex = "cc\\.winboll\\.studio\\.([^.]+)\\.*";
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(szPN);
+ if (matcher.find()) {
+ szBranchName = matcher.group(1);
+ }
+ }*/
+ //ToastUtils.show(szPN);
+
+ Intent intent = new Intent(context, AboutActivity.class);
+ intent.putExtra(AboutActivity.EXTRA_APPINFO, (appInfo == null) ? AboutActivityFactory.buildDefaultAPPInfo():appInfo);
+ context.startActivity(intent);
+ //WinBollActivityManager.getInstance(context).startWinBollActivity(context, intent, AboutActivity.class);
+ }
+}
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
new file mode 100644
index 0000000..d4c38b3
--- /dev/null
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/AboutView.java
@@ -0,0 +1,391 @@
+package cc.winboll.studio.libaes.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/24 15:08:52
+ * @Describe WinBoll应用介绍视图
+ */
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.net.Uri;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import cc.winboll.studio.libaes.R;
+import cc.winboll.studio.libaes.beans.AESModel;
+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 java.io.IOException;
+import mehdi.sakout.aboutpage.AboutPage;
+import mehdi.sakout.aboutpage.Element;
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Credentials;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class AboutView extends LinearLayout {
+
+ public static final String TAG = "AboutView";
+
+ public static final int MSG_APPUPDATE_CHECKED = 0;
+
+ Context mContext;
+ APPInfo mAPPInfo;
+
+ WinBollServiceStatusView mWinBollServiceStatusView;
+ OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener;
+ String mszAppName = "";
+ String mszAppAPKFolderName = "";
+ String mszAppAPKName = "";
+ String mszAppGitName = "";
+ String mszAppVersionName = "";
+ String mszCurrentAppPackageName = "";
+ volatile String mszNewestAppPackageName = "";
+ String mszAppDescription = "";
+ String mszHomePage = "";
+ String mszGitea = "";
+ int mnAppIcon = 0;
+ String mszWinBollServerHost;
+ String mszReleaseAPKName;
+ EditText metDevUserName;
+ EditText metDevUserPassword;
+
+ public AboutView(Context context, APPInfo appInfo) {
+ super(context);
+ mContext = context;
+
+ setAPPInfo(appInfo);
+ initView(context);
+ }
+
+ public AboutView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+
+ initView(context, attrs);
+ }
+
+ public void setAPPInfo(APPInfo appInfo) {
+ mAPPInfo = appInfo;
+ }
+
+ APPInfo createAppInfo(Context context, AttributeSet attrs) {
+ APPInfo appInfo = new APPInfo();
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AboutView);
+ appInfo.setAppName(typedArray.getString(R.styleable.AboutView_app_name));
+ appInfo.setAppAPKFolderName(typedArray.getString(R.styleable.AboutView_app_apkfoldername));
+ appInfo.setAppAPKName(typedArray.getString(R.styleable.AboutView_app_apkname));
+ appInfo.setAppGitName(typedArray.getString(R.styleable.AboutView_app_gitname));
+ appInfo.setAppGitOwner(typedArray.getString(R.styleable.AboutView_app_gitowner));
+ appInfo.setAppGitAPPBranch(typedArray.getString(R.styleable.AboutView_app_gitappbranch));
+ appInfo.setAppGitAPPSubProjectFolder(typedArray.getString(R.styleable.AboutView_app_gitappsubprojectfolder));
+ appInfo.setAppDescription(typedArray.getString(R.styleable.AboutView_appdescription));
+ appInfo.setAppIcon(typedArray.getResourceId(R.styleable.AboutView_appicon, R.drawable.ic_winboll));
+ // 返回一个绑定资源结束的信号给资源
+ typedArray.recycle();
+ return appInfo;
+ }
+
+ void initView(Context context) {
+ mszAppName = mAPPInfo.getAppName();
+ mszAppAPKFolderName = mAPPInfo.getAppAPKFolderName();
+ mszAppAPKName = mAPPInfo.getAppAPKName();
+ mszAppGitName = mAPPInfo.getAppGitName();
+ mszAppDescription = mAPPInfo.getAppDescription();
+ mnAppIcon = mAPPInfo.getAppIcon();
+
+ mszWinBollServerHost = GlobalApplication.isDebuging() ? "https://dev.winboll.cc": "https://www.winboll.cc";
+
+ try {
+ mszAppVersionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ mszCurrentAppPackageName = mszAppAPKName + "_" + mszAppVersionName + ".apk";
+ mszHomePage = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
+ if (mAPPInfo.getAppGitAPPBranch().equals("")) {
+ mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName;
+ } else {
+ mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName + "/src/branch/" + mAPPInfo.getAppGitAPPBranch() + "/" + mAPPInfo.getAppGitAPPSubProjectFolder();
+ }
+
+ if (GlobalApplication.isDebuging()) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View addedView = inflater.inflate(R.layout.view_about_dev, this, false);
+ LinearLayout llMain = addedView.findViewById(R.id.viewaboutdevLinearLayout1);
+ metDevUserName = addedView.findViewById(R.id.viewaboutdevEditText1);
+ metDevUserPassword = addedView.findViewById(R.id.viewaboutdevEditText2);
+ metDevUserName.setText(PrefUtils.getString(mContext, "metDevUserName", ""));
+ metDevUserPassword.setText(PrefUtils.getString(mContext, "metDevUserPassword", ""));
+ //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
+ mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutdevWinBollServiceStatusView1);
+ mWinBollServiceStatusView.setServerHost(mszWinBollServerHost);
+ mWinBollServiceStatusView.setAuthInfo(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
+ //llMain.addView(mDevelopHostConnectionStatusView);
+ llMain.addView(createAboutPage());
+ addView(addedView);
+ } else {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View addedView = inflater.inflate(R.layout.view_about_www, this, false);
+ LinearLayout llMain = addedView.findViewById(R.id.viewaboutwwwLinearLayout1);
+ //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
+ mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutwwwWinBollServiceStatusView1);
+ mWinBollServiceStatusView.setServerHost(mszWinBollServerHost);
+ mWinBollServiceStatusView.setAuthInfo("", "");
+ //llMain.addView(mDevelopHostConnectionStatusView);
+ llMain.addView(createAboutPage());
+ addView(addedView);
+ }
+
+ // 初始化标题栏
+ //setSubtitle(getContext().getString(R.string.text_about));
+
+// LinearLayout llMain = findViewById(R.id.viewaboutLinearLayout1);
+// llMain.addView(createAboutPage());
+
+ // 就读取正式版应用包版本号,设置 Release 应用包文件名
+ String szReleaseAppVersionName = "";
+ try {
+ //LogUtils.d(TAG, String.format("mContext.getPackageName() %s", mContext.getPackageName()));
+ String szSubBetaSuffix = subBetaSuffix(mContext.getPackageName());
+ //LogUtils.d(TAG, String.format("szSubBetaSuffix : %s", szSubBetaSuffix));
+ szReleaseAppVersionName = mContext.getPackageManager().getPackageInfo(szSubBetaSuffix, 0).versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ mszReleaseAPKName = mszAppAPKName + "_" + szReleaseAppVersionName + ".apk";
+
+ }
+
+ void initView(Context context, AttributeSet attrs) {
+ mAPPInfo = createAppInfo(context, attrs);
+ initView(context);
+ }
+
+ public static String subBetaSuffix(String input) {
+ if (input.endsWith(".beta")) {
+ return input.substring(0, input.length() - ".beta".length());
+ }
+ return input;
+ }
+
+ android.os.Handler mHandler = new android.os.Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case MSG_APPUPDATE_CHECKED : {
+ /*//检查当前应用包文件名是否是测试版,如果是就忽略检查
+ if(mszCurrentAppPackageName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) {
+ ToastUtils.show("APP is the beta Version. Version check ignore.");
+ return;
+ }*/
+
+// if (!AppVersionUtils.isHasNewStageReleaseVersion(mszReleaseAPKName, mszNewestAppPackageName)) {
+// ToastUtils.delayedShow("Current app is the newest.", 5000);
+// }
+ if (!AppVersionUtils.isHasNewVersion2(mszCurrentAppPackageName, mszNewestAppPackageName)) {
+ ToastUtils.show("Current app is the newest.");
+ } else {
+ String szMsg = "Current app is :\n[ " + mszCurrentAppPackageName
+ + " ]\nThe last app is :\n[ " + mszNewestAppPackageName
+ + " ]\nIs download the last app?";
+ YesNoAlertDialog.show(mContext, "Application Update Prompt", szMsg, mIsDownlaodUpdateListener);
+ }
+ break;
+ }
+ }
+ }
+ };
+
+ protected View createAboutPage() {
+ // 定义应用调试按钮
+ //
+ Element elementAppMode;
+ if (GlobalApplication.isDebuging()) {
+ elementAppMode = new Element(mContext.getString(R.string.app_normal), R.drawable.ic_winboll);
+ elementAppMode.setOnClickListener(mAppNormalOnClickListener);
+ } else {
+ elementAppMode = new Element(mContext.getString(R.string.app_debug), R.drawable.ic_winboll);
+ elementAppMode.setOnClickListener(mAppDebugOnClickListener);
+ }
+ // 定义 GitWeb 按钮
+ //
+ Element elementGitWeb = new Element(mContext.getString(R.string.gitea_home), R.drawable.ic_winboll);
+ elementGitWeb.setOnClickListener(mGitWebOnClickListener);
+ // 定义检查更新按钮
+ //
+ Element elementAppUpdate = new Element(mContext.getString(R.string.app_update), R.drawable.ic_winboll);
+ elementAppUpdate.setOnClickListener(mAppUpdateOnClickListener);
+
+ String szAppInfo = "";
+ try {
+ szAppInfo = mszAppName + " "
+ + mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName
+ + "\n" + mszAppDescription;
+ } catch (PackageManager.NameNotFoundException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ View aboutPage = new AboutPage(mContext)
+ .setDescription(szAppInfo)
+ //.isRTL(false)
+ //.setCustomFont(String) // or Typeface
+ .setImage(mnAppIcon)
+ //.addItem(versionElement)
+ //.addItem(adsElement)
+ //.addGroup("Connect with us")
+ .addEmail("ZhanGSKen@AliYun.Com")
+ .addWebsite(mszHomePage)
+ .addItem(elementAppMode)
+ .addItem(elementGitWeb)
+ .addItem(elementAppUpdate)
+ //.addFacebook("the.medy")
+ //.addTwitter("medyo80")
+ //.addYoutube("UCdPQtdWIsg7_pi4mrRu46vA")
+ //.addPlayStore("com.ideashower.readitlater.pro")
+ //.addGitHub("medyo")
+ //.addInstagram("medyo80")
+ .create();
+ return aboutPage;
+ }
+
+ View.OnClickListener mAppDebugOnClickListener = new View.OnClickListener(){
+ @Override
+ public void onClick(View view) {
+ setApp2DebugMode(mContext);
+ }
+ };
+
+ View.OnClickListener mAppNormalOnClickListener = new View.OnClickListener(){
+ @Override
+ public void onClick(View view) {
+ setApp2NormalMode(mContext);
+ }
+ };
+
+ public static void setApp2DebugMode(Context context) {
+ Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
+ if (intent != null) {
+ intent.setAction(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ GlobalApplication.setIsDebuging(context, true);
+ AESModel.saveBean(context, new AESModel(true));
+
+ WinBollActivityManager.getInstance(context).finishAll();
+ context.startActivity(intent);
+ }
+ }
+
+ public static void setApp2NormalMode(Context context) {
+ Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
+ if (intent != null) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ GlobalApplication.setIsDebuging(context, false);
+ AESModel.saveBean(context, new AESModel(false));
+
+ WinBollActivityManager.getInstance(context).finishAll();
+ context.startActivity(intent);
+ }
+ }
+
+ View.OnClickListener mGitWebOnClickListener = new View.OnClickListener(){
+ @Override
+ public void onClick(View view) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mszGitea));
+ mContext.startActivity(browserIntent);
+ }
+ };
+
+ View.OnClickListener mAppUpdateOnClickListener = new View.OnClickListener(){
+ @Override
+ public void onClick(View view) {
+ ToastUtils.show("Start app update checking.");
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ String szUrl = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
+ // 构建包含认证信息的请求
+ String credential = "";
+ if (GlobalApplication.isDebuging()) {
+ credential = Credentials.basic(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
+ PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString());
+ PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString());
+ }
+ OkHttpClient client = new OkHttpClient();
+ Request request = new Request.Builder()
+ .url(szUrl)
+ .header("Accept", "text/plain") // 设置正确的Content-Type头
+ .header("Authorization", credential)
+ .build();
+ Call call = client.newCall(request);
+ call.enqueue(new Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ // 处理网络请求失败
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) throws IOException {
+ if (!response.isSuccessful()) {
+ LogUtils.d(TAG, "Unexpected code " + response, Thread.currentThread().getStackTrace());
+ return;
+ }
+
+ try {
+ // 读取响应体作为字符串,注意这里可能需要解码
+ String text = response.body().string();
+ org.jsoup.nodes.Document doc = org.jsoup.Jsoup.parse(text);
+ LogUtils.v(TAG, doc.text());
+
+ // 使用id选择器找到具有特定id的元素
+ org.jsoup.nodes.Element elementWithId = doc.select("#LastRelease").first(); // 获取第一个匹配的元素
+
+ // 提取并打印元素的文本内容
+ mszNewestAppPackageName = elementWithId.text();
+ //ToastUtils.delayedShow(text + "\n" + mszNewestAppPackageName, 5000);
+
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_APPUPDATE_CHECKED));
+ } catch (Exception e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+ });
+ }
+ }).start();
+ }
+ };
+
+ YesNoAlertDialog.OnDialogResultListener mIsDownlaodUpdateListener = new YesNoAlertDialog.OnDialogResultListener() {
+ @Override
+ public void onYes() {
+ String szUrl = mszWinBollServerHost + "/studio/download.php?appname=" + mszAppAPKFolderName + "&apkname=" + mszNewestAppPackageName;
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(szUrl));
+ mContext.startActivity(browserIntent);
+ }
+
+ @Override
+ public void onNo() {
+ }
+ };
+
+ public interface OnRequestDevUserInfoAutofillListener {
+ void requestAutofill(EditText etDevUserName, EditText etDevUserPassword);
+ }
+
+ public void setOnRequestDevUserInfoAutofillListener(OnRequestDevUserInfoAutofillListener l) {
+ mOnRequestDevUserInfoAutofillListener = l;
+ }
+}
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
index 33cbc6d..d4cb61c 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollActivity.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/IWinBollActivity.java
@@ -5,17 +5,15 @@ package cc.winboll.studio.libaes.winboll;
* @Date 2025/03/24 08:23:40
* @Describe WinBoll 活动窗口通用接口
*/
-import android.content.Context;
import android.widget.Toolbar;
-import cc.winboll.studio.libapputils.bean.APPInfo;
+import androidx.appcompat.app.AppCompatActivity;
public interface IWinBollActivity {
public static final String TAG = "IWinBollActivity";
// 获取应用资源上下文
- abstract public Context getApplicationContext();
- abstract public APPInfo getAppInfo();
+ abstract public AppCompatActivity getActivity();
abstract public String getTag();
abstract public Toolbar initToolBar();
abstract public boolean isEnableDisplayHomeAsUp();
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
index 3e78f6d..a975aed 100644
--- a/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollActivityManager.java
+++ b/libaes/src/main/java/cc/winboll/studio/libaes/winboll/WinBollActivityManager.java
@@ -19,300 +19,300 @@ 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.");
-// }
-// }
+ 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/res/layout/activity_about.xml b/libaes/src/main/res/layout/activity_about.xml
new file mode 100644
index 0000000..540c689
--- /dev/null
+++ b/libaes/src/main/res/layout/activity_about.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libaes/src/main/res/layout/view_about_dev.xml b/libaes/src/main/res/layout/view_about_dev.xml
new file mode 100644
index 0000000..1f19c03
--- /dev/null
+++ b/libaes/src/main/res/layout/view_about_dev.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libaes/src/main/res/layout/view_about_www.xml b/libaes/src/main/res/layout/view_about_www.xml
new file mode 100644
index 0000000..69c02d9
--- /dev/null
+++ b/libaes/src/main/res/layout/view_about_www.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+