From b9613efca3f68ab9ba50e412056223cd576dac5e Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Tue, 13 Jan 2026 03:32:37 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=A4=8D=E5=88=B6=20https://gitea.winboll.?= =?UTF-8?q?cc/Studio/AES=5FBck20260112=5F122031=5F590.git=20=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E6=9C=80=E6=96=B0AES=E6=A8=A1=E5=9D=97=E6=BA=90?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 10 +- aes/.gitignore | 1 + aes/README.md | 36 + aes/app_update_description.txt | 1 + aes/build.gradle | 48 ++ aes/build.properties | 8 + aes/proguard-rules.pro | 137 ++++ aes/src/beta/AndroidManifest.xml | 12 + aes/src/beta/res/values/strings.xml | 6 + aes/src/main/AndroidManifest.xml | 42 ++ .../cc/winboll/studio/aes/AboutActivity.java | 59 ++ .../main/java/cc/winboll/studio/aes/App.java | 34 + .../cc/winboll/studio/aes/MainActivity.java | 200 ++++++ .../winboll/studio/aes/SettingsActivity.java | 39 ++ .../aes/TestActivityManagerActivity.java | 33 + .../winboll/studio/aes/WinBoLLActivity.java | 60 ++ aes/src/main/res/drawable/bg_frame.xml | 41 ++ aes/src/main/res/layout/activity_about.xml | 21 + aes/src/main/res/layout/activity_settings.xml | 17 + .../layout/activity_testactivitymanager.xml | 15 + aes/src/main/res/menu/toolbar_main.xml | 41 ++ aes/src/main/res/values/colors.xml | 7 + aes/src/main/res/values/strings.xml | 7 + aes/src/main/res/values/styles.xml | 5 + .../main/res/xml/network_security_config.xml | 6 + aes/src/stage/AndroidManifest.xml | 12 + aes/src/stage/res/values/strings.xml | 6 + gradle.properties | 21 + libaes/.gitignore | 1 + libaes/build.gradle | 71 ++ libaes/build.properties | 8 + libaes/libs/colorpicker-20180319.jar | Bin 0 -> 12740 bytes libaes/proguard-rules.pro | 17 + libaes/src/main/AndroidManifest.xml | 57 ++ .../studio/libaes/DrawerMenuDataAdapter.java | 207 ++++++ .../studio/libaes/ImagePagerAdapter.java | 75 +++ .../activitys/DrawerFragmentActivity.java | 400 +++++++++++ .../libaes/dialogs/LocalFileSelectDialog.java | 204 ++++++ .../libaes/dialogs/StoragePathDialog.java | 57 ++ .../libaes/dialogs/YesNoAlertDialog.java | 60 ++ .../winboll/studio/libaes/enums/ADsMode.java | 32 + .../libaes/enums/PrivacyAgreeStatus.java | 67 ++ .../libaes/interfaces/IWinBoLLActivity.java | 18 + .../studio/libaes/models/AESThemeBean.java | 143 ++++ .../winboll/studio/libaes/models/APPInfo.java | 169 +++++ .../studio/libaes/models/DrawerMenuBean.java | 35 + .../models/WinBoLLClientServiceBean.java | 78 +++ .../unittests/SecondaryLibraryActivity.java | 62 ++ .../unittests/SecondaryLibraryFragment.java | 25 + .../libaes/unittests/TestAButtonFragment.java | 37 + .../TestASupportToolbarActivity.java | 42 ++ .../unittests/TestAToolbarActivity.java | 28 + .../unittests/TestDrawerFragmentActivity.java | 124 ++++ .../unittests/TestViewPageFragment.java | 226 +++++++ .../studio/libaes/utils/AESThemeUtil.java | 211 ++++++ .../studio/libaes/utils/AppVersionUtils.java | 162 +++++ .../studio/libaes/utils/DevelopUtils.java | 35 + .../studio/libaes/utils/MimoUtils.java | 33 + .../utils/MyActivityLifecycleCallbacks.java | 97 +++ .../studio/libaes/utils/PrefUtils.java | 33 + .../studio/libaes/utils/ScreenUtil.java | 64 ++ .../winboll/studio/libaes/utils/WebUtils.java | 102 +++ .../libaes/utils/WinBoLLActivityManager.java | 292 ++++++++ .../winboll/studio/libaes/views/AButton.java | 28 + .../cc/winboll/studio/libaes/views/ACard.java | 45 ++ .../libaes/views/ADrawerMenuListView.java | 19 + .../studio/libaes/views/ADsBannerView.java | 491 ++++++++++++++ .../studio/libaes/views/ADsControlView.java | 633 ++++++++++++++++++ .../studio/libaes/views/AOHPCTCSeekBar.java | 108 +++ .../studio/libaes/views/AOHPCTSCard.java | 43 ++ .../studio/libaes/views/ASupportToolbar.java | 89 +++ .../studio/libaes/views/ATickProgressBar.java | 55 ++ .../winboll/studio/libaes/views/AToolbar.java | 92 +++ .../studio/libaes/views/AboutView.java | 379 +++++++++++ .../res/anim/normal_dialog_enter_center.xml | 35 + .../res/anim/normal_dialog_enter_corner.xml | 15 + .../res/anim/normal_dialog_exit_center.xml | 35 + .../res/anim/normal_dialog_exit_corner.xml | 14 + .../main/res/drawable/acard_frame_main.xml | 62 ++ .../src/main/res/drawable/atoolbar_frame.xml | 62 ++ libaes/src/main/res/drawable/bg_shadow.xml | 41 ++ libaes/src/main/res/drawable/btn_style.xml | 7 + .../src/main/res/drawable/default_shape.xml | 27 + .../res/drawable/ic_arrow_left_right_bold.xml | 11 + .../drawable/ic_arrow_up_circle_outline.xml | 11 + libaes/src/main/res/drawable/ic_call.xml | 11 + .../main/res/drawable/ic_dev_connected.xml | 11 + .../main/res/drawable/ic_dev_disconnected.xml | 11 + libaes/src/main/res/drawable/ic_email.xml | 11 + .../src/main/res/drawable/ic_email_alert.xml | 11 + libaes/src/main/res/drawable/ic_launcher.xml | 13 + .../res/drawable/ic_launcher_background.xml | 170 +++++ .../res/drawable/ic_launcher_foreground.xml | 10 + libaes/src/main/res/drawable/ic_winboll.xml | 13 + .../main/res/drawable/ic_winboll_store.png | Bin 0 -> 197451 bytes .../src/main/res/drawable/ic_winbollbeta.xml | 11 + libaes/src/main/res/drawable/ohpcts_frame.xml | 43 ++ .../src/main/res/drawable/pressed_shape.xml | 22 + .../src/main/res/drawable/shape_gradient.xml | 10 + libaes/src/main/res/drawable/toast_frame.xml | 7 + libaes/src/main/res/drawable/view_border.xml | 8 + libaes/src/main/res/drawable/winboll_help.xml | 27 + libaes/src/main/res/drawable/winboll_logo.xml | 48 ++ .../src/main/res/drawable/winboll_point.xml | 20 + libaes/src/main/res/layout/activity_about.xml | 21 + .../src/main/res/layout/activity_drawer.xml | 57 ++ .../res/layout/activity_drawerfragment.xml | 65 ++ .../res/layout/activity_secondarylibrary.xml | 15 + .../layout/activity_test_aboutfragment.xml | 15 + .../layout/activity_testasupporttoolbar.xml | 15 + .../main/res/layout/activity_testatoolbar.xml | 15 + .../res/layout/dialog_privacy_agreement.xml | 79 +++ .../main/res/layout/dialog_storagepath.xml | 43 ++ .../src/main/res/layout/fragment_abutton.xml | 20 + .../res/layout/fragment_secondarylibrary.xml | 15 + libaes/src/main/res/layout/fragment_test1.xml | 15 + libaes/src/main/res/layout/fragment_test2.xml | 15 + .../src/main/res/layout/fragment_viewpage.xml | 60 ++ .../main/res/layout/listview_drawermenu.xml | 28 + libaes/src/main/res/layout/view_adsbanner.xml | 15 + .../src/main/res/layout/view_adscontrol.xml | 79 +++ libaes/src/main/res/layout/viewpage_acard.xml | 18 + .../main/res/layout/viewpage_aohpctccard.xml | 18 + .../main/res/layout/viewpage_aohpctcsb.xml | 35 + .../res/layout/viewpage_atickprogressbar.xml | 22 + .../main/res/menu/menu_qrcode_long_click.xml | 7 + libaes/src/main/res/menu/toolbar_appdebug.xml | 15 + libaes/src/main/res/menu/toolbar_apptheme.xml | 29 + .../src/main/res/menu/toolbar_drawerbase.xml | 5 + .../res/menu/toolbar_secondarylibrary.xml | 9 + libaes/src/main/res/values-zh/string.xml | 17 + libaes/src/main/res/values/attrs.xml | 75 +++ libaes/src/main/res/values/colors.xml | 45 ++ libaes/src/main/res/values/dimens.xml | 16 + libaes/src/main/res/values/strings.xml | 22 + libaes/src/main/res/values/styles.xml | 255 +++++++ libaes/src/main/res/xml/file_provider.xml | 9 + .../main/res/xml/network_security_config.xml | 16 + settings.gradle | 79 +++ 139 files changed, 8217 insertions(+), 3 deletions(-) create mode 100644 aes/.gitignore create mode 100644 aes/README.md create mode 100644 aes/app_update_description.txt create mode 100644 aes/build.gradle create mode 100644 aes/build.properties create mode 100644 aes/proguard-rules.pro create mode 100644 aes/src/beta/AndroidManifest.xml create mode 100644 aes/src/beta/res/values/strings.xml create mode 100644 aes/src/main/AndroidManifest.xml create mode 100644 aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java create mode 100644 aes/src/main/java/cc/winboll/studio/aes/App.java create mode 100644 aes/src/main/java/cc/winboll/studio/aes/MainActivity.java create mode 100644 aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java create mode 100644 aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java create mode 100644 aes/src/main/java/cc/winboll/studio/aes/WinBoLLActivity.java create mode 100644 aes/src/main/res/drawable/bg_frame.xml create mode 100644 aes/src/main/res/layout/activity_about.xml create mode 100644 aes/src/main/res/layout/activity_settings.xml create mode 100644 aes/src/main/res/layout/activity_testactivitymanager.xml create mode 100644 aes/src/main/res/menu/toolbar_main.xml create mode 100644 aes/src/main/res/values/colors.xml create mode 100644 aes/src/main/res/values/strings.xml create mode 100644 aes/src/main/res/values/styles.xml create mode 100644 aes/src/main/res/xml/network_security_config.xml create mode 100644 aes/src/stage/AndroidManifest.xml create mode 100644 aes/src/stage/res/values/strings.xml create mode 100644 gradle.properties create mode 100644 libaes/.gitignore create mode 100644 libaes/build.gradle create mode 100644 libaes/build.properties create mode 100644 libaes/libs/colorpicker-20180319.jar create mode 100644 libaes/proguard-rules.pro create mode 100644 libaes/src/main/AndroidManifest.xml create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/DrawerMenuDataAdapter.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/ImagePagerAdapter.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/dialogs/LocalFileSelectDialog.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/dialogs/StoragePathDialog.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/enums/ADsMode.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/enums/PrivacyAgreeStatus.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/models/DrawerMenuBean.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryFragment.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/DevelopUtils.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/MimoUtils.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/PrefUtils.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/ScreenUtil.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/WebUtils.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/AButton.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/ACard.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/ADrawerMenuListView.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTCSeekBar.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTSCard.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/ASupportToolbar.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/ATickProgressBar.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/AToolbar.java create mode 100644 libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java create mode 100644 libaes/src/main/res/anim/normal_dialog_enter_center.xml create mode 100644 libaes/src/main/res/anim/normal_dialog_enter_corner.xml create mode 100644 libaes/src/main/res/anim/normal_dialog_exit_center.xml create mode 100644 libaes/src/main/res/anim/normal_dialog_exit_corner.xml create mode 100644 libaes/src/main/res/drawable/acard_frame_main.xml create mode 100644 libaes/src/main/res/drawable/atoolbar_frame.xml create mode 100644 libaes/src/main/res/drawable/bg_shadow.xml create mode 100644 libaes/src/main/res/drawable/btn_style.xml create mode 100644 libaes/src/main/res/drawable/default_shape.xml create mode 100644 libaes/src/main/res/drawable/ic_arrow_left_right_bold.xml create mode 100644 libaes/src/main/res/drawable/ic_arrow_up_circle_outline.xml create mode 100644 libaes/src/main/res/drawable/ic_call.xml create mode 100644 libaes/src/main/res/drawable/ic_dev_connected.xml create mode 100644 libaes/src/main/res/drawable/ic_dev_disconnected.xml create mode 100644 libaes/src/main/res/drawable/ic_email.xml create mode 100644 libaes/src/main/res/drawable/ic_email_alert.xml create mode 100644 libaes/src/main/res/drawable/ic_launcher.xml create mode 100644 libaes/src/main/res/drawable/ic_launcher_background.xml create mode 100644 libaes/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 libaes/src/main/res/drawable/ic_winboll.xml create mode 100644 libaes/src/main/res/drawable/ic_winboll_store.png create mode 100644 libaes/src/main/res/drawable/ic_winbollbeta.xml create mode 100644 libaes/src/main/res/drawable/ohpcts_frame.xml create mode 100644 libaes/src/main/res/drawable/pressed_shape.xml create mode 100644 libaes/src/main/res/drawable/shape_gradient.xml create mode 100644 libaes/src/main/res/drawable/toast_frame.xml create mode 100644 libaes/src/main/res/drawable/view_border.xml create mode 100644 libaes/src/main/res/drawable/winboll_help.xml create mode 100644 libaes/src/main/res/drawable/winboll_logo.xml create mode 100644 libaes/src/main/res/drawable/winboll_point.xml create mode 100644 libaes/src/main/res/layout/activity_about.xml create mode 100644 libaes/src/main/res/layout/activity_drawer.xml create mode 100644 libaes/src/main/res/layout/activity_drawerfragment.xml create mode 100644 libaes/src/main/res/layout/activity_secondarylibrary.xml create mode 100644 libaes/src/main/res/layout/activity_test_aboutfragment.xml create mode 100644 libaes/src/main/res/layout/activity_testasupporttoolbar.xml create mode 100644 libaes/src/main/res/layout/activity_testatoolbar.xml create mode 100644 libaes/src/main/res/layout/dialog_privacy_agreement.xml create mode 100644 libaes/src/main/res/layout/dialog_storagepath.xml create mode 100644 libaes/src/main/res/layout/fragment_abutton.xml create mode 100644 libaes/src/main/res/layout/fragment_secondarylibrary.xml create mode 100644 libaes/src/main/res/layout/fragment_test1.xml create mode 100644 libaes/src/main/res/layout/fragment_test2.xml create mode 100644 libaes/src/main/res/layout/fragment_viewpage.xml create mode 100644 libaes/src/main/res/layout/listview_drawermenu.xml create mode 100644 libaes/src/main/res/layout/view_adsbanner.xml create mode 100644 libaes/src/main/res/layout/view_adscontrol.xml create mode 100644 libaes/src/main/res/layout/viewpage_acard.xml create mode 100644 libaes/src/main/res/layout/viewpage_aohpctccard.xml create mode 100644 libaes/src/main/res/layout/viewpage_aohpctcsb.xml create mode 100644 libaes/src/main/res/layout/viewpage_atickprogressbar.xml create mode 100644 libaes/src/main/res/menu/menu_qrcode_long_click.xml create mode 100644 libaes/src/main/res/menu/toolbar_appdebug.xml create mode 100644 libaes/src/main/res/menu/toolbar_apptheme.xml create mode 100644 libaes/src/main/res/menu/toolbar_drawerbase.xml create mode 100644 libaes/src/main/res/menu/toolbar_secondarylibrary.xml create mode 100644 libaes/src/main/res/values-zh/string.xml create mode 100644 libaes/src/main/res/values/attrs.xml create mode 100644 libaes/src/main/res/values/colors.xml create mode 100644 libaes/src/main/res/values/dimens.xml create mode 100644 libaes/src/main/res/values/strings.xml create mode 100644 libaes/src/main/res/values/styles.xml create mode 100644 libaes/src/main/res/xml/file_provider.xml create mode 100644 libaes/src/main/res/xml/network_security_config.xml create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index 110c6f0..994a6c7 100644 --- a/.gitignore +++ b/.gitignore @@ -94,8 +94,12 @@ lint-results.html ## 忽略 AndroidIDE 临时文件夹 .androidide -## 忽略模块应用编译配置 -/settings.gradle -/gradle.properties +## WinBoLL 基础应用(避免上传敏感配置) /winboll.properties /local.properties + +## WinBoLL 衍生应用, +## 外派类型类库应用需要注释掉以下部分,以便部署通用类库编译配置。 +## APPBase,AES需要上传以下两种配置。 +#/settings.gradle +#/gradle.properties diff --git a/aes/.gitignore b/aes/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/aes/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/aes/README.md b/aes/README.md new file mode 100644 index 0000000..1606637 --- /dev/null +++ b/aes/README.md @@ -0,0 +1,36 @@ +# AES +[![](https://jitpack.io/v/ZhanGSKen/AES.svg)](https://jitpack.io/#ZhanGSKen/AES) + +#### 介绍 +WinBoLL AndroidX 可视化元素类库。 + +#### 软件架构 +适配安卓应用 [AIDE Pro] 的 Gradle 编译结构。 +也适配安卓应用 [AndroidIDE] 的 Gradle 编译结构。 + + +#### Gradle 编译说明 +调试版编译命令 :gradle assembleBetaDebug +阶段版编译命令 :bash .winboll/bashPublishAPKAddTag.sh aes +阶段版类库发布命令 :git pull &&bash .winboll/bashPublishLIBAddTag.sh libaes + +#### 使用说明 + +#### 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 : ZhanGSKen(ZhanGSKen) +4. 新建 Pull Request + + +#### 特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) + +#### 参考文档 diff --git a/aes/app_update_description.txt b/aes/app_update_description.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/aes/app_update_description.txt @@ -0,0 +1 @@ + diff --git a/aes/build.gradle b/aes/build.gradle new file mode 100644 index 0000000..899f105 --- /dev/null +++ b/aes/build.gradle @@ -0,0 +1,48 @@ +apply plugin: 'com.android.application' +apply from: '../.winboll/winboll_app_build.gradle' +apply from: '../.winboll/winboll_lint_build.gradle' + +def genVersionName(def versionName){ + // 检查编译标志位配置 + assert (winbollBuildProps['stageCount'] != null) + assert (winbollBuildProps['baseVersion'] != null) + // 保存基础版本号 + winbollBuildProps.setProperty("baseVersion", "${versionName}"); + //保存编译标志配置 + FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile) + winbollBuildProps.store(fos, "${winbollBuildPropsDesc}"); + fos.close(); + + // 返回编译版本号 + return "${versionName}." + winbollBuildProps['stageCount'] +} + +android { + // 适配MIUI12 + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "cc.winboll.studio.aes" + minSdkVersion 21 + targetSdkVersion 30 + versionCode 1 + // versionName 更新后需要手动设置 + // 项目模块目录的 build.gradle 文件的 stageCount=0 + // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" + versionName "15.15" + if(true) { + versionName = genVersionName("${versionName}") + } + } + + // 米盟 SDK + packagingOptions { + doNotStrip "*/*/libmimo_1011.so" + } +} + +dependencies { + api project(':libaes') + api fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/aes/build.properties b/aes/build.properties new file mode 100644 index 0000000..ce7bba2 --- /dev/null +++ b/aes/build.properties @@ -0,0 +1,8 @@ +#Created by .winboll/winboll_app_build.gradle +#Sun Jan 11 15:36:13 HKT 2026 +stageCount=1 +libraryProject=libaes +baseVersion=15.15 +publishVersion=15.15.0 +buildCount=0 +baseBetaVersion=15.15.1 diff --git a/aes/proguard-rules.pro b/aes/proguard-rules.pro new file mode 100644 index 0000000..a18de74 --- /dev/null +++ b/aes/proguard-rules.pro @@ -0,0 +1,137 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# ============================== 基础通用规则 ============================== +# 保留系统组件 +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference + +# 保留 WinBoLL 核心包及子类(合并简化规则) +-keep class cc.winboll.studio.** { *; } +-keepclassmembers class cc.winboll.studio.** { *; } + +# 保留所有类中的 public static final String TAG 字段(便于日志定位) +-keepclassmembers class * { + public static final java.lang.String TAG; +} + +# 保留序列化类(避免Parcelable/Gson解析异常) +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} + +# 保留 R 文件(避免资源ID混淆) +-keepclassmembers class **.R$* { + public static ; +} + +# 保留 native 方法(避免JNI调用失败) +-keepclasseswithmembernames class * { + native ; +} + +# 保留注解和泛型(避免反射/序列化异常) +-keepattributes *Annotation* +-keepattributes Signature + +# 屏蔽 Java 8+ 警告(适配 Java 7 语法) +-dontwarn java.lang.invoke.* +-dontwarn android.support.v8.renderscript.* +-dontwarn java.util.function.** + +# ============================== 第三方框架专项规则 ============================== +# OkHttp 4.4.1(米盟广告请求依赖,完善Lambda兼容) +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-keep class okhttp3.internal.** { *; } +-keep class okio.** { *; } +-dontwarn okhttp3.internal.platform.** +-dontwarn okio.** + +# Glide 4.9.0(米盟广告图片加载依赖) +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep public enum com.bumptech.glide.load.ImageHeaderParser$ImageType { + **[] $VALUES; + public *; +} +-keepclassmembers class * implements com.bumptech.glide.module.AppGlideModule { + (); +} +-dontwarn com.bumptech.glide.** + +# Gson 2.8.5(米盟广告数据序列化依赖) +-keep class com.google.gson.** { *; } +-keep interface com.google.gson.** { *; } +-keepclassmembers class * { + @com.google.gson.annotations.SerializedName ; +} + +# 米盟 SDK(核心广告组件,完整保留避免加载失败) +-keep class com.miui.zeus.** { *; } +-keep interface com.miui.zeus.** { *; } +# 保留米盟日志字段(便于广告加载失败排查) +-keepclassmembers class com.miui.zeus.mimo.sdk.** { + public static final java.lang.String TAG; +} + +# RecyclerView 1.0.0(米盟广告布局渲染依赖) +-keep class androidx.recyclerview.** { *; } +-keep interface androidx.recyclerview.** { *; } +-keepclassmembers class androidx.recyclerview.widget.RecyclerView$Adapter { + public *; +} + +# 其他第三方框架(按引入依赖保留,无则可删除) +# XXPermissions 18.63 +-keep class com.hjq.permissions.** { *; } +-keep interface com.hjq.permissions.** { *; } + +# ZXing 二维码(核心解析组件) +-keep class com.google.zxing.** { *; } +-keep class com.journeyapps.zxing.** { *; } + +# Jsoup HTML解析 +-keep class org.jsoup.** { *; } + +# Pinyin4j 拼音搜索 +-keep class net.sourceforge.pinyin4j.** { *; } + +# JSch SSH组件 +-keep class com.jcraft.jsch.** { *; } + +# AndroidX 基础组件 +-keep class androidx.appcompat.** { *; } +-keep interface androidx.appcompat.** { *; } + +# ============================== 优化与调试配置 ============================== +# 优化级别(平衡混淆效果与性能) +-optimizationpasses 5 +-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* + +# 调试辅助(保留行号便于崩溃定位) +-verbose +-dontpreverify +-dontusemixedcaseclassnames +-keepattributes SourceFile,LineNumberTable + diff --git a/aes/src/beta/AndroidManifest.xml b/aes/src/beta/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/aes/src/beta/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/aes/src/beta/res/values/strings.xml b/aes/src/beta/res/values/strings.xml new file mode 100644 index 0000000..6f287f2 --- /dev/null +++ b/aes/src/beta/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + + AES+ + diff --git a/aes/src/main/AndroidManifest.xml b/aes/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c0ca77d --- /dev/null +++ b/aes/src/main/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java new file mode 100644 index 0000000..a824a62 --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/AboutActivity.java @@ -0,0 +1,59 @@ +package cc.winboll.studio.aes; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.Toolbar; +import cc.winboll.studio.aes.R; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.models.APPInfo; +import cc.winboll.studio.libappbase.views.AboutView; + +/** + * @Author 豆包&ZhanGSKen + * @Date 2026/01/11 15:16 + * @Describe 应用介绍窗口 + */ +public class AboutActivity extends Activity { + + public static final String TAG = "AboutActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_about); + + // 设置工具栏 + Toolbar toolbar = findViewById(R.id.toolbar); + setActionBar(toolbar); + getActionBar().setSubtitle(TAG); + getActionBar().setDisplayHomeAsUpEnabled(true); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); // 点击导航栏返回按钮,触发 finish() + } + }); + + AboutView aboutView = findViewById(R.id.aboutview); + aboutView.setAPPInfo(genDefaultAppInfo()); + } + + private APPInfo genDefaultAppInfo() { + LogUtils.d(TAG, "genDefaultAppInfo() 调用"); + String branchName = "aes"; + APPInfo appInfo = new APPInfo(); + appInfo.setAppName(getString(R.string.app_name)); + appInfo.setAppIcon(R.drawable.ic_winboll); + appInfo.setAppDescription(getString(R.string.app_description)); + appInfo.setAppGitName("AES"); + appInfo.setAppGitOwner("Studio"); + appInfo.setAppGitAPPBranch(branchName); + appInfo.setAppGitAPPSubProjectFolder(branchName); + appInfo.setAppHomePage("https://www.winboll.cc/apks/index.php?project=AES"); + appInfo.setAppAPKName("AES"); + appInfo.setAppAPKFolderName("AES"); + LogUtils.d(TAG, "genDefaultAppInfo: 应用信息已生成"); + return 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 new file mode 100644 index 0000000..f6816f7 --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/App.java @@ -0,0 +1,34 @@ +package cc.winboll.studio.aes; + +/** + * @Author ZhanGSKen + * @Date 2024/06/13 19:03:58 + * @Describe AES应用类 + */ +import android.view.Gravity; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.ToastUtils; + + +public class App extends GlobalApplication { + + public static final String TAG = "App"; + + @Override + public void onCreate() { + super.onCreate(); + setIsDebugging(BuildConfig.DEBUG); + //setIsDebugging(false); + WinBoLLActivityManager.init(this); + + // 初始化 Toast 框架 + ToastUtils.init(this); + } + + @Override + public void onTerminate() { + super.onTerminate(); + ToastUtils.release(); + } +} diff --git a/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java new file mode 100644 index 0000000..5360023 --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/MainActivity.java @@ -0,0 +1,200 @@ +package cc.winboll.studio.aes; + +/** + * @Author ZhanGSKen + * @Date 2024/06/13 19:05:52 + * @Describe 应用主窗口 + */ +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.dialogs.LocalFileSelectDialog; +import cc.winboll.studio.libaes.dialogs.StoragePathDialog; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.models.DrawerMenuBean; +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.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libappbase.LogUtils; +import com.a4455jkjh.colorpicker.ColorPickerDialog; +import java.util.ArrayList; + +public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActivity { + + + 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_main, menu); +// if(App.isDebugging()) { +// getMenuInflater().inflate(cc.winboll.studio.libaes.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_testactivitymanager) { + WinBoLLActivityManager.getInstance().startWinBoLLActivity(this, TestActivityManagerActivity.class); + //ToastUtils.show("item_testactivitymanager"); + } 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_settings) { + Intent intent = new Intent(this, SettingsActivity.class); + startActivity(intent); + } else if (nItemId == R.id.item_about) { + Intent intent = new Intent(this, AboutActivity.class); + startActivity(intent); + } + + + return super.onOptionsItemSelected(item); + } + + +} diff --git a/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java b/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java new file mode 100644 index 0000000..1767c02 --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/SettingsActivity.java @@ -0,0 +1,39 @@ +package cc.winboll.studio.aes; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import cc.winboll.studio.libaes.views.ADsControlView; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/26 18:01 + * @Describe SettingsActivity + */ +public class SettingsActivity extends Activity { + + public static final String TAG = "SettingsActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settings); + ADsControlView adsControlView = (ADsControlView) findViewById(R.id.ads_control_view); + +// adsControlView.setOnAdsModeSelectedListener(new ADsControlView.OnAdsModeSelectedListener() { +// @Override +// public void onModeSelected(ADsMode selectedMode) { +// if (selectedMode == ADsMode.STANDALONE) { +// // 处理单机模式逻辑(如释放米盟资源) +// ToastUtils.show("STANDALONE"); +// } else if (selectedMode == ADsMode.MIMO_SDK) { +// // 处理米盟SDK模式逻辑(如初始化SDK) +// ToastUtils.show("MIMO_SDK"); +// } +// } +// }); + } + +} diff --git a/aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java b/aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java new file mode 100644 index 0000000..71d114d --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/TestActivityManagerActivity.java @@ -0,0 +1,33 @@ +package cc.winboll.studio.aes; + +import android.app.Activity; +import android.os.Bundle; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/09/28 21:07 + * @Describe 窗口管理类测试窗口 + */ +public class TestActivityManagerActivity extends WinBoLLActivity implements IWinBoLLActivity { + + public static final String TAG = "TestActivityManagerActivity"; + + @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_testactivitymanager); + + } + +} 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..76005db --- /dev/null +++ b/aes/src/main/java/cc/winboll/studio/aes/WinBoLLActivity.java @@ -0,0 +1,60 @@ +package cc.winboll.studio.aes; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/09/29 00:11 + * @Describe WinBoLL 窗口基础类 + */ +import android.app.Activity; +import android.os.Bundle; +import android.view.MenuItem; +import androidx.appcompat.app.AppCompatActivity; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libappbase.LogUtils; + +public class WinBoLLActivity extends AppCompatActivity implements IWinBoLLActivity { + + public static final String TAG = "WinBoLLActivity"; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + + @Override + protected void onResume() { + super.onResume(); + LogUtils.d(TAG, String.format("onResume %s", getTag())); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + /*if (item.getItemId() == R.id.item_log) { + WinBoLLActivityManager.getInstance().startLogActivity(this); + return true; + } else if (item.getItemId() == R.id.item_home) { + startActivity(new Intent(this, MainActivity.class)); + return true; + }*/ + // 在switch语句中处理每个ID,并在处理完后返回true,未处理的情况返回false。 + return super.onOptionsItemSelected(item); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + WinBoLLActivityManager.getInstance().add(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + WinBoLLActivityManager.getInstance().registeRemove(this); + } +} diff --git a/aes/src/main/res/drawable/bg_frame.xml b/aes/src/main/res/drawable/bg_frame.xml new file mode 100644 index 0000000..75b2b94 --- /dev/null +++ b/aes/src/main/res/drawable/bg_frame.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + 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..bfd02eb --- /dev/null +++ b/aes/src/main/res/layout/activity_about.xml @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/aes/src/main/res/layout/activity_settings.xml b/aes/src/main/res/layout/activity_settings.xml new file mode 100644 index 0000000..c8d3432 --- /dev/null +++ b/aes/src/main/res/layout/activity_settings.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/aes/src/main/res/layout/activity_testactivitymanager.xml b/aes/src/main/res/layout/activity_testactivitymanager.xml new file mode 100644 index 0000000..e030ebb --- /dev/null +++ b/aes/src/main/res/layout/activity_testactivitymanager.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/aes/src/main/res/menu/toolbar_main.xml b/aes/src/main/res/menu/toolbar_main.xml new file mode 100644 index 0000000..b87657a --- /dev/null +++ b/aes/src/main/res/menu/toolbar_main.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + 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/strings.xml b/aes/src/main/res/values/strings.xml new file mode 100644 index 0000000..664f43a --- /dev/null +++ b/aes/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + AES + WinBoLL AndroidX 可视化元素类库。 + + diff --git a/aes/src/main/res/values/styles.xml b/aes/src/main/res/values/styles.xml new file mode 100644 index 0000000..1da88ba --- /dev/null +++ b/aes/src/main/res/values/styles.xml @@ -0,0 +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/aes/src/stage/AndroidManifest.xml b/aes/src/stage/AndroidManifest.xml new file mode 100644 index 0000000..ee78d9f --- /dev/null +++ b/aes/src/stage/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/aes/src/stage/res/values/strings.xml b/aes/src/stage/res/values/strings.xml new file mode 100644 index 0000000..ace0c41 --- /dev/null +++ b/aes/src/stage/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..74b1f76 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# 保持与旧版Gradle插件的兼容 +android.disableAutomaticComponentCreation=true diff --git a/libaes/.gitignore b/libaes/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/libaes/.gitignore @@ -0,0 +1 @@ +/build diff --git a/libaes/build.gradle b/libaes/build.gradle new file mode 100644 index 0000000..881bae7 --- /dev/null +++ b/libaes/build.gradle @@ -0,0 +1,71 @@ +apply plugin: 'com.android.library' +apply plugin: 'maven-publish' +apply from: '../.winboll/winboll_lib_build.gradle' +apply from: '../.winboll/winboll_lint_build.gradle' + +android { + // 适配MIUI12 + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + minSdkVersion 21 + targetSdkVersion 30 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + // 米盟 SDK + packagingOptions { + doNotStrip "*/*/libmimo_1011.so" + } +} + +dependencies { + // 权限请求框架:https://github.com/getActivity/XXPermissions + api 'com.github.getActivity:XXPermissions:18.63' + // 下拉控件 + api 'com.baoyz.pullrefreshlayout:library:1.2.0' + // 拼音搜索 + // https://mvnrepository.com/artifact/com.github.open-android/pinyin4j + api 'com.github.open-android:pinyin4j:2.5.0' + // SSH + api 'com.jcraft:jsch:0.1.55' + // Html 解析 + api 'org.jsoup:jsoup:1.13.1' + // 二维码类库 + api 'com.google.zxing:core:3.4.1' + api 'com.journeyapps:zxing-android-embedded:3.6.0' + // 应用介绍页类库 + api 'io.github.medyo:android-about-page:2.0.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 'com.miui.zeus:mimo-ad-sdk:5.3.+'//请使用最新版sdk + //注意:以下5个库必须要引入 + //implementation 'androidx.appcompat:appcompat:1.4.1' + api 'androidx.recyclerview:recyclerview:1.0.0' + api 'com.google.code.gson:gson:2.8.5' + api 'com.github.bumptech.glide:glide:4.9.0' + //annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' + + // WinBoLL库 nexus.winboll.cc 地址 + api 'cc.winboll.studio:libappbase:15.15.3' + // 备用库 jitpack.io 地址 + //api 'com.github.ZhanGSKen:APPBase:appbase-v15.15.3' + + api fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/libaes/build.properties b/libaes/build.properties new file mode 100644 index 0000000..c8dc59e --- /dev/null +++ b/libaes/build.properties @@ -0,0 +1,8 @@ +#Created by .winboll/winboll_app_build.gradle +#Sun Jan 11 15:35:24 HKT 2026 +stageCount=1 +libraryProject=libaes +baseVersion=15.15 +publishVersion=15.15.0 +buildCount=0 +baseBetaVersion=15.15.1 diff --git a/libaes/libs/colorpicker-20180319.jar b/libaes/libs/colorpicker-20180319.jar new file mode 100644 index 0000000000000000000000000000000000000000..b010a12b3c7c8e558d6b402f7c8fb58d924ef6a4 GIT binary patch literal 12740 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 literal 0 HcmV?d00001 diff --git a/libaes/proguard-rules.pro b/libaes/proguard-rules.pro new file mode 100644 index 0000000..536058a --- /dev/null +++ b/libaes/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:/tools/adt-bundle-windows-x86_64-20131030/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/libaes/src/main/AndroidManifest.xml b/libaes/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d4325dc --- /dev/null +++ b/libaes/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/DrawerMenuDataAdapter.java b/libaes/src/main/java/cc/winboll/studio/libaes/DrawerMenuDataAdapter.java new file mode 100644 index 0000000..a9e7bf6 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/DrawerMenuDataAdapter.java @@ -0,0 +1,207 @@ +package cc.winboll.studio.libaes; + +import android.content.Context; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; +import java.util.ArrayList; + +public abstract class DrawerMenuDataAdapter extends BaseAdapter { + + private ArrayList mData; + private int mLayoutResource; //布局id + + + public DrawerMenuDataAdapter() { + } + + public DrawerMenuDataAdapter(ArrayList mData, int mLayoutRes) { + this.mData = mData; + this.mLayoutResource = mLayoutRes; + } + + @Override + public int getCount() { + return mData != null ? mData.size() : 0; + } + + @Override + public T getItem(int position) { + return mData.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutResource + , position); + bindView(viewHolder, getItem(position)); + return viewHolder.getItemView(); + } + + public abstract void bindView(ViewHolder holder, T obj); + + // 添加数据项 + // + public void add(T item) { + if (mData == null) { + mData = new ArrayList<>(); + } + mData.add(item); + notifyDataSetChanged(); + } + + // 添加数据项在指定位置 + // + public void add(int position, T item) { + if (mData == null) { + mData = new ArrayList<>(); + } + mData.add(position, item); + notifyDataSetChanged(); + } + + // 删除数据项 + // + public void remove(T item) { + if (mData != null) { + mData.remove(item); + } + notifyDataSetChanged(); + } + + // 删除指定位置数据项 + // + public void remove(int position) { + if (mData != null) { + mData.remove(position); + } + notifyDataSetChanged(); + } + + // 清理所有数据项 + // + public void clear() { + if (mData != null) { + mData.clear(); + } + notifyDataSetChanged(); + } + + + public static class ViewHolder { + + // 存储在 ListView 的 item 中的 View + SparseArray mSparseArrayView; + // 存放convertView + View mViewItem; + // 游标 + int mnPosition; + Context mContext; + + //构造方法 + // + private ViewHolder(Context context, ViewGroup parent, int layoutResource) { + mSparseArrayView = new SparseArray<>(); + this.mContext = context; + View convertView = LayoutInflater.from(context).inflate(layoutResource, parent, false); + convertView.setTag(this); + mViewItem = convertView; + } + + //绑定 ViewHolder 与数据项 + // + public static ViewHolder bind(Context context, View convertView, ViewGroup parent, + int layoutResource, int position) { + ViewHolder viewHolder; + if (convertView == null) { + viewHolder = new ViewHolder(context, parent, layoutResource); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + viewHolder.mViewItem = convertView; + } + viewHolder.mnPosition = position; + return viewHolder; + } + + @SuppressWarnings("unchecked") + public T getView(int id) { + T t = (T) mSparseArrayView.get(id); + if (t == null) { + t = (T) mViewItem.findViewById(id); + mSparseArrayView.put(id, t); + } + return t; + } + + + + // 获取当前条目 + // + public View getItemView() { + return mViewItem; + } + + + // 获取条目位置 + // + public int getItemPosition() { + return mnPosition; + } + + + // 设置文字 + // + public ViewHolder setText(int id, CharSequence text) { + View view = getView(id); + if (view instanceof TextView) { + ((TextView) view).setText(text); + } + return this; + } + + + // 设置图片 + // + public ViewHolder setImageResource(int id, int drawableResource) { + View view = getView(id); + if (view instanceof ImageView) { + ((ImageView) view).setImageResource(drawableResource); + } else { + view.setBackgroundResource(drawableResource); + } + return this; + } + + // 设置点击监听 + // + public ViewHolder setOnClickListener(int id, View.OnClickListener listener) { + getView(id).setOnClickListener(listener); + return this; + } + + // 设置可见 + // + public ViewHolder setVisibility(int id, int visible) { + getView(id).setVisibility(visible); + return this; + } + + // 设置标签 + // + public ViewHolder setTag(int id, Object obj) { + getView(id).setTag(obj); + return this; + } + + } + +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/ImagePagerAdapter.java b/libaes/src/main/java/cc/winboll/studio/libaes/ImagePagerAdapter.java new file mode 100644 index 0000000..488eb8f --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/ImagePagerAdapter.java @@ -0,0 +1,75 @@ +package cc.winboll.studio.libaes; + +import android.view.View; +import android.view.ViewGroup; +import androidx.viewpager.widget.PagerAdapter; +import java.util.List; + +public class ImagePagerAdapter extends PagerAdapter { + + /* + * 四个必须重写的方法,否则会报错 + * + */ + + private List views; + + //构造方法,拿到views + public ImagePagerAdapter(List views) { + this.views = views; + } + + //以下四个是重写的方法 + // 获取要滑动的控件的数量,在这里我们以滑动的广告栏为例,那么这里就应该是展示的广告图片的ImageView数量 + @Override + public int getCount() { + // TODO Auto-generated method stub + return this.views.size(); + } + + + // 来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可 + @Override + public boolean isViewFromObject(View arg0, Object arg1) { + // TODO Auto-generated method stub + return arg0 == arg1; + } + + + /** + * position是在viewPager中显示图片的下标 + * 把对应的图片放到对应的位置就好了 + * instantiateItem和destroyItem是对应的 + * 一个是创建item,一个是销毁item + * 当要显示的图片可以进行缓存的时候,会调用instantiateItem()进行显示图片的初始化, + * 我们将要显示的ImageView加入到ViewGroup中,然后作为返回值返回即可 + * + * ViewPager 是扩展于 ViewGroup,container参数是当前的ViewPager对象, + * 所有的item都会被加入到ViewPager中, + * position就是 每个item对应的下标 + */ + @Override + public Object instantiateItem(ViewGroup container, int position) { + container.addView(views.get(position)); + return views.get(position); + } + + //如果出现IllegalStateException: The specified child already has a parent. 这样的错误:则可替换为以下的try catch 代码 + /*try{ +     if(views.get(position).getParent()==null){ +   container.addView(views.get(position)); +     }else{ + ((ViewGroup)views.get(position).getParent()).removeView(views.get(position)); + container.addView(views.get(position)); + } + }catch(Exception e){ + e.printStackTrace(); + }*/ + + // PagerAdapter只缓存5张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用destroyItem(),将图片销毁 + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView(views.get(position)); + } +} + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java new file mode 100644 index 0000000..430e4fd --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/activitys/DrawerFragmentActivity.java @@ -0,0 +1,400 @@ +package cc.winboll.studio.libaes.activitys; + +/** + * @Author ZhanGSKen + * @Date 2024/06/13 18:58:54 + * @Describe 可以加入Fragment的有抽屉的活动窗口抽象类 + */ +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import cc.winboll.studio.libaes.DrawerMenuDataAdapter; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.models.AESThemeBean; +import cc.winboll.studio.libaes.models.DrawerMenuBean; +import cc.winboll.studio.libaes.utils.AESThemeUtil; +import cc.winboll.studio.libaes.utils.DevelopUtils; +import cc.winboll.studio.libaes.views.ADrawerMenuListView; +import cc.winboll.studio.libaes.views.ADsBannerView; +import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.LogUtils; +import com.baoyz.widget.PullRefreshLayout; +import java.util.ArrayList; + +public abstract class DrawerFragmentActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { + + public static final String TAG = "DrawerFragmentActivity"; + + static final String SHAREDPREFERENCES_NAME = "SHAREDPREFERENCES_NAME"; + static final String DRAWER_THEME_TYPE = "DRAWER_THEME_TYPE"; + + //protected Context mContext; + ActivityType mActivityType; + ActionBarDrawerToggle mActionBarDrawerToggle; + DrawerLayout mDrawerLayout; + PullRefreshLayout mPullRefreshLayout; + ADrawerMenuListView mADrawerMenuListView; + DrawerMenuDataAdapter mDrawerMenuDataAdapter; + boolean mIsDrawerOpened = false; + boolean mIsDrawerOpening = false; + boolean mIsDrawerClosing = false; + + protected Toolbar mToolbar; + public enum ActivityType { Main, Secondary } + protected volatile AESThemeBean.ThemeType mThemeType; + protected ArrayList malDrawerMenuItem; + abstract protected ActivityType initActivityType(); + //abstract protected View initContentView(LayoutInflater inflater, ViewGroup rootView); + + @Override + protected void onCreate(Bundle savedInstanceState) { + //mContext = this; + mThemeType = getThemeType(); + setThemeStyle(); + super.onCreate(savedInstanceState); + mActivityType = initActivityType(); + initRootView(); + LogUtils.d(TAG, "onCreate end."); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + // 修复:释放广告资源,避免内存泄漏 + ADsBannerView adsBannerView = findViewById(R.id.adsbanner); + if (adsBannerView != null) { + adsBannerView.releaseAdResources(); + } + } + + /*@Override + public Intent getIntent() { + // TODO: Implement this method + return super.getIntent(); + } + + public Context getContext() { + return this.mContext; + }*/ + + @Override + public MenuInflater getMenuInflater() { + // TODO: Implement this method + return super.getMenuInflater(); + } + + /*public void setSubtitle(CharSequence context) { + // TODO: Implement this method + getSupportActionBar().setSubtitle(context); + }*/ + + @Override + public void recreate() { + super.recreate(); + } + + /*@Override + public boolean moveTaskToBack(boolean nonRoot) { + return super.moveTaskToBack(nonRoot); + }*/ + + @Override + public void startActivity(Intent intent) { + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode, Bundle options) { + super.startActivityForResult(intent, requestCode, options); + } + + /*@Override + public FragmentManager getSupportFragmentManager() { + return super.getSupportFragmentManager(); + } + + public void setSubtitle(int resId) { + // TODO: Implement this method + getSupportActionBar().setSubtitle(resId); + } + + public void setTitle(CharSequence context) { + // TODO: Implement this method + getSupportActionBar().setTitle(context); + } + + public void setTitle(int resId) { + // TODO: Implement this method + getSupportActionBar().setTitle(resId); + }*/ + + @Override + public SharedPreferences getSharedPreferences(String name, int mode) { + return super.getSharedPreferences(name, mode); + } + + @Override + public Context getApplicationContext() { + // TODO: Implement this method + return super.getApplicationContext(); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + void setThemeStyle() { + //setTheme(AESThemeBean.getThemeStyle(getThemeType())); + setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext())); + } + + boolean checkThemeStyleChange() { + return mThemeType != getThemeType(); + } + + 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())); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (AESThemeUtil.onAppThemeItemSelected(this, item)) { + recreate(); + } if (DevelopUtils.onDevelopItemSelected(this, item)) { + LogUtils.d(TAG, String.format("onOptionsItemSelected item.getItemId() %d ", item.getItemId())); + } else { + return super.onOptionsItemSelected(item); + } + + return true; + } + + @Override + protected void onResume() { + super.onResume(); + if (checkThemeStyleChange()) { + recreate(); + } + + ADsBannerView adsBannerView = findViewById(R.id.adsbanner); + if (adsBannerView != null) { + adsBannerView.resumeADs(DrawerFragmentActivity.this); + } + } + + void initRootView() { + setContentView(R.layout.activity_drawerfragment); + + mToolbar = findViewById(R.id.activitydrawerfragmentASupportToolbar1); + setSupportActionBar(mToolbar); + + if (mActivityType == ActivityType.Main) { + initMainRootView(); + } else if (mActivityType == ActivityType.Secondary) { + initSecondaryRootView(); + } + } + + void initMainRootView() { + mDrawerLayout = findViewById(R.id.activitydrawerfragmentDrawerLayout1); + mADrawerMenuListView = findViewById(R.id.activitydrawerfragmentDrawerMenuListView1); + mPullRefreshLayout = findViewById(R.id.activitydrawerfragmentPullRefreshLayout1); + + mPullRefreshLayout.setOnRefreshListener(new PullRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + //LogUtils.d(TAG, "onRefresh"); + reinitDrawerMenuItemList(malDrawerMenuItem); + mDrawerMenuDataAdapter.notifyDataSetChanged(); + mPullRefreshLayout.setRefreshing(false); + } + }); + + malDrawerMenuItem = new ArrayList(); + + mDrawerMenuDataAdapter = new DrawerMenuDataAdapter(malDrawerMenuItem, R.layout.listview_drawermenu) { + @Override + public void bindView(ViewHolder holder, DrawerMenuBean obj) { + holder.setImageResource(R.id.listviewdrawermenuImageView1, obj.getIconId()); + holder.setText(R.id.listviewdrawermenuTextView1, obj.getIconName()); + } + }; + mADrawerMenuListView.setAdapter(mDrawerMenuDataAdapter); + mADrawerMenuListView.setOnItemClickListener(this); + + mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.lib_name, R.string.lib_name) { + @Override + public void onDrawerOpened(View drawerView) {//完全打开时触发 + super.onDrawerOpened(drawerView); + mIsDrawerOpened = true; + mIsDrawerOpening = false; + //Toast.makeText(MainActivity.this,"onDrawerOpened",Toast.LENGTH_SHORT).show(); + } + + @Override + public void onDrawerClosed(View drawerView) {//完全关闭时触发 + super.onDrawerClosed(drawerView); + mIsDrawerOpened = false; + mIsDrawerClosing = false; + //Toast.makeText(MainActivity.this,"onDrawerClosed",Toast.LENGTH_SHORT).show(); + } + + /** + * 当抽屉被滑动的时候调用此方法 + * slideOffset表示 滑动的幅度(0-1) + */ + @Override + public void onDrawerSlide(View drawerView, float slideOffset) { + super.onDrawerSlide(drawerView, slideOffset); + } + + /** + * 当抽屉滑动状态改变的时候被调用 + * 状态值是STATE_IDLE(闲置--0), STATE_DRAGGING(拖拽的--1), STATE_SETTLING(固定--2)中之一。 + *具体状态可以慢慢调试 + */ + @Override + public void onDrawerStateChanged(int newState) { + super.onDrawerStateChanged(newState); + } + }; + + //设置显示旋转菜单 + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + //通过下面这句实现toolbar和Drawer的联动:如果没有这行代码,箭头是不会随着侧滑菜单的开关而变换的(或者没有箭头), + // 可以尝试一下,不影响正常侧滑 + mActionBarDrawerToggle.syncState(); + mDrawerLayout.setDrawerListener(mActionBarDrawerToggle); + + //去掉侧滑的默认图标(动画箭头图标),也可以选择不去, + //不去的话把这一行注释掉或者改成true,然后把toolbar.setNavigationIcon注释掉就行了 + //mActionBarDrawerToggle.setDrawerIndicatorEnabled(false); + mToolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mIsDrawerOpened || mIsDrawerOpening) { + mIsDrawerClosing = true; + mIsDrawerOpening = false; + mDrawerLayout.closeDrawer(mPullRefreshLayout); + return; + } + if (!mIsDrawerOpened || mIsDrawerClosing) { + mIsDrawerOpening = true; + mIsDrawerClosing = false; + mDrawerLayout.openDrawer(mPullRefreshLayout); + return; + } + } + }); + + initDrawerMenuItemList(malDrawerMenuItem); + } + + void initSecondaryRootView() { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + mToolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //LogUtils.d(TAG, "onClick " + Integer.toString(v.getId())); + finish(); + } + }); + } + + public int removeFragment(T fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.remove(fragment); + fragmentTransaction.commit(); + return fragmentManager.getFragments().size() - 1; + } + + public int addFragment(T fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.add(R.id.activitydrawerfragmentFrameLayout1, fragment); + fragmentTransaction.commit(); + return fragmentManager.getFragments().size() - 1; + } + + public void showFragment(T fragment) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + for (int i = 0; i < fragmentManager.getFragments().size(); i++) { + if (fragmentManager.getFragments().get(i).equals(fragment)) { + fragmentTransaction.show(fragmentManager.getFragments().get(i)); + } else { + fragmentTransaction.hide(fragmentManager.getFragments().get(i)); + } + } + fragmentTransaction.commit(); + } + + public void showFragment(int nPosition) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + for (int i = 0; i < fragmentManager.getFragments().size(); i++) { + if (i == nPosition) { + fragmentTransaction.show(fragmentManager.getFragments().get(i)); + } else { + fragmentTransaction.hide(fragmentManager.getFragments().get(i)); + } + } + fragmentTransaction.commit(); + } + + protected void initDrawerMenuItemList(ArrayList listDrawerMenu) { + + } + + protected void reinitDrawerMenuItemList(ArrayList listDrawerMenu) { + + } + + public void notifyDrawerMenuDataChanged() { + mDrawerMenuDataAdapter.notifyDataSetChanged(); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + mDrawerLayout.closeDrawer(mPullRefreshLayout); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + if (mActivityType == ActivityType.Main) { + // 主题菜单 + AESThemeUtil.inflateMenu(this, menu); + // 调试工具菜单 + if (GlobalApplication.isDebugging()) { + DevelopUtils.inflateMenu(this, menu); + } + // 应用信息菜单 + getMenuInflater().inflate(R.menu.toolbar_drawerbase, menu); + } + return super.onCreateOptionsMenu(menu); + } + + @Override + protected void onActivityResult(int who, int targetFragment, Intent requestCode) { + super.onActivityResult(who, targetFragment, requestCode); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/LocalFileSelectDialog.java b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/LocalFileSelectDialog.java new file mode 100644 index 0000000..c181865 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/LocalFileSelectDialog.java @@ -0,0 +1,204 @@ +package cc.winboll.studio.libaes.dialogs; + +import android.content.Context; +import android.content.DialogInterface; +import android.widget.TextView; +import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; +import cc.winboll.studio.libappbase.LogUtils; +import java.io.File; +import java.lang.reflect.Field; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +public class LocalFileSelectDialog { + + public static final String TAG = LocalFileSelectDialog.class.getSimpleName(); + + File mfCurrentPath = new File("/storage/emulated/0"); + String mszResultPath = "/storage/emulated/0"; + OKClickListener mOKClickListener; + + Context mContext; + + public LocalFileSelectDialog(Context context) { + mContext = context; + } + + public void open() { + LogUtils.d(TAG, "call open()"); + String[] szlist = getChildFileList(mfCurrentPath); + if (szlist != null) { + showSingleChoiceDialog(szlist, 0); + } + } + + int yourChoice; + protected void showSingleChoiceDialog(final String[] szItems, final int nChoice) { + LogUtils.d(TAG, "call showSingleChoiceDialog(...)"); + yourChoice = nChoice; + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + String sz = mfCurrentPath.getPath(); + + builder.setTitle(sz); + //builder.setCancelable(false); + builder.setSingleChoiceItems(szItems, nChoice, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + yourChoice = which; + } + }); + // 确定按钮 + builder.setPositiveButton("确定", + new DialogInterface.OnClickListener() { + + @Override + public void onClick( + DialogInterface dialog, + int which) { + mszResultPath = mfCurrentPath.getPath() + File.separator + szItems[yourChoice]; + //Toast.makeText(mContext, mszResultPath, Toast.LENGTH_SHORT).show(); + mOKClickListener.onOKClick(mszResultPath); + } + }); + // 下一层文件按钮 + builder.setNegativeButton(">>>", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + File file = new File(mfCurrentPath.getPath() + File.separator + szItems[yourChoice]); + String[] szlist = getChildFileList(file); + if (szlist != null) { + mfCurrentPath = new File(mfCurrentPath.getPath() + File.separator + szItems[yourChoice]); + + showSingleChoiceDialog(szlist, 0); + + } else { + Toast.makeText(mContext, "这是一个最低的目录", Toast.LENGTH_SHORT).show(); + String[] szlistOld = getChildFileList(mfCurrentPath); + showSingleChoiceDialog(szlistOld, yourChoice); + } + + } + }); + // 上一层文件按钮 + builder.setNeutralButton("<<<", + new DialogInterface.OnClickListener() {// 添加返回按钮 + + @Override + public void onClick( + DialogInterface dialog, + int which) {// 响应事件 + + String[] szlist = getChildFileList(mfCurrentPath.getParentFile()); + if (szlist != null) { + mfCurrentPath = mfCurrentPath.getParentFile(); + + showSingleChoiceDialog(szlist, 0); + + } else { + Toast.makeText(mContext, "这是一个最高的目录", Toast.LENGTH_SHORT).show(); + String[] szlistOld = getChildFileList(mfCurrentPath); + showSingleChoiceDialog(szlistOld, yourChoice); + } + + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); + + // 反射原理修改对话框元素 + // + //需要在show()方法之后才能修改 + //修改“确认”、“取消”按钮的字体大小 + //dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextSize(16); + //dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextSize(16); + //dialog.getButton(DialogInterface.BUTTON_NEUTRAL).setTextSize(16); + try { + Field mAlert = AlertDialog.class.getDeclaredField("mAlert"); + mAlert.setAccessible(true); + Object mAlertController = mAlert.get(dialog); + + //通过反射修改title字体大小和颜色 + Field mTitle = mAlertController.getClass().getDeclaredField("mTitleView"); + mTitle.setAccessible(true); + TextView mTitleView = (TextView) mTitle.get(mAlertController); + //mTitleView.setTextSize(16); + //mTitleView.setTextColor(Color.RED); + mTitleView.setSingleLine(false); + + //通过反射修改message字体大小和颜色 + //Field mMessage = mAlertController.getClass().getDeclaredField("mMessageView"); + //mMessage.setAccessible(true); + //TextView mMessageView = (TextView) mMessage.get(mAlertController); + //mMessageView.setTextSize(16); + //mMessageView.setTextColor(Color.GREEN); + } catch (IllegalAccessException e) { + LogUtils.d(TAG, "IllegalAccessException : " + e.getMessage()); + } catch (NoSuchFieldException e) { + LogUtils.d(TAG, "NoSuchFieldException : " + e.getMessage()); + } + } + + public void setOnOKClickListener(OKClickListener listener) { + mOKClickListener = listener; + } + + public interface OKClickListener { + void onOKClick(String szResultPath); + } + + // 读取文件夹子目录 + // + // "/storage/emulated/0"以上 + // 和没有子目录的f参数返回空列表 + protected String[] getChildFileList(File file) { + ArrayList szlistFiles = new ArrayList(); + if (!file.getPath().equals("/storage/emulated")) { + File[] fileList = file.listFiles(); + if (fileList != null) { + for (File fileItem : fileList) { + if (fileItem.getName().charAt(0) != '.') { + if (fileItem.isDirectory()) { + szlistFiles.add(fileItem.getName()); + } + } + } + } + } + Collections.sort(szlistFiles, new SortChineseName(true)); + + if (szlistFiles.size() > 0) { + return szlistFiles.toArray(new String[szlistFiles.size()]); + } else { + return null; + } + } + + private class SortChineseName implements Comparator { + private boolean mIsA2Z = true; + public SortChineseName(boolean isA2Z) { + mIsA2Z = isA2Z; + } + Collator cmp = Collator.getInstance(java.util.Locale.CHINA); + @Override + public int compare(String o1, String o2) { + if (mIsA2Z) { + if (cmp.compare(o1, o2) > 0) { + return 1; + } else if (cmp.compare(o1, o2) < 0) { + return -1; + } + } else { + if (cmp.compare(o1, o2) > 0) { + return -1; + } else if (cmp.compare(o1, o2) < 0) { + return 1; + } + } + return 0; + } + } + +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/StoragePathDialog.java b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/StoragePathDialog.java new file mode 100644 index 0000000..2870a0f --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/StoragePathDialog.java @@ -0,0 +1,57 @@ +package cc.winboll.studio.libaes.dialogs; + +import android.app.Dialog; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.utils.ScreenUtil; + +public class StoragePathDialog extends Dialog { + + public static final String TAG = "StoragePathDialog"; + View.OnClickListener mOnOKClickListener; + + public StoragePathDialog(android.content.Context context) { + super(context); + + } + + public StoragePathDialog(android.content.Context context, int themeResId) { + super(context, (themeResId == 0) ? cc.winboll.studio.libaes.R.style.NormalDialogStyle: themeResId); + // 加载默认布局 + View view = View.inflate(context, R.layout.dialog_storagepath, null); + setContentView(view); + // 添加按键点击监听 + view.findViewById(R.id.dialogstoragepathButton1).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (mOnOKClickListener != null) { + mOnOKClickListener.onClick(view); + } + } + }); + // 使得点击对话框外部不消失对话框 + setCanceledOnTouchOutside(false); + // 设置对话框大小 + ScreenUtil.ScreenSize ss = ScreenUtil.getScreenSize(context); + view.setMinimumHeight((int) (ss.getHeightPixels() * 0.23f)); + Window dialogWindow = getWindow(); + WindowManager.LayoutParams lp = dialogWindow.getAttributes(); + lp.width = (int) (ss.getWidthPixels() * 0.75f); + lp.height = WindowManager.LayoutParams.WRAP_CONTENT; + lp.gravity = Gravity.CENTER; + dialogWindow.setAttributes(lp); + + } + + protected StoragePathDialog(android.content.Context context, boolean cancelable, android.content.DialogInterface.OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + } + + public void setOnOKClickListener(View.OnClickListener listener) { + mOnOKClickListener = listener; + } + +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java new file mode 100644 index 0000000..f176daa --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/dialogs/YesNoAlertDialog.java @@ -0,0 +1,60 @@ +package cc.winboll.studio.libaes.dialogs; + +/** + * @Author ZhanGSKen + * @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/libaes/src/main/java/cc/winboll/studio/libaes/enums/ADsMode.java b/libaes/src/main/java/cc/winboll/studio/libaes/enums/ADsMode.java new file mode 100644 index 0000000..a43743c --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/enums/ADsMode.java @@ -0,0 +1,32 @@ +package cc.winboll.studio.libaes.enums; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/26 17:49 + * @Describe 广告控制模式枚举 + */ +public enum ADsMode { + STANDALONE("单机模式"), // 单机模式(默认) + MIMO_SDK("米盟广告SDK支持模式"), // 米盟广告SDK模式 + STORE_QRCODE("云宝物语模式"); // 米盟广告SDK模式 + + private final String modeName; + + ADsMode(String modeName) { + this.modeName = modeName; + } + + public String getModeName() { + return modeName; + } + + // 根据保存的字符串值解析枚举(SP读取时使用) + public static ADsMode fromValue(String value) { + if (value == null) return STANDALONE; + try { + return ADsMode.valueOf(value); + } catch (IllegalArgumentException e) { + return STANDALONE; + } + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/enums/PrivacyAgreeStatus.java b/libaes/src/main/java/cc/winboll/studio/libaes/enums/PrivacyAgreeStatus.java new file mode 100644 index 0000000..fe9e133 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/enums/PrivacyAgreeStatus.java @@ -0,0 +1,67 @@ +package cc.winboll.studio.libaes.enums; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/27 12:35 + * @Describe 隐私协议签约状态枚举 + * 对应值:0-拒绝,1-赞同,2-未签约(默认) + */ +public enum PrivacyAgreeStatus { + REJECTED(0, "拒绝"), // 0: 拒绝隐私协议 + AGREED(1, "赞同"), // 1: 赞同隐私协议 + UN_SIGNED(2, "未签约"); // 2: 未签约(初始默认状态) + + private final int statusCode; // 对应存储的int值 + private final String statusDesc; // 状态描述(可选,便于日志/UI显示) + + // Java 7 枚举构造方法(必须private) + private PrivacyAgreeStatus(int statusCode, String statusDesc) { + this.statusCode = statusCode; + this.statusDesc = statusDesc; + } + + /** + * 根据int值获取枚举(SP读取时使用,兼容Java 7) + * @param code 存储的int值(0/1/2) + * @return 对应枚举,默认返回UN_SIGNED(未签约) + */ + public static PrivacyAgreeStatus fromCode(int code) { + // Java 7 不支持switch(String),用if-else兼容 + if (code == REJECTED.statusCode) { + return REJECTED; + } else if (code == AGREED.statusCode) { + return AGREED; + } else { + return UN_SIGNED; // 默认未签约 + } + } + + /** + * 根据SP存储的字符串值获取枚举(兼容原逻辑中String类型存储) + * @param codeStr 存储的字符串值("0"/"1"/"2") + * @return 对应枚举,默认返回UN_SIGNED(未签约) + */ + public static PrivacyAgreeStatus fromString(String codeStr) { + if (codeStr == null) { + return UN_SIGNED; + } + try { + int code = Integer.parseInt(codeStr); + return fromCode(code); + } catch (NumberFormatException e) { + // 字符串格式异常时,默认返回未签约 + return UN_SIGNED; + } + } + + // 获取状态码(用于存储到SP) + public int getStatusCode() { + return statusCode; + } + + // 获取状态描述(用于日志/UI显示,可选) + public String getStatusDesc() { + return statusDesc; + } +} + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java new file mode 100644 index 0000000..aa4805b --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/interfaces/IWinBoLLActivity.java @@ -0,0 +1,18 @@ +package cc.winboll.studio.libaes.interfaces; + +/** + * @Author ZhanGSKen + * @Date 2025/05/10 09:34 + * @Describe WinBoLL 窗口操作接口 + */ + import android.app.Activity; + +public abstract interface IWinBoLLActivity { + + public static final String TAG = "IWinBoLLActivity"; + + public static final String ACTION_BIND = IWinBoLLActivity.class.getName() + ".ACTION_BIND"; + + public Activity getActivity(); + public String getTag(); +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java new file mode 100644 index 0000000..dd4d8d8 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/AESThemeBean.java @@ -0,0 +1,143 @@ +package cc.winboll.studio.libaes.models; + +/** + * @Author ZhanGSKen + * @Date 2024/06/14 02:42:57 + * @Describe 主题元素项目类 + */ +import android.util.JsonReader; +import android.util.JsonWriter; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libappbase.BaseBean; +import java.io.IOException; + +public class AESThemeBean extends BaseBean { + + public static final String TAG = "AESThemeBean"; + + public enum ThemeType { + AES("默认主题"), + DEPTH("深奥主题"), + SKY("天空主题"), + GOLDEN("辉煌主题"), + BEARING("智芋主题"), + MEMOR("梦箩主题"), + TAO("黑白主题"); + + private String name; + + // 枚举构造函数 + ThemeType(String name) { + this.name = name; + } + + // 将字符串转换为枚举 + public static ThemeType fromString(String themeTypeStr) { + return ThemeType.valueOf(themeTypeStr.toUpperCase()); // 注意这里用了toUpperCase(),确保匹配时不区分大小写 + } + + // 获取枚举的名称 + public String getName() { + return name; + } + } + + // 保存当前主题 + int currentThemeStyleID = getThemeStyleID(ThemeType.AES); + + public AESThemeBean() { + } + + public AESThemeBean(int currentThemeStyleID) { + this.currentThemeStyleID = currentThemeStyleID; + } + + public void setCurrentThemeTypeID(int currentThemeTypeID) { + this.currentThemeStyleID = currentThemeTypeID; + } + + public int getCurrentThemeTypeID() { + return this.currentThemeStyleID; + } + + @Override + public String getName() { + return AESThemeBean.class.getName(); + } + + @Override + public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException { + super.writeThisToJsonWriter(jsonWriter); + AESThemeBean bean = this; + jsonWriter.name("currentThemeTypeID").value(bean.getCurrentThemeTypeID()); + } + + @Override + public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException { + if(super.initObjectsFromJsonReader(jsonReader, name)) { return true; } + else{ + if (name.equals("currentThemeTypeID")) { + setCurrentThemeTypeID(jsonReader.nextInt()); + } else { + return false; + } + } + return true; + } + + @Override + public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException { + jsonReader.beginObject(); + while (jsonReader.hasNext()) { + String name = jsonReader.nextName(); + if(!initObjectsFromJsonReader(jsonReader, name)) { + jsonReader.skipValue(); + } + } + // 结束 JSON 对象 + jsonReader.endObject(); + return this; + } + + public static int getThemeStyleID(ThemeType themeType) { + int themeStyleID = R.style.AESTheme; + if (AESThemeBean.ThemeType.DEPTH == themeType) { + themeStyleID = R.style.DepthAESTheme; + } else if (AESThemeBean.ThemeType.SKY == themeType) { + themeStyleID = R.style.SkyAESTheme; + } else if (AESThemeBean.ThemeType.GOLDEN == themeType) { + themeStyleID = R.style.GoldenAESTheme; + } else if (AESThemeBean.ThemeType.BEARING == themeType) { + themeStyleID = R.style.BearingAESTheme; + } else if (AESThemeBean.ThemeType.MEMOR == themeType) { + themeStyleID = R.style.MemorAESTheme; + } else if (AESThemeBean.ThemeType.TAO == themeType) { + themeStyleID = R.style.TaoAESTheme; + } else if (AESThemeBean.ThemeType.AES == themeType) { + themeStyleID = R.style.AESTheme; + } + //LogUtils.d(TAG, "themeStyleID " + Integer.toString(themeStyleID)); + return themeStyleID; + } + + public static AESThemeBean.ThemeType getThemeStyleType(int nThemeStyleID) { + AESThemeBean.ThemeType themeStyle = AESThemeBean.ThemeType.AES; + if (R.style.DepthAESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.DEPTH ; + } else if (R.style.SkyAESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.SKY ; + } else if (R.style.GoldenAESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.GOLDEN ; + } else if (R.style.BearingAESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.BEARING ; + } else if (R.style.MemorAESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.MEMOR ; + } else if (R.style.TaoAESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.TAO ; + } else if (R.style.AESTheme == nThemeStyleID) { + themeStyle = AESThemeBean.ThemeType.AES; + } + //LogUtils.d(TAG, "themeStyle " + Integer.toString(themeStyle.ordinal())); + return themeStyle; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java new file mode 100644 index 0000000..cf097e0 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/APPInfo.java @@ -0,0 +1,169 @@ +package cc.winboll.studio.libaes.models; + +/** + * @Author ZhanGSKen + * @Date 2025/01/20 14:19:02 + * @Describe 应用信息类 + */ +import cc.winboll.studio.libaes.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; + // 是否添加调试工具 + boolean isAddDebugTools; + + 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; + this.isAddDebugTools = false; + } + + public APPInfo(String appName, int appIcon, String appDescription, String appGitName, String appGitOwner, String appGitAPPBranch, String appGitAPPSubProjectFolder, String appHomePage, String appAPKName, String appAPKFolderName, boolean isAddDebugTools) { + 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; + this.isAddDebugTools = isAddDebugTools; + } + + public APPInfo() { + String szBranchName = "app"; + this.appName = "APP"; + this.appIcon = R.drawable.ic_launcher; + this.appDescription = "APP Description"; + this.appGitName = "APP"; + this.appGitOwner = "Studio"; + this.appGitAPPBranch = szBranchName; + this.appGitAPPSubProjectFolder = szBranchName; + this.appHomePage = "https://www.winboll.cc/studio/details.php?app=APP"; + this.appAPKName = "APP"; + this.appAPKFolderName = "APP"; + this.isAddDebugTools = false; + } + + public void setIsAddDebugTools(boolean isAddDebugTools) { + this.isAddDebugTools = isAddDebugTools; + } + + public boolean isAddDebugTools() { + return isAddDebugTools; + } + + 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/models/DrawerMenuBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/DrawerMenuBean.java new file mode 100644 index 0000000..662d4d4 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/DrawerMenuBean.java @@ -0,0 +1,35 @@ +package cc.winboll.studio.libaes.models; + +/** + * @Author ZhanGSKen + * @Date 2024/06/14 01:53:34 + * @Describe 抽屉菜单项目类 + */ +public class DrawerMenuBean { + + public static final String TAG = "DrawerMenuBean"; + + private int iconId; + private String iconName; + + public DrawerMenuBean(int iconId, String iconName) { + this.iconId = iconId; + this.iconName = iconName; + } + + public int getIconId() { + return iconId; + } + + public String getIconName() { + return iconName; + } + + public void setIconId(int iconId) { + this.iconId = iconId; + } + + public void setIconName(String iconName) { + this.iconName = iconName; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java b/libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java new file mode 100644 index 0000000..dcd112b --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/models/WinBoLLClientServiceBean.java @@ -0,0 +1,78 @@ +package cc.winboll.studio.libaes.models; + +/** + * @Author ZhanGSKen + * @Date 2025/05/03 19:16 + */ +import android.content.Context; +import android.util.JsonReader; +import android.util.JsonWriter; +import cc.winboll.studio.libappbase.BaseBean; +import java.io.IOException; + +public class WinBoLLClientServiceBean extends BaseBean { + + public static final String TAG = "WinBoLLClientServiceBean"; + + // 服务是否正在使用中 + boolean isEnable; + + public WinBoLLClientServiceBean() { + this.isEnable = false; + } + + public WinBoLLClientServiceBean(boolean isEnable) { + this.isEnable = isEnable; + } + + public void setIsEnable(boolean isEnable) { + this.isEnable = isEnable; + } + + public boolean isEnable() { + return isEnable; + } + + + @Override + public String getName() { + return WinBoLLClientServiceBean.class.getName(); + } + + @Override + public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException { + super.writeThisToJsonWriter(jsonWriter); + WinBoLLClientServiceBean bean = this; + //jsonWriter.name("logLevel").value(bean.getLogLevel().ordinal()); + } + + @Override + public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException { + if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else { +// if (name.equals("logLevel")) { +// setLogLevel(LogUtils.LOG_LEVEL.values()[jsonReader.nextInt()]); +// } else { +// return false; +// } + } + return true; + } + + @Override + public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException { + jsonReader.beginObject(); + while (jsonReader.hasNext()) { + String name = jsonReader.nextName(); + if (!initObjectsFromJsonReader(jsonReader, name)) { + jsonReader.skipValue(); + } + } + // 结束 JSON 对象 + jsonReader.endObject(); + return this; + } + + public static WinBoLLClientServiceBean loadWinBoLLClientServiceBean(Context context) { + return new WinBoLLClientServiceBean(); + } +} 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 new file mode 100644 index 0000000..2373d6a --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryActivity.java @@ -0,0 +1,62 @@ +package cc.winboll.studio.libaes.unittests; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.Toast; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; + +/** + * @Author ZhanGSKen + * @Date 2024/06/15 00:58:10 + * @Describe 第二级窗口 + */ +public class SecondaryLibraryActivity extends DrawerFragmentActivity implements IWinBoLLActivity { + + public static final String TAG = "SecondaryLibraryActivity"; + + SecondaryLibraryFragment mSecondaryLibraryFragment; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return null; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (mSecondaryLibraryFragment == null) { + mSecondaryLibraryFragment = new SecondaryLibraryFragment(); + addFragment(mSecondaryLibraryFragment); + } + showFragment(mSecondaryLibraryFragment); + } + + @Override + public DrawerFragmentActivity.ActivityType initActivityType() { + return DrawerFragmentActivity.ActivityType.Secondary; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.toolbar_secondarylibrary, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int nItemId = item.getItemId(); + if (nItemId == R.id.item_test) { + Toast.makeText(getApplicationContext(), "item_test", Toast.LENGTH_SHORT).show(); + } + return super.onOptionsItemSelected(item); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryFragment.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryFragment.java new file mode 100644 index 0000000..c0ddc14 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/SecondaryLibraryFragment.java @@ -0,0 +1,25 @@ +package cc.winboll.studio.libaes.unittests; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 02:36:34 + * @Describe SecondaryLibraryFragment + */ +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.fragment.app.Fragment; +import cc.winboll.studio.libaes.R; + +public class SecondaryLibraryFragment extends Fragment { + + public static final String TAG = "SecondaryLibraryFragment"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_secondarylibrary, container, false); + + return view; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java new file mode 100644 index 0000000..ce837aa --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAButtonFragment.java @@ -0,0 +1,37 @@ +package cc.winboll.studio.libaes.unittests; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:27:50 + * @Describe TestAButtonFragment + */ +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.fragment.app.Fragment; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.views.AButton; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.ToastUtils; + +public class TestAButtonFragment extends Fragment { + + public static final String TAG = "TestAButtonFragment"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_abutton, container, false); + AButton aButton = view.findViewById(R.id.fragmentabuttonAButton1); + aButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View view) { + LogUtils.d(TAG, "onClick"); + ToastUtils.show("AButton"); + } + + }); + return view; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java new file mode 100644 index 0000000..6fa37b6 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestASupportToolbarActivity.java @@ -0,0 +1,42 @@ +package cc.winboll.studio.libaes.unittests; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:14:00 + * @Describe TestASupportToolbarActivity + */ +import android.app.Activity; +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.utils.AESThemeUtil; + +public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBoLLActivity { + + public static final String TAG = "TestASupportToolbarActivity"; + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return TAG; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + AESThemeUtil.applyAppTheme(this); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_testasupporttoolbar); + Toolbar toolbar = findViewById(R.id.activitytestasupporttoolbarASupportToolbar1); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle(TAG); + + } + + +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java new file mode 100644 index 0000000..bba25fc --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestAToolbarActivity.java @@ -0,0 +1,28 @@ +package cc.winboll.studio.libaes.unittests; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:16:07 + * @Describe TestAToolbarActivity + */ +import android.app.Activity; +import android.os.Bundle; +import android.widget.Toolbar; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.utils.AESThemeUtil; + +public class TestAToolbarActivity extends Activity { + + public static final String TAG = "TestAToolbarActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + AESThemeUtil.applyAppTheme(this); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_testatoolbar); + Toolbar toolbar = findViewById(R.id.activitytestatoolbarAToolbar1); + setActionBar(toolbar); + getActionBar().setTitle(TAG); + } + +} 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 new file mode 100644 index 0000000..ab4fc2b --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestDrawerFragmentActivity.java @@ -0,0 +1,124 @@ +package cc.winboll.studio.libaes.unittests; + +/** + * @Author ZhanGSKen + * @Date 2024/06/30 15:00:51 + */ +import android.app.Activity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.Toast; +import androidx.fragment.app.Fragment; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libaes.models.DrawerMenuBean; +import cc.winboll.studio.libappbase.LogUtils; +import java.util.ArrayList; + +public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBoLLActivity { + + @Override + public Activity getActivity() { + return this; + } + + @Override + public String getTag() { + return null; + } + + public static final String TAG = "TestDrawerFragmentActivity"; + + TestFragment1 mTestFragment1; + TestFragment2 mTestFragment2; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mTestFragment1 = new TestFragment1(); + addFragment(mTestFragment1); + mTestFragment2 = new TestFragment2(); + addFragment(mTestFragment2); + showFragment(0); + } + + @Override + protected DrawerFragmentActivity.ActivityType initActivityType() { + return DrawerFragmentActivity.ActivityType.Main; + } + + @Override + public void initDrawerMenuItemList(ArrayList listDrawerMenu) { + super.initDrawerMenuItemList(listDrawerMenu); + LogUtils.d(TAG, "initDrawerMenuItemList"); + //listDrawerMenu.clear(); + // 添加抽屉菜单项 + listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestFragment1.TAG)); + listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestFragment2.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, TestFragment1.TAG)); + listDrawerMenu.add(new DrawerMenuBean(R.drawable.ic_launcher, TestFragment2.TAG)); + notifyDrawerMenuDataChanged(); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + super.onItemClick(parent, view, position, id); + switch (position) { + case 0 : { + Toast.makeText(getApplicationContext(), "0", Toast.LENGTH_SHORT).show(); + //LogUtils.d(TAG, "MenuItem 1"); + showFragment(mTestFragment1); + break; + } + case 1 : { + //LogUtils.d(TAG, "MenuItem 2"); + showFragment(mTestFragment2); + break; + } + + } + } + + public static class TestFragment1 extends Fragment { + + public static final String TAG = "TestFragment1"; + + View mView; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_test1, container, false); + + return mView; + } + + } + + public static class TestFragment2 extends Fragment { + + public static final String TAG = "TestFragment2"; + + View mView; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_test2, container, false); + + return mView; + } + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java new file mode 100644 index 0000000..1d922fa --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/unittests/TestViewPageFragment.java @@ -0,0 +1,226 @@ +package cc.winboll.studio.libaes.unittests; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:35:56 + * @Describe TestViewPageFragment + */ +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; +import cc.winboll.studio.libaes.ImagePagerAdapter; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.views.AOHPCTCSeekBar; +import cc.winboll.studio.libappbase.LogView; +import cc.winboll.studio.libappbase.ToastUtils; +import java.util.ArrayList; +import java.util.List; + +public class TestViewPageFragment extends Fragment implements ViewPager.OnPageChangeListener, View.OnClickListener { + + public static final String TAG = "TestViewPageFragment"; + + Context mContext; + LogView mLogView; + + private ViewPager viewPager; + private List views; //用来存放放进ViewPager里面的布局 + //实例化存储imageView(导航原点)的集合 + ImageView[] imageViews; + private ImagePagerAdapter adapter;//适配器 + private LinearLayout linearLayout;//下标所在在LinearLayout布局里 + private int currentPoint = 0;//当前被选中中页面的下标 + View mView; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_viewpage, container, false); + mContext = getActivity(); + + mLogView = mView.findViewById(R.id.logview); + mLogView.start(); + + //viewPager = findViewById(R.id.activitymainViewPager1); + initData(); + initView();//调用初始化视图方法 + initPoint();//调用初始化导航原点的方法 + viewPager.addOnPageChangeListener(this);//滑动事件 + //viewPager.setAdapter(new MyAdapter()); + + // 获取屏幕参数 + //ScreenUtil.ScreenSize ss = ScreenUtil.getScreenSize(MainActivity.this); + //Toast.makeText(getApplication(), Integer.toString(ss.getHeightPixels())+" "+Integer.toString(ss.getWidthPixels()), Toast.LENGTH_SHORT).show(); + + return mView; + } + + //初始化view,即显示的图片 + void initView() { + adapter = new ImagePagerAdapter(views); + viewPager = mView.findViewById(R.id.fragmentviewpageViewPager1); + viewPager.setAdapter(adapter); + linearLayout = mView.findViewById(R.id.fragmentviewpageLinearLayout1); + initPoint();//初始化页面下方的点 + viewPager.setOnPageChangeListener(this); + initAOHPCTCSeekBar(); + initAOHPCTCSeekBar2(); + } + + //初始化所要显示的布局 + void initData() { + ViewPager viewPager = mView.findViewById(R.id.fragmentviewpageViewPager1); + LayoutInflater inflater = LayoutInflater.from(mContext); + View view1 = inflater.inflate(R.layout.viewpage_atickprogressbar, viewPager, false); + View view2 = inflater.inflate(R.layout.viewpage_acard, viewPager, false); + View view3 = inflater.inflate(R.layout.viewpage_aohpctccard, viewPager, false); + View view4 = inflater.inflate(R.layout.viewpage_aohpctcsb, viewPager, false); + + views = new ArrayList<>(); + views.add(view1); + views.add(view2); + views.add(view3); + views.add(view4); + } + + //setTag注释 + /* + //View中的setTag(Onbect)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。来 + 代表这个数据,即实例化 + Tag是标签的bai意识,这里的tag是object类型。所以通常会使用setTag()设置不同的Object子类对象, + 然后使用强制转换getTag()获得对象。 + //可以用在多个Button添加一个监听器,每个Button都设置不同的setTag。 + 这个监听器就通过getTag来分辨是哪个Button 被按下。 + public class Main extends Activity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + Button button1 = (Button) findViewById(R.id.Button01); + Button button2 = (Button) findViewById(R.id.Button02); + Button button3 = (Button) findViewById(R.id.Button03); + Button button4 = (Button) findViewById(R.id.Button04); + MyListener listener = new MyListener(); + button1.setTag(1); + button1.setOnClickListener(listener); + button2.setTag(2); + button2.setOnClickListener(listener); + button3.setTag(3); + button3.setOnClickListener(listener); + button4.setTag(4); + button4.setOnClickListener(listener); + } + + public class MyListener implements View.OnClickListener { + + @Override + public void onClick(View v) { + int tag = (Integer) v.getTag(); + switch (tag) { + case 1: + System.out.println(“button1 click”); + break; + case 2: + System.out.println(“button2 click”); + break; + case 3: + System.out.println(“button3 click”); + break; + case 4: + System.out.println(“button4 click”); + break; + } + + */ + + private void initPoint() { + + imageViews = new ImageView[5];//实例化5个图片 + for (int i = 0; i < linearLayout.getChildCount(); i++) { + imageViews[i] = (ImageView) linearLayout.getChildAt(i); + imageViews[i].setImageResource(R.drawable.ic_arrow_left_right_bold); + imageViews[i].setOnClickListener(this);//点击导航点,即可跳转 + imageViews[i].setTag(i);//重复利用实例化的对象 + } + currentPoint = 0;//默认第一个坐标 + imageViews[currentPoint].setImageResource(R.drawable.ic_arrow_up_circle_outline); + } + + //OnPageChangeListener接口要实现的三个方法 + /* onPageScrollStateChanged(int state) + 此方法是在状态改变的时候调用,其中state这个参数有三种状态: + SCROLL_STATE_DRAGGING(1)表示用户手指“按在屏幕上并且开始拖动”的状态 + (手指按下但是还没有拖动的时候还不是这个状态,只有按下并且手指开始拖动后log才打出。) + SCROLL_STATE_IDLE(0)滑动动画做完的状态。 + SCROLL_STATE_SETTLING(2)在“手指离开屏幕”的状态。*/ + @Override + public void onPageScrollStateChanged(int state) { + + } + /* onPageScrolled(int position, float positionOffset, int positionOffsetPixels) + 当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用。其中三个参数的含义分别为: + + position :当前页面,即你点击滑动的页面(从A滑B,则是A页面的position。 + positionOffset:当前页面偏移的百分比 + positionOffsetPixels:当前页面偏移的像素位置*/ + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + /* onPageSelected(int position) + 此方法是页面滑动完后得到调用,position是你当前选中的页面的Position(位置编号) + (从A滑动到B,就是B的position)*/ + public void onPageSelected(int position) { + + ImageView preView = imageViews[currentPoint]; + preView.setImageResource(R.drawable.ic_arrow_left_right_bold); + ImageView currView = imageViews[position]; + currView.setImageResource(R.drawable.ic_arrow_up_circle_outline); + currentPoint = position; + } + + //小圆点点击事件 + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + //通过getTag(),可以判断是哪个控件 + int i = (Integer) v.getTag(); + viewPager.setCurrentItem(i);//直接跳转到某一个页面的情况 + } + + void initAOHPCTCSeekBar() { + AOHPCTCSeekBar seekbar = views.get(3).findViewById(R.id.fragmentviewpageAOHPCTCSeekBar1); + seekbar.setThumb(mContext.getDrawable(R.drawable.ic_launcher)); + //seekbar.setThumbOffset(200); + //seekbar.setThumbOffset(1); + seekbar.setBlurRightDP(50); + seekbar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() { + + @Override + public void onOHPCommit() { + ToastUtils.show("onOHPCommit"); + } + }); + } + + void initAOHPCTCSeekBar2() { + AOHPCTCSeekBar seekbar = views.get(3).findViewById(R.id.fragmentviewpageAOHPCTCSeekBar2); + seekbar.setThumb(mContext.getDrawable(R.drawable.ic_call)); + //seekbar.setThumbOffset(200); + //seekbar.setThumbOffset(1); + seekbar.setBlurRightDP(50); + seekbar.setOnOHPCListener(new AOHPCTCSeekBar.OnOHPCListener() { + + @Override + public void onOHPCommit() { + ToastUtils.show("onOHPCommit 2"); + } + }); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java new file mode 100644 index 0000000..b4e7548 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AESThemeUtil.java @@ -0,0 +1,211 @@ +package cc.winboll.studio.libaes.utils; + +/** + * @Author ZhanGSKen + * @Date 2024/11/29 22:52:09 + * @Describe AES 主题工具集 + */ +import android.app.Activity; +import android.content.Context; +import android.view.Menu; +import android.view.MenuItem; +import androidx.appcompat.app.AppCompatActivity; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; +import cc.winboll.studio.libaes.models.AESThemeBean; + +public class AESThemeUtil { + + public static final String TAG = "AESThemeUtil"; + + static final String SHAREDPREFERENCES_NAME = "SHAREDPREFERENCES_NAME"; + static final String DRAWER_THEME_TYPE = "DRAWER_THEME_TYPE"; + + protected volatile AESThemeBean.ThemeType mThemeType; + + public static int getThemeTypeID(T context) { + AESThemeBean bean = AESThemeBean.loadBean(context, AESThemeBean.class); + return bean == null ? AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES): bean.getCurrentThemeTypeID(); + } + + public static void saveThemeStyleID(T context, int nThemeTypeID) { + AESThemeBean bean = new AESThemeBean(nThemeTypeID); + AESThemeBean.saveBean(context, bean); + } + + public static void applyAppTheme(T activity) { + activity.setTheme(getThemeTypeID(activity)); + } + + public static void applyAppCompatTheme(T activity) { + activity.setTheme(getThemeTypeID(activity)); + } + + /*public static void applyWinBoLLTheme(T activity) { + activity.setTheme(getThemeTypeID(activity.getApplicationContext())); + }*/ + + public static void applyAppTheme(Activity activity, AESThemeBean.ThemeType themeType) { + activity.setTheme(AESThemeBean.getThemeStyleID(themeType)); + } + + public static void applyAppCompatTheme(Activity activity, AESThemeBean.ThemeType themeType) { + activity.setTheme(AESThemeBean.getThemeStyleID(themeType)); + } + + /*public static void applyWinBoLLTheme(Activity activity, AESThemeBean.ThemeType themeType) { + activity.setTheme(AESThemeBean.getThemeStyleID(themeType)); + }*/ + + public static void inflateMenu(T activity, Menu menu) { + activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu); + } + + public static void inflateCompatMenu(T activity, Menu menu) { + activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu); + } + + /*public static void inflateWinBoLLMenu(T activity, Menu menu) { + activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu); + }*/ + + public static boolean onAppThemeItemSelected(T activity, MenuItem item) { + int nThemeStyleID; + if (R.id.item_depththeme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_skytheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.SKY); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_goldentheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.GOLDEN); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_bearingtheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.BEARING); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_memortheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.MEMOR); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_taotheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.TAO); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_defaulttheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } + + return false; + } + + public static boolean onAppCompatThemeItemSelected(T activity, MenuItem item) { + int nThemeStyleID; + if (R.id.item_depththeme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_skytheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.SKY); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_goldentheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.GOLDEN); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_bearingtheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.BEARING); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_memortheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.MEMOR); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_taotheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.TAO); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } else if (R.id.item_defaulttheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES); + saveThemeStyleID(activity, nThemeStyleID); + return true; + } + + return false; + } + + public static boolean onWinBoLLThemeItemSelected(T activity, MenuItem item) { + int nThemeStyleID; + if (R.id.item_depththeme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_skytheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.SKY); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_goldentheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.GOLDEN); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_bearingtheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.BEARING); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_memortheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.MEMOR); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_taotheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.TAO); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_defaulttheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } + + return false; + } + + public static boolean onWinBoLLThemeItemSelected(T activity, MenuItem item) { + int nThemeStyleID; + if (R.id.item_depththeme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_skytheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.SKY); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_goldentheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.GOLDEN); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_bearingtheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.BEARING); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_memortheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.MEMOR); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_taotheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.TAO); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } else if (R.id.item_defaulttheme == item.getItemId()) { + nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.AES); + saveThemeStyleID(activity.getApplicationContext(), nThemeStyleID); + return true; + } + + return false; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java new file mode 100644 index 0000000..e4ac66b --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/AppVersionUtils.java @@ -0,0 +1,162 @@ +package cc.winboll.studio.libaes.utils; + + +/** + * @Author ZhanGSKen + * @Date 2024/08/12 14:45:35 + * @Describe 应用版本工具集 + */ +import cc.winboll.studio.libappbase.LogUtils; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AppVersionUtils { + + public static final String TAG = "AppVersionUtils"; + + // + // 检查新版本是否成立 + // szCurrentCode : 当前版本应用包名 + // szNextCode : 新版本应用包名 + // 返回 :情况1:当前版本是发布版 + // 返回 true (新版本 > 当前版本) + // 情况1:当前版本是Beta版 + // true 新版本 == 当前版本 + // + public static boolean isHasNewVersion2(String szCurrentName, String szNextName) { + LogUtils.d(TAG, String.format("isHasNewVersion2\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName)); + //szCurrentName = "AES_6.2.0-beta0_3234.apk"; + //szNextName = "AES_6.1.12.apk"; + //szCurrentName = "AES_6.2.0-beta0_3234.apk"; + //szNextName = "AES_6.2.0.apk"; + //szCurrentName = "AES_6.2.0-beta0_3234.apk"; + //szNextName = "AES_6.2.2.apk"; + //szCurrentName = "AES_6.2.0-beta0_3234.apk"; + //szNextName = "AES_6.2.0.apk"; + //szCurrentName = "AES_6.1.0.apk"; + //szNextName = "AES_6.2.0.apk"; + //LogUtils.d(TAG, "szCurrentName : " + szCurrentName); + //LogUtils.d(TAG, "szNextName : " + szNextName); + + //boolean isVersionNewer = false; + //if(szCurrentName.equals(szNextName)) { + // isVersionNewer = false; + //} else { + //ToastUtils.show("szCurrent : " + szCurrent + "\nszNext : " + szNext); + //int nApk = szNextName.lastIndexOf(".apk"); + //ToastUtils.show("nApk : " + Integer.toString(nApk)); + //String szNextNoApkName = szNextName.substring(0, nApk); + //ToastUtils.show("szNextNoApkName : " + szNextNoApkName); + //String szCurrentNoApkName = szCurrentName.substring(0, szNextNoApkName.length()); + //ToastUtils.show("szCurrentNoApkName : " + szCurrentNoApkName); + //String str1 = "3.4.50"; + //String str2 = "3.3.60"; + //String str1 = getCodeInPackageName(szCurrentName); + //String str2 = getCodeInPackageName(szNextName); + //String str1 = getCodeInPackageName(szNextName); + //String str2 = getCodeInPackageName(szCurrentName); + //Boolean isVersionNewer2 = checkNewVersion(str1,str2); + //ToastUtils.show("isVersionNewer2 : " + Boolean.toString(isVersionNewer2)); + //ToastUtils.show(checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))); + //return checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName)); + //} + //return isVersionNewer; + if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) { + // 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。 + // 比 AES_6.2.0-beta0_3234.apk 大,如 AES_6.2.1.apk。 + //LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName); + return true; + } + if (szCurrentName.matches(".*_\\d+\\.\\d+\\.\\d+-beta.*\\.apk")) { + String szCurrentReleasePackageName = getReleasePackageName(szCurrentName); + //LogUtils.d(TAG, "szCurrentReleasePackageName : " + szCurrentReleasePackageName); + if (szCurrentReleasePackageName.equals(szNextName)) { + // 与 AES_6.2.0-beta0_3234.apk 版本相同,如 AES_6.2.0.apk。 + //LogUtils.d(TAG, "App stage version is released. Release name : " + szNextName); + return true; + } + } + //LogUtils.d(TAG, "App version is the newest. "); + return false; + } + + public static boolean isHasNewStageReleaseVersion(String szCurrentName, String szNextName) { + LogUtils.d(TAG, String.format("isHasNewStageReleaseVersion\nszCurrentName : %s\nszNextName : %s", szCurrentName, szNextName)); + //szCurrentName = "AES_6.2.12.apk"; + //szNextName = "AES_6.3.12.apk"; + if (checkNewVersion(getCodeInPackageName(szCurrentName), getCodeInPackageName(szNextName))) { + // 比 AES_6.2.0.apk 版本大,如 AES_6.2.1.apk。 + //LogUtils.d(TAG, "App newer stage version is released. Release name : " + szNextName); + return true; + } + return false; + } + + // + // 检查新版本是否成立 + // szCurrentCode : 当前版本 + // szNextCode : 新版本 + // 返回 :true 新版本 > 当前版本 + // + public static Boolean checkNewVersion(String szCurrentCode, String szNextCode) { + if (szCurrentCode == null || szCurrentCode.equals("") || szNextCode == null || szNextCode.equals("")) { + LogUtils.d(TAG, String.format("checkNewVersion unexpected parameters:\nszCurrentCode : %s\nszNextCode : %s", szCurrentCode, szNextCode)); + return false; + } + boolean isNew = false; + String[] appVersionCurrent = szCurrentCode.split("\\."); + String[] appVersionNext = szNextCode.split("\\."); + //根据位数最短的判断 + int lim = appVersionCurrent.length > appVersionNext.length ? appVersionNext.length : appVersionCurrent.length; + //根据位数循环判断各个版本 + for (int i = 0; i < lim; i++) { + if (Integer.parseInt(appVersionNext[i]) > Integer.parseInt(appVersionCurrent[i])) { + isNew = true; + return isNew; + } else if (Integer.parseInt(appVersionNext[i]) == Integer.parseInt(appVersionCurrent[i])) { + continue ; + } else { + isNew = false; + return isNew; + } + } + return isNew; + } + + // + // 截取应用包名称版本号信息 + // 如 :AppUtils_7.0.4-beta1_0120.apk 版本号为 7.0.4 + // 如 :AppUtils_7.0.4.apk 版本号为 7.0.4 + // + public static String getCodeInPackageName(String apkName) { + LogUtils.d(TAG, String.format("getCodeInPackageName apkName : %s", apkName)); + //String apkName = "AppUtils_7.0.0.apk"; + Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+"); + Matcher matcher = pattern.matcher(apkName); + if (matcher.find()) { + String version = matcher.group(); + LogUtils.d(TAG, String.format("version is %s", version)); + return version; + //System.out.println("Version number: " + version); // 输出:7.0.0 + } + LogUtils.d(TAG, String.format("No result.")); + return ""; + } + + // + // 根据Beta版名称生成发布版应用包名称 + // 如 AppUtils_7.0.4-beta1_0120.apk + // 发布版名称就为AppUtils_7.0.4.apk + // + public static String getReleasePackageName(String szBetaPackageName) { + //String szBetaPackageName = "AppUtils_7.0.4-beta1_0120.apk"; + Pattern pattern = Pattern.compile(".*\\d+\\.\\d+\\.\\d+"); + Matcher matcher = pattern.matcher(szBetaPackageName); + if (matcher.find()) { + String szReleasePackageName = matcher.group(); + return szReleasePackageName + ".apk"; + //System.out.println("Version number: " + version); // 输出:7.0.0 + } + return ""; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/DevelopUtils.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/DevelopUtils.java new file mode 100644 index 0000000..377afc3 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/DevelopUtils.java @@ -0,0 +1,35 @@ +package cc.winboll.studio.libaes.utils; + +import android.app.Activity; +import android.view.Menu; +import android.view.MenuItem; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libappbase.LogActivity; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/07 13:31 + * @Describe 应用开发工具类 + */ +public class DevelopUtils { + + public static final String TAG = "DevelopUtils"; + + public static void inflateMenu(T activity, Menu menu) { + activity.getMenuInflater().inflate(R.menu.toolbar_appdebug, menu); + } + + public static boolean onDevelopItemSelected(T activity, MenuItem item) { + if (R.id.item_testappcrash == item.getItemId()) { + for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) { + activity.getString(i); + } + } else if (R.id.item_log == item.getItemId()) { + //ToastUtils.show("Test"); + LogActivity.startLogActivity(activity); + } else { + return false; + } + return true; + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/MimoUtils.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/MimoUtils.java new file mode 100644 index 0000000..2c07337 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/MimoUtils.java @@ -0,0 +1,33 @@ +package cc.winboll.studio.libaes.utils; + +import android.content.Context; +import android.util.DisplayMetrics; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/18 15:23 + * @Describe 米盟 MimoUtils + */ +public final class MimoUtils { + public static final String TAG = "Utils"; + + public static int dpToPx(Context context, float dp) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (dp * displayMetrics.density + 0.5f); + } + + public static int pxToDp(Context context, float px) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (px / displayMetrics.density + 0.5f); + } + + public static int pxToSp(Context context, float pxValue) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (pxValue / displayMetrics.scaledDensity + 0.5f); + } + + public static int spToPx(Context context, float spValue) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (spValue * displayMetrics.scaledDensity + 0.5f); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java new file mode 100644 index 0000000..d32928d --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/MyActivityLifecycleCallbacks.java @@ -0,0 +1,97 @@ +package cc.winboll.studio.libaes.utils; + +/** + * @Author ZhanGSKen + * @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; + +public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { + + public static final String TAG = "MyActivityLifecycleCallbacks"; + + public String mInfo = ""; + + public MyActivityLifecycleCallbacks() { + + } + + void createActivityeInfo(Activity activity) { + StringBuilder sb = new StringBuilder(); + Intent receivedIntent = activity.getIntent(); + sb.append("\nCallingActivity : \n"); + if (activity.getCallingActivity() != null) { + sb.append(activity.getCallingActivity().getPackageName()); + } + sb.append("\nReceived Intent Package : \n"); + sb.append(receivedIntent.getPackage()); + + Bundle extras = receivedIntent.getExtras(); + if (extras != null) { + for (String key : extras.keySet()) { + sb.append("\nIntentInfo"); + sb.append("\n键: "); + sb.append(key); + sb.append(", 值: "); + sb.append(extras.get(key)); + //Log.d("IntentInfo", "键: " + key + ", 值: " + extras.get(key)); + } + } + mInfo = sb.toString(); + //Log.d("IntentInfo", "发送Intent的应用包名: " + senderPackage); + } + + public void showActivityeInfo() { + //ToastUtils.show("ActivityeInfo : " + mInfo); + LogUtils.d(TAG, "ActivityeInfo : " + mInfo); + } + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + // 在这里可以做一些初始化相关的操作,例如记录Activity的创建时间等 + //System.out.println(activity.getLocalClassName() + " was created"); + LogUtils.d(TAG, activity.getLocalClassName() + " was created"); + createActivityeInfo(activity); + } + + @Override + public void onActivityStarted(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was started"); + LogUtils.d(TAG, activity.getLocalClassName() + " was started"); + //createActivityeInfo(activity); + } + + @Override + public void onActivityResumed(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was resumed"); + LogUtils.d(TAG, activity.getLocalClassName() + " was resumed"); + //createActivityeInfo(activity); + } + + @Override + public void onActivityPaused(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was paused"); + LogUtils.d(TAG, activity.getLocalClassName() + " was paused"); + } + + @Override + public void onActivityStopped(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was stopped"); + LogUtils.d(TAG, activity.getLocalClassName() + " was stopped"); + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + // 可以在这里添加保存状态的自定义逻辑 + } + + @Override + public void onActivityDestroyed(Activity activity) { + //System.out.println(activity.getLocalClassName() + " was destroyed"); + LogUtils.d(TAG, activity.getLocalClassName() + " was destroyed"); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/PrefUtils.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/PrefUtils.java new file mode 100644 index 0000000..751a9e5 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/PrefUtils.java @@ -0,0 +1,33 @@ +package cc.winboll.studio.libaes.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/13 06:50 + * @Describe 应用变量保存工具 + */ + +public class PrefUtils { + + public static final String TAG = "PrefUtils"; + + // + // 保存字符串到SharedPreferences的函数 + // + public static void saveString(Context context, String key, String value) { + SharedPreferences sharedPreferences = context.getSharedPreferences("myPrefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(key, value); + editor.apply(); + } + + // + // 从SharedPreferences读取字符串的函数 + // + public static String getString(Context context, String key, String defaultValue) { + SharedPreferences sharedPreferences = context.getSharedPreferences("myPrefs", Context.MODE_PRIVATE); + return sharedPreferences.getString(key, defaultValue); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/ScreenUtil.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/ScreenUtil.java new file mode 100644 index 0000000..20399ea --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/ScreenUtil.java @@ -0,0 +1,64 @@ +package cc.winboll.studio.libaes.utils; + +import android.content.Context; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +public class ScreenUtil { + + // 分辨率宽度和高度计量类 + // + public static class ScreenSize { + int widthPixels; + int heightPixels; + + public ScreenSize(int widthPixels, int heightPixels) { + this.widthPixels = widthPixels; + this.heightPixels = heightPixels; + } + + public void setWidthPixels(int widthPixels) { + this.widthPixels = widthPixels; + } + + public int getWidthPixels() { + return widthPixels; + } + + public void setHeightPixels(int heightPixels) { + this.heightPixels = heightPixels; + } + + public int getHeightPixels() { + return heightPixels; + } + } + + // 获取屏幕分辨率宽度和高度 + // + public static ScreenSize getScreenSize(Context mContext) { + WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + manager.getDefaultDisplay().getMetrics(dm); + return new ScreenSize(dm.widthPixels, dm.heightPixels); + } + + // 获取屏幕宽度 + // + public static int getScreenWidth(Context mContext) { + WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + manager.getDefaultDisplay().getMetrics(dm); + return dm.widthPixels; + } + + // 获取屏幕高度 + // + public static int getScreenHeight(Context mContext) { + WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + manager.getDefaultDisplay().getMetrics(dm); + return dm.heightPixels; + } + +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/WebUtils.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/WebUtils.java new file mode 100644 index 0000000..94d8502 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/WebUtils.java @@ -0,0 +1,102 @@ +package cc.winboll.studio.libaes.utils; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.widget.Toast; + +import cc.winboll.studio.libappbase.LogUtils; + +/** + * @Author 豆包&ZhanGSKen + * @Date 2026/01/05 15:45 + * @LastEditTime 2026/01/05 19:30:00 HKT + * @Describe 网页工具集(优化:新增合法性校验+浏览器可用性检查+链接格式自动修复) + */ +public class WebUtils { + + public static final String TAG = "WebUtils"; + + /** + * 唤起系统默认浏览器打开指定网站 + * @param context 上下文对象(建议使用 ApplicationContext 避免内存泄漏) + * @param url 目标 URL(支持自动修复格式错误) + */ + public static void openUrlInBrowser(Context context, String url) { + // 1. 空指针与合法性校验 + if (context == null) { + LogUtils.e(TAG, "openUrlInBrowser: Context is null"); + return; + } + if (url == null || url.trim().isEmpty()) { + LogUtils.e(TAG, "openUrlInBrowser: Url is null or empty"); + showToast(context, "链接不能为空"); + return; + } + + // 2. 链接格式自动修复(核心新增:处理多斜杠、补全协议头) + String fixedUrl = fixUrlFormat(url.trim()); + LogUtils.d(TAG, "openUrlInBrowser: Fixed url from [" + url + "] to [" + fixedUrl + "]"); + + // 3. 构建隐式意图 + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fixedUrl)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 新任务栈启动 + + // 4. 检查浏览器可用性 + if (intent.resolveActivity(context.getPackageManager()) != null) { + try { + context.startActivity(intent); + } catch (Exception e) { + LogUtils.e(TAG, "openUrlInBrowser: Start activity failed", e); + showToast(context, "打开浏览器失败,请手动复制链接"); + } + } else { + LogUtils.e(TAG, "openUrlInBrowser: No browser app found"); + showToast(context, "未找到可用的浏览器应用"); + } + } + + /** + * 工具方法:修复 URL 格式错误 + * 1. 补全 http/https 协议头 + * 2. 处理协议头后的多斜杠问题(如 https://mmec//path → https://mmec/path) + * @param originalUrl 原始 URL + * @return 修复后的 URL + */ + private static String fixUrlFormat(String originalUrl) { + String url = originalUrl; + + // 步骤1:补全协议头(优先 https) + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "https://" + url; + } + + // 步骤2:修复协议头后的多斜杠问题 + // 匹配 https:// 或 http:// 后的任意数量斜杠,替换为单斜杠 + url = url.replaceAll("(?<=https?://)[/]+", "/"); + + return url; + } + + /** + * 工具方法:显示 Toast 提示(确保在主线程执行) + */ + private static void showToast(final Context context, final String message) { + if (context == null || message == null) { + return; + } + if (Looper.myLooper() == Looper.getMainLooper()) { + Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_SHORT).show(); + } else { + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_SHORT).show(); + } + }); + } + } +} + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java b/libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java new file mode 100644 index 0000000..c95d302 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/utils/WinBoLLActivityManager.java @@ -0,0 +1,292 @@ +package cc.winboll.studio.libaes.utils; + +/** + * @Author ZhanGSKen + * @Date 2025/05/10 10:02 + * @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.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import cc.winboll.studio.libaes.interfaces.IWinBoLLActivity; +import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.LogActivity; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.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 enum WinBoLLUI_TYPE { Aplication, Service } + + GlobalApplication mGlobalApplication; + volatile static WinBoLLActivityManager _mIWinBoLLActivityManager; + Map mActivityListMap; + + volatile static WinBoLLUI_TYPE _WinBoLLUI_TYPE = WinBoLLUI_TYPE.Service; + public static void setWinBoLLUI_TYPE(WinBoLLUI_TYPE winBoLLUI_TYPE) { + _WinBoLLUI_TYPE = winBoLLUI_TYPE; + } + + public static WinBoLLUI_TYPE getWinBoLLUI_TYPE() { + return _WinBoLLUI_TYPE; + } + + WinBoLLActivityManager(GlobalApplication application) { + mGlobalApplication = application; + mActivityListMap = new HashMap(); + } + + public static WinBoLLActivityManager getInstance() { + return _mIWinBoLLActivityManager; + } + + public static synchronized void init(T application) { + if (_mIWinBoLLActivityManager == null) { + _mIWinBoLLActivityManager = new WinBoLLActivityManager(application); + } + } + + /** + * 把Activity添加到管理中 + */ + public void add(T activity) { + if (isActivityActive(activity.getTag())) { + LogUtils.d(TAG, String.format("add(...) %s is active.", activity.getTag())); + } else { + mActivityListMap.put(activity.getTag(), activity); + LogUtils.d(TAG, String.format("Add activity : %s\n_mapActivityList.size() : %d", activity.getTag(), mActivityListMap.size())); + } + } + + // + // activity: 为 null 时, + // intent.putExtra 函数 "tag" 参数为 tag + // activity: 不为 null 时, + // intent.putExtra 函数 "tag" 参数为 activity.getTag() + // + public void startWinBoLLActivity(Context context, Class clazz) { + // 如果窗口已存在就重启窗口 + if (!resumeActivity(clazz)) { + // 新建一个任务窗口 + Intent intent = new Intent(context, clazz); + //打开多任务窗口 flags + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + //intent.putExtra("tag", tag); + context.startActivity(intent); + } + } + + public void startWinBoLLActivity(Context context, Intent intent, Class clazz) { + // 如果窗口已存在就重启窗口 + if (!resumeActivity(clazz)) { + // 新建一个任务窗口 + //Intent intent = new Intent(context, clazz); + //打开多任务窗口 flags + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + //intent.putExtra("tag", tag); + context.startActivity(intent); + } + } + + public void startLogActivity(Context context) { + // 如果窗口已存在就重启窗口 + //if (!resumeActivity(LogActivity.class)) { + // 新建一个任务窗口 + 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); + //} + } + + // + // 判断 tag 绑定的 Activity 是否已经创建 + // + public boolean isActivityActive(String tag) { + return mActivityListMap.get(tag) != null; + } + + Activity getActivityByTag(String tag) { + return (mActivityListMap.get(tag) == null) ?null: mActivityListMap.get(tag).getActivity(); + } + + + // + // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台 + // + public boolean resumeActivity(Class clazz) { + try { + Activity activity = getActivityByTag(clazz.newInstance().getTag()); + if (activity != null) { + return resumeActivity(activity); + } + } catch (InstantiationException | IllegalAccessException e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + return false; + } + + // + // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台 + // + public boolean resumeActivity(String tag) { + Activity activity = getActivityByTag(tag); + if (activity != null) { + return resumeActivity(activity); + } + return false; + } + + // + // 找到tag 绑定的 BaseActivity ,通过 getTaskId() 移动到前台 + // + public boolean resumeActivity(Activity activity) { + ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE); + //返回启动它的根任务(home 或者 MainActivity) + //Intent intent = new Intent(mContext, activity.getClass()); + //TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext); + //stackBuilder.addNextIntentWithParentStack(intent); + //stackBuilder.startActivities(); + am.moveTaskToFront(activity.getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION); + //ToastUtils.show("resumeActivity"); + return true; + } + + + /** + * 结束所有 Activity + */ + public void finishAll() { + try { + //ToastUtils.show(String.format("finishAll() size : %d", _mIWinBoLLActivityList.size())); + for (int i = mActivityListMap.size() - 1; i > -1; i--) { + IWinBoLLActivity iWinBoLLActivity = mActivityListMap.get(i); + ToastUtils.show("finishAll() activity"); + if (iWinBoLLActivity != null && iWinBoLLActivity.getActivity() != null && !iWinBoLLActivity.getActivity().isFinishing() && !iWinBoLLActivity.getActivity().isDestroyed()) { + //ToastUtils.show("activity != null ..."); + if (getWinBoLLUI_TYPE() == WinBoLLUI_TYPE.Service) { + // 结束窗口和最近任务栏, 建议前台服务类应用使用,可以方便用户再次调用 UI 操作。 + iWinBoLLActivity.getActivity().finishAndRemoveTask(); + //ToastUtils.show("finishAll() activity.finishAndRemoveTask();"); + } else if (getWinBoLLUI_TYPE() == WinBoLLUI_TYPE.Aplication) { + // 结束窗口保留最近任务栏,建议前台服务类应用使用,可以保持应用的系统自觉性。 + iWinBoLLActivity.getActivity().finish(); + //ToastUtils.show("finishAll() activity.finish();"); + } else { + ToastUtils.show("WinBollApplication.WinBollUI_TYPE error."); + } + } + } + } catch (Exception e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + } + + /** + * 结束指定Activity + */ + public void finish(T iWinBoLLActivity) { + try { + if (iWinBoLLActivity != null && iWinBoLLActivity.getActivity() != null && !iWinBoLLActivity.getActivity().isFinishing() && !iWinBoLLActivity.getActivity().isDestroyed()) { + //根据tag 移除 MyActivity + //String tag= activity.getTag(); + //_mIWinBoLLActivityList.remove(tag); + //ToastUtils.show("remove"); + //ToastUtils.show("_mIWinBoLLActivityArrayMap.size() " + Integer.toString(_mIWinBoLLActivityArrayMap.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] >> 直接关闭当前窗口 + Activity preActivity = getPreActivity(iWinBoLLActivity); + iWinBoLLActivity.getActivity().finish(); + if (preActivity != null) { + resumeActivity(preActivity); + } + } + + } catch (Exception e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + } + + Activity getPreActivity(IWinBoLLActivity iWinBoLLActivity) { + try { + boolean bingo = false; + IWinBoLLActivity preIWinBoLLActivity = null; + for (Map.Entry entity : mActivityListMap.entrySet()) { + if (entity.getKey().equals(iWinBoLLActivity.getTag())) { + bingo = true; + LogUtils.d(TAG, "bingo"); + break; + } + preIWinBoLLActivity = entity.getValue(); + } + + if (bingo) { + return preIWinBoLLActivity.getActivity(); + } + } catch (Exception e) { + LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); + } + + return null; + } + + public boolean registeRemove(T iWinBoLLActivity) { + IWinBoLLActivity iWinBoLLActivityTest = mActivityListMap.get(iWinBoLLActivity.getTag()); + if (iWinBoLLActivityTest != null) { + mActivityListMap.remove(iWinBoLLActivity.getTag()); + return true; + } + return false; + } + + public void printAvtivityListInfo() { + if (!mActivityListMap.isEmpty()) { + StringBuilder sb = new StringBuilder("Map entries : " + Integer.toString(mActivityListMap.size())); + Iterator> iterator = mActivityListMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + sb.append("\nKey: " + entry.getKey() + ", \nValue: " + entry.getValue().getTag()); + //ToastUtils.show("\nKey: " + entry.getKey() + ", Value: " + entry.getValue().getTag()); + } + sb.append("\nMap entries end."); + LogUtils.d(TAG, sb.toString()); + } else { + LogUtils.d(TAG, "The map is empty."); + } + } +} + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/AButton.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/AButton.java new file mode 100644 index 0000000..5c9c111 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/AButton.java @@ -0,0 +1,28 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:41:22 + * @Describe AButton + */ +import android.content.Context; +import android.util.AttributeSet; +import cc.winboll.studio.libaes.R; + +public class AButton extends android.widget.Button { + + public static final String TAG = "AButton"; + + public AButton(Context context) { + super(context); + } + + public AButton(Context context, AttributeSet attrs) { + super(context, attrs); + setBackground(context.getDrawable(R.drawable.btn_style)); + } + + public AButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ACard.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ACard.java new file mode 100644 index 0000000..4f627f8 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/ACard.java @@ -0,0 +1,45 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:44:27 + * @Describe ACard + */ +import android.content.Context; +import android.util.AttributeSet; +import android.widget.LinearLayout; +import cc.winboll.studio.libaes.R; + +public class ACard extends LinearLayout { + + public static final String TAG = "ACard"; + + public ACard(Context context) { + super(context); + } + + public ACard(Context context, AttributeSet attrs) { + super(context, attrs); + setPadding(0 + 0 + 2 + 1, 0 + 0 + 2 + 1, 0 + 1 + 3 + 1, 0 + 2 + 3 + 1); + + // 获得TypedArray + //TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AToolbar); + // 获得attrs.xml里面的属性值,格式为:名称_属性名,后面是默认值 + //int colorBackgroud = a.getColor(R.styleable.ACard_backgroudColor, context.getColor(R.color.colorACardBackgroung)); + //int centerColor = a.getColor(R.styleable.AToolbar_centerColor, context.getColor(R.color.colorAToolbarCenterColor)); + //int endColor = a.getColor(R.styleable.AToolbar_endColor, context.getColor(R.color.colorAToolbarEndColor)); + //float tSize = a.getDimension(R.styleable.CustomView_tSize, 35); + //p.setColor(tColor); + //p.setTextSize(tSize); + //Drawable drawable = context.getDrawable(R.drawable.frame_atoolbar); + + setBackground(context.getDrawable(R.drawable.acard_frame_main)); + + // 返回一个绑定资源结束的信号给资源 + //a.recycle(); + } + + public ACard(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADrawerMenuListView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADrawerMenuListView.java new file mode 100644 index 0000000..2f4e889 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADrawerMenuListView.java @@ -0,0 +1,19 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2023/05/30 11:30:07 + */ +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ListView; + +public class ADrawerMenuListView extends ListView { + + public static final String TAG = "ADrawerMenuListView"; + + public ADrawerMenuListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java new file mode 100644 index 0000000..89eb74f --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsBannerView.java @@ -0,0 +1,491 @@ +package cc.winboll.studio.libaes.views; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.enums.ADsMode; +import cc.winboll.studio.libaes.utils.MimoUtils; +import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.LogUtils; +import com.miui.zeus.mimo.sdk.ADParams; +import com.miui.zeus.mimo.sdk.BannerAd; +import com.miui.zeus.mimo.sdk.MimoCustomController; +import com.miui.zeus.mimo.sdk.MimoLocation; +import com.miui.zeus.mimo.sdk.MimoSdk; +import java.util.ArrayList; +import java.util.List; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/18 14:41 + * @Describe WinBoLL 横幅广告类 + */ +public class ADsBannerView extends LinearLayout { + + public static final String TAG = "ADsBannerView"; + + + private String BANNER_POS_ID = "802e356f1726f9ff39c69308bfd6f06a"; + private String BANNER_POS_ID_WINBOLL_BETA = "d129ee5a263911f981a6dc7a9802e3e7"; + private String BANNER_POS_ID_WINBOLL = "4ec30efdb32271765b9a4efac902828b"; + + /* + private String BANNER_POS_ID = "802e356f1726f9ff39c69308bfd6f06a"; + private String BANNER_POS_ID_WINBOLL_BETA = "802e356f1726f9ff39c69308bfd6f06a"; + private String BANNER_POS_ID_WINBOLL = "802e356f1726f9ff39c69308bfd6f06a"; + */ + + Context mContext; + View mMianView; + SharedPreferences mSharedPreferences; + ViewGroup mContainer; + BannerAd mBannerAd; + List mAllBanners = new ArrayList<>(); + // 新增:主线程Handler,确保广告操作在主线程执行 + private Handler mMainHandler; + + public ADsBannerView(Context context) { + super(context); + initView(context); + } + + public ADsBannerView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + public ADsBannerView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + public ADsBannerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initView(context); + } + + void initView(Context context) { + this.mContext = context; + initMimoSdk(this.mContext); + + // 初始化主线程Handler(关键:确保广告操作在主线程执行) + mMainHandler = new Handler(Looper.getMainLooper()); + + this.mMianView = inflate(this.mContext, R.layout.view_adsbanner, null); + mContainer = this.mMianView.findViewById(R.id.ads_container); + addView(this.mMianView); + } + + public void resumeADs(final Activity activity) { + // 没有设置米盟广告支持就退出 + if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { + // 2. 释放之前的广告资源 + if (mBannerAd != null) { + mBannerAd.destroy(); + } + return; + } + + // 修复:优化广告请求逻辑(添加生命周期判断 + 主线程执行) + if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { + if (ADsControlView.getAdsModeFromStatic(this.mContext) == ADsMode.MIMO_SDK) { + LogUtils.i(TAG, "已设置播放米盟广告,正在播放..."); + mMainHandler.postDelayed(new Runnable() { + @Override + public void run() { + // 再次校验生命周期,避免延迟执行时Activity已销毁 + if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { + fetchAd(activity); + } + } + }, 1000); // 延迟1秒请求广告,提升页面加载体验 + } + } + } + + /** + * 释放广告资源(关键:避免内存泄漏和空Context调用) + */ + public void releaseAdResources() { + // 没有设置米盟广告支持就退出 + if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { + return; + } + + LogUtils.d(TAG, "releaseAdResources()"); + + // 移除Handler回调 + if (mMainHandler != null) { + mMainHandler.removeCallbacksAndMessages(null); + } + + // 销毁所有广告实例 + if (mAllBanners != null && !mAllBanners.isEmpty()) { + for (BannerAd ad : mAllBanners) { + if (ad != null) { + ad.destroy(); + } + } + mAllBanners.clear(); + } + // 置空当前广告引用 + mBannerAd = null; + // 移除广告容器中的视图 + if (mContainer != null) { + mContainer.removeAllViews(); + } + } + + /** + * 显示广告(核心修复:传递安全的Context + 生命周期校验) + */ + private void showAd(final Activity activity) { + // 没有设置米盟广告支持就退出 + if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { + return; + } + + LogUtils.d(TAG, "showAd()"); + // 1. 生命周期校验:避免Activity已销毁时操作UI + if (activity == null || activity.isFinishing() || activity.isDestroyed()) { + LogUtils.e(TAG, "showAd: Activity is finishing or destroyed"); + return; + } + // 2. 非空校验:广告实例和容器 + if (mBannerAd == null || mContainer == null) { + LogUtils.e(TAG, "showAd: BannerAd or Container is null"); + return; + } + // 3. 创建广告容器(使用ApplicationContext避免内存泄漏) + final FrameLayout container = new FrameLayout(activity.getApplicationContext()); + container.setPadding(0, 0, 0, MimoUtils.dpToPx(activity, 10)); + mContainer.addView(container, new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.WRAP_CONTENT + )); + +// if (mIsBiddingWin) { +// mBannerAd.setPrice(getPrice()); +// } + // 4. 显示广告:传递ApplicationContext,避免Activity Context失效 + mBannerAd.showAd(activity, container, new BannerAd.BannerInteractionListener() { + @Override + public void onAdClick() { + LogUtils.d(TAG, "onAdClick"); + } + + @Override + public void onAdShow() { + LogUtils.d(TAG, "onAdShow"); + } + + @Override + public void onAdDismiss() { + LogUtils.d(TAG, "onAdDismiss"); + // 修复:移除容器时校验Activity状态 + if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && mContainer != null) { + mContainer.removeView(container); + } + } + + @Override + public void onRenderSuccess() { + LogUtils.d(TAG, "onRenderSuccess"); + } + + @Override + public void onRenderFail(int code, String msg) { + LogUtils.e(TAG, "onRenderFail errorCode " + code + " errorMsg " + msg); + // 修复:渲染失败时移除容器 + if (activity != null && !activity.isFinishing() && !activity.isDestroyed() && mContainer != null) { + mContainer.removeView(container); + } + } + }); + } + + /** + * 请求广告(核心修复:Context安全校验 + 异常捕获 + 资源管理) + */ + private void fetchAd(final Activity activity) { + // 没有设置米盟广告支持就退出 + if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { + return; + } + + LogUtils.d(TAG, "fetchAd()"); + // 1. 双重校验:Activity未销毁 + Context非空 + if (activity == null || activity.isFinishing() || activity.isDestroyed() || activity.getApplicationContext() == null) { + LogUtils.e(TAG, "fetchAd: Invalid Context or Activity state"); + return; + } + // 2. 释放之前的广告资源,避免内存泄漏 + if (mBannerAd != null) { + mBannerAd.destroy(); + } + // 3. 初始化广告(使用ApplicationContext,避免Activity Context失效) + try { + mBannerAd = new BannerAd(); + mAllBanners.add(mBannerAd); + } catch (Exception e) { + LogUtils.e(TAG, "fetchAd: Init BannerAd failed", e); + return; + } + // 4. 设置下载监听 + mBannerAd.setDownLoadListener(new BannerAd.BannerDownloadListener() { + @Override + public void onDownloadStarted() { + LogUtils.d(TAG, "onDownloadStarted"); + } + + @Override + public void onDownloadPaused() { + LogUtils.d(TAG, "onDownloadPaused"); + } + + @Override + public void onDownloadFailed(int errorCode) { + String msg = "onDownloadFailed, errorCode = " + errorCode; + LogUtils.d(TAG, msg); + //ToastUtils.show(msg); + } + + @Override + public void onDownloadFinished() { + LogUtils.d(TAG, "onDownloadFinished"); + } + + @Override + public void onDownloadProgressUpdated(int progress) { + LogUtils.d(TAG, "onDownloadProgressUpdated " + progress + "%"); + } + + @Override + public void onInstallFailed(int errorCode) { + LogUtils.d(TAG, "onInstallFailed, errorCode = " + errorCode); + } + + @Override + public void onInstallStart() { + LogUtils.d(TAG, "onInstallStart"); + } + + @Override + public void onInstallSuccess() { + LogUtils.d(TAG, "onInstallSuccess"); + } + + @Override + public void onDownloadCancel() { + LogUtils.d(TAG, "onDownloadCancel"); + } + }); + + // 5. 构建广告参数并请求 + String currentAD_ID = getAD_ID(); + LogUtils.d(TAG, String.format("currentAD_ID = %s", currentAD_ID)); + ADParams params = new ADParams.Builder().setUpId(currentAD_ID).build(); + mBannerAd.loadAd(params, new BannerAd.BannerLoadListener() { + @Override + public void onBannerAdLoadSuccess() { + LogUtils.d(TAG, "onBannerAdLoadSuccess()"); + // 修复:广告加载成功后校验Activity状态 + if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) { + showAd(activity); + //ToastUtils.show("showAd()"); + } + } + + @Override + public void onAdLoadFailed(int errorCode, String errorMsg) { + String msg = "onAdLoadFailed: errorCode = " + errorCode + ", errorMsg = " + errorMsg; + LogUtils.d(TAG, msg); + removeAllBanners(); + } + }); + } + + void removeAllBanners() { + // 没有设置米盟广告支持就退出 + if (ADsControlView.getAdsModeFromStatic(this.mContext) != ADsMode.MIMO_SDK) { + return; + } + + // 修复:加载失败时移除当前广告实例 + if (mAllBanners.contains(mBannerAd)) { + mAllBanners.remove(mBannerAd); + } + mBannerAd.destroy(); + mBannerAd = null; + } + + /** + * 根据当前秒数获取广告ID(原逻辑保留) + */ + private String getAD_ID() { + long currentSecond = System.currentTimeMillis() / 1000; + return (currentSecond % 2 == 0) ? BANNER_POS_ID : + (GlobalApplication.isDebugging() ? BANNER_POS_ID_WINBOLL_BETA : BANNER_POS_ID_WINBOLL); + } + + /** + * 获取广告价格(原逻辑保留,添加空指针校验) + */ +// private long getPrice() { +// if (mBannerAd == null) { +// return 0; +// } +// Map map = mBannerAd.getMediaExtraInfo(); +// if (map == null || map.isEmpty() || !map.containsKey("price")) { +// LogUtils.w(TAG, "getPrice: media extra info is null or no price key"); +// return 0; +// } +// Object priceObj = map.get("price"); +// if (priceObj instanceof Long) { +// return (Long) priceObj; +// } else if (priceObj instanceof Integer) { +// return ((Integer) priceObj).longValue(); +// } else { +// LogUtils.e(TAG, "getPrice: price type is invalid"); +// return 0; +// } +// } + + /** + * 显示隐私协议弹窗(原逻辑保留,优化Context使用) + */ +// private void showPrivacy() { +// // 校验Activity状态,避免弹窗泄露 +// if (getActivity() == null || getActivity().isFinishing() || getActivity().isDestroyed()) { +// return; +// } +// ADsMode adsMode = ADsControlView.getAdsModeFromStatic(this.mContext); +// if (adsMode == ADsMode.STANDALONE) { +// ADsControlView.updateAdsModeByStatic(this.mContext, ADsMode.STANDALONE); +// LogUtils.i(TAG, "单机模式,广告已处于不可用状态..."); +// Toast.makeText(getActivity().getApplicationContext(), "单机模式,广告已处于不可用状态...", Toast.LENGTH_SHORT).show(); +// return; +// } else if (adsMode == ADsMode.MIMO_SDK) { +// ADsControlView.updateAdsModeByStatic(this.mContext, ADsMode.MIMO_SDK); +// LogUtils.i(TAG, "米盟广告SDK支持模式,现在初始化SDK..."); +// initMimoSdk(); +// return; +// } +// else { +// LogUtils.i(TAG, "开始弹出隐私协议..."); +// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); +// builder.setTitle("用户须知"); +// builder.setMessage("小米广告SDK隐私政策: https://dev.mi.com/distribute/doc/details?pId=1688, 请复制到浏览器查看"); +// builder.setIcon(R.drawable.ic_launcher); +// builder.setCancelable(false); // 点击对话框以外的区域不消失 +// builder.setPositiveButton("同意", new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialog, int which) { +// getSharedPreferences().edit() +// .putString(PRIVACY_VALUE, String.valueOf(1)) +// .apply(); +// initMimoSdk(); +// dialog.dismiss(); +// } +// }); +// builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() { +// @Override +// public void onClick(DialogInterface dialog, int which) { +// getSharedPreferences().edit() +// .putString(PRIVACY_VALUE, String.valueOf(0)) +// .apply(); +// dialog.dismiss(); +// } +// }); +// AlertDialog dialog = builder.create(); +// +// // 配置弹窗位置(底部全屏) +// Window window = dialog.getWindow(); +// if (window != null) { +// window.setGravity(Gravity.BOTTOM); +// WindowManager m = getActivity().getWindowManager(); +// Display d = m.getDefaultDisplay(); +// WindowManager.LayoutParams p = window.getAttributes(); +// p.width = d.getWidth(); +// window.setAttributes(p); +// } +// dialog.show(); +// } +// } + + /** + * 初始化米盟SDK(核心修复:传递ApplicationContext + 异常捕获) + */ + private void initMimoSdk(Context context) { + // 1. 安全获取ApplicationContext,避免Activity Context失效 + Context appContext = context.getApplicationContext(); + if (appContext == null) { + LogUtils.e(TAG, "initMimoSdk: ApplicationContext is null"); + return; + } + // 2. 初始化SDK,捕获异常避免崩溃 + try { + MimoSdk.init(appContext, new MimoCustomController() { + @Override + public boolean isCanUseLocation() { + return true; + } + + @Override + public MimoLocation getMimoLocation() { + return null; + } + + @Override + public boolean isCanUseWifiState() { + return true; + } + + @Override + public boolean alist() { + return true; + } + }, new MimoSdk.InitCallback() { + @Override + public void success() { + LogUtils.d(TAG, "MimoSdk init success"); + } + + @Override + public void fail(int code, String msg) { + LogUtils.e(TAG, "MimoSdk init fail, code=" + code + ",msg=" + msg); + } + }); + MimoSdk.setDebugOn(true); + } catch (Exception e) { + LogUtils.e(TAG, "initMimoSdk: init failed", e); + } + } + + + /** + * 获取SharedPreferences实例(原逻辑保留,添加空指针校验) + */ +// SharedPreferences getSharedPreferences() { +//// if (mSharedPreferences == null) { +//// // 修复:使用ApplicationContext获取SharedPreferences,避免Activity Context泄露 +//// Context appContext = getActivity().getApplicationContext(); +//// if (appContext != null) { +//// mSharedPreferences = appContext.getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); +//// } else { +//// LogUtils.e(TAG, "getSharedPreferences: ApplicationContext is null"); +//// // 降级方案:若ApplicationContext为空,使用Activity Context(仅作兼容) +//// mSharedPreferences = getActivity().getSharedPreferences(PRIVACY_FILE, Context.MODE_PRIVATE); +//// } +//// } +// return mSharedPreferences; +// } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java new file mode 100644 index 0000000..c24efca --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/ADsControlView.java @@ -0,0 +1,633 @@ +package cc.winboll.studio.libaes.views; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.text.Html; +import android.util.AttributeSet; +import android.view.Display; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.PopupMenu; +import android.widget.PopupWindow; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.enums.ADsMode; +import cc.winboll.studio.libaes.enums.PrivacyAgreeStatus; +import cc.winboll.studio.libaes.utils.WebUtils; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.ToastUtils; +import com.miui.zeus.mimo.sdk.MimoCustomController; +import com.miui.zeus.mimo.sdk.MimoLocation; +import com.miui.zeus.mimo.sdk.MimoSdk; +import java.lang.reflect.Field; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/11/26 17:51 + * @LastEditTime 2026/01/08 11:00:00 HKT + * @Describe 广告模式控制控件(Java 7 兼容,云宝物语模式) + * 核心修改:将PopupMenu锚点绑定到view_popmenu_anchor_point控件,菜单精准显示在锚点位置 + */ +public class ADsControlView extends LinearLayout { + public static final String TAG = "ADsControlView"; + + // SP存储配置 + private static final String SP_NAME = "ads_control_config"; + private static final String KEY_SELECTED_MODE = "selected_ads_mode"; + ADsMode mADsMode; + private static final String PRIVACY_VALUE = "privacy_value"; + PrivacyAgreeStatus mPrivacyAgreeStatus; + + // Handler消息标识 + private static final int MSG_UPDATE_MODE = 1001; + + // 控件引用 + private RadioGroup rgADsMode; + private RadioButton rbStandalone; + private RadioButton rbMimoSDK; + private RadioButton rbStoreQrcode; + private RelativeLayout rlWinbollStore; + private ImageView ivWinbollStoreQrcode; + // 新增:锚点控件引用 + private TextView viewPopmenuAnchorPoint; + + // 外部监听、SP实例、Handler实例 + private OnAdsModeSelectedListener listener; + private SharedPreferences sharedPreferences; + private InternalHandler mHandler; + private Context mContext; + + // 静态列表:存储所有已创建的控件实例 + private static final java.util.List sControlViews = new java.util.ArrayList(); + + // 常量定义 + private static final String WECHAT_STORE_URL = "https://store.weixin.qq.com/shop/b/XhrPkZgoeHo4zug"; + private static final int MENU_ITEM_OPEN_STORE = 1001; + + // 构造方法(Java 7 兼容) + public ADsControlView(Context context) { + super(context); + initView(context); + } + + public ADsControlView(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + @SuppressWarnings("deprecation") + public ADsControlView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + public void setPrivacyAgreeStatus(PrivacyAgreeStatus privacyAgreeStatus) { + this.mPrivacyAgreeStatus = privacyAgreeStatus; + sharedPreferences.edit().putString(PRIVACY_VALUE, this.mPrivacyAgreeStatus.name()).apply(); + } + + public PrivacyAgreeStatus getPrivacyAgreeStatus() { + String privacyAgreeStatusStr = sharedPreferences.getString(PRIVACY_VALUE, PrivacyAgreeStatus.UN_SIGNED.name()); + PrivacyAgreeStatus privacyAgreeStatus = PrivacyAgreeStatus.fromString(privacyAgreeStatusStr); + return privacyAgreeStatus; + } + + public void setADsMode(ADsMode mADsMode) { + this.mADsMode = mADsMode; + sharedPreferences.edit().putString(KEY_SELECTED_MODE, this.mADsMode.name()).apply(); + updateStoreQrcodeLayoutVisibility(mADsMode); + } + + public ADsMode getADsMode() { + String savedModeStr = sharedPreferences.getString(KEY_SELECTED_MODE, ADsMode.STANDALONE.name()); + mADsMode = ADsMode.fromValue(savedModeStr); + return mADsMode; + } + + /** + * 初始化视图、SP、Handler + */ + private void initView(final Context context) { + this.mContext = context; + + // 加载布局 + LayoutInflater.from(context).inflate(R.layout.view_adscontrol, this, true); + + // 初始化SP + sharedPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); + + // 绑定控件 + rgADsMode = (RadioGroup) findViewById(R.id.rg_ads_mode); + rbStandalone = (RadioButton) findViewById(R.id.rb_standalone); + rbMimoSDK = (RadioButton) findViewById(R.id.rb_mimo_sdk); + rbStoreQrcode = (RadioButton) findViewById(R.id.rb_store_qrcode); + rlWinbollStore = (RelativeLayout) findViewById(R.id.rl_winboll_store); + ivWinbollStoreQrcode = (ImageView) findViewById(R.id.iv_winboll_store); + // 绑定锚点控件 + viewPopmenuAnchorPoint = (TextView) findViewById(R.id.view_popmenu_anchor_point); + + // 初始化Handler + mHandler = new InternalHandler(Looper.getMainLooper()); + + // 核心修改:初始化图片的点击和长按事件(锚点改为view_popmenu_anchor_point) + initImageViewClickAndLongClick(); + + // 注册控件实例 + registerControlView(this); + + // 从SP读取初始模式 + setSelectedMode(getADsMode()); + + // 单选组选择事件监听 + rgADsMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + if (checkedId == R.id.rb_standalone) { + setADsMode(ADsMode.STANDALONE); + if (listener != null) listener.onModeSelected(ADsMode.STANDALONE); + } else if (checkedId == R.id.rb_mimo_sdk) { + handlePrivacyLogic((Activity) context, PrivacyAgreeStatus.UN_SIGNED, new OnPrivacyChangeListener() { + @Override + public void onAgreePrivacy() { + setADsMode(ADsMode.MIMO_SDK); + if (listener != null) listener.onModeSelected(ADsMode.MIMO_SDK); + } + + @Override + public void onDisagreePrivacy() { + setADsMode(ADsMode.STANDALONE); + setSelectedMode(ADsMode.STANDALONE); + if (listener != null) listener.onModeSelected(ADsMode.STANDALONE); + } + }); + } else if (checkedId == R.id.rb_store_qrcode) { + setADsMode(ADsMode.STORE_QRCODE); + if (listener != null) listener.onModeSelected(ADsMode.STORE_QRCODE); + } + } + }); + } + + /** + * 初始化图片的点击和长按事件 + * 核心:将PopupMenu锚点绑定到view_popmenu_anchor_point控件 + */ + private void initImageViewClickAndLongClick() { + if (ivWinbollStoreQrcode == null || viewPopmenuAnchorPoint == null) { + LogUtils.e(TAG, "initImageViewClickAndLongClick: 控件引用为空"); + return; + } + + // 1. 点击事件:简化为提示信息 + ivWinbollStoreQrcode.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + ToastUtils.show("长按图片可打开微信小店"); + LogUtils.d(TAG, "图片点击:提示用户长按打开微信小店"); + } + }); + + // 2. 长按事件:锚点改为view_popmenu_anchor_point + ivWinbollStoreQrcode.setOnLongClickListener(new OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + // 计算锚点控件的屏幕坐标(用于菜单位置微调) + int[] anchorLocation = new int[2]; + viewPopmenuAnchorPoint.getLocationOnScreen(anchorLocation); + final int anchorX = anchorLocation[0]; + final int anchorY = anchorLocation[1]; + + // 创建PopupMenu,锚点绑定到view_popmenu_anchor_point + PopupMenu popupMenu = new PopupMenu(mContext, viewPopmenuAnchorPoint); + // 设置菜单重力:相对锚点居中显示 + popupMenu.setGravity(Gravity.CENTER); + + Menu menu = popupMenu.getMenu(); + menu.add(Menu.NONE, MENU_ITEM_OPEN_STORE, Menu.NONE, "打开微信小店"); + + // 设置菜单点击事件 + popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + if (item.getItemId() == MENU_ITEM_OPEN_STORE) { + WebUtils.openUrlInBrowser(mContext, WECHAT_STORE_URL); + return true; + } + return false; + } + }); + + try { + // 反射获取PopupWindow,微调菜单位置(可选) + Field popupField = PopupMenu.class.getDeclaredField("mPopup"); + popupField.setAccessible(true); + Object popupObject = popupField.get(popupMenu); + if (popupObject instanceof PopupWindow) { + final PopupWindow popupWindow = (PopupWindow) popupObject; + popupWindow.setAnimationStyle(0); // 关闭默认动画 + + // 延迟微调菜单位置(确保布局测量完成) + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + @Override + public void run() { + int menuX = anchorX + viewPopmenuAnchorPoint.getWidth() / 2 - popupWindow.getWidth() / 2; + int menuY = anchorY + viewPopmenuAnchorPoint.getHeight() / 2 - popupWindow.getHeight() / 2; + if (!popupWindow.isShowing()) { + popupWindow.showAtLocation(viewPopmenuAnchorPoint, Gravity.NO_GRAVITY, menuX, menuY); + } + } + }, 30); + } + } catch (NoSuchFieldException | IllegalAccessException e) { + LogUtils.e(TAG, "反射获取PopupWindow失败", e); + } + + // 显示菜单 + popupMenu.show(); + LogUtils.d(TAG, "长按图片,菜单锚点为view_popmenu_anchor_point"); + return true; + } + }); + + // 设置控件可交互标识 + ivWinbollStoreQrcode.setClickable(true); + ivWinbollStoreQrcode.setFocusable(true); + ivWinbollStoreQrcode.setLongClickable(true); + viewPopmenuAnchorPoint.setClickable(false); // 锚点控件不可点击 + viewPopmenuAnchorPoint.setLongClickable(false); + } + + /** + * 从ImageView中提取Bitmap(保留方法,无实际调用) + */ + private Bitmap getBitmapFromImageView(ImageView imageView) { + Drawable drawable = imageView.getDrawable(); + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + return null; + } + + /** + * 压缩Bitmap(备用方法,无实际调用) + */ + private Bitmap compressBitmapBySize(Bitmap src, int maxWidth, int maxHeight) { + if (src == null) return null; + int width = src.getWidth(); + int height = src.getHeight(); + float scale = Math.min((float) maxWidth / width, (float) maxHeight / height); + int newWidth = (int) (width * scale); + int newHeight = (int) (height * scale); + return Bitmap.createScaledBitmap(src, newWidth, newHeight, true); + } + + /** + * 计算Bitmap采样率(备用方法,无实际调用) + */ + private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + if (height > reqHeight || width > reqWidth) { + final int halfHeight = height / 2; + final int halfWidth = width / 2; + while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { + inSampleSize *= 2; + } + } + return inSampleSize; + } + + /** + * 从ImageView反射获取资源ID(备用方法,无实际调用) + */ + private int getResIdFromImageView(ImageView imageView) { + try { + Field field = ImageView.class.getDeclaredField("mSrcResource"); + field.setAccessible(true); + return field.getInt(imageView); + } catch (NoSuchFieldException | IllegalAccessException e) { + LogUtils.e(TAG, "getResIdFromImageView: 反射失败", e); + return 0; + } + } + + /** + * 更新二维码布局显示状态 + */ + private void updateStoreQrcodeLayoutVisibility(ADsMode mode) { + if (rlWinbollStore == null) return; + rlWinbollStore.setVisibility(mode == ADsMode.STORE_QRCODE ? View.VISIBLE : View.GONE); + } + + /** + * 清理SP中的隐私协议状态 + */ + public static void cleanPrivacyStatus(Context context) { + if (context == null) { + LogUtils.e(TAG, "cleanPrivacyStatus: Context is null"); + return; + } + SharedPreferences sp = getPrivacySharedPreferences(context); + sp.edit().remove(PRIVACY_VALUE).apply(); + LogUtils.i(TAG, "隐私协议状态清理成功"); + ToastUtils.show("隐私协议状态已清理"); + } + + /** + * 获取隐私协议SP实例 + */ + private static SharedPreferences getPrivacySharedPreferences(Context context) { + Context appContext = context.getApplicationContext(); + if (appContext != null) { + return appContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); + } + return context.getSharedPreferences(PRIVACY_VALUE, Context.MODE_PRIVATE); + } + + /** + * 处理隐私协议逻辑 + */ + private static void handlePrivacyLogic(final Activity activity, PrivacyAgreeStatus privacyAgreeStatus, final OnPrivacyChangeListener onPrivacyChangeListener) { + if (privacyAgreeStatus == PrivacyAgreeStatus.REJECTED) { + Toast.makeText(activity.getApplicationContext(), "已拒绝隐私协议,广告已处于不可用状态", Toast.LENGTH_SHORT).show(); + return; + } else if (privacyAgreeStatus == PrivacyAgreeStatus.AGREED) { + initMimoSdkStatic(activity.getApplicationContext()); + return; + } else { + AlertDialog dialog = createPrivacyDialog(activity, onPrivacyChangeListener); + Window window = dialog.getWindow(); + if (window != null) { + window.setGravity(Gravity.BOTTOM); + WindowManager m = activity.getWindowManager(); + Display d = m.getDefaultDisplay(); + WindowManager.LayoutParams p = window.getAttributes(); + p.width = d.getWidth(); + window.setAttributes(p); + } + dialog.show(); + } + } + + /** + * 初始化米盟SDK + */ + private static void initMimoSdkStatic(Context appContext) { + if (appContext == null) return; + try { + MimoSdk.init(appContext, new MimoCustomController() { + @Override + public boolean isCanUseLocation() { + return true; + } + + @Override + public MimoLocation getMimoLocation() { + return null; + } + + @Override + public boolean isCanUseWifiState() { + return true; + } + + @Override + public boolean alist() { + return true; + } + }, new MimoSdk.InitCallback() { + @Override + public void success() { + LogUtils.d(TAG, "米盟SDK初始化成功"); + } + + @Override + public void fail(int code, String msg) { + LogUtils.e(TAG, "米盟SDK初始化失败:" + code + ", " + msg); + } + }); + MimoSdk.setDebugOn(true); + } catch (Exception e) { + LogUtils.e(TAG, "米盟SDK初始化异常", e); + } + } + + /** + * 静态方法:更新SP中的模式 + */ + public static void updateAdsModeByStatic(Context context, ADsMode mode) { + if (context == null || mode == null) return; + SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); + sp.edit().putString(KEY_SELECTED_MODE, mode.name()).apply(); + InternalHandler.sendUpdateModeMessage(mode); + } + + /** + * 静态方法:读取SP中的模式 + */ + public static ADsMode getAdsModeFromStatic(Context context) { + if (context == null) return ADsMode.STANDALONE; + SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); + String savedModeStr = sp.getString(KEY_SELECTED_MODE, ADsMode.STANDALONE.name()); + return ADsMode.fromValue(savedModeStr); + } + + /** + * 注册控件实例 + */ + private static void registerControlView(ADsControlView view) { + synchronized (sControlViews) { + if (!sControlViews.contains(view)) { + sControlViews.add(view); + } + } + } + + /** + * 移除控件实例 + */ + private static void unregisterControlView(ADsControlView view) { + synchronized (sControlViews) { + sControlViews.remove(view); + } + } + + /** + * 设置选中模式 + */ + private void setSelectedMode(final ADsMode mode) { + final ADsMode mode2 = (mode == null) ? ADsMode.STANDALONE : mode; + if (Looper.myLooper() == Looper.getMainLooper()) { + if (mode2 == ADsMode.STANDALONE) { + rbStandalone.setChecked(true); + } else if (mode2 == ADsMode.MIMO_SDK) { + rbMimoSDK.setChecked(true); + } else if (mode2 == ADsMode.STORE_QRCODE) { + rbStoreQrcode.setChecked(true); + } + updateStoreQrcodeLayoutVisibility(mode2); + } else { + mHandler.post(new Runnable() { + @Override + public void run() { + setSelectedMode(mode2); + } + }); + } + } + + /** + * 获取选中模式 + */ + public ADsMode getSelectedMode() { + int checkedId = rgADsMode.getCheckedRadioButtonId(); + if (checkedId == R.id.rb_mimo_sdk) { + return ADsMode.MIMO_SDK; + } else if (checkedId == R.id.rb_store_qrcode) { + return ADsMode.STORE_QRCODE; + } else { + return ADsMode.STANDALONE; + } + } + + /** + * 设置外部监听 + */ + public void setOnAdsModeSelectedListener(OnAdsModeSelectedListener listener) { + this.listener = listener; + } + + /** + * 内部Handler类 + */ + private static class InternalHandler extends Handler { + static volatile InternalHandler _InternalHandler; + + public InternalHandler(Looper looper) { + super(looper); + _InternalHandler = this; + } + + public static void sendUpdateModeMessage(ADsMode mode) { + if (mode == null || _InternalHandler == null) return; + Message msg = _InternalHandler.obtainMessage(); + msg.what = MSG_UPDATE_MODE; + msg.obj = mode; + _InternalHandler.sendMessage(msg); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == MSG_UPDATE_MODE) { + ADsMode mode = (ADsMode) msg.obj; + if (mode == null) return; + synchronized (sControlViews) { + for (ADsControlView view : sControlViews) { + if (view != null && view.isShown() && view.isAttachedToWindow()) { + view.setSelectedMode(mode); + view.updateStoreQrcodeLayoutVisibility(mode); + } + } + } + } + } + } + + /** + * 生命周期:控件销毁 + */ + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + } + unregisterControlView(this); + } + + /** + * 外部监听接口 + */ + public interface OnAdsModeSelectedListener { + void onModeSelected(ADsMode selectedMode); + } + + /** + * 隐私协议监听接口 + */ + public interface OnPrivacyChangeListener { + void onAgreePrivacy(); + void onDisagreePrivacy(); + } + + /** + * 创建隐私协议对话框 + */ + private static AlertDialog createPrivacyDialog(final Activity activity, final OnPrivacyChangeListener onPrivacyChangeListener) { + View dialogView = LayoutInflater.from(activity).inflate(R.layout.dialog_privacy_agreement, null); + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setView(dialogView).setCancelable(false); + final AlertDialog dialog = builder.create(); + + final TextView tvPrivacyUrl = (TextView) dialogView.findViewById(R.id.tv_privacy_url); + Button btnAgree = (Button) dialogView.findViewById(R.id.btn_agree); + Button btnDisagree = (Button) dialogView.findViewById(R.id.btn_disagree); + + tvPrivacyUrl.setText(Html.fromHtml("" + tvPrivacyUrl.getText().toString() + "")); + tvPrivacyUrl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + String url = tvPrivacyUrl.getText().toString().trim(); + ToastUtils.show("隐私协议链接:" + url); + } + }); + tvPrivacyUrl.setClickable(true); + tvPrivacyUrl.setFocusable(true); + + btnAgree.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (onPrivacyChangeListener != null) { + onPrivacyChangeListener.onAgreePrivacy(); + } + dialog.dismiss(); + } + }); + + btnDisagree.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (onPrivacyChangeListener != null) { + onPrivacyChangeListener.onDisagreePrivacy(); + } + dialog.dismiss(); + } + }); + + return dialog; + } +} + diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTCSeekBar.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTCSeekBar.java new file mode 100644 index 0000000..432fbde --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTCSeekBar.java @@ -0,0 +1,108 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:46:30 + * @Describe AOneHundredPercantClickToCommitSeekBar + */ +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.SeekBar; +import cc.winboll.studio.libappbase.LogUtils; + +public class AOHPCTCSeekBar extends SeekBar { + + public static final String TAG = "AOHPCTCSeekBar"; + + volatile int thumbWidth = 1; + volatile int progressBarWidth = 1; + // 设置按钮模糊右边边缘像素 + volatile int blurRightDP = 1; + // 是否从起点拉动的标志 + volatile boolean isStartSeek = false; + + // 外部接口对象,确定事件提交会调用该对象的方法 + OnOHPCListener mOnOHPCListener; + + + public void setBlurRightDP(int blurRight) { + this.blurRightDP = blurRight; + } + + public void setOnOHPCListener(OnOHPCListener listener) { + mOnOHPCListener = listener; + } + + public interface OnOHPCListener { + abstract void onOHPCommit(); + } + + public AOHPCTCSeekBar(Context context) { + super(context); + initView(context); + } + + public AOHPCTCSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + public AOHPCTCSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + void initView(Context context) { + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (thumbWidth + blurRightDP > event.getX() && event.getX() > 0) { + getParent().requestDisallowInterceptTouchEvent(true); + isStartSeek = true; + } + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (isStartSeek) { + super.dispatchTouchEvent(event); + } + } else if (event.getAction() == MotionEvent.ACTION_UP + || event.getAction() == MotionEvent.ACTION_CANCEL) { + getParent().requestDisallowInterceptTouchEvent(false); + if (getProgress() == progressBarWidth) { + mOnOHPCListener.onOHPCommit(); + } + // 重置控件状态 + setProgress(0); + isStartSeek = false; + } + return true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + //int height = MeasureSpec.getSize(heightMeasureSpec); + //LogUtils.d(TAG, String.format("width %d height %d", width, height)); + + // 获取SeekBar的图标宽度 + Drawable thumbDrawable = getThumb(); + if (thumbDrawable != null) { + // 获取图标宽度 + thumbWidth = thumbDrawable.getIntrinsicWidth(); + } + + // 获取进度条宽度 + progressBarWidth = width; + + //LogUtils.d(TAG, String.format("thumbWidth %d progressBarWidth %d", thumbWidth, progressBarWidth)); + + // 设置图标位置 + setThumbOffset(0); + // 设置进度条刻度 + setMax(progressBarWidth); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTSCard.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTSCard.java new file mode 100644 index 0000000..a7120ea --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/AOHPCTSCard.java @@ -0,0 +1,43 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:49:23 + * @Describe AOneHundredPercantClickToStartCard + */ +import android.content.Context; +import android.util.AttributeSet; + +public class AOHPCTSCard extends ACard { + + public static final String TAG = "AOHPCTSCard"; + + public AOHPCTSCard(Context context) { + super(context); + } + + public AOHPCTSCard(Context context, AttributeSet attrs) { + super(context, attrs); + //setPadding(0 + 0 + 2 + 1, 0 + 0 + 2 + 1, 0 + 1 + 3 + 1, 0 + 2 + 3 + 1); + + // 获得TypedArray + //TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AToolbar); + // 获得attrs.xml里面的属性值,格式为:名称_属性名,后面是默认值 + //int colorBackgroud = a.getColor(R.styleable.ACard_backgroudColor, context.getColor(R.color.colorACardBackgroung)); + //int centerColor = a.getColor(R.styleable.AToolbar_centerColor, context.getColor(R.color.colorAToolbarCenterColor)); + //int endColor = a.getColor(R.styleable.AToolbar_endColor, context.getColor(R.color.colorAToolbarEndColor)); + //float tSize = a.getDimension(R.styleable.CustomView_tSize, 35); + //p.setColor(tColor); + //p.setTextSize(tSize); + //Drawable drawable = context.getDrawable(R.drawable.frame_atoolbar); + + //setBackground(context.getDrawable(R.drawable.acard_frame_main)); + + // 返回一个绑定资源结束的信号给资源 + //a.recycle(); + } + + public AOHPCTSCard(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ASupportToolbar.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ASupportToolbar.java new file mode 100644 index 0000000..c384919 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/ASupportToolbar.java @@ -0,0 +1,89 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:54:40 + * @Describe ASupportToolbar + */ +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; +import android.util.AttributeSet; +import androidx.appcompat.widget.Toolbar; +import cc.winboll.studio.libaes.R; +import android.graphics.drawable.Drawable; +import androidx.core.content.ContextCompat; +import android.graphics.PorterDuff; + +public class ASupportToolbar extends Toolbar { + + public static final String TAG = "ASupportToolbar"; + + int mTitleTextColor; + int mStartColor; + int mCenterColor; + int mEndColor; + LayerDrawable ld; + GradientDrawable[] array = new GradientDrawable[3]; + //private GradientDrawable gradientDrawable; + + public ASupportToolbar(Context context) { + super(context); + } + + public ASupportToolbar(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ASupportToolbar, R.attr.aSupportToolbar, 0); + mTitleTextColor = a.getColor(R.styleable.ASupportToolbar_attrASupportToolbarTitleTextColor, Color.GREEN); + mStartColor = a.getColor(R.styleable.ASupportToolbar_attrASupportToolbarStartColor, Color.BLUE); + mCenterColor = a.getColor(R.styleable.ASupportToolbar_attrASupportToolbarCenterColor, Color.RED); + mEndColor = a.getColor(R.styleable.ASupportToolbar_attrASupportToolbarEndColor, Color.YELLOW); + // 返回一个绑定资源结束的信号给资源 + a.recycle(); + notifyColorChange(); + } + + void notifyColorChange() { + // 工具栏描边 + int nStroke = 5; + + //分别为开始颜色,中间夜色,结束颜色 + int colors0[] = { mEndColor , mCenterColor, mStartColor}; + GradientDrawable gradientDrawable0; + array[2] = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors0); + gradientDrawable0 = array[2]; + gradientDrawable0.setShape(GradientDrawable.RECTANGLE); + gradientDrawable0.setColors(colors0); //添加颜色组 + gradientDrawable0.setGradientType(GradientDrawable.LINEAR_GRADIENT);//设置线性渐变 + gradientDrawable0.setCornerRadius(20); + + int colors1[] = { mCenterColor , mCenterColor, mCenterColor }; + GradientDrawable gradientDrawable1; + array[1] = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors1); + gradientDrawable1 = array[1]; + gradientDrawable1.setShape(GradientDrawable.RECTANGLE); + gradientDrawable1.setColors(colors1); //添加颜色组 + gradientDrawable1.setGradientType(GradientDrawable.LINEAR_GRADIENT);//设置线性渐变 + gradientDrawable1.setCornerRadius(20); + + int colors2[] = { mEndColor, mCenterColor, mStartColor }; + GradientDrawable gradientDrawable2; + array[0] = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors2); + gradientDrawable2 = array[0]; + gradientDrawable2.setShape(GradientDrawable.RECTANGLE); + gradientDrawable2.setColors(colors2); //添加颜色组 + gradientDrawable2.setGradientType(GradientDrawable.LINEAR_GRADIENT);//设置线性渐变 + gradientDrawable2.setCornerRadius(20); + + ld = new LayerDrawable(array); //参数为上面的Drawable数组 + ld.setLayerInset(2, nStroke * 2, nStroke * 2, getWidth() + nStroke * 2, getHeight() + nStroke * 2); + ld.setLayerInset(1, nStroke, nStroke, getWidth() + nStroke, getHeight() + nStroke); + ld.setLayerInset(0, 0, 0, getWidth(), getHeight()); + + setBackgroundDrawable(ld); + setTitleTextColor(mTitleTextColor); + setSubtitleTextColor(mTitleTextColor); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/ATickProgressBar.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/ATickProgressBar.java new file mode 100644 index 0000000..ddba22b --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/ATickProgressBar.java @@ -0,0 +1,55 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:56:38 + * @Describe ATickProgressBar + */ +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.widget.ProgressBar; + +public class ATickProgressBar extends ProgressBar { + + public static final String TAG = "ATickProgressBar"; + + int mnStepDistantce = 100 / 10; + int mnProgress = 0; + + public ATickProgressBar(Context context) { + super(context); + + } + + public ATickProgressBar(Context context, AttributeSet attrs) { + super(context, attrs); + setProgress(50); + } + + public int stepOnTick(int nStepDistantce) { + if (mnProgress < 100) { + int nProgressOld = mnProgress; + mnProgress += nStepDistantce; + new Handler().postDelayed(new Runnable(){ + + @Override + public void run() { + ; + } + }, 1000); + return nProgressOld; + } else { + return mnProgress; + } + } + + /*@Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int nWidthSize = MeasureSpec.getSize(widthMeasureSpec); + int nHeightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(nWidthSize, nHeightSize); + }*/ +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/AToolbar.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/AToolbar.java new file mode 100644 index 0000000..39b9249 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/AToolbar.java @@ -0,0 +1,92 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @Date 2024/07/16 01:58:01 + * @Describe AToolbar + */ +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; +import android.util.AttributeSet; +import android.widget.Toolbar; +import cc.winboll.studio.libaes.R; + +public class AToolbar extends Toolbar { + + public static final String TAG = "AToolbar"; + + int mTitleTextColor; + int mStartColor; + int mCenterColor; + int mEndColor; + LayerDrawable ld; + GradientDrawable[] array = new GradientDrawable[3]; + + public AToolbar(Context context) { + super(context); + } + + public AToolbar(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AToolbar, R.attr.aToolbar, 0); + mTitleTextColor = a.getColor(R.styleable.AToolbar_attrAToolbarTitleTextColor, Color.GREEN); + mStartColor = a.getColor(R.styleable.AToolbar_attrAToolbarStartColor, Color.BLUE); + mCenterColor = a.getColor(R.styleable.AToolbar_attrAToolbarCenterColor, Color.RED); + mEndColor = a.getColor(R.styleable.AToolbar_attrAToolbarEndColor, Color.YELLOW); + // 返回一个绑定资源结束的信号给资源 + a.recycle(); + + notifyColorChange(); + } + + public AToolbar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + void notifyColorChange() { + // 工具栏描边 + int nStroke = 5; + + //分别为开始颜色,中间夜色,结束颜色 + int colors0[] = { mEndColor , mCenterColor, mStartColor}; + GradientDrawable gradientDrawable0; + array[2] = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors0); + gradientDrawable0 = array[2]; + gradientDrawable0.setShape(GradientDrawable.RECTANGLE); + gradientDrawable0.setColors(colors0); //添加颜色组 + gradientDrawable0.setGradientType(GradientDrawable.LINEAR_GRADIENT);//设置线性渐变 + gradientDrawable0.setCornerRadius(20); + + int colors1[] = { mCenterColor , mCenterColor, mCenterColor }; + GradientDrawable gradientDrawable1; + array[1] = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors1); + gradientDrawable1 = array[1]; + gradientDrawable1.setShape(GradientDrawable.RECTANGLE); + gradientDrawable1.setColors(colors1); //添加颜色组 + gradientDrawable1.setGradientType(GradientDrawable.LINEAR_GRADIENT);//设置线性渐变 + gradientDrawable1.setCornerRadius(20); + + int colors2[] = { mEndColor, mCenterColor, mStartColor }; + GradientDrawable gradientDrawable2; + array[0] = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors2); + gradientDrawable2 = array[0]; + gradientDrawable2.setShape(GradientDrawable.RECTANGLE); + gradientDrawable2.setColors(colors2); //添加颜色组 + gradientDrawable2.setGradientType(GradientDrawable.LINEAR_GRADIENT);//设置线性渐变 + gradientDrawable2.setCornerRadius(20); + + + ld = new LayerDrawable(array); //参数为上面的Drawable数组 + ld.setLayerInset(2, nStroke * 2, nStroke * 2, getWidth() + nStroke * 2, getHeight() + nStroke * 2); + ld.setLayerInset(1, nStroke, nStroke, getWidth() + nStroke, getHeight() + nStroke); + ld.setLayerInset(0, 0, 0, getWidth(), getHeight()); + + setBackgroundDrawable(ld); + setTitleTextColor(mTitleTextColor); + setSubtitleTextColor(mTitleTextColor); + } +} diff --git a/libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java b/libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java new file mode 100644 index 0000000..9f5ed56 --- /dev/null +++ b/libaes/src/main/java/cc/winboll/studio/libaes/views/AboutView.java @@ -0,0 +1,379 @@ +package cc.winboll.studio.libaes.views; + +/** + * @Author ZhanGSKen + * @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.View; +import android.widget.EditText; +import android.widget.LinearLayout; +import cc.winboll.studio.libaes.R; +import cc.winboll.studio.libaes.dialogs.YesNoAlertDialog; +import cc.winboll.studio.libaes.models.APPInfo; +import cc.winboll.studio.libaes.utils.AppVersionUtils; +import cc.winboll.studio.libaes.utils.PrefUtils; +import cc.winboll.studio.libaes.utils.WinBoLLActivityManager; +import cc.winboll.studio.libappbase.GlobalApplication; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.ToastUtils; +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; + + static Context _mContext; + APPInfo mAPPInfo; + + //WinBoLLServiceStatusView mWinBoLLServiceStatusView; + OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener; + String mszAppName = ""; + String mszAppAPKFolderName = ""; + String mszAppAPKName = ""; + String mszAppGitName = ""; + String mszAppVersionName = ""; + String mszCurrentAppPackageName = ""; + boolean mIsAddDebugTools; + 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)); + appInfo.setIsAddDebugTools(typedArray.getBoolean(R.styleable.AboutView_is_adddebugtools, false)); + // 返回一个绑定资源结束的信号给资源 + 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.isDebugging() ? "https://yun-preivew.winboll.cc": "https://yun.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 = mAPPInfo.getAppHomePage(); + //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(); + } + + addView(createAboutPage()); + + // 初始化标题栏 + //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() { + // 定义 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()); + } + AboutPage aboutPage = new AboutPage(_mContext); + aboutPage.setDescription(szAppInfo) + //.isRTL(false) + //.setCustomFont(String) // or Typeface + .setImage(mnAppIcon) + //.addItem(versionElement) + //.addItem(adsElement) + //.addGroup("Connect with us") + .addEmail("WinBoLLStudio") + .addWebsite(mszHomePage) + .addItem(elementGitWeb); + //.addItem(elementAppUpdate); + //.addFacebook("the.medy") + //.addTwitter("medyo80") + //.addYoutube("UCdPQtdWIsg7_pi4mrRu46vA") + //.addPlayStore("com.ideashower.readitlater.pro") + //.addGitHub("medyo") + //.addInstagram("medyo80") + //.create(); + + /*if (mAPPInfo.isAddDebugTools()) { + // 定义应用调试按钮 + // + Element elementAppMode; + if (GlobalApplication.isDebugging()) { + 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); + } + aboutPage.addItem(elementAppMode); + }*/ + + return aboutPage.create(); + } + + View.OnClickListener mAppDebugOnClickListener = new View.OnClickListener(){ + @Override + public void onClick(View view) { + //ToastUtils.show("mAppDebugOnClickListener"); + setApp2DebugMode(_mContext); + } + }; + + View.OnClickListener mAppNormalOnClickListener = new View.OnClickListener(){ + @Override + public void onClick(View view) { + //ToastUtils.show("mAppNormalOnClickListener"); + 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.setIsDebugging(true); + GlobalApplication.saveDebugStatus((GlobalApplication)_mContext.getApplicationContext()); + + WinBoLLActivityManager.getInstance().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.setIsDebugging(false); + GlobalApplication.saveDebugStatus((GlobalApplication)_mContext.getApplicationContext()); + + WinBoLLActivityManager.getInstance().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.isDebugging()) { + credential = Credentials.basic(metDevUserName.getText().toString(), metDevUserPassword.getText().toString()); + PrefUtils.saveString(_mContext, "metDevUserName", metDevUserName.getText().toString()); + PrefUtils.saveString(_mContext, "metDevUserPassword", metDevUserPassword.getText().toString()); + } else { + String username = "WinBoLL"; + String password = "WinBoLLPowerByZhanGSKen"; + credential = Credentials.basic(username, password); + } + + Request request = new Request.Builder() + .url(szUrl) + .header("Accept", "text/plain") // 设置正确的Content-Type头 + .header("Authorization", credential) + .build(); + OkHttpClient client = new OkHttpClient(); + 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/res/anim/normal_dialog_enter_center.xml b/libaes/src/main/res/anim/normal_dialog_enter_center.xml new file mode 100644 index 0000000..7a6ac10 --- /dev/null +++ b/libaes/src/main/res/anim/normal_dialog_enter_center.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/libaes/src/main/res/anim/normal_dialog_enter_corner.xml b/libaes/src/main/res/anim/normal_dialog_enter_corner.xml new file mode 100644 index 0000000..edfc076 --- /dev/null +++ b/libaes/src/main/res/anim/normal_dialog_enter_corner.xml @@ -0,0 +1,15 @@ + + + + diff --git a/libaes/src/main/res/anim/normal_dialog_exit_center.xml b/libaes/src/main/res/anim/normal_dialog_exit_center.xml new file mode 100644 index 0000000..4d69f65 --- /dev/null +++ b/libaes/src/main/res/anim/normal_dialog_exit_center.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/libaes/src/main/res/anim/normal_dialog_exit_corner.xml b/libaes/src/main/res/anim/normal_dialog_exit_corner.xml new file mode 100644 index 0000000..4b9d1fc --- /dev/null +++ b/libaes/src/main/res/anim/normal_dialog_exit_corner.xml @@ -0,0 +1,14 @@ + + + + diff --git a/libaes/src/main/res/drawable/acard_frame_main.xml b/libaes/src/main/res/drawable/acard_frame_main.xml new file mode 100644 index 0000000..f8780ff --- /dev/null +++ b/libaes/src/main/res/drawable/acard_frame_main.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/atoolbar_frame.xml b/libaes/src/main/res/drawable/atoolbar_frame.xml new file mode 100644 index 0000000..280f018 --- /dev/null +++ b/libaes/src/main/res/drawable/atoolbar_frame.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/bg_shadow.xml b/libaes/src/main/res/drawable/bg_shadow.xml new file mode 100644 index 0000000..6d3d898 --- /dev/null +++ b/libaes/src/main/res/drawable/bg_shadow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/btn_style.xml b/libaes/src/main/res/drawable/btn_style.xml new file mode 100644 index 0000000..7c6bb83 --- /dev/null +++ b/libaes/src/main/res/drawable/btn_style.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/libaes/src/main/res/drawable/default_shape.xml b/libaes/src/main/res/drawable/default_shape.xml new file mode 100644 index 0000000..8a405ca --- /dev/null +++ b/libaes/src/main/res/drawable/default_shape.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/ic_arrow_left_right_bold.xml b/libaes/src/main/res/drawable/ic_arrow_left_right_bold.xml new file mode 100644 index 0000000..8d6dc41 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_arrow_left_right_bold.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/libaes/src/main/res/drawable/ic_arrow_up_circle_outline.xml b/libaes/src/main/res/drawable/ic_arrow_up_circle_outline.xml new file mode 100644 index 0000000..38c794a --- /dev/null +++ b/libaes/src/main/res/drawable/ic_arrow_up_circle_outline.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/libaes/src/main/res/drawable/ic_call.xml b/libaes/src/main/res/drawable/ic_call.xml new file mode 100644 index 0000000..c5802bb --- /dev/null +++ b/libaes/src/main/res/drawable/ic_call.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/libaes/src/main/res/drawable/ic_dev_connected.xml b/libaes/src/main/res/drawable/ic_dev_connected.xml new file mode 100644 index 0000000..1fb2f26 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_dev_connected.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/libaes/src/main/res/drawable/ic_dev_disconnected.xml b/libaes/src/main/res/drawable/ic_dev_disconnected.xml new file mode 100644 index 0000000..4267975 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_dev_disconnected.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/libaes/src/main/res/drawable/ic_email.xml b/libaes/src/main/res/drawable/ic_email.xml new file mode 100644 index 0000000..d526b26 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_email.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/libaes/src/main/res/drawable/ic_email_alert.xml b/libaes/src/main/res/drawable/ic_email_alert.xml new file mode 100644 index 0000000..f3ed613 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_email_alert.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/libaes/src/main/res/drawable/ic_launcher.xml b/libaes/src/main/res/drawable/ic_launcher.xml new file mode 100644 index 0000000..f269b7e --- /dev/null +++ b/libaes/src/main/res/drawable/ic_launcher.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/libaes/src/main/res/drawable/ic_launcher_background.xml b/libaes/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..9486190 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/ic_launcher_foreground.xml b/libaes/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..872b04e --- /dev/null +++ b/libaes/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,10 @@ + + + + diff --git a/libaes/src/main/res/drawable/ic_winboll.xml b/libaes/src/main/res/drawable/ic_winboll.xml new file mode 100644 index 0000000..f269b7e --- /dev/null +++ b/libaes/src/main/res/drawable/ic_winboll.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/libaes/src/main/res/drawable/ic_winboll_store.png b/libaes/src/main/res/drawable/ic_winboll_store.png new file mode 100644 index 0000000000000000000000000000000000000000..e8bb856357601e0c6420b59893c663633925ed86 GIT binary patch literal 197451 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

QO^I)RLaP@EH>fa5fJ){jFewr}D$^}w6D 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 literal 0 HcmV?d00001 diff --git a/libaes/src/main/res/drawable/ic_winbollbeta.xml b/libaes/src/main/res/drawable/ic_winbollbeta.xml new file mode 100644 index 0000000..f4876a0 --- /dev/null +++ b/libaes/src/main/res/drawable/ic_winbollbeta.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/libaes/src/main/res/drawable/ohpcts_frame.xml b/libaes/src/main/res/drawable/ohpcts_frame.xml new file mode 100644 index 0000000..caf8c6d --- /dev/null +++ b/libaes/src/main/res/drawable/ohpcts_frame.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/pressed_shape.xml b/libaes/src/main/res/drawable/pressed_shape.xml new file mode 100644 index 0000000..ed448af --- /dev/null +++ b/libaes/src/main/res/drawable/pressed_shape.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/drawable/shape_gradient.xml b/libaes/src/main/res/drawable/shape_gradient.xml new file mode 100644 index 0000000..c164fe9 --- /dev/null +++ b/libaes/src/main/res/drawable/shape_gradient.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/libaes/src/main/res/drawable/toast_frame.xml b/libaes/src/main/res/drawable/toast_frame.xml new file mode 100644 index 0000000..c4b8f8a --- /dev/null +++ b/libaes/src/main/res/drawable/toast_frame.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/libaes/src/main/res/drawable/view_border.xml b/libaes/src/main/res/drawable/view_border.xml new file mode 100644 index 0000000..58b374a --- /dev/null +++ b/libaes/src/main/res/drawable/view_border.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/libaes/src/main/res/drawable/winboll_help.xml b/libaes/src/main/res/drawable/winboll_help.xml new file mode 100644 index 0000000..564175f --- /dev/null +++ b/libaes/src/main/res/drawable/winboll_help.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/libaes/src/main/res/drawable/winboll_logo.xml b/libaes/src/main/res/drawable/winboll_logo.xml new file mode 100644 index 0000000..ea28987 --- /dev/null +++ b/libaes/src/main/res/drawable/winboll_logo.xml @@ -0,0 +1,48 @@ + + + + + + + + diff --git a/libaes/src/main/res/drawable/winboll_point.xml b/libaes/src/main/res/drawable/winboll_point.xml new file mode 100644 index 0000000..48028cc --- /dev/null +++ b/libaes/src/main/res/drawable/winboll_point.xml @@ -0,0 +1,20 @@ + + + + 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..7d2a2ca --- /dev/null +++ b/libaes/src/main/res/layout/activity_about.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/libaes/src/main/res/layout/activity_drawer.xml b/libaes/src/main/res/layout/activity_drawer.xml new file mode 100644 index 0000000..cd1723d --- /dev/null +++ b/libaes/src/main/res/layout/activity_drawer.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/layout/activity_drawerfragment.xml b/libaes/src/main/res/layout/activity_drawerfragment.xml new file mode 100644 index 0000000..22ce6ef --- /dev/null +++ b/libaes/src/main/res/layout/activity_drawerfragment.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libaes/src/main/res/layout/activity_secondarylibrary.xml b/libaes/src/main/res/layout/activity_secondarylibrary.xml new file mode 100644 index 0000000..bf0f2d8 --- /dev/null +++ b/libaes/src/main/res/layout/activity_secondarylibrary.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/libaes/src/main/res/layout/activity_test_aboutfragment.xml b/libaes/src/main/res/layout/activity_test_aboutfragment.xml new file mode 100644 index 0000000..6476c15 --- /dev/null +++ b/libaes/src/main/res/layout/activity_test_aboutfragment.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/libaes/src/main/res/layout/activity_testasupporttoolbar.xml b/libaes/src/main/res/layout/activity_testasupporttoolbar.xml new file mode 100644 index 0000000..a92a8ca --- /dev/null +++ b/libaes/src/main/res/layout/activity_testasupporttoolbar.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/libaes/src/main/res/layout/activity_testatoolbar.xml b/libaes/src/main/res/layout/activity_testatoolbar.xml new file mode 100644 index 0000000..a30473e --- /dev/null +++ b/libaes/src/main/res/layout/activity_testatoolbar.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/libaes/src/main/res/layout/dialog_privacy_agreement.xml b/libaes/src/main/res/layout/dialog_privacy_agreement.xml new file mode 100644 index 0000000..ebe6fe2 --- /dev/null +++ b/libaes/src/main/res/layout/dialog_privacy_agreement.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + +