diff --git a/aes/build.gradle b/aes/build.gradle
index c6a3a6c..13025d9 100644
--- a/aes/build.gradle
+++ b/aes/build.gradle
@@ -19,17 +19,17 @@ def genVersionName(def versionName){
android {
compileSdkVersion 32
- buildToolsVersion "33.0.3"
+ buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.aes"
minSdkVersion 24
- targetSdkVersion 30
+ targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
// 项目模块目录的 build.gradle 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
- versionName "7.6"
+ versionName "15.2"
if(true) {
versionName = genVersionName("${versionName}")
}
@@ -41,29 +41,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
- }
}
dependencies {
api project(':libaes')
-
- //api 'cc.winboll.studio:winboll-shared:1.6.5'
- api 'io.github.medyo:android-about-page:2.0.0'
- api 'com.github.getActivity:ToastUtils:10.5'
- api 'com.jcraft:jsch:0.1.55'
- api 'org.jsoup:jsoup:1.13.1'
- api 'com.squareup.okhttp3:okhttp:4.4.1'
-
- api 'androidx.appcompat:appcompat:1.0.0'
- api 'androidx.fragment:fragment:1.0.0'
- api 'com.google.android.material:material:1.0.0'
-
- api 'cc.winboll.studio:libapputils:9.2.1'
- api 'cc.winboll.studio:libappbase:1.0.3'
-
api fileTree(dir: 'libs', include: ['*.jar'])
}
diff --git a/aes/build.properties b/aes/build.properties
index 69caa9a..e14ab66 100644
--- a/aes/build.properties
+++ b/aes/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Sun Jan 19 04:58:59 GMT 2025
-stageCount=3
+#Mon Mar 31 02:04:47 HKT 2025
+stageCount=4
libraryProject=libaes
-baseVersion=7.6
-publishVersion=7.6.2
-buildCount=4
-baseBetaVersion=7.6.3
+baseVersion=15.2
+publishVersion=15.2.3
+buildCount=0
+baseBetaVersion=15.2.4
diff --git a/aes/src/main/AndroidManifest.xml b/aes/src/main/AndroidManifest.xml
index cc00d93..d123b21 100644
--- a/aes/src/main/AndroidManifest.xml
+++ b/aes/src/main/AndroidManifest.xml
@@ -8,9 +8,10 @@
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
- android:theme="@style/WinBoll.SupportThemeNoActionBar"
+ android:theme="@style/MyAESTheme"
android:requestLegacyExternalStorage="true"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:networkSecurityConfig="@xml/network_security_config">
+
+
diff --git a/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java
new file mode 100644
index 0000000..208327c
--- /dev/null
+++ b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java
@@ -0,0 +1,91 @@
+package cc.winboll.studio.aes;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @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.LinearLayout;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+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;
+
+public class AboutActivity extends WinBollActivity implements IWinBollActivity {
+
+ public static final String TAG = "AboutActivity";
+
+ Context mContext;
+ Toolbar mToolbar;
+
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = this;
+ setContentView(R.layout.activity_about);
+
+ mToolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(mToolbar);
+ mToolbar.setSubtitle(TAG);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ AboutView aboutView = CreateAboutView();
+ // 在 Activity 的 onCreate 或其他生命周期方法中调用
+// LinearLayout layout = new LinearLayout(this);
+// layout.setOrientation(LinearLayout.VERTICAL);
+// // 创建布局参数(宽度和高度)
+// ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+// ViewGroup.LayoutParams.MATCH_PARENT,
+// ViewGroup.LayoutParams.MATCH_PARENT
+// );
+// addContentView(aboutView, params);
+
+ LinearLayout layout = findViewById(R.id.aboutviewroot_ll);
+ // 创建布局参数(宽度和高度)
+ ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ );
+ layout.addView(aboutView, params);
+
+ GlobalApplication.getWinBollActivityManager().add(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ GlobalApplication.getWinBollActivityManager().registeRemove(this);
+ }
+
+ public AboutView CreateAboutView() {
+ String szBranchName = "aes";
+ APPInfo appInfo = new APPInfo();
+ appInfo.setAppName("AES");
+ appInfo.setAppIcon(cc.winboll.studio.libaes.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 new AboutView(mContext, appInfo);
+ }
+}
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..2eefe56 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,7 +16,8 @@ public class App extends GlobalApplication {
@Override
public void onCreate() {
super.onCreate();
- //setIsDebug(BuildConfig.DEBUG);
+ 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 cafaf1e..7d76e83 100644
--- a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
+++ b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java
@@ -5,12 +5,193 @@ package cc.winboll.studio.aes;
* @Date 2024/06/13 19:05:52
* @Describe 应用主窗口
*/
-import cc.winboll.studio.libaes.unittests.LibraryActivity;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Toast;
+import cc.winboll.studio.aes.R;
+import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
+import cc.winboll.studio.libaes.beans.DrawerMenuBean;
+import cc.winboll.studio.libaes.dialogs.LocalFileSelectDialog;
+import cc.winboll.studio.libaes.dialogs.StoragePathDialog;
+import cc.winboll.studio.libaes.unittests.SecondaryLibraryActivity;
+import cc.winboll.studio.libaes.unittests.TestAButtonFragment;
+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.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 {
+
-public class MainActivity extends LibraryActivity {
-
public static final String TAG = "MainActivity";
+
+ TestAButtonFragment mTestAButtonFragment;
+ TestViewPageFragment mTestViewPageFragment;
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (mTestAButtonFragment == null) {
+ mTestAButtonFragment = new TestAButtonFragment();
+ addFragment(mTestAButtonFragment);
+ }
+ showFragment(mTestAButtonFragment);
+ //setSubtitle(TAG);
+ //ToastUtils.show("onCreate");
+ }
+
+ @Override
+ public void initDrawerMenuItemList(ArrayList listDrawerMenu) {
+ super.initDrawerMenuItemList(listDrawerMenu);
+ LogUtils.d(TAG, "initDrawerMenuItemList");
+ //listDrawerMenu.clear();
+ // 添加抽屉菜单项
+ listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestAButtonFragment.TAG));
+ listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestViewPageFragment.TAG));
+ notifyDrawerMenuDataChanged();
+ }
+
+ @Override
+ public void reinitDrawerMenuItemList(ArrayList listDrawerMenu) {
+ super.reinitDrawerMenuItemList(listDrawerMenu);
+ LogUtils.d(TAG, "reinitDrawerMenuItemList");
+ //listDrawerMenu.clear();
+ // 添加抽屉菜单项
+ listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestAButtonFragment.TAG));
+ listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestViewPageFragment.TAG));
+ notifyDrawerMenuDataChanged();
+ }
+
+ @Override
+ public DrawerFragmentActivity.ActivityType initActivityType() {
+ return DrawerFragmentActivity.ActivityType.Main;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.toolbar_library, menu);
+ if(App.isDebuging()) {
+ getMenuInflater().inflate(cc.winboll.studio.libapputils.R.menu.toolbar_studio_debug, menu);
+ }
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ super.onItemClick(parent, view, position, id);
+ switch (position) {
+ case 0 : {
+ if (mTestAButtonFragment == null) {
+ mTestAButtonFragment = new TestAButtonFragment();
+ addFragment(mTestAButtonFragment);
+ }
+ showFragment(mTestAButtonFragment);
+ break;
+ }
+ case 1 : {
+ if (mTestViewPageFragment == null) {
+ mTestViewPageFragment = new TestViewPageFragment();
+ addFragment(mTestViewPageFragment);
+ }
+ showFragment(mTestViewPageFragment);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int nItemId = item.getItemId();
+// if (item.getItemId() == R.id.item_log) {
+// WinBollActivityManager.getInstance(this).startWinBollActivity(getApplicationContext(), LogActivity.class);
+// } else
+ if (nItemId == R.id.item_atoast) {
+ Toast.makeText(getApplication(), "item_testatoast", Toast.LENGTH_SHORT).show();
+ } else if (nItemId == R.id.item_atoolbar) {
+ Intent intent = new Intent(this, TestAToolbarActivity.class);
+ startActivity(intent);
+
+ } else if (nItemId == R.id.item_asupporttoolbar) {
+ Intent intent = new Intent(this, TestASupportToolbarActivity.class);
+ startActivity(intent);
+
+ } else if (nItemId == R.id.item_colordialog) {
+ ColorPickerDialog dlg = new ColorPickerDialog(this, getResources().getColor(R.color.colorPrimary));
+ dlg.setOnColorChangedListener(new com.a4455jkjh.colorpicker.view.OnColorChangedListener() {
+
+ @Override
+ public void beforeColorChanged() {
+ }
+
+ @Override
+ public void onColorChanged(int color) {
+
+ }
+
+ @Override
+ public void afterColorChanged() {
+ }
+
+
+ });
+ dlg.show();
+
+ } else if (nItemId == R.id.item_dialogstoragepath) {
+ final StoragePathDialog dialog = new StoragePathDialog(this, 0);
+ dialog.setOnOKClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ }
+ });
+ dialog.show();
+
+ } else if (nItemId == R.id.item_localfileselectdialog) {
+ final LocalFileSelectDialog dialog = new LocalFileSelectDialog(this);
+ dialog.setOnOKClickListener(new LocalFileSelectDialog.OKClickListener() {
+ @Override
+ public void onOKClick(String sz) {
+ Toast.makeText(getApplication(), sz, Toast.LENGTH_SHORT).show();
+ //dialog.dismiss();
+ }
+ });
+ dialog.open();
+
+ } else if (nItemId == R.id.item_secondarylibraryactivity) {
+ Intent intent = new Intent(this, SecondaryLibraryActivity.class);
+ startActivity(intent);
+ } else if (nItemId == R.id.item_drawerfragmentactivity) {
+ Intent intent = new Intent(this, TestDrawerFragmentActivity.class);
+ startActivity(intent);
+ }
+ else if (nItemId == R.id.item_about) {
+ Intent intent = new Intent(this, AboutActivity.class);
+ startActivity(intent);
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
}
diff --git a/aes/src/main/java/cc/winboll/studio/aes/WinBollActivity.java b/aes/src/main/java/cc/winboll/studio/aes/WinBollActivity.java
new file mode 100644
index 0000000..a57c782
--- /dev/null
+++ b/aes/src/main/java/cc/winboll/studio/aes/WinBollActivity.java
@@ -0,0 +1,50 @@
+package cc.winboll.studio.aes;
+
+import android.app.Activity;
+import android.os.Bundle;
+import androidx.appcompat.app.AppCompatActivity;
+import cc.winboll.studio.libaes.beans.AESThemeBean;
+import cc.winboll.studio.libaes.utils.AESThemeUtil;
+import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/30 00:34:02
+ * @Describe WinBoll 活动窗口通用基类
+ */
+public class WinBollActivity extends AppCompatActivity implements IWinBollActivity {
+
+ public static final String TAG = "WinBollActivity";
+
+ protected volatile AESThemeBean.ThemeType mThemeType;
+
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ mThemeType = getThemeType();
+ setThemeStyle();
+ super.onCreate(savedInstanceState);
+ }
+
+ AESThemeBean.ThemeType getThemeType() {
+ /*SharedPreferences sharedPreferences = getSharedPreferences(
+ SHAREDPREFERENCES_NAME, MODE_PRIVATE);
+ return AESThemeBean.ThemeType.values()[((sharedPreferences.getInt(DRAWER_THEME_TYPE, AESThemeBean.ThemeType.DEFAULT.ordinal())))];
+ */
+ return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(getApplicationContext()));
+ }
+
+ void setThemeStyle() {
+ //setTheme(AESThemeBean.getThemeStyle(getThemeType()));
+ setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
+ }
+}
diff --git a/aes/src/main/res/layout/activity_about.xml b/aes/src/main/res/layout/activity_about.xml
new file mode 100644
index 0000000..3de4825
--- /dev/null
+++ b/aes/src/main/res/layout/activity_about.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
diff --git a/libaes/src/main/res/menu/toolbar_library.xml b/aes/src/main/res/menu/toolbar_library.xml
similarity index 99%
rename from libaes/src/main/res/menu/toolbar_library.xml
rename to aes/src/main/res/menu/toolbar_library.xml
index d01cea5..b12aef8 100644
--- a/libaes/src/main/res/menu/toolbar_library.xml
+++ b/aes/src/main/res/menu/toolbar_library.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/aes/src/main/res/values/colors.xml b/aes/src/main/res/values/colors.xml
new file mode 100644
index 0000000..87d3836
--- /dev/null
+++ b/aes/src/main/res/values/colors.xml
@@ -0,0 +1,7 @@
+
+
+ #FF00B322
+ #FF005C12
+ #FF8DFFA2
+ #FFFFFB8D
+
diff --git a/aes/src/main/res/values/styles.xml b/aes/src/main/res/values/styles.xml
index c5c6ef3..1da88ba 100644
--- a/aes/src/main/res/values/styles.xml
+++ b/aes/src/main/res/values/styles.xml
@@ -1,5 +1,5 @@
-
diff --git a/aes/src/main/res/xml/network_security_config.xml b/aes/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000..ee39aa4
--- /dev/null
+++ b/aes/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,6 @@
+
+
+
+ winboll.cc
+
+
diff --git a/androiddemo/build.gradle b/androiddemo/build.gradle
index 8357611..1ac4156 100644
--- a/androiddemo/build.gradle
+++ b/androiddemo/build.gradle
@@ -18,25 +18,18 @@ def genVersionName(def versionName){
}
android {
- productFlavors {
- beta {
- }
- stage {
- }
- }
-
- compileSdkVersion 30
- buildToolsVersion "30.0.3"
+ compileSdkVersion 32
+ buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.androiddemo"
- minSdkVersion 26
+ minSdkVersion 24
targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
- versionName "1.0"
+ versionName "15.0"
if(true) {
versionName = genVersionName("${versionName}")
}
@@ -53,22 +46,26 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
- // 吐司类库
- implementation 'com.github.getActivity:ToastUtils:10.5'
-
// Android 类库
- // https://mvnrepository.com/artifact/com.android.support/support-v4
- implementation 'com.android.support:support-v4:28.0.0'
+ //api 'com.android.support:appcompat-v7:28.0.0'
+ api('com.android.support:appcompat-v7:28.0.0'){
+ exclude group: "com.android.support", module: "support-vector-drawable"
+ }
// https://mvnrepository.com/artifact/com.android.support/support-compat
- implementation 'com.android.support:support-compat:28.0.0'
+ api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
+ // https://mvnrepository.com/artifact/com.android.support/support-v4
+ api 'com.android.support:support-v4:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-media-compat
- implementation 'com.android.support:support-media-compat:28.0.0'
+ api 'com.android.support:support-media-compat:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-core-utils
- implementation 'com.android.support:support-core-utils:28.0.0'
+ api 'com.android.support:support-core-utils:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-core-ui
- implementation 'com.android.support:support-core-ui:28.0.0'
+ api 'com.android.support:support-core-ui:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-fragment
- implementation 'com.android.support:support-fragment:28.0.0'
+ api 'com.android.support:support-fragment:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
- implementation 'com.android.support:recyclerview-v7:28.0.0'
+ api 'com.android.support:recyclerview-v7:28.0.0'
+
+ api 'cc.winboll.studio:libapputils:15.2.1'
+ api 'cc.winboll.studio:libappbase:15.2.2'
}
diff --git a/androiddemo/build.properties b/androiddemo/build.properties
index 4d98e2f..ab0ea42 100644
--- a/androiddemo/build.properties
+++ b/androiddemo/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Tue Mar 11 18:02:14 GMT 2025
+#Sat Mar 29 04:34:14 GMT 2025
stageCount=0
libraryProject=
-baseVersion=1.0
-publishVersion=1.0.0
-buildCount=1
-baseBetaVersion=1.0.1
+baseVersion=15.0
+publishVersion=15.0.0
+buildCount=15
+baseBetaVersion=15.0.1
diff --git a/androiddemo/src/main/AndroidManifest.xml b/androiddemo/src/main/AndroidManifest.xml
index 43eac9a..57a1145 100644
--- a/androiddemo/src/main/AndroidManifest.xml
+++ b/androiddemo/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:resizeableActivity="true"
- android:name=".GlobalApplication">
+ android:name=".App">
+ android:orientation="vertical">
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/androidxdemo/build.gradle b/androidxdemo/build.gradle
index fcf214f..bafc5cf 100644
--- a/androidxdemo/build.gradle
+++ b/androidxdemo/build.gradle
@@ -18,15 +18,8 @@ def genVersionName(def versionName){
}
android {
- productFlavors {
- beta {
- }
- stage {
- }
- }
-
- compileSdkVersion 30
- buildToolsVersion "30.0.3"
+ compileSdkVersion 32
+ buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.androidxdemo"
@@ -36,7 +29,7 @@ android {
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
- versionName "1.0"
+ versionName "15.0"
if(true) {
versionName = genVersionName("${versionName}")
}
@@ -54,23 +47,27 @@ dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
// SSH
- implementation 'com.jcraft:jsch:0.1.55'
+ api 'com.jcraft:jsch:0.1.55'
// Html 解析
- implementation 'org.jsoup:jsoup:1.13.1'
+ api 'org.jsoup:jsoup:1.13.1'
// 二维码类库
- implementation 'com.google.zxing:core:3.4.1'
- implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
+ api 'com.google.zxing:core:3.4.1'
+ api 'com.journeyapps:zxing-android-embedded:3.6.0'
// 应用介绍页类库
- implementation 'io.github.medyo:android-about-page:2.0.0'
+ api 'io.github.medyo:android-about-page:2.0.0'
// 吐司类库
- implementation 'com.github.getActivity:ToastUtils:10.5'
+ api 'com.github.getActivity:ToastUtils:10.5'
// 网络连接类库
- implementation 'com.squareup.okhttp3:okhttp:4.4.1'
- // Android 类库
- implementation 'androidx.appcompat:appcompat:1.1.0'
- implementation 'androidx.viewpager:viewpager:1.0.0'
- implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
- implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
- implementation 'androidx.fragment:fragment:1.1.0'
- implementation 'com.google.android.material:material:1.4.0'
+ api 'com.squareup.okhttp3:okhttp:4.4.1'
+ // AndroidX 类库
+ 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'
+ //api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
+ //api 'androidx.fragment:fragment:1.1.0'
+
+ api 'cc.winboll.studio:libaes:15.2.1'
+ api 'cc.winboll.studio:libapputils:15.2.1'
+ api 'cc.winboll.studio:libappbase:15.2.2'
}
diff --git a/androidxdemo/build.properties b/androidxdemo/build.properties
index 8d115d9..887dea4 100644
--- a/androidxdemo/build.properties
+++ b/androidxdemo/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Tue Mar 11 18:25:43 GMT 2025
+#Sat Mar 29 04:28:00 GMT 2025
stageCount=0
libraryProject=
-baseVersion=1.0
-publishVersion=1.0.0
-buildCount=4
-baseBetaVersion=1.0.1
+baseVersion=15.0
+publishVersion=15.0.0
+buildCount=11
+baseBetaVersion=15.0.1
diff --git a/androidxdemo/src/main/AndroidManifest.xml b/androidxdemo/src/main/AndroidManifest.xml
index 6d0c707..1b70e90 100644
--- a/androidxdemo/src/main/AndroidManifest.xml
+++ b/androidxdemo/src/main/AndroidManifest.xml
@@ -8,9 +8,9 @@
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
- android:theme="@style/AppTheme"
+ android:theme="@style/MyAppTheme"
android:resizeableActivity="true"
- android:name=".GlobalApplication">
+ android:name=".App">
-
\ No newline at end of file
+
diff --git a/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/GlobalApplication.java b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/App.java
similarity index 97%
rename from androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/GlobalApplication.java
rename to androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/App.java
index 7abaf88..baa9df1 100644
--- a/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/GlobalApplication.java
+++ b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/App.java
@@ -1,7 +1,6 @@
package cc.winboll.studio.androidxdemo;
import android.app.Activity;
-import android.app.Application;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -22,6 +21,7 @@ import android.widget.HorizontalScrollView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
+import cc.winboll.studio.libappbase.GlobalApplication;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
@@ -39,15 +39,15 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
-public class GlobalApplication extends Application {
+public class App extends GlobalApplication {
private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
@Override
public void onCreate() {
super.onCreate();
- CrashHandler.getInstance().registerGlobal(this);
- CrashHandler.getInstance().registerPart(this);
+ //CrashHandler.getInstance().registerGlobal(this);
+ //CrashHandler.getInstance().registerPart(this);
}
public static void write(InputStream input, OutputStream output) throws IOException {
@@ -252,7 +252,7 @@ public class GlobalApplication extends Application {
private static String getKernel() {
try {
- return GlobalApplication.toString(new FileInputStream("/proc/version")).trim();
+ return App.toString(new FileInputStream("/proc/version")).trim();
} catch (Throwable e) {
return e.getMessage();
}
@@ -331,4 +331,4 @@ public class GlobalApplication extends Application {
restart();
}
}
-}
\ No newline at end of file
+}
diff --git a/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java
index de5c892..a912358 100644
--- a/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java
+++ b/androidxdemo/src/main/java/cc/winboll/studio/androidxdemo/MainActivity.java
@@ -3,17 +3,26 @@ package cc.winboll.studio.androidxdemo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
+import cc.winboll.studio.libappbase.LogView;
public class MainActivity extends AppCompatActivity {
-
+
+ LogView mLogView;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
+
Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
-
+
+ mLogView = findViewById(R.id.logview);
}
-
-}
\ No newline at end of file
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mLogView.start();
+ }
+}
diff --git a/androidxdemo/src/main/res/layout/activity_main.xml b/androidxdemo/src/main/res/layout/activity_main.xml
index 034ba40..12fdc32 100644
--- a/androidxdemo/src/main/res/layout/activity_main.xml
+++ b/androidxdemo/src/main/res/layout/activity_main.xml
@@ -34,5 +34,18 @@
+
+
+
+
+
+
diff --git a/androidxdemo/src/main/res/values/styles.xml b/androidxdemo/src/main/res/values/styles.xml
index 0eb88fe..a70e242 100644
--- a/androidxdemo/src/main/res/values/styles.xml
+++ b/androidxdemo/src/main/res/values/styles.xml
@@ -1,7 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/libappbase/build.gradle b/libappbase/build.gradle
index 92cddde..2071132 100644
--- a/libappbase/build.gradle
+++ b/libappbase/build.gradle
@@ -4,11 +4,12 @@ apply from: '../.winboll/winboll_lib_build.gradle'
apply from: '../.winboll/winboll_lint_build.gradle'
android {
+
compileSdkVersion 32
buildToolsVersion "32.0.0"
defaultConfig {
- minSdkVersion 26
+ minSdkVersion 24
targetSdkVersion 29
}
buildTypes {
@@ -21,4 +22,25 @@ android {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
+
+ // Android 类库
+ //api 'com.android.support:appcompat-v7:28.0.0'
+ api('com.android.support:appcompat-v7:28.0.0'){
+ //exclude group: "com.android.support", module: "support-vector-drawable"
+ exclude group: "com.android.support:animated-vector-drawable:28.0.0"
+ }
+ // https://mvnrepository.com/artifact/com.android.support/support-compat
+ //api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
+ // https://mvnrepository.com/artifact/com.android.support/support-v4
+ api 'com.android.support:support-v4:28.0.0'
+ // https://mvnrepository.com/artifact/com.android.support/support-media-compat
+ api 'com.android.support:support-media-compat:28.0.0'
+ // https://mvnrepository.com/artifact/com.android.support/support-core-utils
+ api 'com.android.support:support-core-utils:28.0.0'
+ // https://mvnrepository.com/artifact/com.android.support/support-core-ui
+ api 'com.android.support:support-core-ui:28.0.0'
+ // https://mvnrepository.com/artifact/com.android.support/support-fragment
+ api 'com.android.support:support-fragment:28.0.0'
+ // https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
+ api 'com.android.support:recyclerview-v7:28.0.0'
}
diff --git a/libappbase/build.properties b/libappbase/build.properties
index 32dc46b..e5371fa 100644
--- a/libappbase/build.properties
+++ b/libappbase/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Mon Mar 24 14:06:10 HKT 2025
-stageCount=10
+#Sat Mar 29 11:27:54 HKT 2025
+stageCount=3
libraryProject=libappbase
-baseVersion=15.0
-publishVersion=15.0.9
+baseVersion=15.2
+publishVersion=15.2.2
buildCount=0
-baseBetaVersion=15.0.10
+baseBetaVersion=15.2.3
diff --git a/libappbase/src/main/AndroidManifest.xml b/libappbase/src/main/AndroidManifest.xml
index 69597ba..dee879c 100644
--- a/libappbase/src/main/AndroidManifest.xml
+++ b/libappbase/src/main/AndroidManifest.xml
@@ -9,19 +9,33 @@
+
+
+
+ android:launchMode="singleInstance"
+ android:process=":CrashActivity"/>
+ android:launchMode="singleInstance"
+ android:process=":GlobalCrashActivity"/>
-
+
+
+
-
+
@@ -75,7 +91,9 @@
-
+
@@ -87,4 +105,4 @@
-
\ No newline at end of file
+
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/APPBaseModel.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/APPBaseModel.java
new file mode 100644
index 0000000..a71f1d1
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/APPBaseModel.java
@@ -0,0 +1,73 @@
+package cc.winboll.studio.libappbase;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/25 02:52:46
+ * @Describe 基础应用数据模型
+ */
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import cc.winboll.studio.libappbase.BaseBean;
+import java.io.IOException;
+
+public class APPBaseModel extends BaseBean {
+
+ public static final String TAG = "APPBaseModel";
+
+ // 应用是否处于正在调试状态
+ //
+ boolean isDebuging = false;
+
+ public APPBaseModel() {
+ this.isDebuging = false;
+ }
+
+ public APPBaseModel(boolean isDebuging) {
+ this.isDebuging = isDebuging;
+ }
+
+ public void setIsDebuging(boolean isDebuging) {
+ this.isDebuging = isDebuging;
+ }
+
+ public boolean isDebuging() {
+ return isDebuging;
+ }
+
+ @Override
+ public String getName() {
+ return APPBaseModel.class.getName();
+ }
+
+ @Override
+ public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
+ super.writeThisToJsonWriter(jsonWriter);
+ jsonWriter.name("isDebuging").value(isDebuging());
+ }
+
+ @Override
+ public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
+ if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
+ if (name.equals("isDebuging")) {
+ setIsDebuging(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/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java
index 50564f0..5bfb740 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/CrashHandler.java
@@ -339,6 +339,7 @@ public final class CrashHandler {
int padding = dp2px(16);
message.setPadding(padding, padding, padding, padding);
message.setText(mLog);
+ message.setTextColor(Color.BLACK);
message.setTextIsSelectable(true);
}
hw.addView(message);
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java
index a5d77d1..9cff4a1 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java
@@ -7,75 +7,88 @@ package cc.winboll.studio.libappbase;
*/
import android.app.Application;
import android.content.Context;
-import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import cc.winboll.studio.libappbase.utils.ToastUtils;
+import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
+import cc.winboll.studio.libappbase.winboll.MyActivityLifecycleCallbacks;
public class GlobalApplication extends Application {
public static final String TAG = "GlobalApplication";
- final static String PREFS = GlobalApplication.class.getName() + "PREFS";
- final static String PREFS_ISDEBUGING = "PREFS_ISDEBUGING";
-
-
- private static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
-
+ volatile static GlobalApplication _GlobalApplication;
// 是否处于调试状态
volatile static boolean isDebuging = false;
+ MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
- public static void setIsDebuging(Context context, boolean isDebuging) {
+ public static void setIsDebuging(boolean isDebuging) {
GlobalApplication.isDebuging = isDebuging;
- // 获取SharedPreferences实例
- SharedPreferences sharedPreferences = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
- // 获取编辑器
- SharedPreferences.Editor editor = sharedPreferences.edit();
- // 保存数据
- editor.putBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
- // 提交更改
- editor.apply();
+ }
+
+ public static void saveDebugStatus() {
+ if (_GlobalApplication != null) {
+ APPBaseModel.saveBeanToFile(getAPPBaseModelFilePath(), new APPBaseModel(GlobalApplication.isDebuging));
+ }
+ }
+
+ public static GlobalApplication getInstance() {
+ return _GlobalApplication;
+ }
+
+ static String getAPPBaseModelFilePath() {
+ return _GlobalApplication.getDataDir().getPath() + "/APPBaseModel.json";
}
public static boolean isDebuging() {
return isDebuging;
}
- @Override
- public Context getApplicationContext() {
- return super.getApplicationContext();
- }
-
- public Application getApplication() {
- return this;
+ public static WinBollActivityManager getWinBollActivityManager() {
+ return WinBollActivityManager.getInstance(_GlobalApplication);
}
@Override
public void onCreate() {
super.onCreate();
- //GlobalApplication.isDebuging = true;
- //GlobalApplication.setIsDebuging(this, true);
+ // 保存初始实例
+ _GlobalApplication = this;
+
+ setIsDebuging(true);
+ // 添加日志模块
LogUtils.init(this);
//LogUtils.setLogLevel(LogUtils.LOG_LEVEL.Debug);
//LogUtils.setTAGListEnable(GlobalApplication.TAG, true);
//LogUtils.setALlTAGListEnable(true);
//LogUtils.d(TAG, "LogUtils init");
-
// 设置应用异常处理窗口
CrashHandler.init(this);
-
- // 设置应用调试状态
- //SharedPreferences sharedPreferences = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
- //GlobalApplication.isDebuging = sharedPreferences.getBoolean(PREFS_ISDEBUGING, GlobalApplication.isDebuging);
-
// 初始化 Toast 框架
ToastUtils.init(this);
- // 设置 Toast 布局样式
- //ToastUtils.setView(R.layout.toast_custom_view);
- //ToastUtils.setStyle(new WhiteToastStyle());
- //ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
+
+ // 应用保存的调试标志
+ APPBaseModel appBaseModel = APPBaseModel.loadBeanFromFile(getAPPBaseModelFilePath(), APPBaseModel.class);
+ if (appBaseModel == null) {
+ setIsDebuging(false);
+ saveDebugStatus();
+ } else {
+ setIsDebuging(appBaseModel.isDebuging());
+ }
+
+ getWinBollActivityManager().setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Service);
+ // 注册窗口回调监听
+ mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks();
+ registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
+ }
+
+
+ @Override
+ public void onTerminate() {
+ super.onTerminate();
+ // 注销回调(非必须,但建议释放资源)
+ unregisterActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
}
public static String getAppName(Context context) {
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java
index 8163acf..dbf8c8a 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashActivity.java
@@ -4,26 +4,20 @@ package cc.winboll.studio.libappbase;
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/11 00:14:05
*/
-import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.res.TypedArray;
-import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
-import android.text.SpannableString;
-import android.text.style.ForegroundColorSpan;
+import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
-import android.widget.LinearLayout;
-import android.widget.TextView;
import android.widget.Toast;
import cc.winboll.studio.libappbase.R;
-public final class GlobalCrashActivity extends Activity implements MenuItem.OnMenuItemClickListener {
+public final class GlobalCrashActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
private static final int MENUITEM_COPY = 0;
private static final int MENUITEM_RESTART = 1;
@@ -45,10 +39,10 @@ public final class GlobalCrashActivity extends Activity implements MenuItem.OnMe
setContentView(R.layout.activity_globalcrash);
mGlobalCrashReportView = findViewById(R.id.activityglobalcrashGlobalCrashReportView1);
mGlobalCrashReportView.setReport(mLog);
- setActionBar(mGlobalCrashReportView.getToolbar());
+ setSupportActionBar(mGlobalCrashReportView.getToolbar());
- getActionBar().setTitle(CrashHandler.TITTLE);
- getActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
+ getSupportActionBar().setTitle(CrashHandler.TITTLE);
+ getSupportActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
}
@Override
@@ -98,20 +92,4 @@ public final class GlobalCrashActivity extends Activity implements MenuItem.OnMe
mGlobalCrashReportView.updateMenuStyle();
return true;
}
-
- void joinQQGroup(String key) {
- // 创建Intent
- Intent intent = new Intent();
- // 设置动作
- intent.setAction("android.intent.action.VIEW");
- // 设置数据为网址的URI
- Uri content_url = Uri.parse("https://www.winboll.cc");
- intent.setData(content_url);
- // 添加标志
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // 设置类名和活动名
- intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
- // 启动Activity
- startActivity(intent);
- }
}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashReportView.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashReportView.java
index efdfb3a..533e5da 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashReportView.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalCrashReportView.java
@@ -8,6 +8,7 @@ package cc.winboll.studio.libappbase;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
+import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
@@ -16,7 +17,6 @@ import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TextView;
import cc.winboll.studio.libappbase.R;
-import android.widget.Toolbar;
public class GlobalCrashReportView extends LinearLayout {
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java
index a49ea55..e3524d5 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java
@@ -220,7 +220,17 @@ public class LogUtils {
}
static boolean isLoggable(String tag, LOG_LEVEL logLevel) {
- return _IsInited && mapTAGList.get(tag) && isInTheLevel(logLevel);
+ if (!_IsInited) {
+ return false;
+ }
+ if (mapTAGList.get(tag) == null
+ || !mapTAGList.get(tag)) {
+ return false;
+ }
+ if (!isInTheLevel(logLevel)) {
+ return false;
+ }
+ return true;
}
static boolean isInTheLevel(LOG_LEVEL logLevel) {
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java
index 9b8721d..345489f 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java
@@ -10,6 +10,8 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -18,6 +20,8 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.HorizontalScrollView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Spinner;
@@ -42,6 +46,7 @@ public class LogView extends RelativeLayout {
Context mContext;
ScrollView mScrollView;
TextView mTextView;
+ EditText metTagSearch;
CheckBox mSelectableCheckBox;
CheckBox mSelectAllTAGCheckBox;
TAGListAdapter mTAGListAdapter;
@@ -107,9 +112,41 @@ public class LogView extends RelativeLayout {
//
mScrollView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogScrollViewLog);
mTextView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogTextViewLog);
+ metTagSearch = findViewById(cc.winboll.studio.libappbase.R.id.tagsearch_et);
// 获取Log Level spinner实例
mLogLevelSpinner = findViewById(cc.winboll.studio.libappbase.R.id.viewlogSpinner1);
+ metTagSearch.addTextChangedListener(new TextWatcher() {
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int p, int p1, int p2) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ LogUtils.d(TAG, s.toString());
+ if (s.length() > 0) {
+ scrollToTag(s.toString());
+ } else {
+ HorizontalScrollView hsRoot = findViewById(R.id.viewlogHorizontalScrollView1);
+ hsRoot.smoothScrollTo(0, 0);
+ mListViewTags.resetScrollToStart();
+ }
+// mListViewTags.postDelayed(new Runnable() {
+// @Override
+// public void run() {
+// mListViewTags.scrollToItem(5);
+// }
+// }, 100);
+ }
+ // 其他方法留空或按需实现
+ });
+
+
(findViewById(cc.winboll.studio.libappbase.R.id.viewlogButtonClean)).setOnClickListener(new View.OnClickListener(){
@Override
@@ -233,6 +270,60 @@ public class LogView extends RelativeLayout {
scrollLogUp();
}
+ public void scrollToTag(final String prefix) {
+ if (mTAGListAdapter == null || prefix == null || prefix.length() == 0) {
+ LogUtils.d(TAG, "参数为空,无法滚动");
+ return;
+ }
+
+ final List itemList = mTAGListAdapter.getItemList();
+
+ mListViewTags.post(new Runnable() {
+ @Override
+ public void run() {
+ // 查找匹配的标签位置
+ int targetPosition = -1;
+
+ for (int i = 0; i < itemList.size(); i++) {
+ String tag = itemList.get(i).getTag();
+ if (tag != null && tag.toLowerCase().startsWith(prefix.toLowerCase())) {
+ targetPosition = i;
+
+ break;
+ }
+ }
+
+ if (targetPosition != -1) {
+ // 优化滚动逻辑
+ //mListViewTags.setSelection(targetPosition);
+ //mListViewTags.invalidateViews(); // 强制刷新所有可见项
+
+ // 单独刷新目标视图
+// View targetView = mListViewTags.getChildAt(targetPosition);
+// if (targetView != null) {
+// targetView.requestLayout();
+// targetView.requestFocus();
+// }
+
+ final int scrollPosition = targetPosition;
+
+ // 延迟滚动确保布局完成
+ mListViewTags.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ LogUtils.d(TAG, String.format("scrollPosition %d", scrollPosition));
+ mListViewTags.scrollToItem(scrollPosition);
+ }
+ }, 100);
+ } else {
+ LogUtils.d(TAG, "未找到匹配的标签前缀:" + prefix);
+ }
+ }
+ });
+ }
+
+
+
class LogViewHandler extends Handler {
final static int MSG_LOGVIEW_UPDATE = 0;
@@ -300,6 +391,30 @@ public class LogView extends RelativeLayout {
public void setChecked(boolean checked) {
isChecked = checked;
}
+
+ // getter/setter...
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TAGItemModel that = (TAGItemModel) o;
+ // 手动处理空值比较(Java 6 不支持 Objects.equals)
+ if (tag == null) {
+ return that.tag == null;
+ } else {
+ return tag.equals(that.tag);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return tag == null ? 0 : tag.hashCode(); // 手动处理空值
+ }
}
@@ -314,7 +429,11 @@ public class LogView extends RelativeLayout {
mapOrigin = map;
loadMap(mapOrigin);
}
-
+
+ public List getItemList() {
+ return itemList;
+ }
+
@Override
public int getCount() {
return itemList.size();
@@ -344,7 +463,7 @@ public class LogView extends RelativeLayout {
loadMap(mapOrigin);
super.notifyDataSetChanged();
}
-
+
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/dialogs/YesNoAlertDialog.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/dialogs/YesNoAlertDialog.java
new file mode 100644
index 0000000..84446d7
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/dialogs/YesNoAlertDialog.java
@@ -0,0 +1,60 @@
+package cc.winboll.studio.libappbase.dialogs;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/28 17:40:47
+ * @Date 2024/08/12 14:46:25
+ * @Describe 询问用户确定与否的选择框
+ */
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class YesNoAlertDialog {
+
+ public static final String TAG = "YesNoAlertDialog";
+
+ public static void show(Context context, String szTitle, String szMessage, final OnDialogResultListener listener) {
+ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
+ context);
+
+ // set title
+ alertDialogBuilder.setTitle(szTitle);
+
+ // set dialog message
+ alertDialogBuilder
+ .setMessage(szMessage)
+ .setCancelable(true)
+ .setOnCancelListener(new DialogInterface.OnCancelListener(){
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ listener.onNo();
+ }
+ })
+ .setPositiveButton("YES", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // if this button is clicked, close
+ // current activity
+ listener.onYes();
+ }
+ })
+ .setNegativeButton("NO", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // if this button is clicked, just close
+ // the dialog box and do nothing
+ dialog.cancel();
+ }
+ });
+
+ // create alert dialog
+ AlertDialog alertDialog = alertDialogBuilder.create();
+
+ // show it
+ alertDialog.show();
+ }
+
+ public interface OnDialogResultListener {
+ abstract void onYes();
+ abstract void onNo();
+ }
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java
index 782d8fa..083b3a4 100644
--- a/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java
@@ -9,23 +9,34 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ListView;
+import android.widget.Scroller;
import cc.winboll.studio.libappbase.LogUtils;
public class HorizontalListView extends ListView {
-
public static final String TAG = "HorizontalListView";
- int verticalOffset = 0;
+ private int verticalOffset = 0;
+ private Scroller scroller;
+ private int totalWidth;
public HorizontalListView(Context context) {
super(context);
+ init();
}
public HorizontalListView(Context context, AttributeSet attrs) {
super(context, attrs);
+ init();
}
public HorizontalListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ scroller = new Scroller(getContext());
+ setHorizontalScrollBarEnabled(true);
+ setVerticalScrollBarEnabled(false);
}
public void setVerticalOffset(int verticalOffset) {
@@ -38,28 +49,81 @@ public class HorizontalListView extends ListView {
int childCount = getChildCount();
int left = getPaddingLeft();
int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
- LogUtils.d(TAG, String.format("HorizontalListView的高度 %d", viewHeight));
-
+ totalWidth = left;
+
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
- // 计算每个子视图的宽度和高度
int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
- //LogUtils.d(TAG, String.format("child : width %d , height %d", width, height));
- // 设置子视图的位置,实现水平布局
-
child.layout(left, verticalOffset, left + width, verticalOffset + height);
left += width;
}
+ totalWidth = left + getPaddingRight();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
- //super.onMeasure(widthMeasureSpec, newHeightMeasureSpec);
int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
- //LogUtils.d(TAG, String.format("newWidthMeasureSpec %d, newHeightMeasureSpec %d", newWidthMeasureSpec, newHeightMeasureSpec));
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
}
+
+ @Override
+ public void computeScroll() {
+ if (scroller.computeScrollOffset()) {
+ scrollTo(scroller.getCurrX(), scroller.getCurrY());
+ postInvalidate();
+ }
+ }
+
+ public void smoothScrollTo(int x, int y) {
+ int dx = x - getScrollX();
+ int dy = y - getScrollY();
+ scroller.startScroll(getScrollX(), getScrollY(), dx, dy, 300); // 300ms平滑动画
+ invalidate();
+ }
+
+ @Override
+ public int computeHorizontalScrollRange() {
+ return totalWidth;
+ }
+
+ @Override
+ public int computeHorizontalScrollOffset() {
+ return getScrollX();
+ }
+
+ @Override
+ public int computeHorizontalScrollExtent() {
+ return getWidth();
+ }
+
+ public void scrollToItem(int position) {
+ if (position < 0 || position >= getChildCount()) {
+ LogUtils.d(TAG, "无效的position: " + position);
+ return;
+ }
+
+ View targetView = getChildAt(position);
+ int targetLeft = targetView.getLeft();
+ int scrollX = targetLeft - getPaddingLeft();
+
+ // 修正最大滚动范围计算
+ int maxScrollX = totalWidth;
+ scrollX = Math.max(0, Math.min(scrollX, maxScrollX));
+
+ // 强制重新布局和绘制
+ requestLayout();
+ invalidateViews();
+ smoothScrollTo(scrollX, 0);
+ LogUtils.d(TAG, String.format("滚动到position: %d, scrollX: %d computeHorizontalScrollRange() %d", position, scrollX, computeHorizontalScrollRange()));
+ }
+
+ public void resetScrollToStart() {
+ // 强制重新布局和绘制
+ requestLayout();
+ invalidateViews();
+ smoothScrollTo(0, 0);
+ }
}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/IWinBollActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/IWinBollActivity.java
new file mode 100644
index 0000000..47c8b59
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/IWinBollActivity.java
@@ -0,0 +1,18 @@
+package cc.winboll.studio.libappbase.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/24 08:23:40
+ * @Describe WinBoll 活动窗口通用接口
+ */
+import android.app.Activity;
+import android.widget.Toolbar;
+
+public interface IWinBollActivity {
+
+ public static final String TAG = "IWinBollActivity";
+
+ // 获取活动窗口
+ abstract public Activity getActivity();
+ abstract public String getTag();
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/LogActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/LogActivity.java
new file mode 100644
index 0000000..c739743
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/LogActivity.java
@@ -0,0 +1,48 @@
+package cc.winboll.studio.libappbase.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/25 20:34:47
+ * @Describe 应用日志窗口
+ */
+import android.app.Activity;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.WindowManager;
+import cc.winboll.studio.libappbase.LogView;
+import cc.winboll.studio.libappbase.R;
+import cc.winboll.studio.libappbase.utils.ToastUtils;
+
+public class LogActivity extends Activity implements IWinBollActivity {
+
+ public static final String TAG = "LogActivity";
+
+ LogView mLogView;
+
+ @Override
+ public Activity getActivity() {
+ return this;
+ }
+
+ @Override
+ public String getTag() {
+ return TAG;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_log);
+ //ToastUtils.show("LogActivity onCreate");
+
+ mLogView = findViewById(R.id.logview);
+ mLogView.start();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mLogView.start();
+ }
+
+}
diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/MyActivityLifecycleCallbacks.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/MyActivityLifecycleCallbacks.java
new file mode 100644
index 0000000..774ab8b
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/MyActivityLifecycleCallbacks.java
@@ -0,0 +1,98 @@
+package cc.winboll.studio.libappbase.winboll;
+
+/**
+ * @Author ZhanGSKen@AliYun.Com
+ * @Date 2025/03/25 04:29:19
+ */
+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/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/WinBollActivityManager.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/WinBollActivityManager.java
new file mode 100644
index 0000000..e6c3255
--- /dev/null
+++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/winboll/WinBollActivityManager.java
@@ -0,0 +1,356 @@
+package cc.winboll.studio.libappbase.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.GlobalApplication;
+import cc.winboll.studio.libappbase.LogUtils;
+import cc.winboll.studio.libappbase.utils.ToastUtils;
+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 // 退出应用后,清理所有最近任务栏任务记录窗口
+ };
+
+ // 应用类型标志
+ static volatile WinBollUI_TYPE _mWinBollUI_TYPE = WinBollUI_TYPE.Service;
+
+ GlobalApplication mGlobalApplication;
+ static volatile WinBollActivityManager _Instance;
+ static volatile Map _mapIWinBollList;
+ volatile IWinBollActivity mFirstIWinBollActivity;
+
+ WinBollActivityManager(GlobalApplication application) {
+ mGlobalApplication = application;
+ _mapIWinBollList = new HashMap();
+ }
+
+ public static synchronized WinBollActivityManager getInstance(GlobalApplication application) {
+ LogUtils.d(TAG, "getInstance");
+ if (_Instance == null) {
+ LogUtils.d(TAG, "_Instance == null");
+ _Instance = new WinBollActivityManager(application);
+ }
+ return _Instance;
+ }
+
+ //
+ // 设置 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) {
+ String tag = ((IWinBollActivity)iWinBoll).getTag();
+ LogUtils.d(TAG, String.format("add(T iWinBoll) tag is %s", tag));
+ if (isActive(tag)) {
+ LogUtils.d(TAG, String.format("isActive(tag) is true, tag : %s.", tag));
+ } else {
+ // 设置起始活动窗口,以便最后退出时提问
+ if (mFirstIWinBollActivity == null && _mapIWinBollList.size() == 0) {
+ LogUtils.d(TAG, "Set firstIWinBollActivity, iWinBoll.getTag() is %s" + iWinBoll.getTag());
+ mFirstIWinBollActivity = 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 = ((IWinBollActivity)clazz.newInstance()).getTag();
+ LogUtils.d(TAG, String.format("startWinBollActivity(Context context, Class clazz) tag is %s", tag));
+ if (isActive(tag)) {
+ resumeActivity(context, tag);
+ return;
+ }
+ //ToastUtils.show("startWinBollActivity(Context context, Class clazz)");
+
+ // 新建一个任务窗口
+ 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);
+ context.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 = ((IWinBollActivity)clazz.newInstance()).getTag();
+ LogUtils.d(TAG, String.format("startWinBollActivity(Context context, Intent intent, Class clazz) tag is %s", tag));
+ 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);
+ context.startActivity(intent);
+ } catch (InstantiationException | IllegalAccessException e) {
+ LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
+ }
+ }
+
+ public void startLogActivity(Context context) {
+ // 如果窗口已存在就重启窗口
+ String tag = LogActivity.TAG;
+ if (isActive(tag)) {
+ resumeActivity(context, tag);
+ return;
+ }
+
+ // 新建一个任务窗口
+ Intent intent = new Intent(context, LogActivity.class);
+ //打开多任务窗口 flags
+ // Define the bounds.
+// Rect bounds = new Rect(0, 0, 800, 200);
+// // Set the bounds as an activity option.
+// ActivityOptions options = ActivityOptions.makeBasic();
+// options.setLaunchBounds(bounds);
+ intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+
+ intent.putExtra(EXTRA_TAG, tag);
+
+ //context.startActivity(intent, options.toBundle());
+ context.startActivity(intent);
+ }
+
+ public boolean isFirstIWinBollActivity(IWinBollActivity iWinBollActivity) {
+ return mFirstIWinBollActivity != null && mFirstIWinBollActivity == iWinBollActivity;
+ }
+
+ //
+ // 判断 tag绑定的 MyActivity是否存在
+ //
+ public boolean isActive(String tag) {
+ LogUtils.d(TAG, String.format("isActive(String tag) tag is %s", tag));
+ //printIWinBollListInfo();
+ 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(...) iWinBoll is null tag by %s", tag));
+ return false;
+ }
+ }
+
+ static IWinBollActivity getIWinBoll(String tag) {
+ LogUtils.d(TAG, String.format("getIWinBoll(String tag) %s", tag));
+ return _mapIWinBollList.get(tag);
+ }
+
+ //
+ // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台
+ //
+ public void resumeActivity(Context context, String tag) {
+ LogUtils.d(TAG, "resumeActivity(Context context, String tag)");
+ T iWinBoll = (T)getIWinBoll(tag);
+ LogUtils.d(TAG, String.format("iWinBoll.getTag() %s", iWinBoll.getTag()));
+ //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) {
+ LogUtils.d(TAG, "resumeActivity(Context context, T iWinBoll)");
+ ActivityManager am = (ActivityManager) mGlobalApplication.getSystemService(Context.ACTIVITY_SERVICE);
+ //返回启动它的根任务(home 或者 MainActivity)
+ Intent intent = new Intent(mGlobalApplication, iWinBoll.getClass());
+ TaskStackBuilder stackBuilder = TaskStackBuilder.create(mGlobalApplication);
+ stackBuilder.addNextIntentWithParentStack(intent);
+ stackBuilder.startActivities();
+ //moveTaskToFront(YourTaskId, 0);
+ //ToastUtils.show("resumeActivity am.moveTaskToFront");
+ LogUtils.d(TAG, String.format("iWinBoll.getActivity().getTaskId() %d", iWinBoll.getActivity().getTaskId()));
+ am.moveTaskToFront(iWinBoll.getActivity().getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
+ LogUtils.d(TAG, "am.moveTaskToFront");
+ }
+
+
+ //
+ // 结束所有 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(mGlobalApplication, 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/libappbase/src/main/res/drawable/bg_shadow.xml b/libappbase/src/main/res/drawable/bg_shadow.xml
index f4d1bd7..6d3d898 100644
--- a/libappbase/src/main/res/drawable/bg_shadow.xml
+++ b/libappbase/src/main/res/drawable/bg_shadow.xml
@@ -10,8 +10,8 @@
+ android:endColor="#0F000000"
+ android:startColor="#0F000000" />
+
+
+
+
\ No newline at end of file
diff --git a/libappbase/src/main/res/drawable/ic_dev_disconnected.xml b/libappbase/src/main/res/drawable/ic_dev_disconnected.xml
new file mode 100644
index 0000000..4267975
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_dev_disconnected.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/libappbase/src/main/res/drawable/ic_email.xml b/libappbase/src/main/res/drawable/ic_email.xml
new file mode 100644
index 0000000..d526b26
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_email.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_email_alert.xml b/libappbase/src/main/res/drawable/ic_email_alert.xml
new file mode 100644
index 0000000..f3ed613
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_email_alert.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_launcher.xml b/libappbase/src/main/res/drawable/ic_launcher.xml
index 568f996..21f28b1 100644
--- a/libappbase/src/main/res/drawable/ic_launcher.xml
+++ b/libappbase/src/main/res/drawable/ic_launcher.xml
@@ -1,13 +1,13 @@
-
- -
+
+ android:drawable="@drawable/ic_winboll_logo">
+
diff --git a/libappbase/src/main/res/drawable/ic_launcher_background.xml b/libappbase/src/main/res/drawable/ic_launcher_background.xml
index f63ec09..9486190 100644
--- a/libappbase/src/main/res/drawable/ic_launcher_background.xml
+++ b/libappbase/src/main/res/drawable/ic_launcher_background.xml
@@ -5,7 +5,7 @@
android:viewportWidth="108"
android:viewportHeight="108">
+
+ -
+
+
diff --git a/libappbase/src/main/res/drawable/ic_winboll_help.xml b/libappbase/src/main/res/drawable/ic_winboll_help.xml
new file mode 100644
index 0000000..564175f
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_winboll_help.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_winboll_log.xml b/libappbase/src/main/res/drawable/ic_winboll_log.xml
new file mode 100644
index 0000000..011f2b2
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_winboll_log.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_winboll_logo.xml b/libappbase/src/main/res/drawable/ic_winboll_logo.xml
new file mode 100644
index 0000000..ea28987
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_winboll_logo.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_winboll_point.xml b/libappbase/src/main/res/drawable/ic_winboll_point.xml
new file mode 100644
index 0000000..48028cc
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_winboll_point.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/ic_winbollbeta.xml b/libappbase/src/main/res/drawable/ic_winbollbeta.xml
new file mode 100644
index 0000000..06fa725
--- /dev/null
+++ b/libappbase/src/main/res/drawable/ic_winbollbeta.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/shape_gradient.xml b/libappbase/src/main/res/drawable/shape_gradient.xml
new file mode 100644
index 0000000..c164fe9
--- /dev/null
+++ b/libappbase/src/main/res/drawable/shape_gradient.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/libappbase/src/main/res/drawable/view_border.xml b/libappbase/src/main/res/drawable/view_border.xml
new file mode 100644
index 0000000..58b374a
--- /dev/null
+++ b/libappbase/src/main/res/drawable/view_border.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/libappbase/src/main/res/layout/activity_log.xml b/libappbase/src/main/res/layout/activity_log.xml
index dfcde4f..a5f2ea2 100644
--- a/libappbase/src/main/res/layout/activity_log.xml
+++ b/libappbase/src/main/res/layout/activity_log.xml
@@ -1,16 +1,14 @@
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
-
+
+
diff --git a/libappbase/src/main/res/layout/view_globalcrashreport.xml b/libappbase/src/main/res/layout/view_globalcrashreport.xml
index 1aff5e5..cda2c96 100644
--- a/libappbase/src/main/res/layout/view_globalcrashreport.xml
+++ b/libappbase/src/main/res/layout/view_globalcrashreport.xml
@@ -7,9 +7,9 @@
android:layout_height="match_parent"
android:id="@+id/viewglobalcrashreportLinearLayout1">
-
+
+
+ android:layout_weight="1.0"
+ android:id="@+id/viewlogHorizontalScrollView1">
+
diff --git a/libappbase/src/main/res/values/styles.xml b/libappbase/src/main/res/values/styles.xml
index da69f41..13f26cd 100644
--- a/libappbase/src/main/res/values/styles.xml
+++ b/libappbase/src/main/res/values/styles.xml
@@ -1,7 +1,7 @@
-