From 5bf499de14ecc9246d237d94e206fd6a444f68d3 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Mon, 12 Jan 2026 13:13:52 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=9F=BA=E7=A1=80=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .winboll/Readme.txt | 18 + .winboll/bashCheckGitCommitStatus.sh | 32 ++ .winboll/bashCommitAppPublishBuildFlagInfo.sh | 17 + .winboll/bashCommitLibReleaseBuildFlagInfo.sh | 48 +++ .winboll/bashPublishAPKAddTag.sh | 223 ++++++++++++ .winboll/bashPublishDebugAPKAddTag.sh | 166 +++++++++ .winboll/bashPublishLIBAddTag.sh | 14 + .winboll/winboll_app_build.gradle | 339 ++++++++++++++++++ .winboll/winboll_lib_build.gradle | 211 +++++++++++ .winboll/winboll_lint_build.gradle | 50 +++ 10 files changed, 1118 insertions(+) create mode 100644 .winboll/Readme.txt create mode 100644 .winboll/bashCheckGitCommitStatus.sh create mode 100644 .winboll/bashCommitAppPublishBuildFlagInfo.sh create mode 100644 .winboll/bashCommitLibReleaseBuildFlagInfo.sh create mode 100644 .winboll/bashPublishAPKAddTag.sh create mode 100644 .winboll/bashPublishDebugAPKAddTag.sh create mode 100644 .winboll/bashPublishLIBAddTag.sh create mode 100644 .winboll/winboll_app_build.gradle create mode 100644 .winboll/winboll_lib_build.gradle create mode 100644 .winboll/winboll_lint_build.gradle diff --git a/.winboll/Readme.txt b/.winboll/Readme.txt new file mode 100644 index 0000000..f618520 --- /dev/null +++ b/.winboll/Readme.txt @@ -0,0 +1,18 @@ +## WinBoLL 主机编译事项提醒 + +## 类库类型源码发布 +# 类库发布使用以下面命令 +git pull && bash .winboll/bashPublishLIBAddTag.sh <类库模块文件夹名称> + +## 纯应用类型源码发布 +# 应用发布使用以下命令 +git pull && bash .winboll/bashPublishAPKAddTag.sh <应用模块文件夹名称> + +## 编译时提问。Add Github Workflows Tag? (yes/No) +回答yes: 将会添加一个 GitHub 工作流标签 + GitHub 仓库会执行以该标签为标志的编译工作流。 +回答No(默认): 就忽略 GitHub 标签,忽略 GitHub 工作流调用。 + +## Github Workflows 工作流设置注意事项 +应用名称改变时需要修改.github/workflows/android.yml文件设置, +在第79行:asset_name: 处有应用包名称设置。 diff --git a/.winboll/bashCheckGitCommitStatus.sh b/.winboll/bashCheckGitCommitStatus.sh new file mode 100644 index 0000000..1adb83c --- /dev/null +++ b/.winboll/bashCheckGitCommitStatus.sh @@ -0,0 +1,32 @@ +#!/usr/bin/bash + +# 使用 `-z` 命令检查变量是否为空 +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Script parameter error: $0" + exit 2 +fi + +# 进入项目根目录 +cd ${1} +echo -e "Work dir : \n"`pwd` + +git config --global --add safe.directory "${1}" +echo "Current dir : "`pwd` +versionName=${2} + +## 设置要检查的标签 +tag="v"${versionName} + +## 如果Git已经提交了所有代码就执行标签检查操作 +if [[ -n $(git diff --stat) ]] +then + echo 'Source is no commit git completely, tag action cancel.' + exit 1 +else + echo "Git status is clean." + if [ "$(git tag -l ${tag})" == "${tag}" ]; then + echo "Tag ${tag} exist." + exit 2 + fi + echo "${0}: Git tag is checked OK: (${tag})" +fi diff --git a/.winboll/bashCommitAppPublishBuildFlagInfo.sh b/.winboll/bashCommitAppPublishBuildFlagInfo.sh new file mode 100644 index 0000000..791e58c --- /dev/null +++ b/.winboll/bashCommitAppPublishBuildFlagInfo.sh @@ -0,0 +1,17 @@ +#!/usr/bin/bash +## 提交新的 APK 编译配置标志信息,并推送到Git仓库。 + +# 使用 `-z` 命令检查变量是否为空 +if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then + echo "$0 Script parameter error." + echo "(Script Demo : [ bashCommitAppPublishBuildFlagInfo.sh ])" + exit 2 +fi + +# 进入项目根目录 +cd ${1} +echo -e "Work dir : \n"`pwd` + +git add . +git commit -m "<$4>APK ${2} ${3} Publish." +git push origin && git push origin --tags diff --git a/.winboll/bashCommitLibReleaseBuildFlagInfo.sh b/.winboll/bashCommitLibReleaseBuildFlagInfo.sh new file mode 100644 index 0000000..d92f320 --- /dev/null +++ b/.winboll/bashCommitLibReleaseBuildFlagInfo.sh @@ -0,0 +1,48 @@ +#!/usr/bin/bash +## 提交新的 Library 编译配置标志信息,并推送到Git仓库。 + +# 检查是否指定了将要发布的类库名称 +# 使用 `-z` 命令检查变量是否为空 +if [ -z "$1" ]; then + echo "Library name error: $0" + exit 2 +fi + +## 开始执行脚本 +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 .. +fi +## 本脚本需要在项目根目录下执行 +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 -e "Work dir error." + exit 1 +fi + +# 就读取脚本 .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="v7.6.4-test1" +# 正式设置标签时使用 +#tag="v"${PUBLISH_VERSION} + +git add . +git commit -m "<$1>Library Release ${PUBLISH_VERSION}" +git push origin && git push origin --tags diff --git a/.winboll/bashPublishAPKAddTag.sh b/.winboll/bashPublishAPKAddTag.sh new file mode 100644 index 0000000..082dc7e --- /dev/null +++ b/.winboll/bashPublishAPKAddTag.sh @@ -0,0 +1,223 @@ +#!/usr/bin/bash +# ============================================================================== +# WinBoLL 应用发布脚本 +# 功能:检查Git源码状态 → 编译Stage Release包 → 添加WinBoLL标签 → 提交并推送源码 +# 依赖:build.properties、app_update_description.txt(项目根目录下) +# 使用:./script_name.sh +# 作者:豆包&ZhanGSKen +# ============================================================================== + +# ==================== 常量定义 ==================== +# 脚本退出码 +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标签(格式:-v) + 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标签(格式:-v-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 + echo "[ERROR] 未指定应用名称!使用方式:${0} " + exit ${EXIT_CODE_ERR_NO_APP_NAME} +fi +APP_NAME=$1 +echo "[INFO] 待发布应用名称:${APP_NAME}" + +# 2. 检查并切换到项目根目录(确保build.properties存在) +echo "[INFO] 当前工作目录:$(pwd)" +if [[ ! -e "${APP_NAME}/build.properties" ]]; then + echo "[WARNING] 当前目录不存在${APP_NAME}/build.properties,尝试切换到上级目录..." + cd .. + echo "[INFO] 切换后工作目录:$(pwd)" +fi + +# 验证最终工作目录是否正确 +if [[ ! -e "${APP_NAME}/build.properties" ]]; then + echo "[ERROR] 工作目录错误!${APP_NAME}/build.properties 文件不存在。" + exit ${EXIT_CODE_ERR_WORK_DIR} +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 + echo "[ERROR] 源码与标签推送失败!" + exit 1 +fi + +# ==================== 主流程结束 ==================== +echo "=============================================" +echo " WinBoLL 应用发布完成!" +echo "=============================================" +exit ${EXIT_CODE_SUCCESS} + diff --git a/.winboll/bashPublishDebugAPKAddTag.sh b/.winboll/bashPublishDebugAPKAddTag.sh new file mode 100644 index 0000000..0deb526 --- /dev/null +++ b/.winboll/bashPublishDebugAPKAddTag.sh @@ -0,0 +1,166 @@ +#!/usr/bin/bash + +# 检查是否指定了将要发布的调试版应用名称 +# 使用 `-z` 命令检查变量是否为空 +if [ -z "$1" ]; then + echo "No APP name specified : $0" + exit 2 +fi + +## 定义相关函数 +## 检查 Git 源码是否完全提交了,完全提交就返回0 +function checkGitSources { + #local input="$1" + #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="v7.6.4-test1" + # 正式调试版设置标签时使用 + tag=$1"-v"${PUBLISH_VERSION}"-debug" + 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="v7.6.4-beta" + # 正式设置标签时使用 + tag=$1"-"v"${BASE_BETA_VERSION}-beta-debug + 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 .. +fi +## 本脚本需要在项目根目录下执行 +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 -e "Work dir error." + exit 1 +fi + +# 检查源码状态 +result=$(checkGitSources) +if [[ $? -eq 0 ]]; then + echo $result + # 如果Git已经提交了所有代码就执行标签和应用发布操作 + + # 预先询问是否添加工作流标签 + echo "Add Github Workflows Tag? (yes/no)" + result=$(askAddWorkflowsTag) + nAskAddWorkflowsTag=$? + echo $result + + # 发布应用 + echo "Publishing WinBoLL Debug APK ..." + # 脚本调试时使用 + #bash gradlew :$1:assembleBetaDebug + # 正式发布调试版 + bash gradlew :$1:assembleStageDebug + echo "Publishing WinBoLL Debug 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 Debug 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 diff --git a/.winboll/bashPublishLIBAddTag.sh b/.winboll/bashPublishLIBAddTag.sh new file mode 100644 index 0000000..7ab6a3a --- /dev/null +++ b/.winboll/bashPublishLIBAddTag.sh @@ -0,0 +1,14 @@ +#!/usr/bin/bash + +# 检查是否指定了将要发布的类库名称 +# 使用 `-z` 命令检查变量是否为空 +if [ -z "$1" ]; then + echo "No Library name specified : $0" + exit 2 +fi + +## 正式发布使用 +git pull && bash gradlew :$1:publishReleasePublicationToWinBoLLReleaseRepository && bash .winboll/bashCommitLibReleaseBuildFlagInfo.sh $1 + +## 调试使用 +#bash gradlew :$1:publishSnapshotWinBoLLPublicationToWinBoLLSnapshotRepository && bash .winboll/bashCommitLibReleaseBuildFlagInfo.sh $1 diff --git a/.winboll/winboll_app_build.gradle b/.winboll/winboll_app_build.gradle new file mode 100644 index 0000000..3522fd3 --- /dev/null +++ b/.winboll/winboll_app_build.gradle @@ -0,0 +1,339 @@ +// WinBoLL 应用签名配置 +// + +android { + def winbollProps = new Properties() + def winbollPropsFile = rootProject.file("${winbollFilePath}") + if(winbollPropsFile.exists()) { + winbollProps.load(new FileInputStream(winbollPropsFile)) + } + + // 读取秘钥配置文件 + // + def keyProps = new Properties() + def keyPropsFile = rootProject.file("${keyPropsFilePath}") + //println 'Test keystore path' + //println 'KeyProsFile :' + Boolean.toString(keyPropsFile.exists()) + //assert(false) + if(keyPropsFile.exists()) { + keyProps.load(new FileInputStream(keyPropsFile)) + } + + // 配置签名 + signingConfigs { + if(keyPropsFile.exists()) { + winboll { + assert(keyProps['keyAlias'] != null && keyProps['keyPassword'] != null && keyProps['storeFile'] != null && keyProps['storePassword'] != null) + keyAlias keyProps['keyAlias'] + keyPassword keyProps['keyPassword'] + storeFile keyProps['storeFile'] ? file(keyProps['storeFile']) : null + storePassword keyProps['storePassword'] + } + } + } + buildTypes { + debug { + if(keyPropsFile.exists()) { + signingConfig signingConfigs.winboll + } + } + release { + if(keyPropsFile.exists()) { + signingConfig signingConfigs.winboll + } + + minifyEnabled true // 开启混淆(核心开关) + shrinkResources true // 可选:移除无用资源(进一步减小体积) + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), // 官方默认规则(优化版) + 'proguard-rules.pro' // 自定义规则文件 + } + + } + + flavorDimensions "WinBoLLApp" + productFlavors { + beta { + // 检查编译标志位配置 + assert (winbollBuildProps['buildCount'] != null) + dimension "WinBoLLApp" + applicationIdSuffix ".beta" + LocalDateTime localDateTimeNow = LocalDateTime.now(ZoneId.of("Asia/Shanghai")); + versionNameSuffix "-beta" + winbollBuildProps['buildCount'] + "_" + localDateTimeNow.format('mmss') + } + stage { + dimension "WinBoLLApp" + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + // 应用包输出配置 + // + android.applicationVariants.all { variant -> + // + // GitHub 应用包输出配置 + // 1. 配置 Beta Release 版应用包输出 + // 注意 :GitHub 打包使用 android.yml 的 "bash ./gradlew assembleBetaRelease" 命令 + // + if(variant.flavorName == "beta" && variant.buildType.name == "release") { + /* 后期管理预留代码 */ + /* 暂时没有需要的 GitHub 应用包输出配置 */ + /* GitHub 部分代码忽略 */ + } + + // + // WinBoLL 应用包输出配置 + // 1. 配置 Stage Release 版应用包输出 + // 2. 配置 Beta Debug 版应用包输出 + // + if((variant.flavorName == "beta" && variant.buildType.name == "debug") + || (variant.flavorName == "beta" && variant.buildType.name == "release") + || (variant.flavorName == "stage" && variant.buildType.name == "debug") + || (variant.flavorName == "stage" && variant.buildType.name == "release")) { + println "Project root directory: " + project.rootDir.toString() + println "Project root directory name : " + project.rootDir.name + def outputPath="${project.projectDir.absolutePath}/build/outputs/apk/${variant.buildType.name}" + //def outputFileName="${rootProject.name}_${versionName}.apk" + def outputFileName=project.rootDir.name + "_${versionName}.apk" + + // 创建 WinBoLL Studio 发布接口文件夹 + File fWinBoLLStudioDir = file("/sdcard/WinBoLLStudio/APKs"); + if(!fWinBoLLStudioDir.exists()) { + //fWinBoLLStudioDir.mkdirs(); + // 如果没有发布接口文件就不用进行APK发布和源码管理操作 + // 当前编译环境不是 WinBoLL 主机, 以下将忽略APK发布和源码管理操作。 + println 'The current compilation environment is not in WinBoLL host, and the following APK publishing and source management operations will be ignore.' + } else { + /// WINBOLL 主机的 APK 发布和源码管理操作 /// + variant.getAssembleProvider().get().doFirst { + /* 后期管理预留代码 */ + } //doFirst { + + // 编译输出后处理文件部分 + // + variant.getAssembleProvider().get().doLast { + variant.outputs.forEach{ file-> + // 如果正在调试,就拷贝到 WinBoLL 备份管理文件夹 + // + if(variant.flavorName == "beta"&&variant.buildType.name == "debug"){ + //File outBuildBckDir = new File(fWinBoLLStudioDir, "/${rootProject.name}/${variant.buildType.name}") + File outBuildBckDir = new File(fWinBoLLStudioDir, "/" + project.rootDir.name + "/${variant.buildType.name}") + // 创建目标路径目录 + if(!outBuildBckDir.exists()) { + outBuildBckDir.mkdirs(); + println "Output Folder Created.(WinBoLLStudio) : " + outBuildBckDir.getAbsolutePath() + } + if(outBuildBckDir.exists()) { + copy{ + from file.outputFile + into outBuildBckDir + rename { + String fileName -> "${outputFileName}" + } + println "Output APK (WinBoLLStudio): " + outBuildBckDir.getAbsolutePath() + "/${outputFileName}" + } + // 检查编译标志位配置 + assert (winbollBuildProps['buildCount'] != null) + assert (winbollBuildProps['libraryProject'] != null) + //构建计数增加 + int buildCount = Integer.parseInt(winbollBuildProps['buildCount']) + 1; + // 设置编译计数 + winbollBuildProps.setProperty("buildCount", Integer.toString(buildCount)); + + //保存编译标志配置 + FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile) + winbollBuildProps.store(fos, "${winbollBuildPropsDesc}"); + fos.close(); + println "\n\n>>> Project build.properties saved.\n\n"; + + if(winbollBuildProps['libraryProject'] != "") { + // 如果应用 build.properties 文件设置了类库模块项目文件名 + // 就拷贝一份新的编译标志配置到类库项目文件夹 + File libraryProjectBuildPropsFile = new File("$RootProjectDir/" + winbollBuildProps['libraryProject'] + "/build.properties") + assert(winbollBuildPropsFile.exists()) + assert(libraryProjectBuildPropsFile.exists()) + java.nio.file.Path sourceFilePath = winbollBuildPropsFile.toPath(); + java.nio.file.Path targetFilePath = libraryProjectBuildPropsFile.toPath(); + // 使用copyTo()方法复制文件,如果目标文件存在会被覆盖,可选参数可以选择不覆盖 + java.nio.file.Files.copy(sourceFilePath, targetFilePath, java.nio.file.StandardCopyOption.REPLACE_EXISTING); + + println "\n\n>>> Library Project build.properties saved.\n\n"; + } + } + } + + // 如果正在发布,就拷贝到 WinBoLL 标签管理文件夹,和处理 Git 仓库管理任务。 + // + if(variant.flavorName == "stage"&&variant.buildType.name == "release"){ + // 发布 APK 文件 + // + // 截取版本号的版本字段为短版本名 + String szVersionName = "${versionName}" + String[] szlistTemp = szVersionName.split("-") + String szShortVersionName = szlistTemp[0] + //String szCommonTagAPKName = "${rootProject.name}_" + szShortVersionName + ".apk" + String szCommonTagAPKName = project.rootDir.name + "_" + szShortVersionName + ".apk" + println "CommonTagAPKName is : " + szCommonTagAPKName + + //File outTagDir = new File(fWinBoLLStudioDir, "/${rootProject.name}/tag/") + File outTagDir = new File(fWinBoLLStudioDir, "/" + project.rootDir.name + "/tag/") + // 创建目标路径目录 + if(!outTagDir.exists()) { + outTagDir.mkdirs(); + println "Output Folder Created.(Tags) : " + outTagDir.getAbsolutePath() + } + + if(outTagDir.exists()) { + File targetAPK = new File(outTagDir, "${szCommonTagAPKName}") + if(targetAPK.exists()) { + // 标签版本APK文件已经存在,构建拷贝任务停止 + assert (!targetAPK.exists()) + // 可选择删除并继续输出APK文件 + //delete targetAPK + } + // 复制一个备份 + copy{ + from file.outputFile + into outTagDir + rename { + String fileName -> "${outputFileName}" + } + println "Output APK (Tags): "+ outTagDir.getAbsolutePath() + "/${outputFileName}" + } + // 复制一个并重命名为短版本名 + copy{ + from file.outputFile + into outTagDir + rename { + String fileName -> "${szCommonTagAPKName}" + } + println "Output APK (Tags): "+ outTagDir.getAbsolutePath() + "/${szCommonTagAPKName}" + } + // 检查编译标志位配置 + assert (winbollBuildProps['stageCount'] != null) + assert (winbollBuildProps['publishVersion'] != null) + assert (winbollBuildProps['buildCount'] != null) + assert (winbollBuildProps['baseVersion'] != null) + assert (winbollBuildProps['baseBetaVersion'] != null) + assert (winbollBuildProps['libraryProject'] != null) + + // 设置类库的默认版本名 + winbollBuildProps.setProperty("publishVersion", "${versionName}"); + // Stage 发布计数增加 + int stageCount = Integer.parseInt(winbollBuildProps['stageCount']) + 1; + winbollBuildProps.setProperty("stageCount", Integer.toString(stageCount)); + // 设置类库的默认Beta版本名 + winbollBuildProps.setProperty("baseBetaVersion", winbollBuildProps['baseVersion'] + "." + Integer.toString(stageCount)); + // 构建计数重置 + winbollBuildProps.setProperty("buildCount", "0"); + + //保存编译标志配置 + FileOutputStream fos = new FileOutputStream(winbollBuildPropsFile) + winbollBuildProps.store(fos, "${winbollBuildPropsDesc}"); + fos.close(); + + if(winbollBuildProps['libraryProject'] != "") { + // 如果应用 build.properties 文件设置了类库模块项目文件名 + // 就拷贝一份新的编译标志配置到类库项目文件夹 + File libraryProjectBuildPropsFile = new File("$RootProjectDir/" + winbollBuildProps['libraryProject'] + "/build.properties") + assert(winbollBuildPropsFile.exists()) + assert(libraryProjectBuildPropsFile.exists()) + java.nio.file.Path sourceFilePath = winbollBuildPropsFile.toPath(); + java.nio.file.Path targetFilePath = libraryProjectBuildPropsFile.toPath(); + // 使用copyTo()方法复制文件,如果目标文件存在会被覆盖,可选参数可以选择不覆盖 + java.nio.file.Files.copy(sourceFilePath, targetFilePath, java.nio.file.StandardCopyOption.REPLACE_EXISTING); + } + + // 提交新的编译标志配置 + println 'exec bashCommitAppPublishBuildFlagInfoFilePath ...' + def resultCommitBuildFlag = exec { + commandLine 'bash', '--', "${RootProjectDir}/${bashCommitAppPublishBuildFlagInfoFilePath}", "${RootProjectDir}", "${versionName}", variant.buildType.name , rootProject.name + } + // 检查bash命令的返回值(假设非零表示失败) + assert(resultCommitBuildFlag.getExitValue() == 0) + } + } // if(variant.buildType.name == "release"){ + + // 如果正在调试发布版,就只生成和输出APK文件,不处理 Git 仓库提交与更新问题。 + // + if(variant.flavorName == "stage"&&variant.buildType.name == "debug"){ + // 发布 APK 文件 + // + // 截取版本号的版本字段为短版本名 + String szVersionName = "${versionName}" + String[] szlistTemp = szVersionName.split("-") + String szShortVersionName = szlistTemp[0] + //String szCommonTagAPKName = "${rootProject.name}_" + szShortVersionName + ".apk" + String szCommonTagAPKName = project.rootDir.name + "_" + szShortVersionName + ".apk" + println "CommonTagAPKName is : " + szCommonTagAPKName + + //File outTagDir = new File(fWinBoLLStudioDir, "/${rootProject.name}/tag/") + File outTagDir = new File(fWinBoLLStudioDir, "/" + project.rootDir.name + "/${variant.buildType.name}/") + // 创建目标路径目录 + if(!outTagDir.exists()) { + outTagDir.mkdirs(); + println "Output Folder Created.(Tags) : " + outTagDir.getAbsolutePath() + } + + if(outTagDir.exists()) { + File targetAPK = new File(outTagDir, "${szCommonTagAPKName}") + if(targetAPK.exists()) { + // 标签版本APK文件已经存在,构建拷贝任务停止 + println '如果是在调试 Stage 版应用包构建,请删除(注:在debug目录)现有的 Stage 应用包('+targetAPK.getAbsolutePath()+')。再编译一次。' + assert (!targetAPK.exists()) + // 可选择删除并继续输出APK文件 + //delete targetAPK + } + // 复制一个备份 + copy{ + from file.outputFile + into outTagDir + rename { + String fileName -> "${outputFileName}" + } + println "Output APK (Tags): "+ outTagDir.getAbsolutePath() + "/${outputFileName}" + } + // 复制一个并重命名为短版本名 + copy{ + from file.outputFile + into outTagDir + rename { + String fileName -> "${szCommonTagAPKName}" + } + println "Output APK (Tags): "+ outTagDir.getAbsolutePath() + "/${szCommonTagAPKName}" + } + + //不保存编译标志配置 + } + } + + // 如果配置了APK额外输出路径,就复制一份拷贝到额外路径。 + // + if(winbollProps != null && winbollProps['ExtraAPKOutputPath'] != null ) { + File apkFile = new File(winbollProps['ExtraAPKOutputPath']) + File outCommonDir = apkFile.getParentFile(); + String commandAPKName = apkFile.getName(); + if(outCommonDir.exists()) { + copy{ + from file.outputFile + into outCommonDir + rename { + String fileName -> "${commandAPKName}" + } + println "Output APK (Common): " + outCommonDir.getAbsolutePath() + "/${commandAPKName}" + } + } + } + + + } + }// End of (variant.getAssembleProvider().get().doLast {) + }/// WINBOLL 主机的 APK 发布和源码管理操作结束 /// + } + + } // End of (android.applicationVariants.all { variant ->) +} + diff --git a/.winboll/winboll_lib_build.gradle b/.winboll/winboll_lib_build.gradle new file mode 100644 index 0000000..f63aa52 --- /dev/null +++ b/.winboll/winboll_lib_build.gradle @@ -0,0 +1,211 @@ +// 本机和 WinBoLL Maven 仓库传输配置。 +// + +def getDefaultVersion(){ + // 检查编译标志位配置 + assert (winbollBuildProps['publishVersion'] != null) + // 返回编译版本号 + return winbollBuildProps['publishVersion'] +} + +def siteUrl = 'https://winboll.cc/?page=studio/details.php&app=${rootProject.name}' // 项目主页 +def gitUrl = 'https://gitea.winboll.cc/WinBoLL/${rootProject.name}' // 项目的git地址 +def DefaultGroupId = 'cc.winboll.studio' // 类库所有者groupId +def DefaultVersion = getDefaultVersion() // 版本号 +def DeveloperId='zhangsken' // 开发者账号 +def DeveloperName='ZhanGSKen' // 开发者名称 +def DeveloperEMail='zhangsken@188.com' // 开发者邮箱地址 +def LicenseName='The Apache Software License, Version 2.0' +def LicenseUrl='http://www.apache.org/licenses/LICENSE-2.0.txt' + +Properties properties = new Properties() + +afterEvaluate { + publishing { + repositories { + if(file("${RootProjectDir}/${winbollFilePath}").exists()) { + properties.load(file("${RootProjectDir}/${winbollFilePath}").newDataInputStream()) + def NexusUserName = properties.getProperty("Nexus.name") + def NexusPassword = properties.getProperty("Nexus.password") + // WinBoLL Release 仓库 + maven{ + //仓库的名字和地址 + name = "WinBoLLRelease" + url="https://nexus.winboll.cc/repository/maven-releases/" + // 仓库用户名密码 + credentials { + username = NexusUserName + password = NexusPassword + } + } + // WinBoLL Snapshot 仓库 + maven{ + //仓库的名字和地址 + name = "WinBoLLSnapshot" + url="https://nexus.winboll.cc/repository/maven-snapshots/" + // 仓库用户名密码 + credentials { + username = NexusUserName + password = NexusPassword + } + } + } + } + publications { + // Local Maven 仓库传输任务 + // + release(MavenPublication) { + groupId = DefaultGroupId + artifactId = project.name + version = DefaultVersion + + //from components.java + // 必须有这个 否则不会上传AAR包 + afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) } + // 上传source,这样使用方可以看到方法注释 + //artifact generateSourcesJar + //要上传的aar路径 + //artifact "$buildDir/outputs/aar/${project.getName()}-release.aar" + //artifact "$buildDir/outputs/aar/${project.getName()}-debug.aar" + + //对pom进行的操作 + pom.withXml{ + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + //将所有的默认依赖移除 + //it.parent().remove(it) + } + } + pom { + name = artifactId + url = siteUrl + licenses { + license { //证书说明 + name=LicenseName // 开源协议名称 + url=LicenseUrl // 协议地址 + } + } + developers { + developer { + id=DeveloperId // 开发者账号 + name=DeveloperName // 开发者名称 + email=DeveloperEMail // 开发者邮箱地址 + } + } + //软件配置管理 + scm { + connection=gitUrl + developerConnection=gitUrl + url=siteUrl + } + } + } + + // WinBoLL Maven Release 仓库传输任务 + // + releaseWinBoLL(MavenPublication) { + // 需要使用的变体,假设有free和pay两个变体,可以选择一个 + //from components.free + + groupId = DefaultGroupId // 文件的groupId + artifactId = project.name //文件的名字 + version = DefaultVersion //版本号 + + //from components.java + // 必须有这个 否则不会上传AAR包 + afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) } + // 上传source,这样使用方可以看到方法注释 + //artifact generateSourcesJar + //要上传的aar路径 + //artifact "$buildDir/outputs/aar/${project.getName()}-release.aar" + //artifact "$buildDir/outputs/aar/${project.getName()}-debug.aar" + + //对pom进行的操作 + pom.withXml{ + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + //将所有的默认依赖移除 + //it.parent().remove(it) + } + } + pom { + name = artifactId + url = siteUrl + licenses { + license { //证书说明 + name=LicenseName // 开源协议名称 + url=LicenseUrl // 协议地址 + } + } + developers { + developer { + id=DeveloperId // 开发者账号 + name=DeveloperName // 开发者名称 + email=DeveloperEMail // 开发者邮箱地址 + } + } + //软件配置管理 + scm { + connection=gitUrl + developerConnection=gitUrl + url=siteUrl + } + } + + } // 创建名为 release 的任务结束 + + // WinBoLL Maven Snapshot 仓库传输任务 + // + snapshotWinBoLL(MavenPublication) { + // 需要使用的变体,假设有free和pay两个变体,可以选择一个 + //from components.free + + groupId = DefaultGroupId // 文件的groupId + artifactId = project.name //文件的名字 + version = DefaultVersion + "-SNAPSHOT" //版本号 + + //from components.java + // 必须有这个 否则不会上传AAR包 + afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) } + // 上传source,这样使用方可以看到方法注释 + //artifact generateSourcesJar + //要上传的aar路径 + //artifact "$buildDir/outputs/aar/${project.getName()}-release.aar" + //artifact "$buildDir/outputs/aar/${project.getName()}-debug.aar" + + //对pom进行的操作 + pom.withXml{ + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + //将所有的默认依赖移除 + //it.parent().remove(it) + } + } + pom { + name = artifactId + url = siteUrl + licenses { + license { //证书说明 + name=LicenseName // 开源协议名称 + url=LicenseUrl // 协议地址 + } + } + developers { + developer { + id=DeveloperId // 开发者账号 + name=DeveloperName // 开发者名称 + email=DeveloperEMail // 开发者邮箱地址 + } + } + //软件配置管理 + scm { + connection=gitUrl + developerConnection=gitUrl + url=siteUrl + } + } + } // 创建名为 snapshot 的任务结束 + } + + } +} diff --git a/.winboll/winboll_lint_build.gradle b/.winboll/winboll_lint_build.gradle new file mode 100644 index 0000000..b2ec440 --- /dev/null +++ b/.winboll/winboll_lint_build.gradle @@ -0,0 +1,50 @@ +android { + lintOptions { + // true--关闭lint报告的分析进度 + //quiet true + // true--错误发生后停止gradle构建 + abortOnError false + // true--只报告error + //ignoreWarnings true + // true--忽略有错误的文件的全/绝对路径(默认是true) + //absolutePaths true + // true--检查所有问题点,包含其他默认关闭项 + checkAllWarnings true + // true--所有warning当做error + //warningsAsErrors true + // 关闭指定问题检查 + //disable 'ExpiredTargetSdkVersion','HardcodedText','UnknownNullness','ButtonStyle','GradleDependency','UnusedResources' + // 打开指定问题检查 + //enable 'RtlHardcoded','RtlCompat', 'RtlEnabled' + // 仅检查指定问题 + //check 'NewApi', 'InlinedApi' + // true--error输出文件不包含源码行号 + //noLines true + // true--显示错误的所有发生位置,不截取 + showAll true + // 回退lint设置(默认规则) + //lintConfig file("default-lint.xml") + // true--生成txt格式报告(默认false) + //textReport true + // 重定向输出;可以是文件或'stdout' + //textOutput 'stdout' + // true--生成XML格式报告 + xmlReport true + // 指定xml报告文档(默认lint-results.xml) + xmlOutput file("${lintXmlReportFilePath}") + // true--生成HTML报告(带问题解释,源码位置,等) + htmlReport true + // html报告可选路径(构建器默认是lint-results.html ) + htmlOutput file("${lintHTMLReportFilePath}") + // true--所有正式版构建执行规则生成崩溃的lint检查,如果有崩溃问题将停止构建 + checkReleaseBuilds true + // 在发布版本编译时检查(即使不包含lint目标),指定问题的规则生成崩溃 + //fatal 'NewApi', 'InlineApi' + // 指定问题的规则生成错误 + //error 'Wakelock', 'TextViewEdits' + // 指定问题的规则生成警告 + //warning 'ResourceAsColor' + // 忽略指定问题的规则(同关闭检查) + //ignore 'TypographyQuotes' + } +}