Compare commits
14 Commits
powerbell-
...
powerbell-
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d69d4da09 | |||
| c98685440d | |||
| 7183338c97 | |||
| e18ed1b0fd | |||
| 98c334f442 | |||
| 9d42a3e1e9 | |||
| 411af44303 | |||
| 9afb072351 | |||
| b0c91f3ee4 | |||
| b21d5ecdb5 | |||
| 47c328cd25 | |||
| 7134d4e1c8 | |||
| 778a1bc98e | |||
| bb94f87597 |
87
.github/workflows/android.yml
vendored
87
.github/workflows/android.yml
vendored
@@ -1,87 +0,0 @@
|
|||||||
name: Android CI
|
|
||||||
|
|
||||||
# 触发器
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- *-beta
|
|
||||||
pull_request:
|
|
||||||
tags:
|
|
||||||
- *-beta
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
# 设置 JDK 环境
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: set up JDK 11
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '11'
|
|
||||||
distribution: 'temurin'
|
|
||||||
cache: gradle
|
|
||||||
|
|
||||||
- name: Grant execute permission for gradlew
|
|
||||||
run: chmod +x gradlew
|
|
||||||
|
|
||||||
# 获取应用打包秘钥库
|
|
||||||
- name: Checkout Android Keystore
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: zhangsken/keystore # 存储应用打包用的 keystore 的仓库(格式:用户名/仓库名)
|
|
||||||
token: ${{ secrets.APP_SECRET_TOKEN_1 }} # 连接仓库的 token , 需要单独配置
|
|
||||||
path: keystore # 仓库的根目录名
|
|
||||||
|
|
||||||
# 打包 Stage Release 版本应用
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: bash ./gradlew assembleBetaRelease
|
|
||||||
# 创建release
|
|
||||||
- name: Create Release
|
|
||||||
id: create_release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.APP_SECRET_TOKEN_1 }}
|
|
||||||
# GitHub 会自动创建 GITHUB_TOKEN 密码以在工作流程中使用。
|
|
||||||
# 您可以使用 GITHUB_TOKEN 在工作流程运行中进行身份验证。
|
|
||||||
# 当您启用 GitHub Actions 时,GitHub 在您的仓库中安装 GitHub 应用程序。
|
|
||||||
# GITHUB_TOKEN 密码是一种 GitHub 应用程序 安装访问令牌。
|
|
||||||
# 您可以使用安装访问令牌代表仓库中安装的 GitHub 应用程序 进行身份验证。
|
|
||||||
# 令牌的权限仅限于包含您的工作流程的仓库。 更多信息请参阅“GITHUB_TOKEN 的权限”。
|
|
||||||
# 在每个作业开始之前, GitHub 将为作业提取安装访问令牌。 令牌在作业完成后过期。
|
|
||||||
with:
|
|
||||||
tag_name: ${{ github.ref }}
|
|
||||||
release_name: Release ${{ github.ref }}
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
|
|
||||||
# 获取 APK 版本号
|
|
||||||
- name: Get Version Name
|
|
||||||
uses: actions/github-script@v3
|
|
||||||
id: get-version
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const str=process.env.GITHUB_REF;
|
|
||||||
return str.substring(str.indexOf("v"));
|
|
||||||
result-encoding: string
|
|
||||||
# 上传至 Release 的资源
|
|
||||||
- name: Upload Release Asset
|
|
||||||
id: upload-release-asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.APP_SECRET_TOKEN_1 }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # 上传网址,无需改动
|
|
||||||
#asset_path: app/build/outputs/apk/release/app-release.apk # 上传路径(Release)
|
|
||||||
asset_path: app/build/outputs/apk/beta/release/app-beta-release.apk # 上传路径(WinBoll Stage Release)
|
|
||||||
asset_name: WinBoll-${{steps.get-version.outputs.result}}0.apk # 资源名
|
|
||||||
asset_content_type: application/vnd.android.package-archiv # 资源类型
|
|
||||||
|
|
||||||
# 存档打包的文件
|
|
||||||
- name: Archive production artifacts
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: build
|
|
||||||
path: app/build/outputs # 将打包之后的文件全部上传(里面会有混淆的 map 文件)
|
|
||||||
@@ -1,166 +1,223 @@
|
|||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
|
# ==============================================================================
|
||||||
|
# WinBoLL 应用发布脚本
|
||||||
|
# 功能:检查Git源码状态 → 编译Stage Release包 → 添加WinBoLL标签 → 提交并推送源码
|
||||||
|
# 依赖:build.properties、app_update_description.txt(项目根目录下)
|
||||||
|
# 使用:./script_name.sh <APP_NAME>
|
||||||
|
# 作者:豆包&ZhanGSKen<zhangsken@qq.com>
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
# 检查是否指定了将要发布的应用名称
|
# ==================== 常量定义 ====================
|
||||||
# 使用 `-z` 命令检查变量是否为空
|
# 脚本退出码
|
||||||
|
EXIT_CODE_SUCCESS=0
|
||||||
|
EXIT_CODE_ERR_NO_APP_NAME=2
|
||||||
|
EXIT_CODE_ERR_WORK_DIR=1
|
||||||
|
EXIT_CODE_ERR_GIT_CHECK=1
|
||||||
|
EXIT_CODE_ERR_ADD_WINBOLL_TAG=1
|
||||||
|
|
||||||
|
# Gradle 任务(正式发布)
|
||||||
|
GRADLE_TASK_PUBLISH="assembleStageRelease"
|
||||||
|
# Gradle 任务(调试用,注释备用)
|
||||||
|
# GRADLE_TASK_DEBUG="assembleBetaDebug"
|
||||||
|
|
||||||
|
# ==================== 函数定义 ====================
|
||||||
|
# 检查Git源码是否已完全提交(无未提交变更)
|
||||||
|
# 返回值:0=已完全提交,1=存在未提交变更
|
||||||
|
function checkGitSources() {
|
||||||
|
# 配置Git安全目录(解决权限问题)
|
||||||
|
git config --global --add safe.directory "$(pwd)"
|
||||||
|
|
||||||
|
# 检查是否有未提交的变更
|
||||||
|
if [[ -n $(git diff --stat) ]]; then
|
||||||
|
echo "[ERROR] Git源码存在未提交变更,请先提交所有修改!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[INFO] Git源码检查通过:所有变更已提交。"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 询问是否添加GitHub Workflows标签(当前逻辑注释,保留扩展能力)
|
||||||
|
# 返回值:1=用户选择是,0=用户选择否
|
||||||
|
function askAddWorkflowsTag() {
|
||||||
|
read -p "是否添加GitHub Workflows标签?(Y/n) " answer
|
||||||
|
if [[ $answer =~ ^[Yy]$ ]]; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 添加WinBoLL正式标签
|
||||||
|
# 参数:$1=应用名称(项目根目录名)
|
||||||
|
# 返回值:0=标签添加成功,1=标签已存在/添加失败
|
||||||
|
function addWinBoLLTag() {
|
||||||
|
local app_name=$1
|
||||||
|
local build_prop_path="${app_name}/build.properties"
|
||||||
|
|
||||||
|
# 从build.properties中提取publishVersion
|
||||||
|
local publish_version=$(grep -o "publishVersion=.*" "${build_prop_path}" | awk -F '=' '{print $2}')
|
||||||
|
if [[ -z ${publish_version} ]]; then
|
||||||
|
echo "[ERROR] 未从${build_prop_path}中提取到publishVersion配置!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "[INFO] 从${build_prop_path}读取到publishVersion:${publish_version}"
|
||||||
|
|
||||||
|
# 构造WinBoLL标签(格式:<APP_NAME>-v<publishVersion>)
|
||||||
|
local tag="${app_name}-v${publish_version}"
|
||||||
|
echo "[INFO] 准备添加WinBoLL标签:${tag}"
|
||||||
|
|
||||||
|
# 检查标签是否已存在
|
||||||
|
if [[ "$(git tag -l ${tag})" == "${tag}" ]]; then
|
||||||
|
echo "[ERROR] WinBoLL标签${tag}已存在!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 添加带注释的标签(注释来自app_update_description.txt)
|
||||||
|
git tag -a "${tag}" -F "${app_name}/app_update_description.txt"
|
||||||
|
echo "[INFO] WinBoLL标签${tag}添加成功!"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 添加GitHub Workflows Beta标签(当前逻辑注释,保留扩展能力)
|
||||||
|
# 参数:$1=应用名称(项目根目录名)
|
||||||
|
# 返回值:0=标签添加成功,1=标签已存在/添加失败
|
||||||
|
function addWorkflowsTag() {
|
||||||
|
local app_name=$1
|
||||||
|
local build_prop_path="${app_name}/build.properties"
|
||||||
|
|
||||||
|
# 从build.properties中提取baseBetaVersion
|
||||||
|
local base_beta_version=$(grep -o "baseBetaVersion=.*" "${build_prop_path}" | awk -F '=' '{print $2}')
|
||||||
|
if [[ -z ${base_beta_version} ]]; then
|
||||||
|
echo "[ERROR] 未从${build_prop_path}中提取到baseBetaVersion配置!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "[INFO] 从${build_prop_path}读取到baseBetaVersion:${base_beta_version}"
|
||||||
|
|
||||||
|
# 构造Workflows标签(格式:<APP_NAME>-v<baseBetaVersion>-beta)
|
||||||
|
local tag="${app_name}-v${base_beta_version}-beta"
|
||||||
|
echo "[INFO] 准备添加Workflows标签:${tag}"
|
||||||
|
|
||||||
|
# 检查标签是否已存在
|
||||||
|
if [[ "$(git tag -l ${tag})" == "${tag}" ]]; then
|
||||||
|
echo "[ERROR] Workflows标签${tag}已存在!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 添加带注释的标签(注释来自app_update_description.txt)
|
||||||
|
git tag -a "${tag}" -F "${app_name}/app_update_description.txt"
|
||||||
|
echo "[INFO] Workflows标签${tag}添加成功!"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==================== 主流程开始 ====================
|
||||||
|
echo "============================================="
|
||||||
|
echo " WinBoLL 应用发布脚本"
|
||||||
|
echo "============================================="
|
||||||
|
|
||||||
|
# 1. 检查应用名称参数是否指定
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "No APP name specified : $0"
|
echo "[ERROR] 未指定应用名称!使用方式:${0} <APP_NAME>"
|
||||||
exit 2
|
exit ${EXIT_CODE_ERR_NO_APP_NAME}
|
||||||
fi
|
fi
|
||||||
|
APP_NAME=$1
|
||||||
|
echo "[INFO] 待发布应用名称:${APP_NAME}"
|
||||||
|
|
||||||
## 定义相关函数
|
# 2. 检查并切换到项目根目录(确保build.properties存在)
|
||||||
## 检查 Git 源码是否完全提交了,完全提交就返回0
|
echo "[INFO] 当前工作目录:$(pwd)"
|
||||||
function checkGitSources {
|
if [[ ! -e "${APP_NAME}/build.properties" ]]; then
|
||||||
#local input="$1"
|
echo "[WARNING] 当前目录不存在${APP_NAME}/build.properties,尝试切换到上级目录..."
|
||||||
#echo "The string is: $input"
|
|
||||||
git config --global --add safe.directory `pwd`
|
|
||||||
if [[ -n $(git diff --stat) ]]
|
|
||||||
then
|
|
||||||
local result="Source is no commit completely."
|
|
||||||
echo $result
|
|
||||||
# 脚本调试时使用
|
|
||||||
#return 0
|
|
||||||
# 正式检查源码时使用
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
local result="Git Source Check OK."
|
|
||||||
echo $result
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function askAddWorkflowsTag {
|
|
||||||
read answer
|
|
||||||
if [[ $answer =~ ^[Yy]$ ]]; then
|
|
||||||
#echo "You chose yes."
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
#echo "You chose no."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function addWinBoLLTag {
|
|
||||||
# 就读取脚本 .winboll/winboll_app_build.gradle 生成的 publishVersion。
|
|
||||||
# 如果文件中有 publishVersion 这一项,
|
|
||||||
# 使用grep找到包含"publishVersion="的那一行,然后用awk提取其后的值
|
|
||||||
PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}')
|
|
||||||
echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >"
|
|
||||||
## 设新的 WinBoLL 标签
|
|
||||||
# 脚本调试时使用
|
|
||||||
#tag="projectname-v7.6.4-test1"
|
|
||||||
# 正式设置标签时使用
|
|
||||||
tag=$1"-v"${PUBLISH_VERSION}
|
|
||||||
echo "< WinBoLL Tag To: $tag >";
|
|
||||||
# 检查是否已经添加了 WinBoLL Tag
|
|
||||||
if [ "$(git tag -l ${tag})" == "${tag}" ]; then
|
|
||||||
echo -e "< WinBoLL Tag ${tag} exist! >"
|
|
||||||
return 1 # WinBoLL标签重复
|
|
||||||
fi
|
|
||||||
# 添加WinBoLL标签
|
|
||||||
git tag -a ${tag} -F $1/app_update_description.txt
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function addWorkflowsTag {
|
|
||||||
# 就读取脚本 .winboll/winboll_app_build.gradle 生成的 baseBetaVersion。
|
|
||||||
# 如果文件中有 baseBetaVersion 这一项,
|
|
||||||
# 使用grep找到包含"baseBetaVersion="的那一行,然后用awk提取其后的值
|
|
||||||
BASE_BETA_VERSION=$(grep -o "baseBetaVersion=.*" $1/build.properties | awk -F '=' '{print $2}')
|
|
||||||
echo "< $1/build.properties baseBetaVersion : ${BASE_BETA_VERSION} >"
|
|
||||||
## 设新的 workflows 标签
|
|
||||||
# 脚本调试时使用
|
|
||||||
#tag="projectname-v7.6.4-beta"
|
|
||||||
# 正式设置标签时使用
|
|
||||||
tag=$1"-v"${BASE_BETA_VERSION}-beta
|
|
||||||
echo "< Workflows Tag To: $tag >";
|
|
||||||
# 检查是否已经添加了工作流 Tag
|
|
||||||
if [ "$(git tag -l ${tag})" == "${tag}" ]; then
|
|
||||||
echo -e "< Github Workflows Tag ${tag} exist! >"
|
|
||||||
return 1 # 工作流标签重复
|
|
||||||
fi
|
|
||||||
# 添加工作流标签
|
|
||||||
git tag -a ${tag} -F $1/app_update_description.txt
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
## 开始执行脚本
|
|
||||||
echo -e "Current dir : \n"`pwd`
|
|
||||||
# 检查当前目录是否是项目根目录
|
|
||||||
if [[ -e $1/build.properties ]]; then
|
|
||||||
echo "The $1/build.properties file exists."
|
|
||||||
echo -e "Work dir correctly."
|
|
||||||
else
|
|
||||||
echo "The $1/build.properties file does not exist."
|
|
||||||
echo "尝试进入根目录"
|
|
||||||
# 进入项目根目录
|
|
||||||
cd ..
|
cd ..
|
||||||
|
echo "[INFO] 切换后工作目录:$(pwd)"
|
||||||
fi
|
fi
|
||||||
## 本脚本需要在项目根目录下执行
|
|
||||||
echo -e "Current dir : \n"`pwd`
|
# 验证最终工作目录是否正确
|
||||||
# 检查当前目录是否是项目根目录
|
if [[ ! -e "${APP_NAME}/build.properties" ]]; then
|
||||||
if [[ -e $1/build.properties ]]; then
|
echo "[ERROR] 工作目录错误!${APP_NAME}/build.properties 文件不存在。"
|
||||||
echo "The $1/build.properties file exists."
|
exit ${EXIT_CODE_ERR_WORK_DIR}
|
||||||
echo -e "Work dir correctly."
|
fi
|
||||||
|
echo "[INFO] 工作目录验证通过:${APP_NAME}/build.properties 存在。"
|
||||||
|
|
||||||
|
# 3. 检查Git源码状态
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo " 步骤1:检查Git源码状态"
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
checkGitSources
|
||||||
|
if [[ $? -ne ${EXIT_CODE_SUCCESS} ]]; then
|
||||||
|
echo "[ERROR] Git源码检查失败,脚本终止!"
|
||||||
|
exit ${EXIT_CODE_ERR_GIT_CHECK}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. 编译Stage Release版本APK
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo " 步骤2:编译Stage Release APK"
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo "[INFO] 开始执行Gradle任务:${GRADLE_TASK_PUBLISH}"
|
||||||
|
# 调试用(注释正式任务,启用调试任务)
|
||||||
|
# bash gradlew :${APP_NAME}:${GRADLE_TASK_DEBUG}
|
||||||
|
bash gradlew :${APP_NAME}:${GRADLE_TASK_PUBLISH}
|
||||||
|
|
||||||
|
if [[ $? -ne ${EXIT_CODE_SUCCESS} ]]; then
|
||||||
|
echo "[ERROR] Gradle编译任务失败!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[INFO] Stage Release APK编译成功!"
|
||||||
|
|
||||||
|
# 5. 添加WinBoLL正式标签
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo " 步骤3:添加WinBoLL标签"
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
addWinBoLLTag ${APP_NAME}
|
||||||
|
if [[ $? -ne ${EXIT_CODE_SUCCESS} ]]; then
|
||||||
|
echo "[ERROR] WinBoLL标签添加失败,脚本终止!"
|
||||||
|
exit ${EXIT_CODE_ERR_ADD_WINBOLL_TAG}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 6. (可选)添加GitHub Workflows标签(当前逻辑注释,保留扩展能力)
|
||||||
|
# echo "---------------------------------------------"
|
||||||
|
# echo " 步骤4:添加Workflows标签(可选)"
|
||||||
|
# echo "---------------------------------------------"
|
||||||
|
# echo "是否添加GitHub Workflows Beta标签?(Y/n) "
|
||||||
|
# askAddWorkflowsTag
|
||||||
|
# nAskAddWorkflowsTag=$?
|
||||||
|
# if [[ ${nAskAddWorkflowsTag} -eq 1 ]]; then
|
||||||
|
# addWorkflowsTag ${APP_NAME}
|
||||||
|
# if [[ $? -ne ${EXIT_CODE_SUCCESS} ]]; then
|
||||||
|
# echo "[ERROR] Workflows标签添加失败,脚本终止!"
|
||||||
|
# exit 1
|
||||||
|
# fi
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# 7. 清理更新描述文件
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo " 步骤5:清理更新描述文件"
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo "" > "${APP_NAME}/app_update_description.txt"
|
||||||
|
echo "[INFO] 已清空${APP_NAME}/app_update_description.txt"
|
||||||
|
|
||||||
|
# 8. 提交并推送源码与标签
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
echo " 步骤6:提交并推送源码"
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
git add .
|
||||||
|
git commit -m "<${APP_NAME}> 开始新的Stage版本开发。"
|
||||||
|
echo "[INFO] 源码提交成功,开始推送..."
|
||||||
|
|
||||||
|
# 推送源码到远程仓库
|
||||||
|
git push origin
|
||||||
|
# 推送标签到远程仓库
|
||||||
|
git push origin --tags
|
||||||
|
|
||||||
|
if [[ $? -eq ${EXIT_CODE_SUCCESS} ]]; then
|
||||||
|
echo "[INFO] 源码与标签推送成功!"
|
||||||
else
|
else
|
||||||
echo "The $1/build.properties file does not exist."
|
echo "[ERROR] 源码与标签推送失败!"
|
||||||
echo -e "Work dir error."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 检查源码状态
|
# ==================== 主流程结束 ====================
|
||||||
result=$(checkGitSources)
|
echo "============================================="
|
||||||
if [[ $? -eq 0 ]]; then
|
echo " WinBoLL 应用发布完成!"
|
||||||
echo $result
|
echo "============================================="
|
||||||
# 如果Git已经提交了所有代码就执行标签和应用发布操作
|
exit ${EXIT_CODE_SUCCESS}
|
||||||
|
|
||||||
# 预先询问是否添加工作流标签
|
|
||||||
#echo "Add Github Workflows Tag? (yes/No)"
|
|
||||||
#result=$(askAddWorkflowsTag)
|
|
||||||
#nAskAddWorkflowsTag=$?
|
|
||||||
#echo $result
|
|
||||||
|
|
||||||
# 发布应用
|
|
||||||
echo "Publishing WinBoLL APK ..."
|
|
||||||
# 脚本调试时使用
|
|
||||||
#bash gradlew :$1:assembleBetaDebug
|
|
||||||
# 正式发布
|
|
||||||
bash gradlew :$1:assembleStageRelease
|
|
||||||
echo "Publishing WinBoLL APK OK."
|
|
||||||
|
|
||||||
# 添加 WinBoLL 标签
|
|
||||||
result=$(addWinBoLLTag $1)
|
|
||||||
echo $result
|
|
||||||
if [[ $? -eq 0 ]]; then
|
|
||||||
echo $result
|
|
||||||
# WinBoLL 标签添加成功
|
|
||||||
else
|
|
||||||
echo -e "${0}: addWinBoLLTag $1\n${result}\nAdd WinBoLL tag cancel."
|
|
||||||
exit 1 # addWinBoLLTag 异常
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 添加 GitHub 工作流标签
|
|
||||||
#if [[ $nAskAddWorkflowsTag -eq 1 ]]; then
|
|
||||||
# 如果用户选择添加工作流标签
|
|
||||||
#result=$(addWorkflowsTag $1)
|
|
||||||
#if [[ $? -eq 0 ]]; then
|
|
||||||
# echo $result
|
|
||||||
# 工作流标签添加成功
|
|
||||||
#else
|
|
||||||
#echo -e "${0}: addWorkflowsTag $1\n${result}\nAdd workflows tag cancel."
|
|
||||||
#exit 1 # addWorkflowsTag 异常
|
|
||||||
#fi
|
|
||||||
#fi
|
|
||||||
|
|
||||||
## 清理更新描述文件内容
|
|
||||||
echo "" > $1/app_update_description.txt
|
|
||||||
|
|
||||||
# 设置新版本开发参数配置
|
|
||||||
# 提交配置
|
|
||||||
git add .
|
|
||||||
git commit -m "<$1>Start New Stage Version."
|
|
||||||
echo "Push sources to git repositories ..."
|
|
||||||
# 推送源码到所有仓库
|
|
||||||
git push origin && git push origin --tags
|
|
||||||
else
|
|
||||||
echo -e "${0}: checkGitSources\n${result}\nShell cancel."
|
|
||||||
exit 1 # checkGitSources 异常
|
|
||||||
fi
|
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -5,10 +5,11 @@
|
|||||||
## ☁ ☁ ☁ WinBoLL APP ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
## ☁ ☁ ☁ WinBoLL APP ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||||
# ☁ ☁ WinBoLL Studio Android 应用开源项目。☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
# ☁ ☁ WinBoLL Studio Android 应用开源项目。☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||||
# ☁ ☁ ☁ WinBoLL 网站地址 https://www.winboll.cc/ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
# ☁ ☁ ☁ WinBoLL 网站地址 https://www.winboll.cc/ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||||
# ☁ ☁ ☁ WinBoLL 源码地址 <https://gitea.winboll.cc/Studio/APPBase> ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
# ☁ ☁ ☁ WinBoLL 源码地址 <https://gitea.winboll.cc/Studio/WinBoLL.git> ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||||
# ☁ ☁ ☁ GitHub 源码地址 <https://github.com/ZhanGSKen/APPBase.git> ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
# ☁ ☁ ☁ GitHub 源码地址 <https://github.com/ZhanGSKen/WinBoLL.git> ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||||
# ☁ ☁ ☁ 码云 源码地址 <https://gitee.com/zhangsken/appbase.git> ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
# ☁ ☁ ☁ 码云 源码地址 <https://gitee.com/zhangsken/winboll.git> ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||||
|
# ☁ ☁ ☁ 在 jitpack.io 托管的 APPBase 类库源码<https://github.com/ZhanGSKen/APPBase.git> ☁ ☁ ☁ ☁
|
||||||
|
# ☁ ☁ ☁ 在 jitpack.io 托管的 AES 类库源码<https://github.com/ZhanGSKen/AES.git> ☁ ☁ ☁ ☁
|
||||||
## WinBoLL 提问
|
## WinBoLL 提问
|
||||||
同样是 /sdcard 目录,在开发 Android 应用时,
|
同样是 /sdcard 目录,在开发 Android 应用时,
|
||||||
能否实现手机编译与电脑编译的源码同步。
|
能否实现手机编译与电脑编译的源码同步。
|
||||||
@@ -154,3 +155,11 @@ $ bash gradlew assembleBetaDebug
|
|||||||
$ bash gradlew assembleStageDebug
|
$ bash gradlew assembleStageDebug
|
||||||
|
|
||||||
### 若是 winboll.properties 文件的 [ExtraAPKOutputPath] 属性设置了路径。编译器也会复制一份 APK 到这个路径。
|
### 若是 winboll.properties 文件的 [ExtraAPKOutputPath] 属性设置了路径。编译器也会复制一份 APK 到这个路径。
|
||||||
|
|
||||||
|
# 应用版本号命名方式
|
||||||
|
## statge 渠道
|
||||||
|
V<应用开发环境编号><应用功能变更号><应用调试阶段号>
|
||||||
|
如:APPBase_15.7.0
|
||||||
|
## beta 渠道
|
||||||
|
V<应用开发环境编号><应用功能变更号><应用调试阶段号>-beta<调试编译计数>_<调试编译时间(分钟+秒钟)>
|
||||||
|
如:APPBase_15.9.6-beta8_5413
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ dependencies {
|
|||||||
//api 'cc.winboll.studio:libappbase:15.12.2'
|
//api 'cc.winboll.studio:libappbase:15.12.2'
|
||||||
|
|
||||||
// WinBoLL备用库 jitpack.io 地址
|
// WinBoLL备用库 jitpack.io 地址
|
||||||
api 'com.github.ZhanGSKen:AES:aes-v15.12.8'
|
api 'com.github.ZhanGSKen:AES:aes-v15.12.9'
|
||||||
api 'com.github.ZhanGSKen:APPBase:appbase-v15.14.1'
|
api 'com.github.ZhanGSKen:APPBase:appbase-v15.14.1'
|
||||||
|
|
||||||
//api fileTree(dir: 'libs', include: ['*.aar'])
|
//api fileTree(dir: 'libs', include: ['*.aar'])
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Tue Dec 30 20:07:05 HKT 2025
|
#Mon Jan 05 19:22:24 HKT 2026
|
||||||
stageCount=45
|
stageCount=47
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.14
|
baseVersion=15.14
|
||||||
publishVersion=15.14.44
|
publishVersion=15.14.46
|
||||||
buildCount=0
|
buildCount=0
|
||||||
baseBetaVersion=15.14.45
|
baseBetaVersion=15.14.47
|
||||||
|
|||||||
@@ -15,19 +15,21 @@ import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
|
|||||||
import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView;
|
import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用全局入口类(适配Android API 30,基于Java 7编写)
|
* 应用全局入口类
|
||||||
|
* 适配:Java7 语法规范 | Android API30 系统版本
|
||||||
* 核心策略:极致强制缓存 - 无论内存紧张程度,永不自动清理任何缓存(Bitmap/视图控件/路径记录)
|
* 核心策略:极致强制缓存 - 无论内存紧张程度,永不自动清理任何缓存(Bitmap/视图控件/路径记录)
|
||||||
*
|
|
||||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||||
* @Version 1.0.0
|
* @Date 2025-12-29 15:30:00
|
||||||
* @Date 2025-12-29
|
* @LastModified 2026-01-02 19:01:00
|
||||||
*/
|
*/
|
||||||
public class App extends GlobalApplication {
|
public class App extends GlobalApplication {
|
||||||
|
|
||||||
// ==================== 常量定义 ====================
|
// ====================================== 常量区 - 置顶排序 (按功能归类) ======================================
|
||||||
|
// 基础日志TAG
|
||||||
private static final String TAG = "App";
|
private static final String TAG = "App";
|
||||||
|
// 缓存保护专用TAG
|
||||||
private static final String CACHE_PROTECT_TAG = "FORCE_CACHE_PROTECT";
|
private static final String CACHE_PROTECT_TAG = "FORCE_CACHE_PROTECT";
|
||||||
|
// 电池无效值常量(修复拼写错误:INVALID_BATTERY_VALUE)
|
||||||
private static final int INVALID_BATTERY_VALUE = -1;
|
private static final int INVALID_BATTERY_VALUE = -1;
|
||||||
|
|
||||||
// 组件跳转常量
|
// 组件跳转常量
|
||||||
@@ -40,268 +42,278 @@ public class App extends GlobalApplication {
|
|||||||
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
|
public static final String ACTION_SWITCHTO_CN1 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN1";
|
||||||
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
|
public static final String ACTION_SWITCHTO_CN2 = "cc.winboll.studio.powerbell.App.ACTION_SWITCHTO_CN2";
|
||||||
|
|
||||||
// ==================== 静态属性 ====================
|
// ====================================== 静态属性区 - 全局单例/状态 (按核心程度排序) ======================================
|
||||||
|
// 应用单例
|
||||||
private static App sApp;
|
private static App sApp;
|
||||||
|
|
||||||
// 配置与缓存
|
// 配置与缓存工具 (全局单例)
|
||||||
public static AppConfigUtils sAppConfigUtils;
|
public static AppConfigUtils sAppConfigUtils;
|
||||||
private static AppCacheUtils sAppCacheUtils;
|
private static AppCacheUtils sAppCacheUtils;
|
||||||
|
|
||||||
// 资源与视图缓存(强制驻留)
|
// 资源与视图缓存 (强制驻留,极致缓存核心)
|
||||||
public static BackgroundSourceUtils sBackgroundSourceUtils;
|
public static BackgroundSourceUtils sBackgroundSourceUtils;
|
||||||
public static BitmapCacheUtils sBitmapCacheUtils;
|
public static BitmapCacheUtils sBitmapCacheUtils;
|
||||||
private static MemoryCachedBackgroundView sMemoryCachedBackgroundView;
|
private static MemoryCachedBackgroundView sMemoryCachedBackgroundView;
|
||||||
|
|
||||||
// 状态
|
// 系统状态 (电池电量)
|
||||||
public static volatile int sQuantityOfElectricity = INVALID_BATTERY_VALUE;
|
public static volatile int sQuantityOfElectricity = INVALID_BATTERY_VALUE;
|
||||||
|
|
||||||
// 系统工具
|
// 系统工具 (通知管理器)
|
||||||
private static NotificationManagerUtils sNotificationManagerUtils;
|
private static NotificationManagerUtils sNotificationManagerUtils;
|
||||||
|
|
||||||
// ==================== 成员属性 ====================
|
// ====================================== 成员属性区 - 非静态成员 (广播接收器) ======================================
|
||||||
|
|
||||||
private GlobalApplicationReceiver mGlobalReceiver;
|
private GlobalApplicationReceiver mGlobalReceiver;
|
||||||
|
|
||||||
// ==================== 公共静态方法 (工具/单例) ====================
|
// ====================================== 公共静态方法 - 单例/工具获取 (对外入口) ======================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取应用单例
|
* 获取应用全局单例实例
|
||||||
|
* @return 应用单例App实例
|
||||||
*/
|
*/
|
||||||
public static App getInstance() {
|
public static App getInstance() {
|
||||||
LogUtils.d(TAG, "getInstance() called | Result: " + sApp);
|
LogUtils.d(TAG, "【getInstance】应用单例获取方法调用 | 当前实例:" + sApp);
|
||||||
return sApp;
|
return sApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取配置工具实例
|
* 获取配置工具类单例实例
|
||||||
|
* @param context 上下文对象
|
||||||
|
* @return 配置工具类AppConfigUtils实例
|
||||||
*/
|
*/
|
||||||
public static AppConfigUtils getAppConfigUtils(Context context) {
|
public static AppConfigUtils getAppConfigUtils(Context context) {
|
||||||
String contextName = context != null ? context.getClass().getSimpleName() : "null";
|
String contextClass = context != null ? context.getClass().getSimpleName() : "null";
|
||||||
LogUtils.d(TAG, "getAppConfigUtils() called with: context = [" + contextName + "]");
|
LogUtils.d(TAG, "【getAppConfigUtils】配置工具获取方法调用 | 入参Context类型:" + contextClass);
|
||||||
|
|
||||||
if (sAppConfigUtils == null) {
|
if (sAppConfigUtils == null) {
|
||||||
sAppConfigUtils = AppConfigUtils.getInstance(context);
|
sAppConfigUtils = AppConfigUtils.getInstance(context);
|
||||||
LogUtils.d(TAG, "getAppConfigUtils: Initialized new instance");
|
LogUtils.d(TAG, "【getAppConfigUtils】配置工具实例为空,已初始化新实例");
|
||||||
}
|
}
|
||||||
return sAppConfigUtils;
|
return sAppConfigUtils;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存工具实例
|
* 获取缓存工具类单例实例
|
||||||
|
* @param context 上下文对象
|
||||||
|
* @return 缓存工具类AppCacheUtils实例
|
||||||
*/
|
*/
|
||||||
public static AppCacheUtils getAppCacheUtils(Context context) {
|
public static AppCacheUtils getAppCacheUtils(Context context) {
|
||||||
String contextName = context != null ? context.getClass().getSimpleName() : "null";
|
String contextClass = context != null ? context.getClass().getSimpleName() : "null";
|
||||||
LogUtils.d(TAG, "getAppCacheUtils() called with: context = [" + contextName + "]");
|
LogUtils.d(TAG, "【getAppCacheUtils】缓存工具获取方法调用 | 入参Context类型:" + contextClass);
|
||||||
|
|
||||||
if (sAppCacheUtils == null) {
|
if (sAppCacheUtils == null) {
|
||||||
sAppCacheUtils = AppCacheUtils.getInstance(context);
|
sAppCacheUtils = AppCacheUtils.getInstance(context);
|
||||||
LogUtils.d(TAG, "getAppCacheUtils: Initialized new instance");
|
LogUtils.d(TAG, "【getAppCacheUtils】缓存工具实例为空,已初始化新实例");
|
||||||
}
|
}
|
||||||
return sAppCacheUtils;
|
return sAppCacheUtils;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 公共成员方法 (业务) ====================
|
// ====================================== 公共成员方法 - 业务逻辑 (实例方法) ======================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除电池历史数据
|
* 清除电池历史数据
|
||||||
*/
|
*/
|
||||||
public void clearBatteryHistory() {
|
public void clearBatteryHistory() {
|
||||||
LogUtils.d(TAG, "clearBatteryHistory() called");
|
LogUtils.d(TAG, "【clearBatteryHistory】清除电池历史数据方法调用");
|
||||||
if (sAppCacheUtils != null) {
|
if (sAppCacheUtils != null) {
|
||||||
sAppCacheUtils.clearBatteryHistory();
|
sAppCacheUtils.clearBatteryHistory();
|
||||||
LogUtils.d(TAG, "clearBatteryHistory: Success");
|
LogUtils.d(TAG, "【clearBatteryHistory】电池历史数据清除成功");
|
||||||
} else {
|
} else {
|
||||||
LogUtils.w(TAG, "clearBatteryHistory: Failed, sAppCacheUtils is null");
|
LogUtils.w(TAG, "【clearBatteryHistory】电池历史数据清除失败 | 缓存工具实例sAppCacheUtils为空");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 手动清理所有缓存(仅主动调用生效)
|
|
||||||
*/
|
|
||||||
public static void manualClearAllCache() {
|
|
||||||
LogUtils.w(CACHE_PROTECT_TAG, "manualClearAllCache() called - Manual trigger only");
|
|
||||||
|
|
||||||
if (sBitmapCacheUtils != null) {
|
|
||||||
sBitmapCacheUtils.clearAllCache();
|
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "manualClearAllCache: Bitmap cache cleared");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 仅置空引用,不销毁实例(符合极致缓存策略)
|
|
||||||
if (sMemoryCachedBackgroundView != null) {
|
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "manualClearAllCache: View cache reference cleared");
|
|
||||||
sMemoryCachedBackgroundView = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogUtils.w(CACHE_PROTECT_TAG, "manualClearAllCache: Manual cleanup finished");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取视图缓存实例
|
* 获取视图缓存实例
|
||||||
|
* @return 视图缓存MemoryCachedBackgroundView实例
|
||||||
*/
|
*/
|
||||||
public MemoryCachedBackgroundView getMemoryCachedBackgroundView() {
|
public MemoryCachedBackgroundView getMemoryCachedBackgroundView() {
|
||||||
LogUtils.d(TAG, "getMemoryCachedBackgroundView() called | Current: " + sMemoryCachedBackgroundView);
|
LogUtils.d(TAG, "【getMemoryCachedBackgroundView】视图缓存获取方法调用 | 当前实例:" + sMemoryCachedBackgroundView);
|
||||||
return sMemoryCachedBackgroundView;
|
return sMemoryCachedBackgroundView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================================== 公共静态方法 - 业务逻辑 (全局工具方法) ======================================
|
||||||
/**
|
/**
|
||||||
* 发送通知消息
|
* 手动清理所有缓存(仅主动调用生效,符合极致缓存策略)
|
||||||
|
*/
|
||||||
|
public static void manualClearAllCache() {
|
||||||
|
LogUtils.w(CACHE_PROTECT_TAG, "【manualClearAllCache】手动清理缓存方法调用 | 仅主动触发生效");
|
||||||
|
|
||||||
|
// 清理Bitmap缓存
|
||||||
|
if (sBitmapCacheUtils != null) {
|
||||||
|
sBitmapCacheUtils.clearAllCache();
|
||||||
|
LogUtils.d(CACHE_PROTECT_TAG, "【manualClearAllCache】Bitmap缓存已清理");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仅置空视图缓存引用,不销毁实例(极致缓存策略)
|
||||||
|
if (sMemoryCachedBackgroundView != null) {
|
||||||
|
LogUtils.d(CACHE_PROTECT_TAG, "【manualClearAllCache】视图缓存引用已置空 | 实例保留");
|
||||||
|
sMemoryCachedBackgroundView = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtils.w(CACHE_PROTECT_TAG, "【manualClearAllCache】手动清理缓存操作完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送通知消息(仅调试模式下生效)
|
||||||
|
* @param title 通知标题
|
||||||
|
* @param content 通知内容
|
||||||
*/
|
*/
|
||||||
public static void notifyMessage(String title, String content) {
|
public static void notifyMessage(String title, String content) {
|
||||||
LogUtils.d(TAG, "notifyMessage() called with: title = [" + title + "], content = [" + content + "]");
|
LogUtils.d(TAG, "【notifyMessage】发送通知消息方法调用 | 标题:" + title + " | 内容:" + content);
|
||||||
|
|
||||||
boolean canSend = isDebugging() && sApp != null && sNotificationManagerUtils != null;
|
boolean canSend = isDebugging() && sApp != null && sNotificationManagerUtils != null;
|
||||||
if (canSend) {
|
if (canSend) {
|
||||||
NotificationMessage message = new NotificationMessage(title, content, "");
|
NotificationMessage message = new NotificationMessage(title, content, "");
|
||||||
sNotificationManagerUtils.showMessageNotification(sApp, message);
|
sNotificationManagerUtils.showMessageNotification(sApp, message);
|
||||||
LogUtils.d(TAG, "notifyMessage: Sent successfully");
|
LogUtils.d(TAG, "【notifyMessage】通知消息发送成功");
|
||||||
} else {
|
} else {
|
||||||
LogUtils.d(TAG, "notifyMessage: Send failed, conditions not met");
|
LogUtils.d(TAG, "【notifyMessage】通知消息发送失败 | 条件不满足:调试模式=" + isDebugging() + " | 应用实例=" + (sApp != null) + " | 通知工具=" + (sNotificationManagerUtils != null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 生命周期方法 ====================
|
// ====================================== 生命周期方法 - 应用全局生命周期 (重写父类方法) ======================================
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
LogUtils.d(TAG, "onCreate() called | Initializing application...");
|
LogUtils.d(TAG, "【onCreate】应用启动生命周期方法调用 | 开始初始化应用...");
|
||||||
|
|
||||||
|
// 初始化应用单例与调试模式
|
||||||
sApp = this;
|
sApp = this;
|
||||||
setIsDebugging(BuildConfig.DEBUG);
|
setIsDebugging(BuildConfig.DEBUG);
|
||||||
LogUtils.d(TAG, "onCreate: Debug mode = " + BuildConfig.DEBUG);
|
LogUtils.d(TAG, "【onCreate】应用单例已初始化 | 调试模式:" + BuildConfig.DEBUG);
|
||||||
|
|
||||||
// 初始化核心组件
|
// 初始化核心组件
|
||||||
initBaseTools();
|
initBaseTools();
|
||||||
initUtils();
|
initUtils();
|
||||||
initReceiver();
|
initReceiver();
|
||||||
|
|
||||||
LogUtils.d(TAG, "onCreate: Application initialization completed. Force-cache strategy active.");
|
LogUtils.d(TAG, "【onCreate】应用初始化完成 | 极致强制缓存策略已激活");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTerminate() {
|
public void onTerminate() {
|
||||||
super.onTerminate();
|
super.onTerminate();
|
||||||
LogUtils.d(TAG, "onTerminate() called | Releasing non-cache resources");
|
LogUtils.d(TAG, "【onTerminate】应用终止生命周期方法调用 | 开始释放非缓存资源...");
|
||||||
|
|
||||||
// 仅释放非缓存资源
|
// 释放非缓存资源
|
||||||
ToastUtils.release();
|
ToastUtils.release();
|
||||||
releaseNotificationManager();
|
releaseNotificationManager();
|
||||||
releaseReceiver();
|
releaseReceiver();
|
||||||
|
|
||||||
// 核心策略:不清理缓存
|
// 核心策略:不清理任何缓存
|
||||||
LogUtils.w(CACHE_PROTECT_TAG, "onTerminate: Force-cache active, caches remain in memory");
|
LogUtils.w(CACHE_PROTECT_TAG, "【onTerminate】极致缓存策略生效 | 所有缓存将保留在内存中");
|
||||||
LogUtils.d(TAG, "onTerminate: Non-cache resources released");
|
LogUtils.d(TAG, "【onTerminate】非缓存资源释放完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTrimMemory(int level) {
|
public void onTrimMemory(int level) {
|
||||||
super.onTrimMemory(level);
|
super.onTrimMemory(level);
|
||||||
LogUtils.w(CACHE_PROTECT_TAG, "onTrimMemory() called with level: " + level + " | Ignoring, caches protected");
|
LogUtils.w(CACHE_PROTECT_TAG, "【onTrimMemory】系统内存修剪回调 | 内存等级:" + level + " | 忽略修剪,缓存强制保护");
|
||||||
logDetailedCacheStatus();
|
logDetailedCacheStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLowMemory() {
|
public void onLowMemory() {
|
||||||
super.onLowMemory();
|
super.onLowMemory();
|
||||||
LogUtils.w(CACHE_PROTECT_TAG, "onLowMemory() called | Force-cache active, no cleanup performed");
|
LogUtils.w(CACHE_PROTECT_TAG, "【onLowMemory】系统低内存回调 | 极致缓存策略生效 | 不执行任何缓存清理操作");
|
||||||
logDetailedCacheStatus();
|
logDetailedCacheStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 私有初始化方法 ====================
|
// ====================================== 私有初始化方法 - 组件初始化 (按依赖顺序排序) ======================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化基础工具类
|
* 初始化基础工具类(Activity管理、Toast、通知管理器)
|
||||||
*/
|
*/
|
||||||
private void initBaseTools() {
|
private void initBaseTools() {
|
||||||
LogUtils.d(TAG, "initBaseTools: Starting...");
|
LogUtils.d(TAG, "【initBaseTools】基础工具类初始化开始...");
|
||||||
WinBoLLActivityManager.init(this);
|
WinBoLLActivityManager.init(this);
|
||||||
ToastUtils.init(this);
|
ToastUtils.init(this);
|
||||||
sNotificationManagerUtils = new NotificationManagerUtils(this);
|
sNotificationManagerUtils = new NotificationManagerUtils(this);
|
||||||
LogUtils.d(TAG, "initBaseTools: Completed");
|
LogUtils.d(TAG, "【initBaseTools】基础工具类初始化完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化核心工具与缓存(极致强制驻留)
|
* 初始化核心工具与缓存(极致强制驻留,缓存核心)
|
||||||
*/
|
*/
|
||||||
private void initUtils() {
|
private void initUtils() {
|
||||||
LogUtils.d(TAG, "initUtils: Starting with force-cache strategy");
|
LogUtils.d(TAG, "【initUtils】核心工具与缓存初始化开始 | 极致缓存策略激活");
|
||||||
|
|
||||||
// 1. 配置与基础缓存
|
// 1. 配置与基础缓存工具初始化
|
||||||
sAppConfigUtils = getAppConfigUtils(this);
|
sAppConfigUtils = getAppConfigUtils(this);
|
||||||
sAppCacheUtils = getAppCacheUtils(this);
|
sAppCacheUtils = getAppCacheUtils(this);
|
||||||
|
|
||||||
// 2. 资源与Bitmap缓存
|
// 2. 资源与Bitmap缓存工具初始化(永久驻留)
|
||||||
sBackgroundSourceUtils = BackgroundSourceUtils.getInstance(this);
|
sBackgroundSourceUtils = BackgroundSourceUtils.getInstance(this);
|
||||||
sBackgroundSourceUtils.loadSettings();
|
sBackgroundSourceUtils.loadSettings();
|
||||||
sBitmapCacheUtils = BitmapCacheUtils.getInstance();
|
sBitmapCacheUtils = BitmapCacheUtils.getInstance();
|
||||||
LogUtils.d(TAG, "initUtils: Resource & Bitmap tools initialized (Permanent)");
|
LogUtils.d(TAG, "【initUtils】资源与Bitmap缓存工具初始化完成 | 永久驻留内存");
|
||||||
|
|
||||||
// 3. 视图缓存
|
// 3. 视图缓存初始化(永久驻留,无实例则创建)
|
||||||
sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getLastInstance(this);
|
sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getLastInstance(this);
|
||||||
if (sMemoryCachedBackgroundView == null) {
|
if (sMemoryCachedBackgroundView == null) {
|
||||||
sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, sBackgroundSourceUtils.getCurrentBackgroundBean(), true);
|
sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, sBackgroundSourceUtils.getCurrentBackgroundBean(), true);
|
||||||
LogUtils.d(TAG, "initUtils: View cache - New instance created");
|
LogUtils.d(TAG, "【initUtils】视图缓存无现有实例,已创建新实例");
|
||||||
}
|
}
|
||||||
LogUtils.d(TAG, "initUtils: View cache initialized (Permanent)");
|
LogUtils.d(TAG, "【initUtils】视图缓存初始化完成 | 永久驻留内存");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册全局广播接收器
|
* 注册全局广播接收器
|
||||||
*/
|
*/
|
||||||
private void initReceiver() {
|
private void initReceiver() {
|
||||||
LogUtils.d(TAG, "initReceiver: Starting...");
|
LogUtils.d(TAG, "【initReceiver】全局广播接收器注册开始...");
|
||||||
mGlobalReceiver = new GlobalApplicationReceiver(this);
|
mGlobalReceiver = new GlobalApplicationReceiver(this);
|
||||||
mGlobalReceiver.registerAction();
|
mGlobalReceiver.registerAction();
|
||||||
LogUtils.d(TAG, "initReceiver: Completed");
|
LogUtils.d(TAG, "【initReceiver】全局广播接收器注册完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 私有释放方法 ====================
|
// ====================================== 私有释放方法 - 资源释放 (按创建逆序排序) ======================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 释放广播接收器
|
* 释放全局广播接收器
|
||||||
*/
|
*/
|
||||||
private void releaseReceiver() {
|
private void releaseReceiver() {
|
||||||
LogUtils.d(TAG, "releaseReceiver: Starting...");
|
LogUtils.d(TAG, "【releaseReceiver】全局广播接收器释放开始...");
|
||||||
if (mGlobalReceiver != null) {
|
if (mGlobalReceiver != null) {
|
||||||
mGlobalReceiver.unregisterAction();
|
mGlobalReceiver.unregisterAction();
|
||||||
mGlobalReceiver = null;
|
mGlobalReceiver = null;
|
||||||
LogUtils.d(TAG, "releaseReceiver: Completed");
|
LogUtils.d(TAG, "【releaseReceiver】全局广播接收器释放完成");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 释放通知管理器
|
* 释放通知管理器资源
|
||||||
*/
|
*/
|
||||||
private void releaseNotificationManager() {
|
private void releaseNotificationManager() {
|
||||||
LogUtils.d(TAG, "releaseNotificationManager: Starting...");
|
LogUtils.d(TAG, "【releaseNotificationManager】通知管理器资源释放开始...");
|
||||||
if (sNotificationManagerUtils != null) {
|
if (sNotificationManagerUtils != null) {
|
||||||
sNotificationManagerUtils.release();
|
sNotificationManagerUtils.release();
|
||||||
sNotificationManagerUtils = null;
|
sNotificationManagerUtils = null;
|
||||||
LogUtils.d(TAG, "releaseNotificationManager: Completed");
|
LogUtils.d(TAG, "【releaseNotificationManager】通知管理器资源释放完成");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 私有辅助方法 ====================
|
// ====================================== 私有辅助方法 - 日志/工具 (辅助功能) ======================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录当前缓存详细状态(用于调试监控)
|
* 记录当前缓存详细状态(用于调试监控,极致缓存策略监控)
|
||||||
*/
|
*/
|
||||||
private void logDetailedCacheStatus() {
|
private void logDetailedCacheStatus() {
|
||||||
LogUtils.d(TAG, "logDetailedCacheStatus: Reporting cache state");
|
LogUtils.d(TAG, "【logDetailedCacheStatus】缓存状态监控日志开始...");
|
||||||
|
|
||||||
|
// Bitmap缓存状态
|
||||||
if (sBitmapCacheUtils != null) {
|
if (sBitmapCacheUtils != null) {
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "Cache Status: BitmapCache [Valid]");
|
LogUtils.d(CACHE_PROTECT_TAG, "【缓存状态】BitmapCache - 有效");
|
||||||
try {
|
try {
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "Cache Detail: Bitmap Count = " + sBitmapCacheUtils.getCacheCount());
|
LogUtils.d(CACHE_PROTECT_TAG, "【缓存详情】Bitmap缓存数量:" + sBitmapCacheUtils.getCacheCount());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "Cache Detail: Failed to get bitmap count - " + e.getMessage());
|
LogUtils.e(CACHE_PROTECT_TAG, "【缓存详情】获取Bitmap缓存数量失败", e);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LogUtils.d(CACHE_PROTECT_TAG, "【缓存状态】BitmapCache - 未初始化");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 视图缓存状态
|
||||||
if (sMemoryCachedBackgroundView != null) {
|
if (sMemoryCachedBackgroundView != null) {
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "Cache Status: ViewCache [Valid]");
|
LogUtils.d(CACHE_PROTECT_TAG, "【缓存状态】ViewCache - 有效");
|
||||||
LogUtils.d(CACHE_PROTECT_TAG, "Cache Detail: View Instance Count = " + MemoryCachedBackgroundView.getInstanceCount());
|
LogUtils.d(CACHE_PROTECT_TAG, "【缓存详情】视图实例数量:" + MemoryCachedBackgroundView.getInstanceCount());
|
||||||
|
} else {
|
||||||
|
LogUtils.d(CACHE_PROTECT_TAG, "【缓存状态】ViewCache - 引用已置空(实例可能保留)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,118 +13,131 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
style="@style/DefaultAToolbar"/>
|
style="@style/DefaultAToolbar"/>
|
||||||
|
|
||||||
<LinearLayout
|
<ScrollView
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:gravity="right">
|
android:layout_weight="1.0">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:background="@drawable/bg_frame"
|
|
||||||
android:padding="10dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="TTS语音服务设置:"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="<仅限在切换充电状态时,发送的TTS语音提醒。用于提醒用户当前的服务设置状态。>"
|
|
||||||
android:textSize="12sp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right">
|
||||||
|
|
||||||
<CheckBox
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="用电提醒启用时的TTS贴心服务"
|
android:background="@drawable/bg_frame"
|
||||||
android:onClick="onEnableUsePowerTts"
|
android:padding="10dp">
|
||||||
android:id="@+id/activitysettingsCheckBox1"/>
|
|
||||||
|
|
||||||
<CheckBox
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="充电提醒启用时的TTS贴心服务"
|
android:text="TTS语音服务设置:"/>
|
||||||
android:onClick="onEnableChargeTts"
|
|
||||||
android:id="@+id/activitysettingsCheckBox2"/>
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="<仅限在切换充电状态时,发送的TTS语音提醒。用于提醒用户当前的服务设置状态。>"
|
||||||
|
android:textSize="12sp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="用电提醒启用时的TTS贴心服务"
|
||||||
|
android:onClick="onEnableUsePowerTts"
|
||||||
|
android:id="@+id/activitysettingsCheckBox1"/>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="充电提醒启用时的TTS贴心服务"
|
||||||
|
android:onClick="onEnableChargeTts"
|
||||||
|
android:id="@+id/activitysettingsCheckBox2"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="检查TTS语音悬浮窗权限"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:onClick="onCheckTTSDrawOverlaysPermission"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@drawable/bg_frame"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="电量图表绘制风格设置:"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<cc.winboll.studio.powerbell.views.BatteryStyleView
|
||||||
|
android:id="@+id/battery_style_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1200dp"
|
||||||
|
app:batteryPreviewColor="@color/colorPrimary"
|
||||||
|
app:previewBatteryValue="100"
|
||||||
|
app:defaultSelectedStyle="zebra_style"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="right">
|
android:background="@drawable/bg_frame"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
<Button
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="检查TTS语音悬浮窗权限"
|
android:text="米盟广告SDK设置:"/>
|
||||||
android:padding="10dp"
|
|
||||||
android:onClick="onCheckTTSDrawOverlaysPermission"/>
|
<cc.winboll.studio.libaes.views.ADsControlView
|
||||||
|
android:id="@+id/ads_control_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</ScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/bg_frame"
|
|
||||||
android:padding="10dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="米盟广告SDK设置:"/>
|
|
||||||
|
|
||||||
<cc.winboll.studio.libaes.views.ADsControlView
|
|
||||||
android:id="@+id/ads_control_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/bg_frame"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:layout_weight="1.0">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="电量图表绘制风格设置:"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<cc.winboll.studio.powerbell.views.BatteryStyleView
|
|
||||||
android:id="@+id/battery_style_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1200dp"
|
|
||||||
app:batteryPreviewColor="@color/colorPrimary"
|
|
||||||
app:previewBatteryValue="100"
|
|
||||||
app:defaultSelectedStyle="zebra_style"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sun Dec 07 03:42:32 HKT 2025
|
#Wed Dec 31 20:28:06 HKT 2025
|
||||||
stageCount=8
|
stageCount=9
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.11
|
baseVersion=15.11
|
||||||
publishVersion=15.11.7
|
publishVersion=15.11.8
|
||||||
buildCount=0
|
buildCount=0
|
||||||
baseBetaVersion=15.11.8
|
baseBetaVersion=15.11.9
|
||||||
|
|||||||
Reference in New Issue
Block a user