Compare commits

..

57 Commits

Author SHA1 Message Date
ZhanGSKen
f33956c872 <aes>APK 15.6.0 release Publish. 2025-04-29 15:14:21 +08:00
ZhanGSKen
9283ad709f 升级版本号 2025-04-29 15:13:53 +08:00
ZhanGSKen
459fff1531 <aes>APK 15.5.0 release Publish. 2025-04-29 15:11:54 +08:00
ZhanGSKen
b4fb680b8c 更新 Android API 目标版本,更新基础类库,把 WinBoll 改为 WinBoLL。 2025-04-29 15:09:25 +08:00
ZhanGSKen
5a1f1f2d73 修改 WinBoll 为 WinBoLL 2025-04-29 13:04:45 +08:00
ZhanGSKen
0e4dc85dfa Merge remote-tracking branch 'origin/appbase' into aes 2025-04-29 12:48:41 +08:00
ZhanGSKen
2be7e2cbaf 编译测试 2025-04-29 12:21:17 +08:00
ZhanGSKen
24f598294e 编译调试 2025-04-29 12:19:32 +08:00
ZhanGSKen
b5e918b364 更新应用图标 2025-04-29 12:18:51 +08:00
ZhanGSKen
50561a2f67 更换Android适配版本 2025-04-29 12:18:32 +08:00
ZhanGSKen
204642a5cd <aes>Start New Stage Version. 2025-04-29 00:22:19 +08:00
ZhanGSKen
daf10dd727 <aes>Start New Stage Version. 2025-04-29 00:21:59 +08:00
ZhanGSKen
2005ba6aee 设置版本号 2025-04-29 00:21:37 +08:00
ZhanGSKen
6adc96449b <aes>Start New Stage Version. 2025-04-29 00:19:26 +08:00
ZhanGSKen
4d8675f1f7 编译测试 2025-04-29 00:10:58 +08:00
ZhanGSKen
2467f3b5a8 Merge remote-tracking branch 'origin/appbase' into aes 2025-04-29 00:08:31 +08:00
ZhanGSKen
32a0e47c87 <appbase>APK 15.7.3 release Publish. 2025-04-28 21:17:52 +08:00
ZhanGSKen
82af906fed <appbase>APK 15.7.2 release Publish. 2025-04-28 21:14:11 +08:00
ZhanGSKen
d13a8a445e <appbase>APK 15.7.1 release Publish. 2025-04-28 21:13:53 +08:00
ZhanGSKen
6d02c9fc49 <appbase>APK 15.7.0 release Publish. 2025-04-28 21:13:29 +08:00
ZhanGSKen
10a8c2c1ed <appbase>Start New Stage Version. 2025-04-28 21:08:18 +08:00
ZhanGSKen
bff0ec4e57 设定版本号 2025-04-28 21:07:08 +08:00
ZhanGSKen
aa101977f0 把 WinBoll 名称改为 WinBoLL 2025-04-28 21:04:17 +08:00
ZhanGSKen
a88e1b2d99 git repos fix 2025-04-28 20:12:28 +08:00
ZhanGSKen
363fa0c3b3 <appbase>Start New Stage Version. 2025-04-28 20:06:05 +08:00
ZhanGSKen
ebb0df2a74 <appbase>Start New Stage Version. 2025-04-28 20:05:46 +08:00
ZhanGSKen
ed193119f6 设定版本号(baseBetaVersion 版本要比publishVersion 版本加多 1 个版本) 2025-04-28 00:36:58 +08:00
ZhanGSKen
b8834627ae 编译测试 2025-04-27 21:10:23 +08:00
ZhanGSKen
164c00ee0d Merge remote-tracking branch 'origin/appbase' into aes 2025-04-27 21:03:34 +08:00
ZhanGSKen
f4a054663e 设定版本号 2025-04-27 21:02:50 +08:00
ZhanGSKen
d17dd8073d 编译测试 2025-04-27 21:00:31 +08:00
ZhanGSKen
b34d777c9f 合并appbase 2025-04-27 20:55:34 +08:00
ZhanGSKen
7150974d01 根目录 Gradle 配置回复,移除就的秘钥配置文件。 2025-04-27 20:42:01 +08:00
ZhanGSKen
c2794e7322 回复先前版本 2025-04-27 20:28:37 +08:00
ZhanGSKen
2ce07bbcf3 <libaes>Library Release 15.4.1 2025-04-27 17:40:14 +08:00
ZhanGSKen
7932e25def <aes>APK 15.4.1 release Publish. 2025-04-27 17:39:51 +08:00
ZhanGSKen
191de5c511 <aes>APK 15.4.0 release Publish. 2025-04-27 17:39:39 +08:00
ZhanGSKen
d520c9ae06 <aes>Start New Stage Version. 2025-04-27 17:36:17 +08:00
ZhanGSKen
933abbc261 <aes>Start New Stage Version. 2025-04-27 17:36:08 +08:00
ZhanGSKen
14a161ab3f 更新版本号 2025-04-27 17:35:16 +08:00
ZhanGSKen
248b8084dc Merge branch 'aes' of https://zhangsken.winboll.cc/ZhanGSKen/APPBase.git into aes 2025-04-27 17:31:08 +08:00
ZhanGSKen
006cefea2a <aes>Start New Stage Version. 2025-04-27 17:30:08 +08:00
ZhanGSKen
ad1b6ca3e9 编译测试 2025-04-27 17:26:24 +08:00
ZhanGSKen
37c93658b3 <aes>Start New Stage Version. 2025-04-27 14:03:25 +08:00
ZhanGSKen
65aae2146e 更新版本号 2025-04-27 14:03:03 +08:00
ZhanGSKen
58eba26eb5 <aes>Start New Stage Version. 2025-04-27 14:00:56 +08:00
ZhanGSKen
a32b10cdec 更新类库 2025-04-27 13:48:45 +08:00
ZhanGSKen
4737ce92e1 <apputils>Start New Stage Version. 2025-04-27 11:14:42 +08:00
ZhanGSKen
839bf72eca <libappbase>Library Release 15.4.8 2025-04-27 11:03:44 +08:00
ZhanGSKen
3f2ec872f8 <appbase>APK 15.4.8 release Publish. 2025-04-27 11:03:35 +08:00
ZhanGSKen
b62cbc043b 移除类库依赖 2025-04-27 11:02:06 +08:00
ZhanGSKen
b60de856ca Merge branch 'appbase' into winboll 2025-04-26 21:16:41 +08:00
ZhanGSKen
37d5d1efe0 更新秘钥配置方式,更新APK文件输出目录,更新说明书。 2025-04-26 20:29:31 +08:00
ZhanGSKen
c11102d729 开发者联系邮箱 2025-04-26 19:16:10 +08:00
ZhanGSKen
6cc04f8e6f 修正说明书标题部分 2025-04-26 17:52:58 +08:00
ZhanGSKen
2bc7db1dca 将appbase子项目拷贝为winboll子项目。 2025-04-24 20:19:19 +08:00
ZhanGSKen
96f31e252c 设置类库资源地址引用顺序。 2025-04-24 20:11:58 +08:00
92 changed files with 3064 additions and 394 deletions

View File

@@ -1,4 +1,4 @@
## WinBoll 主机编译事项提醒 ## WinBoLL 主机编译事项提醒
## 类库类型源码发布 ## 类库类型源码发布
# 类库发布使用以下面命令 # 类库发布使用以下面命令

View File

@@ -37,7 +37,7 @@ fi
# 使用grep找到包含"publishVersion="的那一行然后用awk提取其后的值 # 使用grep找到包含"publishVersion="的那一行然后用awk提取其后的值
PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}') PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}')
echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >" echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >"
## 设新的 WinBoll 标签 ## 设新的 WinBoLL 标签
# 脚本调试时使用 # 脚本调试时使用
#tag="v7.6.4-test1" #tag="v7.6.4-test1"
# 正式设置标签时使用 # 正式设置标签时使用

View File

@@ -38,24 +38,24 @@ function askAddWorkflowsTag {
fi fi
} }
function addWinBollTag { function addWinBoLLTag {
# 就读取脚本 .winboll/winboll_app_build.gradle 生成的 publishVersion。 # 就读取脚本 .winboll/winboll_app_build.gradle 生成的 publishVersion。
# 如果文件中有 publishVersion 这一项, # 如果文件中有 publishVersion 这一项,
# 使用grep找到包含"publishVersion="的那一行然后用awk提取其后的值 # 使用grep找到包含"publishVersion="的那一行然后用awk提取其后的值
PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}') PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}')
echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >" echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >"
## 设新的 WinBoll 标签 ## 设新的 WinBoLL 标签
# 脚本调试时使用 # 脚本调试时使用
#tag="projectname-v7.6.4-test1" #tag="projectname-v7.6.4-test1"
# 正式设置标签时使用 # 正式设置标签时使用
tag=$1"-v"${PUBLISH_VERSION} tag=$1"-v"${PUBLISH_VERSION}
echo "< WinBoll Tag To: $tag >"; echo "< WinBoLL Tag To: $tag >";
# 检查是否已经添加了 WinBoll Tag # 检查是否已经添加了 WinBoLL Tag
if [ "$(git tag -l ${tag})" == "${tag}" ]; then if [ "$(git tag -l ${tag})" == "${tag}" ]; then
echo -e "< WinBoll Tag ${tag} exist! >" echo -e "< WinBoLL Tag ${tag} exist! >"
return 1 # WinBoll标签重复 return 1 # WinBoLL标签重复
fi fi
# 添加WinBoll标签 # 添加WinBoLL标签
git tag -a ${tag} -F $1/app_update_description.txt git tag -a ${tag} -F $1/app_update_description.txt
return 0 return 0
} }
@@ -119,22 +119,22 @@ if [[ $? -eq 0 ]]; then
echo $result echo $result
# 发布应用 # 发布应用
echo "Publishing WinBoll APK ..." echo "Publishing WinBoLL APK ..."
# 脚本调试时使用 # 脚本调试时使用
#bash gradlew :$1:assembleBetaDebug #bash gradlew :$1:assembleBetaDebug
# 正式发布 # 正式发布
bash gradlew :$1:assembleStageRelease bash gradlew :$1:assembleStageRelease
echo "Publishing WinBoll APK OK." echo "Publishing WinBoLL APK OK."
# 添加 WinBoll 标签 # 添加 WinBoLL 标签
result=$(addWinBollTag $1) result=$(addWinBoLLTag $1)
echo $result echo $result
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo $result echo $result
# WinBoll 标签添加成功 # WinBoLL 标签添加成功
else else
echo -e "${0}: addWinBollTag $1\n${result}\nAdd WinBoll tag cancel." echo -e "${0}: addWinBoLLTag $1\n${result}\nAdd WinBoLL tag cancel."
exit 1 # addWinBollTag 异常 exit 1 # addWinBoLLTag 异常
fi fi
# 添加 GitHub 工作流标签 # 添加 GitHub 工作流标签

View File

@@ -38,24 +38,24 @@ function askAddWorkflowsTag {
fi fi
} }
function addWinBollTag { function addWinBoLLTag {
# 就读取脚本 .winboll/winboll_app_build.gradle 生成的 publishVersion。 # 就读取脚本 .winboll/winboll_app_build.gradle 生成的 publishVersion。
# 如果文件中有 publishVersion 这一项, # 如果文件中有 publishVersion 这一项,
# 使用grep找到包含"publishVersion="的那一行然后用awk提取其后的值 # 使用grep找到包含"publishVersion="的那一行然后用awk提取其后的值
PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}') PUBLISH_VERSION=$(grep -o "publishVersion=.*" $1/build.properties | awk -F '=' '{print $2}')
echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >" echo "< $1/build.properties publishVersion : ${PUBLISH_VERSION} >"
## 设新的 WinBoll 标签 ## 设新的 WinBoLL 标签
# 脚本调试时使用 # 脚本调试时使用
#tag="v7.6.4-test1" #tag="v7.6.4-test1"
# 正式调试版设置标签时使用 # 正式调试版设置标签时使用
tag=$1"-v"${PUBLISH_VERSION}"-debug" tag=$1"-v"${PUBLISH_VERSION}"-debug"
echo "< WinBoll Tag To: $tag >"; echo "< WinBoLL Tag To: $tag >";
# 检查是否已经添加了 WinBoll Tag # 检查是否已经添加了 WinBoLL Tag
if [ "$(git tag -l ${tag})" == "${tag}" ]; then if [ "$(git tag -l ${tag})" == "${tag}" ]; then
echo -e "< WinBoll Tag ${tag} exist! >" echo -e "< WinBoLL Tag ${tag} exist! >"
return 1 # WinBoll标签重复 return 1 # WinBoLL标签重复
fi fi
# 添加WinBoll标签 # 添加WinBoLL标签
git tag -a ${tag} -F $1/app_update_description.txt git tag -a ${tag} -F $1/app_update_description.txt
return 0 return 0
} }
@@ -119,22 +119,22 @@ if [[ $? -eq 0 ]]; then
echo $result echo $result
# 发布应用 # 发布应用
echo "Publishing WinBoll Debug APK ..." echo "Publishing WinBoLL Debug APK ..."
# 脚本调试时使用 # 脚本调试时使用
#bash gradlew :$1:assembleBetaDebug #bash gradlew :$1:assembleBetaDebug
# 正式发布调试版 # 正式发布调试版
bash gradlew :$1:assembleStageDebug bash gradlew :$1:assembleStageDebug
echo "Publishing WinBoll Debug APK OK." echo "Publishing WinBoLL Debug APK OK."
# 添加 WinBoll 标签 # 添加 WinBoLL 标签
result=$(addWinBollTag $1) result=$(addWinBoLLTag $1)
echo $result echo $result
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo $result echo $result
# WinBoll 标签添加成功 # WinBoLL 标签添加成功
else else
echo -e "${0}: addWinBollTag $1\n${result}\nAdd WinBoll tag cancel." echo -e "${0}: addWinBoLLTag $1\n${result}\nAdd WinBoLL tag cancel."
exit 1 # addWinBollTag 异常 exit 1 # addWinBoLLTag 异常
fi fi
# 添加 GitHub 工作流标签 # 添加 GitHub 工作流标签

View File

@@ -8,7 +8,7 @@ if [ -z "$1" ]; then
fi fi
## 正式发布使用 ## 正式发布使用
git pull && bash gradlew :$1:publishReleasePublicationToWinBollReleaseRepository && bash .winboll/bashCommitLibReleaseBuildFlagInfo.sh $1 git pull && bash gradlew :$1:publishReleasePublicationToWinBoLLReleaseRepository && bash .winboll/bashCommitLibReleaseBuildFlagInfo.sh $1
## 调试使用 ## 调试使用
#bash gradlew :$1:publishSnapshotWinBollPublicationToWinBollSnapshotRepository && bash .winboll/bashCommitLibReleaseBuildFlagInfo.sh $1 #bash gradlew :$1:publishSnapshotWinBoLLPublicationToWinBoLLSnapshotRepository && bash .winboll/bashCommitLibReleaseBuildFlagInfo.sh $1

View File

@@ -1,4 +1,4 @@
// WinBoll 应用签名配置 // WinBoLL 应用签名配置
// //
android { android {
@@ -31,18 +31,18 @@ android {
} }
} }
flavorDimensions "WinBollApp" flavorDimensions "WinBoLLApp"
productFlavors { productFlavors {
beta { beta {
// 检查编译标志位配置 // 检查编译标志位配置
assert (winbollBuildProps['buildCount'] != null) assert (winbollBuildProps['buildCount'] != null)
dimension "WinBollApp" dimension "WinBoLLApp"
applicationIdSuffix ".beta" applicationIdSuffix ".beta"
LocalDateTime localDateTimeNow = LocalDateTime.now(ZoneId.of("Asia/Shanghai")); LocalDateTime localDateTimeNow = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
versionNameSuffix "-beta" + winbollBuildProps['buildCount'] + "_" + localDateTimeNow.format('mmss') versionNameSuffix "-beta" + winbollBuildProps['buildCount'] + "_" + localDateTimeNow.format('mmss')
} }
stage { stage {
dimension "WinBollApp" dimension "WinBoLLApp"
} }
} }
@@ -61,7 +61,7 @@ android {
} }
// //
// WinBoll 应用包输出配置 // WinBoLL 应用包输出配置
// 1. 配置 Stage Release 版应用包输出 // 1. 配置 Stage Release 版应用包输出
// 2. 配置 Beta Debug 版应用包输出 // 2. 配置 Beta Debug 版应用包输出
// //
@@ -74,13 +74,13 @@ android {
//def outputFileName="${rootProject.name}_${versionName}.apk" //def outputFileName="${rootProject.name}_${versionName}.apk"
def outputFileName=project.rootDir.name + "_${versionName}.apk" def outputFileName=project.rootDir.name + "_${versionName}.apk"
// 创建 WinBoll Studio 发布接口文件夹 // 创建 WinBoLL Studio 发布接口文件夹
File fWinBollStudioDir = file("/sdcard/WinBollStudio/APKs"); File fWinBoLLStudioDir = file("/sdcard/WinBoLLStudio/APKs");
if(!fWinBollStudioDir.exists()) { if(!fWinBoLLStudioDir.exists()) {
//fWinBollStudioDir.mkdirs(); //fWinBoLLStudioDir.mkdirs();
// 如果没有发布接口文件就不用进行APK发布和源码管理操作 // 如果没有发布接口文件就不用进行APK发布和源码管理操作
// 当前编译环境不是 WinBoll 主机, 以下将忽略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.' println 'The current compilation environment is not in WinBoLL host, and the following APK publishing and source management operations will be ignore.'
} else { } else {
/// WINBOLL 主机的 APK 发布和源码管理操作 /// /// WINBOLL 主机的 APK 发布和源码管理操作 ///
variant.getAssembleProvider().get().doFirst { variant.getAssembleProvider().get().doFirst {
@@ -91,15 +91,15 @@ android {
// //
variant.getAssembleProvider().get().doLast { variant.getAssembleProvider().get().doLast {
variant.outputs.forEach{ file-> variant.outputs.forEach{ file->
// 如果正在调试,就拷贝到 WinBoll 备份管理文件夹 // 如果正在调试,就拷贝到 WinBoLL 备份管理文件夹
// //
if(variant.flavorName == "beta"&&variant.buildType.name == "debug"){ if(variant.flavorName == "beta"&&variant.buildType.name == "debug"){
//File outBuildBckDir = new File(fWinBollStudioDir, "/${rootProject.name}/${variant.buildType.name}") //File outBuildBckDir = new File(fWinBoLLStudioDir, "/${rootProject.name}/${variant.buildType.name}")
File outBuildBckDir = new File(fWinBollStudioDir, "/" + project.rootDir.name + "/${variant.buildType.name}") File outBuildBckDir = new File(fWinBoLLStudioDir, "/" + project.rootDir.name + "/${variant.buildType.name}")
// 创建目标路径目录 // 创建目标路径目录
if(!outBuildBckDir.exists()) { if(!outBuildBckDir.exists()) {
outBuildBckDir.mkdirs(); outBuildBckDir.mkdirs();
println "Output Folder Created.(WinBollStudio) : " + outBuildBckDir.getAbsolutePath() println "Output Folder Created.(WinBoLLStudio) : " + outBuildBckDir.getAbsolutePath()
} }
if(outBuildBckDir.exists()) { if(outBuildBckDir.exists()) {
copy{ copy{
@@ -108,7 +108,7 @@ android {
rename { rename {
String fileName -> "${outputFileName}" String fileName -> "${outputFileName}"
} }
println "Output APK (WinBollStudio): " + outBuildBckDir.getAbsolutePath() + "/${outputFileName}" println "Output APK (WinBoLLStudio): " + outBuildBckDir.getAbsolutePath() + "/${outputFileName}"
} }
// 检查编译标志位配置 // 检查编译标志位配置
assert (winbollBuildProps['buildCount'] != null) assert (winbollBuildProps['buildCount'] != null)
@@ -137,7 +137,7 @@ android {
} }
} }
// 如果正在发布,就拷贝到 WinBoll 标签管理文件夹 // 如果正在发布,就拷贝到 WinBoLL 标签管理文件夹
// //
if((variant.flavorName == "stage"&&variant.buildType.name == "debug") if((variant.flavorName == "stage"&&variant.buildType.name == "debug")
|| (variant.flavorName == "stage"&&variant.buildType.name == "release")){ || (variant.flavorName == "stage"&&variant.buildType.name == "release")){
@@ -151,8 +151,8 @@ android {
String szCommonTagAPKName = project.rootDir.name + "_" + szShortVersionName + ".apk" String szCommonTagAPKName = project.rootDir.name + "_" + szShortVersionName + ".apk"
println "CommonTagAPKName is : " + szCommonTagAPKName println "CommonTagAPKName is : " + szCommonTagAPKName
//File outTagDir = new File(fWinBollStudioDir, "/${rootProject.name}/tag/") //File outTagDir = new File(fWinBoLLStudioDir, "/${rootProject.name}/tag/")
File outTagDir = new File(fWinBollStudioDir, "/" + project.rootDir.name + "/tag/") File outTagDir = new File(fWinBoLLStudioDir, "/" + project.rootDir.name + "/tag/")
// 创建目标路径目录 // 创建目标路径目录
if(!outTagDir.exists()) { if(!outTagDir.exists()) {
outTagDir.mkdirs(); outTagDir.mkdirs();

View File

@@ -1,4 +1,4 @@
// 本机和 WinBoll Maven 仓库传输配置。 // 本机和 WinBoLL Maven 仓库传输配置。
// //
def getDefaultVersion(){ def getDefaultVersion(){
@@ -9,12 +9,12 @@ def getDefaultVersion(){
} }
def siteUrl = 'https://winboll.cc/?page=studio/details.php&app=${rootProject.name}' // 项目主页 def siteUrl = 'https://winboll.cc/?page=studio/details.php&app=${rootProject.name}' // 项目主页
def gitUrl = 'https://gitea.winboll.cc/WinBoll/${rootProject.name}' // 项目的git地址 def gitUrl = 'https://gitea.winboll.cc/WinBoLL/${rootProject.name}' // 项目的git地址
def DefaultGroupId = 'cc.winboll.studio' // 类库所有者groupId def DefaultGroupId = 'cc.winboll.studio' // 类库所有者groupId
def DefaultVersion = getDefaultVersion() // 版本号 def DefaultVersion = getDefaultVersion() // 版本号
def DeveloperId='zhangsken' // 开发者账号 def DeveloperId='zhangsken' // 开发者账号
def DeveloperName='ZhanGSKen' // 开发者名称 def DeveloperName='ZhanGSKen' // 开发者名称
def DeveloperEMail='ZhanGSKen@QQ.COM' // 开发者邮箱地址 def DeveloperEMail='zhangsken@188.com' // 开发者邮箱地址
def LicenseName='The Apache Software License, Version 2.0' def LicenseName='The Apache Software License, Version 2.0'
def LicenseUrl='http://www.apache.org/licenses/LICENSE-2.0.txt' def LicenseUrl='http://www.apache.org/licenses/LICENSE-2.0.txt'
@@ -27,10 +27,10 @@ afterEvaluate {
properties.load(file("${RootProjectDir}/${winbollFilePath}").newDataInputStream()) properties.load(file("${RootProjectDir}/${winbollFilePath}").newDataInputStream())
def NexusUserName = properties.getProperty("Nexus.name") def NexusUserName = properties.getProperty("Nexus.name")
def NexusPassword = properties.getProperty("Nexus.password") def NexusPassword = properties.getProperty("Nexus.password")
// WinBoll Release 仓库 // WinBoLL Release 仓库
maven{ maven{
//仓库的名字和地址 //仓库的名字和地址
name = "WinBollRelease" name = "WinBoLLRelease"
url="https://nexus.winboll.cc/repository/maven-releases/" url="https://nexus.winboll.cc/repository/maven-releases/"
// 仓库用户名密码 // 仓库用户名密码
credentials { credentials {
@@ -38,10 +38,10 @@ afterEvaluate {
password = NexusPassword password = NexusPassword
} }
} }
// WinBoll Snapshot 仓库 // WinBoLL Snapshot 仓库
maven{ maven{
//仓库的名字和地址 //仓库的名字和地址
name = "WinBollSnapshot" name = "WinBoLLSnapshot"
url="https://nexus.winboll.cc/repository/maven-snapshots/" url="https://nexus.winboll.cc/repository/maven-snapshots/"
// 仓库用户名密码 // 仓库用户名密码
credentials { credentials {
@@ -101,9 +101,9 @@ afterEvaluate {
} }
} }
// WinBoll Maven Release 仓库传输任务 // WinBoLL Maven Release 仓库传输任务
// //
releaseWinBoll(MavenPublication) { releaseWinBoLL(MavenPublication) {
// 需要使用的变体假设有free和pay两个变体可以选择一个 // 需要使用的变体假设有free和pay两个变体可以选择一个
//from components.free //from components.free
@@ -154,9 +154,9 @@ afterEvaluate {
} // 创建名为 release 的任务结束 } // 创建名为 release 的任务结束
// WinBoll Maven Snapshot 仓库传输任务 // WinBoLL Maven Snapshot 仓库传输任务
// //
snapshotWinBoll(MavenPublication) { snapshotWinBoLL(MavenPublication) {
// 需要使用的变体假设有free和pay两个变体可以选择一个 // 需要使用的变体假设有free和pay两个变体可以选择一个
//from components.free //from components.free

127
README.md
View File

@@ -1,23 +1,23 @@
# ☁ ☁ ☁ WinBoll APP ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ # ☁ ☁ ☁ WinBoLL APP ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
# ☁ ☁ 这是 WinBoll 系列 APP 汇总项目。☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ # ☁ ☁ WinBoLL Studio Android 应用开源项目。☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
# ☁ ☁ ☁ WinBoll 网站地址 https://www.winboll.cc/studio/app/ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ # ☁ ☁ ☁ WinBoLL 网站地址 https://www.winboll.cc/ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
## WinBoll 提问 ## WinBoLL 提问
同样是 /sdcard 目录,在开发 Android 应用时, 同样是 /sdcard 目录,在开发 Android 应用时,
能否实现手机编译与电脑编译的源码同步。 能否实现手机编译与电脑编译的源码同步。
☁因而 WinBoll 项目组诞生了。 ☁因而 WinBoLL 项目组诞生了。
## WinBoll 项目组研发计划 ## WinBoLL 项目组研发计划
致力于把 WinBoll-APP 应用在手机端 Android 项目开发。 致力于把 WinBoLL-APP 应用在手机端 Android 项目开发。
也在探索 https://gitea.winboll.cc/<WinBoll 项目组>/APP.git 应用于 WinBoll-APP APK 分发。 也在探索 https://gitea.winboll.cc/<WinBoLL 项目组>/APP.git 应用于 WinBoLL-APP APK 分发。
更想进阶 https://github.com/<WinBoll 项目组>/APP.git 应用于 WinBoll-APP Beta APK 分发。 更想进阶 https://github.com/<WinBoLL 项目组>/APP.git 应用于 WinBoLL-APP Beta APK 分发。
## WinBoll-APP 汗下... ## WinBoLL-APP 汗下...
#### ☁应用何置如此呢。且观用户云云。 #### ☁应用何置如此呢。且观用户云云。
#### ☁ 正当下 ☁ ### #### ☁ 正当下 ☁ ###
#### ☁ 且容傻家叙说 ☁ WinBoll-APP 应用场景 #### ☁ 且容傻家叙说 ☁ WinBoLL-APP 应用场景
### ☁ WinBoll 设备资源概述 ### ☁ WinBoLL 设备资源概述
#### ☁ 1. Raid Disk. #### ☁ 1. Raid Disk.
概述:这是一个矩阵存储类设备。 概述:这是一个矩阵存储类设备。
优点:该设备具有数据容错存储功能, 优点:该设备具有数据容错存储功能,
@@ -40,74 +40,79 @@
设备位于操作系统内部文件系统。 设备位于操作系统内部文件系统。
数据持久性与操作系统挂钩。 数据持久性与操作系统挂钩。
#### ☁ 4. WinBoll 用户资源概述。 #### ☁ 4. WinBoLL 用户资源概述。
1> /home/<用户名> 位于 WinBoll 操作系统目录下。 1> /home/<用户名> 位于 WinBoLL 操作系统目录下。
2> /rdisk/<用户名> 挂载用户 Raid Disk. 2> /rdisk/<用户名> 挂载用户 Raid Disk.
3> /data/<用户名> 挂载用户 Data Disk. 3> /data/<用户名> 挂载用户 Data Disk.
4> /sdcard/<用户名> 挂载用户 SSD Disk. 4> /sdcard/<用户名> 挂载用户 SSD Disk.
#### ☁ 5. WinBoll-APP 用户资源概述。 #### ☁ 5. WinBoLL-APP 用户资源概述。
1> /sdcard 挂载用户手机 SD 存储/storage/emulated/0 1> /sdcard 挂载用户手机 SD 存储/storage/emulated/0
### ☁ 稍稍歇 ☁ ### ### ☁ 稍稍歇 ☁ ###
### ☁ 急急停 ☁ WinBoll 应用前置条件 ### ☁ 急急停 ☁ WinBoLL 应用前置条件
☁ WinBoll 主机建立 1Panel MySQL 应用。 ☁ WinBoLL 主机建立 1Panel MySQL 应用。
☁ WinBoll 主机建立 1Panel Gitea 应用。 ☁ WinBoLL 主机建立 1Panel Gitea 应用。
☁ WinBoll 主机设置 WinBoll 应用为非登录状态。 ☁ WinBoLL 主机设置 WinBoLL 应用为非登录状态。
☁ WinBoll 主机建立 WinBoll 账户与 WinBoll 用户组。 ☁ WinBoLL 主机建立 WinBoLL 账户与 WinBoLL 用户组。
☁ WinBoll 账户 User ID 为: J。 ☁ WinBoLL 账户 User ID 为: J。
☁ WinBoll 用户组 Group ID 为: Studio。 ☁ WinBoLL 用户组 Group ID 为: Studio。
☁ WinBoll 主机 WinBoll 1Panel Gitea 建立 WinBoll 工作组。 ☁ WinBoLL 主机 WinBoLL 1Panel Gitea 建立 WinBoLL 工作组。
☁ WinBoll 主机 WinBoll 1Panel Gitea 用户项目 APK 编译输出目录为 /sdcard/WinBollStudio/<用户名>/APKs/ ☁ WinBoLL 主机 WinBoLL 1Panel Gitea 用户项目 APK 编译输出目录为 /sdcard/WinBoLLStudio/<用户名>/APKs/
☁ WinBoll 项目配置文件示例为 "<WinBoll 项目根目录>/.winboll/winboll.properties-demo"(WinBoll 项目已设置) ☁ WinBoLL 项目配置文件示例为 "<WinBoLL 项目根目录>/.winboll/winboll.properties-demo"(WinBoLL 项目已设置)
☁ WinBoll 项目配置文件为 "<WinBoll 项目根目录>/.winboll/winboll.properties" ☁ WinBoLL 项目配置文件为 "<WinBoLL 项目根目录>/.winboll/winboll.properties"
☁ WinBoll 项目配置文件设定为源码提交时忽略。(WinBoll 项目已设置) ☁ WinBoLL 项目配置文件设定为源码提交时忽略。(WinBoLL 项目已设置)
☁ Gradle 项目配置文件示例为 "<WinBoll 项目根目录>/.winboll/local.properties-demo"(WinBoll 项目已设置) ☁ Gradle 项目配置文件示例为 "<WinBoLL 项目根目录>/.winboll/local.properties-demo"(WinBoLL 项目已设置)
☁ Gradle 项目配置文件为 "<WinBoll 项目根目录>/local.properties"(WinBoll 项目已设置) ☁ Gradle 项目配置文件为 "<WinBoLL 项目根目录>/local.properties"(WinBoLL 项目已设置)
☁ Gradle 项目配置文件设定为源码提交时忽略。(WinBoll 项目已设置) ☁ Gradle 项目配置文件设定为源码提交时忽略。(WinBoLL 项目已设置)
### ☁ 登高处 ☁ WinBoll 应用需求规划 ### ☁ 登高处 ☁ WinBoLL 应用需求规划
☁ WinBoll 主机建立 WinBoll 客户端用户数据库为 MySQL winbollclient 数据库。 ☁ WinBoLL 主机建立 WinBoLL 客户端用户数据库为 MySQL winbollclient 数据库。
☁ WinBoll 主机设置 WinBoll 客户端用户信息存储在 winbollclient 数据库中。 ☁ WinBoLL 主机设置 WinBoLL 客户端用户信息存储在 winbollclient 数据库中。
☁ MySQL winbollclient 数据库中 ☁ MySQL winbollclient 数据库中
WinBoll 客户端用户信息设定为: WinBoLL 客户端用户信息设定为:
<用户名, 验证密码, 验证邮箱, 验证手机, 唯一存储令牌Token, 备用验证邮箱>。 <用户名, 验证密码, 验证邮箱, 验证手机, 唯一存储令牌Token, 备用验证邮箱>。
☁ WinBoll 项目源码仓库托管在 WinBoll 1Panel Gitea 目录 /opt/1panel/apps/gitea/gitea/data/git/repositories/studio/app.git中。 ☁ WinBoLL 项目源码仓库托管在 WinBoLL 1Panel Gitea 目录 /opt/1panel/apps/gitea/gitea/data/git/repositories/studio/app.git中。
☁ WinBoll 主机提供 WinBoll 1Panel Gitea 应用的 WinBoll 项目源码仓库存取功能。Gitea 应用已提供) ☁ WinBoLL 主机提供 WinBoLL 1Panel Gitea 应用的 WinBoLL 项目源码仓库存取功能。Gitea 应用已提供)
☁ WinBoll 主机提供 WinBoll Gitea 项目仓库存档功能。Gitea 应用已提供) ☁ WinBoLL 主机提供 WinBoLL Gitea 项目仓库存档功能。Gitea 应用已提供)
☁ 提供 WinBoll 客户端用户登录功能。Gitea 应用已提供) ☁ 提供 WinBoLL 客户端用户登录功能。Gitea 应用已提供)
### ☁ 看远方 ☁ ### ### ☁ 看远方 ☁ ###
### ☁ 心忧虑 ☁ WinBoll-APP 应用前置需求 ### ☁ 心忧虑 ☁ WinBoLL-APP 应用前置需求
☁ WinBoll-APP WinBoll 项目根目录设定为手机的 /sdcard/WinBollStudio/Sources 目录。(需要用户手动建立文件夹) ☁ WinBoLL-APP WinBoLL 项目根目录设定为手机的 /sdcard/WinBoLLStudio/Sources 目录。(需要用户手动建立文件夹)
☁ WinBoll-APP 具有手机 /sdcard/WinBoll 目录的存储权限。(需要手机操作系统授权) ☁ WinBoLL-APP 具有手机 /sdcard/WinBoLL 目录的存储权限。(需要手机操作系统授权)
☁ WinBoll-APP WinBoll 项目仓库源码存储路径为 /sdcard/WinBollStudio/Sources/APP.git需要用户手动建立文件夹 ☁ WinBoLL-APP WinBoLL 项目仓库源码存储路径为 /sdcard/WinBoLLStudio/Sources/APP.git需要用户手动建立文件夹
☁ WinBoll-APP 项目 APK 编译输出目录为 /sdcard/WinBollStudio/APKs/ ☁ WinBoLL-APP 项目 APK 编译输出目录为 /sdcard/WinBoLLStudio/APKs/
☁ WinBoll-APP 应用签名验证可定制化。WinBoll 项目已提供) ☁ WinBoLL-APP 应用签名验证可定制化。WinBoLL 项目已提供)
☁ WinBoll-APP 与系列衍生 APP 应用共享 cc.winboll.studio 命名空间资源。WinBoll 项目已提供) ☁ WinBoLL-APP 与系列衍生 APP 应用共享 cc.winboll.studio 命名空间资源。WinBoLL 项目已提供)
☁ WinBoll-APP 用户客户端信息存储在命名空间为 WinBoll APP MySQLLite 应用的 winbollappclient 数据库中。 ☁ WinBoLL-APP 用户客户端信息存储在命名空间为 WinBoLL APP MySQLLite 应用的 winbollappclient 数据库中。
☁ WinBoll-APP MySQLLite 应用的 winbollappclient 数据库中, ☁ WinBoLL-APP MySQLLite 应用的 winbollappclient 数据库中,
WinBoll 用户客户端信息设定为: WinBoLL 用户客户端信息设定为:
<用户名, 唯一存储令牌Token>。 <用户名, 唯一存储令牌Token>。
### ☁ 云游四方 ☁ ### ### ☁ 云游四方 ☁ ###
### ☁ 呔! ☁ WinBoll-APP 应用需求规划 ### ☁ 呔! ☁ WinBoLL-APP 应用需求规划
WinBoll-APP 提供手机目录 /sdcard/WinBollStudio/Sources 的 WinBoll 项目源码管理功能。 如要使用 WinBoLL Android 项目的 Gradle 编译功能,则需要设置以下两个文件夹。
☁ 1. 则需要建立数据存储目录 /sdcard/WinBoLLStudio/APKs。
WinBoLL 项目源码编译出来的安装包会拷贝一份到 /sdcard/WinBoLLStudio/APKs 目录下。
☁ 2. 则需要建立数据存储目录 /sdcard/AppProjects。
WinBoLL 项目源码编译出来的安装包会拷贝一份并命名 "app.apk" 的安装文件为到 /sdcard/AppProjects 目录下。
### ☁ 吁! ☁ WinBoll-APP 共享计划前景
☁ WinBoll-APP 将会实现 https://winboll.cc/api 访问功能。
☁ WinBoll-APP 将会实现手机端 Android 应用的开发与管理功能。
## ☁ WinBoll ☁ WinBoll 主机忧虑 ###吁! ☁ WinBoLL-APP 共享计划前景
☁ WinBoll 将会提供 gitea.winboll.cc 域名用户注册登录功能。 ☁ WinBoLL-APP 将会实现 https://winboll.cc/api 访问功能。
☁ WinBoll 将会提供 WinBoll-APP 及其衍生应用的 Gitea 仓库管理服务 ☁ WinBoLL-APP 将会实现手机端 Android 应用的开发与管理功能
☁ WinBoll 将会提供 winboll.cc 域名 WinBoll 项目组注册登录功能。
## ☁ WinBoLL ☁ WinBoLL 主机忧虑
☁ WinBoLL 将会提供 gitea.winboll.cc 域名用户注册登录功能。
☁ WinBoLL 将会提供 WinBoLL-APP 及其衍生应用的 Gitea 仓库管理服务。
☁ WinBoLL 将会提供 winboll.cc 域名 WinBoLL 项目组注册登录功能。
# 本项目要实际运用需要注意以下几个步骤: # 本项目要实际运用需要注意以下几个步骤:
# 在项目根目录下: # 在项目根目录下:
## 1. 项目模块编译环境设置(必须)settings.gradle-demo 要复制为 settings.gradle并取消相应项目模块的注释。 ## 1. 项目模块编译环境设置(必须)settings.gradle-demo 要复制为 settings.gradle并取消相应项目模块的注释。
## 2. 项目 Android SDK 编译环境设置(可选)local.properties-demo 要复制为 local.properties并按需要设置 Android SDK 目录。 ## 2. 项目 Android SDK 编译环境设置(可选)local.properties-demo 要复制为 local.properties并按需要设置 Android SDK 目录。
## 3. 类库型模块编译环境设置(可选)winboll.properties-demo 要复制为 winboll.properties并按需要设置 WinBoll Maven 库登录用户信息。 ## 3. 类库型模块编译环境设置(可选)winboll.properties-demo 要复制为 winboll.properties并按需要设置 WinBoLL Maven 库登录用户信息。
# ☆类库型项目编译方法 # ☆类库型项目编译方法
@@ -116,12 +121,12 @@
设置属性 libraryProject=<类库项目模块文件夹名称> 设置属性 libraryProject=<类库项目模块文件夹名称>
### 再编译测试项目 ### 再编译测试项目
$ bash .winboll/bashPublishAPKAddTag.sh <应用项目模块文件夹名称> $ bash .winboll/bashPublishAPKAddTag.sh <应用项目模块文件夹名称>
#### 测试项目编译后,编译器会复制一份 APK 到以下路径:"/sdcard/WinBollStudio/APKs/<项目根目录名称>/tag/" 文件夹。 #### 测试项目编译后,编译器会复制一份 APK 到以下路径:"/sdcard/WinBoLLStudio/APKs/<项目根目录名称>/tag/" 文件夹。
### 最后编译类库项目 ### 最后编译类库项目
$ bash .winboll/bashPublishLIBAddTag.sh <类库项目模块文件夹名称> $ bash .winboll/bashPublishLIBAddTag.sh <类库项目模块文件夹名称>
#### 类库模块编译命令执行后,编译器会发布到 WinBoll Nexus Maven 库Maven 库地址可以参阅根项目目录配置 build.gradle 文件。 #### 类库模块编译命令执行后,编译器会发布到 WinBoLL Nexus Maven 库Maven 库地址可以参阅根项目目录配置 build.gradle 文件。
# ☆应用型项目编译方法 # ☆应用型项目编译方法
## 直接调用以下命令编译应用型项目 ## 直接调用以下命令编译应用型项目
$ bash .winboll/bashPublishAPKAddTag.sh <应用项目模块文件夹名称> $ bash .winboll/bashPublishAPKAddTag.sh <应用项目模块文件夹名称>
#### 应用模块编译命令执行后,编译器会复制一份 APK 到以下路径:"/sdcard/WinBollStudio/APKs/<项目根目录名称>/tag/" 文件夹。 #### 应用模块编译命令执行后,编译器会复制一份 APK 到以下路径:"/sdcard/WinBoLLStudio/APKs/<项目根目录名称>/tag/" 文件夹。

View File

@@ -24,12 +24,12 @@ android {
defaultConfig { defaultConfig {
applicationId "cc.winboll.studio.aes" applicationId "cc.winboll.studio.aes"
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 29 targetSdkVersion 30
versionCode 1 versionCode 1
// versionName 更新后需要手动设置 // versionName 更新后需要手动设置
// 项目模块目录的 build.gradle 文件的 stageCount=0 // 项目模块目录的 build.gradle 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.2" versionName "15.6"
if(true) { if(true) {
versionName = genVersionName("${versionName}") versionName = genVersionName("${versionName}")
} }

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Thu Apr 03 11:14:05 HKT 2025 #Tue Apr 29 15:14:21 HKT 2025
stageCount=7 stageCount=1
libraryProject=libaes libraryProject=libaes
baseVersion=15.2 baseVersion=15.6
publishVersion=15.2.6 publishVersion=15.6.0
buildCount=0 buildCount=0
baseBetaVersion=15.2.7 baseBetaVersion=15.6.1

View File

@@ -10,14 +10,13 @@ import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libaes.winboll.APPInfo; import cc.winboll.studio.libaes.winboll.APPInfo;
import cc.winboll.studio.libaes.winboll.AboutView; import cc.winboll.studio.libaes.winboll.AboutView;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
public class AboutActivity extends WinBollActivity implements IWinBollActivity { public class AboutActivity extends WinBoLLActivity implements IWinBoLLActivity {
public static final String TAG = "AboutActivity"; public static final String TAG = "AboutActivity";
@@ -64,13 +63,13 @@ public class AboutActivity extends WinBollActivity implements IWinBollActivity {
); );
layout.addView(aboutView, params); layout.addView(aboutView, params);
GlobalApplication.getWinBollActivityManager().add(this); GlobalApplication.getWinBoLLActivityManager().add(this);
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
GlobalApplication.getWinBollActivityManager().registeRemove(this); GlobalApplication.getWinBoLLActivityManager().registeRemove(this);
} }
public AboutView CreateAboutView() { public AboutView CreateAboutView() {

View File

@@ -8,6 +8,7 @@ package cc.winboll.studio.aes;
import android.view.Gravity; import android.view.Gravity;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import com.hjq.toast.ToastUtils; import com.hjq.toast.ToastUtils;
import com.hjq.toast.style.WhiteToastStyle;
public class App extends GlobalApplication { public class App extends GlobalApplication {
@@ -21,8 +22,8 @@ public class App extends GlobalApplication {
// 初始化 Toast 框架 // 初始化 Toast 框架
ToastUtils.init(this); ToastUtils.init(this);
// 设置 Toast 布局样式 // 设置 Toast 布局样式
ToastUtils.setView(R.layout.view_toast); //ToastUtils.setView(R.layout.view_toast);
//ToastUtils.setStyle(new WhiteToastStyle()); ToastUtils.setStyle(new WhiteToastStyle());
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200); ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
} }

View File

@@ -25,12 +25,12 @@ import cc.winboll.studio.libaes.unittests.TestAToolbarActivity;
import cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity; import cc.winboll.studio.libaes.unittests.TestDrawerFragmentActivity;
import cc.winboll.studio.libaes.unittests.TestViewPageFragment; import cc.winboll.studio.libaes.unittests.TestViewPageFragment;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import com.a4455jkjh.colorpicker.ColorPickerDialog; import com.a4455jkjh.colorpicker.ColorPickerDialog;
import com.hjq.toast.ToastUtils; import com.hjq.toast.ToastUtils;
import java.util.ArrayList; import java.util.ArrayList;
public class MainActivity extends DrawerFragmentActivity implements IWinBollActivity { public class MainActivity extends DrawerFragmentActivity implements IWinBoLLActivity {
public static final String TAG = "MainActivity"; public static final String TAG = "MainActivity";
@@ -123,7 +123,7 @@ public class MainActivity extends DrawerFragmentActivity implements IWinBollActi
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
int nItemId = item.getItemId(); int nItemId = item.getItemId();
// if (item.getItemId() == R.id.item_log) { // if (item.getItemId() == R.id.item_log) {
// WinBollActivityManager.getInstance(this).startWinBollActivity(getApplicationContext(), LogActivity.class); // WinBoLLActivityManager.getInstance(this).startWinBoLLActivity(getApplicationContext(), LogActivity.class);
// } else // } else
if (nItemId == R.id.item_atoast) { if (nItemId == R.id.item_atoast) {
Toast.makeText(getApplication(), "item_testatoast", Toast.LENGTH_SHORT).show(); Toast.makeText(getApplication(), "item_testatoast", Toast.LENGTH_SHORT).show();

View File

@@ -5,17 +5,17 @@ import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import cc.winboll.studio.libaes.beans.AESThemeBean; import cc.winboll.studio.libaes.beans.AESThemeBean;
import cc.winboll.studio.libaes.utils.AESThemeUtil; import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import android.view.MenuItem; import android.view.MenuItem;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/30 00:34:02 * @Date 2025/03/30 00:34:02
* @Describe WinBoll 活动窗口通用基类 * @Describe WinBoLL 活动窗口通用基类
*/ */
public class WinBollActivity extends AppCompatActivity implements IWinBollActivity { public class WinBoLLActivity extends AppCompatActivity implements IWinBoLLActivity {
public static final String TAG = "WinBollActivity"; public static final String TAG = "WinBoLLActivity";
protected volatile AESThemeBean.ThemeType mThemeType; protected volatile AESThemeBean.ThemeType mThemeType;

View File

@@ -25,12 +25,12 @@ android {
defaultConfig { defaultConfig {
applicationId "cc.winboll.studio.appbase" applicationId "cc.winboll.studio.appbase"
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 29 targetSdkVersion 30
versionCode 1 versionCode 1
// versionName 更新后需要手动设置 // versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0 // .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.4" versionName "15.7"
if(true) { if(true) {
versionName = genVersionName("${versionName}") versionName = genVersionName("${versionName}")
} }

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Sun Apr 27 10:05:57 HKT 2025 #Tue Apr 29 04:20:48 GMT 2025
stageCount=8 stageCount=4
libraryProject=libappbase libraryProject=libappbase
baseVersion=15.4 baseVersion=15.7
publishVersion=15.4.7 publishVersion=15.7.3
buildCount=0 buildCount=5
baseBetaVersion=15.4.8 baseBetaVersion=15.7.4

View File

@@ -5,7 +5,7 @@
<application <application
android:name=".App" android:name=".App"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_miapp"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/MyAPPBaseTheme" android:theme="@style/MyAPPBaseTheme"
android:resizeableActivity="true" android:resizeableActivity="true"

View File

@@ -29,7 +29,7 @@ android {
// versionName 更新后需要手动设置 // versionName 更新后需要手动设置
// 项目模块目录的 build.gradle 文件的 stageCount=0 // 项目模块目录的 build.gradle 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.3" versionName "15.2"
if(true) { if(true) {
versionName = genVersionName("${versionName}") versionName = genVersionName("${versionName}")
} }

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Sun Apr 27 11:19:49 HKT 2025 #Sat Mar 29 12:14:55 HKT 2025
stageCount=1 stageCount=2
libraryProject=libapputils libraryProject=libapputils
baseVersion=15.3 baseVersion=15.2
publishVersion=15.3.0 publishVersion=15.2.1
buildCount=0 buildCount=0
baseBetaVersion=15.3.1 baseBetaVersion=15.2.2

View File

@@ -8,11 +8,12 @@ package cc.winboll.studio.apputils;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager; import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class WinBollActivityBase extends Activity implements IWinBollActivity { public class WinBollActivityBase extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "WinBollActivityBase"; public static final String TAG = "WinBollActivityBase";

View File

@@ -7,9 +7,9 @@ buildscript {
maven { url "file:///sdcard/.m2/repository" } maven { url "file:///sdcard/.m2/repository" }
// Nexus Maven 库地址 // Nexus Maven 库地址
// "WinBoll Release" // "WinBoLL Release"
maven { url "https://nexus.winboll.cc/repository/maven-public/" } maven { url "https://nexus.winboll.cc/repository/maven-public/" }
// "WinBoll Snapshot" // "WinBoLL Snapshot"
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" } maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
maven { url 'https://maven.aliyun.com/repository/public/' } maven { url 'https://maven.aliyun.com/repository/public/' }
@@ -32,9 +32,9 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
// Nexus Maven 库地址 // Nexus Maven 库地址
// "WinBoll Release" // "WinBoLL Release"
maven { url "https://nexus.winboll.cc/repository/maven-public/" } maven { url "https://nexus.winboll.cc/repository/maven-public/" }
// "WinBoll Snapshot" // "WinBoLL Snapshot"
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" } maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
maven { url 'https://maven.aliyun.com/repository/public/' } maven { url 'https://maven.aliyun.com/repository/public/' }

View File

@@ -9,7 +9,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 29 targetSdkVersion 30
} }
buildTypes { buildTypes {
release { release {
@@ -45,12 +45,12 @@ dependencies {
api 'com.squareup.okhttp3:okhttp:4.4.1' api 'com.squareup.okhttp3:okhttp:4.4.1'
// AndroidX 类库 // AndroidX 类库
api 'androidx.appcompat:appcompat:1.1.0' api 'androidx.appcompat:appcompat:1.1.0'
api 'com.google.android.material:material:1.4.0' //api 'com.google.android.material:material:1.4.0'
//api 'androidx.viewpager:viewpager:1.0.0' //api 'androidx.viewpager:viewpager:1.0.0'
//api 'androidx.vectordrawable:vectordrawable:1.1.0' //api 'androidx.vectordrawable:vectordrawable:1.1.0'
//api 'androidx.vectordrawable:vectordrawable-animated:1.1.0' //api 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
//api 'androidx.fragment:fragment:1.1.0' //api 'androidx.fragment:fragment:1.1.0'
api 'cc.winboll.studio:libapputils:15.2.2' api 'cc.winboll.studio:libapputils:15.3.4'
api 'cc.winboll.studio:libappbase:15.2.2' api 'cc.winboll.studio:libappbase:15.7.6'
} }

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Thu Apr 03 11:13:53 HKT 2025 #Tue Apr 29 15:14:21 HKT 2025
stageCount=7 stageCount=1
libraryProject=libaes libraryProject=libaes
baseVersion=15.2 baseVersion=15.6
publishVersion=15.2.6 publishVersion=15.6.0
buildCount=0 buildCount=0
baseBetaVersion=15.2.7 baseBetaVersion=15.6.1

View File

@@ -17,13 +17,13 @@
<activity android:name="cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity" <activity android:name="cc.winboll.studio.libaes.unittests.TestASupportToolbarActivity"
android:exported="true"/> android:exported="true"/>
<service android:name="cc.winboll.studio.libaes.winboll.WinBollClientService" <service android:name="cc.winboll.studio.libaes.winboll.WinBoLLClientService"
android:exported="true"/> android:exported="true"/>
<service android:name="cc.winboll.studio.libaes.winboll.AssistantService" <service android:name="cc.winboll.studio.libaes.winboll.AssistantService"
android:exported="true"/> android:exported="true"/>
<service android:name="cc.winboll.studio.libaes.winboll.WinBollMail" <service android:name="cc.winboll.studio.libaes.winboll.WinBoLLMail"
android:exported="true"/> android:exported="true"/>
</application> </application>

View File

@@ -29,11 +29,11 @@ import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libaes.views.ADrawerMenuListView; import cc.winboll.studio.libaes.views.ADrawerMenuListView;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import com.baoyz.widget.PullRefreshLayout; import com.baoyz.widget.PullRefreshLayout;
import java.util.ArrayList; import java.util.ArrayList;
public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBollActivity,AdapterView.OnItemClickListener { public abstract class DrawerFragmentActivity extends AppCompatActivity implements IWinBoLLActivity,AdapterView.OnItemClickListener {
public static final String TAG = "DrawerFragmentActivity"; public static final String TAG = "DrawerFragmentActivity";
@@ -177,7 +177,7 @@ public abstract class DrawerFragmentActivity extends AppCompatActivity implement
getString(i); getString(i);
} }
} else if (R.id.item_log == item.getItemId()) { } else if (R.id.item_log == item.getItemId()) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this); GlobalApplication.getWinBoLLActivityManager().startLogActivity(this);
} else if (R.id.item_about == item.getItemId()) { } else if (R.id.item_about == item.getItemId()) {
LogUtils.d(TAG, "onAbout"); LogUtils.d(TAG, "onAbout");
} else if (android.R.id.home == item.getItemId()) { } else if (android.R.id.home == item.getItemId()) {

View File

@@ -7,14 +7,14 @@ import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
/** /**
* @Author ZhanGSKen@QQ.COM * @Author ZhanGSKen@QQ.COM
* @Date 2024/06/15 00:58:10 * @Date 2024/06/15 00:58:10
* @Describe 第二级窗口 * @Describe 第二级窗口
*/ */
public class SecondaryLibraryActivity extends DrawerFragmentActivity implements IWinBollActivity { public class SecondaryLibraryActivity extends DrawerFragmentActivity implements IWinBoLLActivity {
public static final String TAG = "SecondaryLibraryActivity"; public static final String TAG = "SecondaryLibraryActivity";

View File

@@ -11,9 +11,9 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.utils.AESThemeUtil; import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBollActivity { public class TestASupportToolbarActivity extends AppCompatActivity implements IWinBoLLActivity {
public static final String TAG = "TestASupportToolbarActivity"; public static final String TAG = "TestASupportToolbarActivity";

View File

@@ -10,9 +10,9 @@ import android.os.Bundle;
import android.widget.Toolbar; import android.widget.Toolbar;
import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.utils.AESThemeUtil; import cc.winboll.studio.libaes.utils.AESThemeUtil;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
public class TestAToolbarActivity extends Activity implements IWinBollActivity { public class TestAToolbarActivity extends Activity implements IWinBoLLActivity {
public static final String TAG = "TestAToolbarActivity"; public static final String TAG = "TestAToolbarActivity";

View File

@@ -11,16 +11,15 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.R;
import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity;
import cc.winboll.studio.libaes.beans.DrawerMenuBean; import cc.winboll.studio.libaes.beans.DrawerMenuBean;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity; import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity;
import java.util.ArrayList; import java.util.ArrayList;
public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBollActivity { public class TestDrawerFragmentActivity extends DrawerFragmentActivity implements IWinBoLLActivity {
@Override @Override
public Activity getActivity() { public Activity getActivity() {

View File

@@ -41,7 +41,7 @@ public class AESThemeUtil {
activity.setTheme(getThemeTypeID(activity)); activity.setTheme(getThemeTypeID(activity));
} }
/*public static <T extends WinBollActivity> void applyWinBollTheme(T activity) { /*public static <T extends WinBoLLActivity> void applyWinBoLLTheme(T activity) {
activity.setTheme(getThemeTypeID(activity.getApplicationContext())); activity.setTheme(getThemeTypeID(activity.getApplicationContext()));
}*/ }*/
@@ -53,7 +53,7 @@ public class AESThemeUtil {
activity.setTheme(AESThemeBean.getThemeStyleID(themeType)); activity.setTheme(AESThemeBean.getThemeStyleID(themeType));
} }
/*public static <T extends WinBollActivity> void applyWinBollTheme(Activity activity, AESThemeBean.ThemeType themeType) { /*public static <T extends WinBoLLActivity> void applyWinBoLLTheme(Activity activity, AESThemeBean.ThemeType themeType) {
activity.setTheme(AESThemeBean.getThemeStyleID(themeType)); activity.setTheme(AESThemeBean.getThemeStyleID(themeType));
}*/ }*/
@@ -65,7 +65,7 @@ public class AESThemeUtil {
activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu); activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu);
} }
/*public static <T extends WinBollActivity> void inflateWinBollMenu(T activity, Menu menu) { /*public static <T extends WinBoLLActivity> void inflateWinBoLLMenu(T activity, Menu menu) {
activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu); activity.getMenuInflater().inflate(R.menu.toolbar_apptheme, menu);
}*/ }*/
@@ -131,7 +131,7 @@ public class AESThemeUtil {
return false; return false;
} }
public static <T extends AppCompatActivity> boolean onWinBollThemeItemSelected(T activity, MenuItem item) { public static <T extends AppCompatActivity> boolean onWinBoLLThemeItemSelected(T activity, MenuItem item) {
int nThemeStyleID; int nThemeStyleID;
if (R.id.item_depththeme == item.getItemId()) { if (R.id.item_depththeme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH); nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH);
@@ -162,7 +162,7 @@ public class AESThemeUtil {
return false; return false;
} }
public static <T extends DrawerFragmentActivity> boolean onWinBollThemeItemSelected(T activity, MenuItem item) { public static <T extends DrawerFragmentActivity> boolean onWinBoLLThemeItemSelected(T activity, MenuItem item) {
int nThemeStyleID; int nThemeStyleID;
if (R.id.item_depththeme == item.getItemId()) { if (R.id.item_depththeme == item.getItemId()) {
nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH); nThemeStyleID = AESThemeBean.getThemeStyleID(AESThemeBean.ThemeType.DEPTH);

View File

@@ -3,7 +3,7 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/24 15:08:52 * @Date 2025/03/24 15:08:52
* @Describe WinBoll应用介绍视图 * @Describe WinBoLL应用介绍视图
*/ */
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -43,7 +43,7 @@ public class AboutView extends LinearLayout {
Context mContext; Context mContext;
APPInfo mAPPInfo; APPInfo mAPPInfo;
WinBollServiceStatusView mWinBollServiceStatusView; WinBoLLServiceStatusView mWinBoLLServiceStatusView;
OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener; OnRequestDevUserInfoAutofillListener mOnRequestDevUserInfoAutofillListener;
String mszAppName = ""; String mszAppName = "";
String mszAppAPKFolderName = ""; String mszAppAPKFolderName = "";
@@ -57,7 +57,7 @@ public class AboutView extends LinearLayout {
String mszHomePage = ""; String mszHomePage = "";
String mszGitea = ""; String mszGitea = "";
int mnAppIcon = 0; int mnAppIcon = 0;
String mszWinBollServerHost; String mszWinBoLLServerHost;
String mszReleaseAPKName; String mszReleaseAPKName;
EditText metDevUserName; EditText metDevUserName;
EditText metDevUserPassword; EditText metDevUserPassword;
@@ -107,7 +107,7 @@ public class AboutView extends LinearLayout {
mszAppDescription = mAPPInfo.getAppDescription(); mszAppDescription = mAPPInfo.getAppDescription();
mnAppIcon = mAPPInfo.getAppIcon(); mnAppIcon = mAPPInfo.getAppIcon();
mszWinBollServerHost = GlobalApplication.isDebuging() ? "https://dev.winboll.cc": "https://www.winboll.cc"; mszWinBoLLServerHost = GlobalApplication.isDebuging() ? "https://dev.winboll.cc": "https://www.winboll.cc";
try { try {
mszAppVersionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName; mszAppVersionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
@@ -115,7 +115,7 @@ public class AboutView extends LinearLayout {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
} }
mszCurrentAppPackageName = mszAppAPKName + "_" + mszAppVersionName + ".apk"; mszCurrentAppPackageName = mszAppAPKName + "_" + mszAppVersionName + ".apk";
mszHomePage = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName; mszHomePage = mszWinBoLLServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
if (mAPPInfo.getAppGitAPPBranch().equals("")) { if (mAPPInfo.getAppGitAPPBranch().equals("")) {
mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName; mszGitea = "https://gitea.winboll.cc/" + mAPPInfo.getAppGitOwner() + "/" + mszAppGitName;
} else { } else {
@@ -132,9 +132,9 @@ public class AboutView extends LinearLayout {
metDevUserName.setText(PrefUtils.getString(mContext, "metDevUserName", "")); metDevUserName.setText(PrefUtils.getString(mContext, "metDevUserName", ""));
metDevUserPassword.setText(PrefUtils.getString(mContext, "metDevUserPassword", "")); metDevUserPassword.setText(PrefUtils.getString(mContext, "metDevUserPassword", ""));
//mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context); //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutdevWinBollServiceStatusView1); mWinBoLLServiceStatusView = addedView.findViewById(R.id.viewaboutdevWinBoLLServiceStatusView1);
mWinBollServiceStatusView.setServerHost(mszWinBollServerHost); mWinBoLLServiceStatusView.setServerHost(mszWinBoLLServerHost);
mWinBollServiceStatusView.setAuthInfo(metDevUserName.getText().toString(), metDevUserPassword.getText().toString()); mWinBoLLServiceStatusView.setAuthInfo(metDevUserName.getText().toString(), metDevUserPassword.getText().toString());
//llMain.addView(mDevelopHostConnectionStatusView); //llMain.addView(mDevelopHostConnectionStatusView);
llMain.addView(createAboutPage()); llMain.addView(createAboutPage());
addView(addedView); addView(addedView);
@@ -143,9 +143,9 @@ public class AboutView extends LinearLayout {
View addedView = inflater.inflate(R.layout.view_about_www, this, false); View addedView = inflater.inflate(R.layout.view_about_www, this, false);
LinearLayout llMain = addedView.findViewById(R.id.viewaboutwwwLinearLayout1); LinearLayout llMain = addedView.findViewById(R.id.viewaboutwwwLinearLayout1);
//mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context); //mDevelopHostConnectionStatusView = new DevelopHostConnectionStatusView(context);
mWinBollServiceStatusView = addedView.findViewById(R.id.viewaboutwwwWinBollServiceStatusView1); mWinBoLLServiceStatusView = addedView.findViewById(R.id.viewaboutwwwWinBoLLServiceStatusView1);
mWinBollServiceStatusView.setServerHost(mszWinBollServerHost); mWinBoLLServiceStatusView.setServerHost(mszWinBoLLServerHost);
mWinBollServiceStatusView.setAuthInfo("", ""); mWinBoLLServiceStatusView.setAuthInfo("", "");
//llMain.addView(mDevelopHostConnectionStatusView); //llMain.addView(mDevelopHostConnectionStatusView);
llMain.addView(createAboutPage()); llMain.addView(createAboutPage());
addView(addedView); addView(addedView);
@@ -291,7 +291,7 @@ public class AboutView extends LinearLayout {
GlobalApplication.setIsDebuging(true); GlobalApplication.setIsDebuging(true);
GlobalApplication.saveDebugStatus(); GlobalApplication.saveDebugStatus();
GlobalApplication.getWinBollActivityManager().finishAll(); GlobalApplication.getWinBoLLActivityManager().finishAll();
context.startActivity(intent); context.startActivity(intent);
} }
} }
@@ -303,7 +303,7 @@ public class AboutView extends LinearLayout {
GlobalApplication.setIsDebuging(false); GlobalApplication.setIsDebuging(false);
GlobalApplication.saveDebugStatus(); GlobalApplication.saveDebugStatus();
GlobalApplication.getWinBollActivityManager().finishAll(); GlobalApplication.getWinBoLLActivityManager().finishAll();
context.startActivity(intent); context.startActivity(intent);
} }
} }
@@ -323,7 +323,7 @@ public class AboutView extends LinearLayout {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
String szUrl = mszWinBollServerHost + "/studio/details.php?app=" + mszAppAPKFolderName; String szUrl = mszWinBoLLServerHost + "/studio/details.php?app=" + mszAppAPKFolderName;
// 构建包含认证信息的请求 // 构建包含认证信息的请求
String credential = ""; String credential = "";
if (GlobalApplication.isDebuging()) { if (GlobalApplication.isDebuging()) {
@@ -331,8 +331,8 @@ public class AboutView extends LinearLayout {
PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString()); PrefUtils.saveString(mContext, "metDevUserName", metDevUserName.getText().toString());
PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString()); PrefUtils.saveString(mContext, "metDevUserPassword", metDevUserPassword.getText().toString());
} else { } else {
String username = "WinBoll"; String username = "WinBoLL";
String password = "WinBollPowerByZhanGSKen"; String password = "WinBoLLPowerByZhanGSKen";
credential = Credentials.basic(username, password); credential = Credentials.basic(username, password);
} }
@@ -384,7 +384,7 @@ public class AboutView extends LinearLayout {
YesNoAlertDialog.OnDialogResultListener mIsDownlaodUpdateListener = new YesNoAlertDialog.OnDialogResultListener() { YesNoAlertDialog.OnDialogResultListener mIsDownlaodUpdateListener = new YesNoAlertDialog.OnDialogResultListener() {
@Override @Override
public void onYes() { public void onYes() {
String szUrl = mszWinBollServerHost + "/studio/download.php?appname=" + mszAppAPKFolderName + "&apkname=" + mszNewestAppPackageName; String szUrl = mszWinBoLLServerHost + "/studio/download.php?appname=" + mszAppAPKFolderName + "&apkname=" + mszNewestAppPackageName;
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(szUrl)); Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(szUrl));
mContext.startActivity(browserIntent); mContext.startActivity(browserIntent);
} }

View File

@@ -11,14 +11,14 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.IBinder; import android.os.IBinder;
import cc.winboll.studio.libaes.winboll.WinBollClientService; import cc.winboll.studio.libaes.winboll.WinBoLLClientService;
import cc.winboll.studio.libappbase.utils.ServiceUtils; import cc.winboll.studio.libappbase.utils.ServiceUtils;
public class AssistantService extends Service { public class AssistantService extends Service {
public final static String TAG = "AssistantService"; public final static String TAG = "AssistantService";
WinBollClientServiceBean mWinBollServiceBean; WinBoLLClientServiceBean mWinBoLLServiceBean;
MyServiceConnection mMyServiceConnection; MyServiceConnection mMyServiceConnection;
volatile boolean mIsServiceRunning; volatile boolean mIsServiceRunning;
@@ -30,7 +30,7 @@ public class AssistantService extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this); mWinBoLLServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this);
if (mMyServiceConnection == null) { if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection(); mMyServiceConnection = new MyServiceConnection();
} }
@@ -55,8 +55,8 @@ public class AssistantService extends Service {
// 运行服务内容 // 运行服务内容
// //
void run() { void run() {
mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this); mWinBoLLServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this);
if (mWinBollServiceBean.isEnable()) { if (mWinBoLLServiceBean.isEnable()) {
if (mIsServiceRunning == false) { if (mIsServiceRunning == false) {
// 设置运行状态 // 设置运行状态
mIsServiceRunning = true; mIsServiceRunning = true;
@@ -70,11 +70,11 @@ public class AssistantService extends Service {
// 唤醒和绑定主进程 // 唤醒和绑定主进程
// //
void wakeupAndBindMain() { void wakeupAndBindMain() {
if (ServiceUtils.isServiceRunning(getApplicationContext(), WinBollClientService.class.getName()) == false) { if (ServiceUtils.isServiceRunning(getApplicationContext(), WinBoLLClientService.class.getName()) == false) {
startForegroundService(new Intent(AssistantService.this, WinBollClientService.class)); startForegroundService(new Intent(AssistantService.this, WinBoLLClientService.class));
} }
bindService(new Intent(AssistantService.this, WinBollClientService.class), mMyServiceConnection, Context.BIND_IMPORTANT); bindService(new Intent(AssistantService.this, WinBoLLClientService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
} }
// //
@@ -87,8 +87,8 @@ public class AssistantService extends Service {
@Override @Override
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(ComponentName name) {
mWinBollServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(AssistantService.this); mWinBoLLServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(AssistantService.this);
if (mWinBollServiceBean.isEnable()) { if (mWinBoLLServiceBean.isEnable()) {
wakeupAndBindMain(); wakeupAndBindMain();
} }
} }

View File

@@ -3,7 +3,7 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:11:27 * @Date 2025/03/28 19:11:27
* @Describe WinBoll UI 状态图标枚举 * @Describe WinBoLL UI 状态图标枚举
*/ */
import cc.winboll.studio.libaes.R; import cc.winboll.studio.libaes.R;

View File

@@ -3,15 +3,15 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:08:45 * @Date 2025/03/28 19:08:45
* @Describe WinBollService 服务 Binder * @Describe WinBoLLService 服务 Binder
*/ */
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
public interface IWinBollClientServiceBinder { public interface IWinBoLLClientServiceBinder {
public static final String TAG = "IWinBollClientServiceBinder"; public static final String TAG = "IWinBoLLClientServiceBinder";
public WinBollClientService getService(); public WinBoLLClientService getService();
public Drawable getCurrentStatusIconDrawable(); public Drawable getCurrentStatusIconDrawable();
} }

View File

@@ -3,7 +3,7 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:06:54 * @Date 2025/03/28 19:06:54
* @Describe WinBoll 客户端服务 * @Describe WinBoLL 客户端服务
*/ */
import android.app.Service; import android.app.Service;
import android.content.ComponentName; import android.content.ComponentName;
@@ -19,28 +19,28 @@ import cc.winboll.studio.libappbase.utils.ServiceUtils;
import cc.winboll.studio.libapputils.utils.PrefUtils; import cc.winboll.studio.libapputils.utils.PrefUtils;
import com.hjq.toast.ToastUtils; import com.hjq.toast.ToastUtils;
public class WinBollClientService extends Service implements IWinBollClientServiceBinder { public class WinBoLLClientService extends Service implements IWinBoLLClientServiceBinder {
public static final String TAG = "WinBollClientService"; public static final String TAG = "WinBoLLClientService";
WinBollClientServiceBean mWinBollClientServiceBean; WinBoLLClientServiceBean mWinBoLLClientServiceBean;
MyServiceConnection mMyServiceConnection; MyServiceConnection mMyServiceConnection;
volatile boolean mIsWinBollClientThreadRunning; volatile boolean mIsWinBoLLClientThreadRunning;
volatile boolean mIsEnableService; volatile boolean mIsEnableService;
volatile WinBollClientThread mWinBollClientThread; volatile WinBoLLClientThread mWinBoLLClientThread;
public boolean isWinBollClientThreadRunning() { public boolean isWinBoLLClientThreadRunning() {
return mIsWinBollClientThreadRunning; return mIsWinBoLLClientThreadRunning;
} }
@Override @Override
public WinBollClientService getService() { public WinBoLLClientService getService() {
return WinBollClientService.this; return WinBoLLClientService.this;
} }
@Override @Override
public Drawable getCurrentStatusIconDrawable() { public Drawable getCurrentStatusIconDrawable() {
return mIsWinBollClientThreadRunning ? return mIsWinBoLLClientThreadRunning ?
getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NORMAL)) getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NORMAL))
: getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NEWS)); : getDrawable(EWUIStatusIconDrawable.getIconDrawableId(EWUIStatusIconDrawable.NEWS));
} }
@@ -54,9 +54,9 @@ public class WinBollClientService extends Service implements IWinBollClientServi
public void onCreate() { public void onCreate() {
//ToastUtils.show("onCreate"); //ToastUtils.show("onCreate");
super.onCreate(); super.onCreate();
mWinBollClientThread = null; mWinBoLLClientThread = null;
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this); mWinBoLLClientServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this);
mIsEnableService = mWinBollClientServiceBean.isEnable(); mIsEnableService = mWinBoLLClientServiceBean.isEnable();
if (mMyServiceConnection == null) { if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection(); mMyServiceConnection = new MyServiceConnection();
@@ -74,23 +74,23 @@ public class WinBollClientService extends Service implements IWinBollClientServi
// 返回运行参数持久化存储后服务状态控制参数 // 返回运行参数持久化存储后服务状态控制参数
// 无论 Intent 传入如何服务状态一直以持久化存储后的参数控制 // 无论 Intent 传入如何服务状态一直以持久化存储后的参数控制
// PS: 另外当然可以通过 Intent 传入的指标来修改 mWinBollServiceBean // PS: 另外当然可以通过 Intent 传入的指标来修改 mWinBoLLServiceBean
// 不过本服务的应用方向会变得繁琐 // 不过本服务的应用方向会变得繁琐
// 现阶段只要满足手机端启动与停止本服务WinBoll 客户端实例运行在手机端就可以了 // 现阶段只要满足手机端启动与停止本服务WinBoLL 客户端实例运行在手机端就可以了
return mIsEnableService ? Service.START_STICKY: super.onStartCommand(intent, flags, startId); return mIsEnableService ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
} }
synchronized void runMainThread() { synchronized void runMainThread() {
if (mWinBollClientThread == null) { if (mWinBoLLClientThread == null) {
//ToastUtils.show("runMainThread()"); //ToastUtils.show("runMainThread()");
mWinBollClientThread = new WinBollClientThread(); mWinBoLLClientThread = new WinBoLLClientThread();
mWinBollClientThread.start(); mWinBoLLClientThread.start();
} }
} }
void syncWinBollClientThreadStatus() { void syncWinBoLLClientThreadStatus() {
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(this); mWinBoLLClientServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this);
mIsEnableService = mWinBollClientServiceBean.isEnable(); mIsEnableService = mWinBoLLClientServiceBean.isEnable();
LogUtils.d(TAG, String.format("mIsEnableService %s", mIsEnableService)); LogUtils.d(TAG, String.format("mIsEnableService %s", mIsEnableService));
} }
@@ -99,9 +99,9 @@ public class WinBollClientService extends Service implements IWinBollClientServi
// //
void wakeupAndBindAssistant() { void wakeupAndBindAssistant() {
if (ServiceUtils.isServiceRunning(getApplicationContext(), AssistantService.class.getName()) == false) { if (ServiceUtils.isServiceRunning(getApplicationContext(), AssistantService.class.getName()) == false) {
startService(new Intent(WinBollClientService.this, AssistantService.class)); startService(new Intent(WinBoLLClientService.this, AssistantService.class));
//LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService"); //LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService");
bindService(new Intent(WinBollClientService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT); bindService(new Intent(WinBoLLClientService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
} }
} }
@@ -115,8 +115,8 @@ public class WinBollClientService extends Service implements IWinBollClientServi
@Override @Override
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(ComponentName name) {
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(WinBollClientService.this); mWinBoLLClientServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(WinBoLLClientService.this);
if (mWinBollClientServiceBean.isEnable()) { if (mWinBoLLClientServiceBean.isEnable()) {
// 唤醒守护进程 // 唤醒守护进程
wakeupAndBindAssistant(); wakeupAndBindAssistant();
} }
@@ -134,15 +134,15 @@ public class WinBollClientService extends Service implements IWinBollClientServi
super.onStart(intent, startId); super.onStart(intent, startId);
} }
void setWinBollServiceEnableStatus(boolean isEnable) { void setWinBoLLServiceEnableStatus(boolean isEnable) {
WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(this); WinBoLLClientServiceBean bean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(this);
bean.setIsEnable(isEnable); bean.setIsEnable(isEnable);
WinBollClientServiceBean.saveWinBollServiceBean(this, bean); WinBoLLClientServiceBean.saveWinBoLLServiceBean(this, bean);
} }
boolean getWinBollServiceEnableStatus(Context context) { boolean getWinBoLLServiceEnableStatus(Context context) {
mWinBollClientServiceBean = WinBollClientServiceBean.loadWinBollClientServiceBean(context); mWinBoLLClientServiceBean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(context);
return mWinBollClientServiceBean.isEnable(); return mWinBoLLClientServiceBean.isEnable();
} }
/*public interface OnServiceStatusChangeListener { /*public interface OnServiceStatusChangeListener {
@@ -153,24 +153,24 @@ public class WinBollClientService extends Service implements IWinBollClientServi
mOnServerStatusChangeListener = l; mOnServerStatusChangeListener = l;
}*/ }*/
class WinBollClientThread extends Thread { class WinBoLLClientThread extends Thread {
@Override @Override
public void run() { public void run() {
super.run(); super.run();
LogUtils.d(TAG, "run syncWinBollClientThreadStatus"); LogUtils.d(TAG, "run syncWinBoLLClientThreadStatus");
syncWinBollClientThreadStatus(); syncWinBoLLClientThreadStatus();
if (mIsEnableService) { if (mIsEnableService) {
if (mIsWinBollClientThreadRunning == false) { if (mIsWinBoLLClientThreadRunning == false) {
// 设置运行状态 // 设置运行状态
mIsWinBollClientThreadRunning = true; mIsWinBoLLClientThreadRunning = true;
LogUtils.d(TAG, "WinBollClientThread run()"); LogUtils.d(TAG, "WinBoLLClientThread run()");
// 唤醒守护进程 // 唤醒守护进程
//wakeupAndBindAssistant(); //wakeupAndBindAssistant();
while (mIsEnableService) { while (mIsEnableService) {
// 显示运行状态 // 显示运行状态
WinBollServiceStatusView.startConnection(); WinBoLLServiceStatusView.startConnection();
LogUtils.d(TAG, String.format("while mIsEnableService is %s", mIsEnableService)); LogUtils.d(TAG, String.format("while mIsEnableService is %s", mIsEnableService));
try { try {
@@ -178,13 +178,13 @@ public class WinBollClientService extends Service implements IWinBollClientServi
} catch (InterruptedException e) { } catch (InterruptedException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
} }
syncWinBollClientThreadStatus(); syncWinBoLLClientThreadStatus();
} }
// 服务进程退出, 重置进程运行状态 // 服务进程退出, 重置进程运行状态
WinBollServiceStatusView.stopConnection(); WinBoLLServiceStatusView.stopConnection();
mIsWinBollClientThreadRunning = false; mIsWinBoLLClientThreadRunning = false;
mWinBollClientThread = null; mWinBoLLClientThread = null;
} }
} }
} }

View File

@@ -3,7 +3,7 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:05:15 * @Date 2025/03/28 19:05:15
* @Describe WinBollService 运行参数配置 * @Describe WinBoLLService 运行参数配置
*/ */
import android.content.Context; import android.content.Context;
import android.util.JsonReader; import android.util.JsonReader;
@@ -11,13 +11,13 @@ import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean; import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException; import java.io.IOException;
public class WinBollClientServiceBean extends BaseBean { public class WinBoLLClientServiceBean extends BaseBean {
public static final String TAG = "WinBollClientServiceBean"; public static final String TAG = "WinBoLLClientServiceBean";
volatile boolean isEnable; volatile boolean isEnable;
public WinBollClientServiceBean() { public WinBoLLClientServiceBean() {
isEnable = false; isEnable = false;
} }
@@ -31,13 +31,13 @@ public class WinBollClientServiceBean extends BaseBean {
@Override @Override
public String getName() { public String getName() {
return WinBollClientServiceBean.class.getName(); return WinBoLLClientServiceBean.class.getName();
} }
@Override @Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException { public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter); super.writeThisToJsonWriter(jsonWriter);
WinBollClientServiceBean bean = this; WinBoLLClientServiceBean bean = this;
jsonWriter.name("isEnable").value(bean.isEnable()); jsonWriter.name("isEnable").value(bean.isEnable());
} }
@@ -67,12 +67,12 @@ public class WinBollClientServiceBean extends BaseBean {
return this; return this;
} }
public static WinBollClientServiceBean loadWinBollClientServiceBean(Context context) { public static WinBoLLClientServiceBean loadWinBoLLClientServiceBean(Context context) {
WinBollClientServiceBean bean = WinBollClientServiceBean.loadBean(context, WinBollClientServiceBean.class); WinBoLLClientServiceBean bean = WinBoLLClientServiceBean.loadBean(context, WinBoLLClientServiceBean.class);
return bean == null ? new WinBollClientServiceBean() : bean; return bean == null ? new WinBoLLClientServiceBean() : bean;
} }
public static boolean saveWinBollServiceBean(WinBollClientService service, WinBollClientServiceBean bean) { public static boolean saveWinBoLLServiceBean(WinBoLLClientService service, WinBoLLClientServiceBean bean) {
return WinBollClientServiceBean.saveBean(service, bean); return WinBoLLClientServiceBean.saveBean(service, bean);
} }
} }

View File

@@ -3,15 +3,15 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 19:13:20 * @Date 2025/03/28 19:13:20
* @Describe WinBoll 邮件服务 * @Describe WinBoLL 邮件服务
*/ */
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.IBinder; import android.os.IBinder;
public class WinBollMail extends Service { public class WinBoLLMail extends Service {
public static final String TAG = "WinBollMail"; public static final String TAG = "WinBoLLMail";
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {

View File

@@ -3,7 +3,7 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/29 15:57:28 * @Date 2025/03/29 15:57:28
* @Describe WinBoll 服务器服务情况测试访问进程 * @Describe WinBoLL 服务器服务情况测试访问进程
*/ */
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import java.io.IOException; import java.io.IOException;
@@ -20,9 +20,9 @@ interface TextCallback {
void onFailure(Exception e); void onFailure(Exception e);
} }
public class WinBollServerConnectionThread extends Thread { public class WinBoLLServerConnectionThread extends Thread {
public static final String TAG = "WinBollClientService"; public static final String TAG = "WinBoLLClientService";
private final String url; private final String url;
private final String username; private final String username;
@@ -33,12 +33,12 @@ public class WinBollServerConnectionThread extends Thread {
private final TextCallback callback; // 新增回调成员变量 private final TextCallback callback; // 新增回调成员变量
// 新增带回调的构造函数 // 新增带回调的构造函数
public WinBollServerConnectionThread(String url, String username, String password, TextCallback callback) { public WinBoLLServerConnectionThread(String url, String username, String password, TextCallback callback) {
this(url, username, password, 10000, 10000, 5, callback); this(url, username, password, 10000, 10000, 5, callback);
} }
// 修改原有构造函数添加回调参数 // 修改原有构造函数添加回调参数
public WinBollServerConnectionThread(String url, String username, String password, public WinBoLLServerConnectionThread(String url, String username, String password,
int connectTimeout, int readTimeout, int maxRetries, TextCallback callback) { int connectTimeout, int readTimeout, int maxRetries, TextCallback callback) {
this.url = url; this.url = url;
this.username = username; this.username = username;

View File

@@ -3,8 +3,9 @@ package cc.winboll.studio.libaes.winboll;
/** /**
* @Author ZhanGSKen@AliYun.Com * @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 17:41:55 * @Date 2025/03/28 17:41:55
* @Describe WinBoll 服务主机连接状态视图 * @Describe WinBoLL 服务主机连接状态视图
*/ */
import cc.winboll.studio.libaes.R;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -18,10 +19,9 @@ import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import cc.winboll.studio.libaes.winboll.WinBollClientService; import cc.winboll.studio.libaes.winboll.WinBoLLClientService;
import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libapputils.R;
import cc.winboll.studio.libapputils.utils.PrefUtils; import cc.winboll.studio.libapputils.utils.PrefUtils;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@@ -32,23 +32,23 @@ import java.time.format.DateTimeFormatter;
//import okhttp3.Response; //import okhttp3.Response;
//import okhttp3.Route; //import okhttp3.Route;
public class WinBollServiceStatusView extends LinearLayout { public class WinBoLLServiceStatusView extends LinearLayout {
public static final String TAG = "WinBollServiceStatusView"; public static final String TAG = "WinBoLLServiceStatusView";
public static final int MSG_CONNECTION_INFO = 0; public static final int MSG_CONNECTION_INFO = 0;
public static final int MSG_UPDATE_CONNECTION_STATUS = 1; public static final int MSG_UPDATE_CONNECTION_STATUS = 1;
static WinBollServiceStatusView _WinBollServiceStatusView; static WinBoLLServiceStatusView _WinBoLLServiceStatusView;
Context mContext; Context mContext;
//boolean mIsConnected; //boolean mIsConnected;
volatile ConnectionThread mConnectionThread; volatile ConnectionThread mConnectionThread;
String mszServerHost; String mszServerHost;
WinBollClientService mWinBollService; WinBoLLClientService mWinBoLLService;
ImageView mImageView; ImageView mImageView;
TextView mTextView; TextView mTextView;
WinBollServiceViewHandler mWinBollServiceViewHandler; WinBoLLServiceViewHandler mWinBoLLServiceViewHandler;
//WebView mWebView; //WebView mWebView;
static volatile ConnectionStatus mConnectionStatus; static volatile ConnectionStatus mConnectionStatus;
View.OnClickListener mViewOnClickListener; View.OnClickListener mViewOnClickListener;
@@ -66,11 +66,11 @@ public class WinBollServiceStatusView extends LinearLayout {
ServiceConnection connection = new ServiceConnection() { ServiceConnection connection = new ServiceConnection() {
@Override @Override
public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) {
IWinBollClientServiceBinder binder = (IWinBollClientServiceBinder) service; IWinBoLLClientServiceBinder binder = (IWinBoLLClientServiceBinder) service;
mWinBollService = binder.getService(); mWinBoLLService = binder.getService();
isBound = true; isBound = true;
// 可以在这里调用Service的方法进行通信比如获取数据 // 可以在这里调用Service的方法进行通信比如获取数据
mImageView.setBackgroundDrawable(mWinBollService.getCurrentStatusIconDrawable()); mImageView.setBackgroundDrawable(mWinBoLLService.getCurrentStatusIconDrawable());
} }
@Override @Override
@@ -79,25 +79,25 @@ public class WinBollServiceStatusView extends LinearLayout {
} }
}; };
public WinBollServiceStatusView(Context context) { public WinBoLLServiceStatusView(Context context) {
super(context); super(context);
mContext = context; mContext = context;
initView(); initView();
} }
public WinBollServiceStatusView(Context context, AttributeSet attrs) { public WinBoLLServiceStatusView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
mContext = context; mContext = context;
initView(); initView();
} }
public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) { public WinBoLLServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
mContext = context; mContext = context;
initView(); initView();
} }
public WinBollServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public WinBoLLServiceStatusView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
mContext = context; mContext = context;
initView(); initView();
@@ -110,13 +110,13 @@ public class WinBollServiceStatusView extends LinearLayout {
} }
void initView() { void initView() {
_WinBollServiceStatusView = this; _WinBoLLServiceStatusView = this;
mImageView = new ImageView(mContext); mImageView = new ImageView(mContext);
setImageViewByConnection(mImageView, false); setImageViewByConnection(mImageView, false);
mConnectionStatus = getConnectionStatus(); mConnectionStatus = getConnectionStatus();
//mIsConnected = false; //mIsConnected = false;
//mWinBollServerHostConnectionStatus = WinBollServerHostConnectionStatus.DISCONNECTED; //mWinBoLLServerHostConnectionStatus = WinBoLLServerHostConnectionStatus.DISCONNECTED;
//ToastUtils.show("initView()"); //ToastUtils.show("initView()");
mViewOnClickListener = new View.OnClickListener(){ mViewOnClickListener = new View.OnClickListener(){
@@ -125,10 +125,10 @@ public class WinBollServiceStatusView extends LinearLayout {
LogUtils.d(TAG, "onClick()"); LogUtils.d(TAG, "onClick()");
if (mConnectionStatus == ConnectionStatus.CONNECTED) { if (mConnectionStatus == ConnectionStatus.CONNECTED) {
LogUtils.d(TAG, "Click to stop service."); LogUtils.d(TAG, "Click to stop service.");
WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext); WinBoLLClientServiceBean bean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(mContext);
bean.setIsEnable(false); bean.setIsEnable(false);
WinBollClientServiceBean.saveBean(mContext, bean); WinBoLLClientServiceBean.saveBean(mContext, bean);
Intent intent = new Intent(mContext, WinBollClientService.class); Intent intent = new Intent(mContext, WinBoLLClientService.class);
mContext.stopService(intent); mContext.stopService(intent);
//stopConnectionThread(); //stopConnectionThread();
mTextView.setText(""); mTextView.setText("");
@@ -136,10 +136,10 @@ public class WinBollServiceStatusView extends LinearLayout {
mConnectionStatus = ConnectionStatus.DISCONNECTED; mConnectionStatus = ConnectionStatus.DISCONNECTED;
} else if (mConnectionStatus == ConnectionStatus.DISCONNECTED) { } else if (mConnectionStatus == ConnectionStatus.DISCONNECTED) {
LogUtils.d(TAG, "Click to start service."); LogUtils.d(TAG, "Click to start service.");
WinBollClientServiceBean bean = WinBollClientServiceBean.loadWinBollClientServiceBean(mContext); WinBoLLClientServiceBean bean = WinBoLLClientServiceBean.loadWinBoLLClientServiceBean(mContext);
bean.setIsEnable(true); bean.setIsEnable(true);
WinBollClientServiceBean.saveBean(mContext, bean); WinBoLLClientServiceBean.saveBean(mContext, bean);
Intent intent = new Intent(mContext, WinBollClientService.class); Intent intent = new Intent(mContext, WinBoLLClientService.class);
mContext.startService(intent); mContext.startService(intent);
//startConnectionThread(); //startConnectionThread();
} }
@@ -148,7 +148,7 @@ public class WinBollServiceStatusView extends LinearLayout {
setOnClickListener(mViewOnClickListener); setOnClickListener(mViewOnClickListener);
addView(mImageView); addView(mImageView);
mTextView = new TextView(mContext); mTextView = new TextView(mContext);
mWinBollServiceViewHandler = new WinBollServiceViewHandler(this); mWinBoLLServiceViewHandler = new WinBoLLServiceViewHandler(this);
addView(mTextView); addView(mTextView);
/*mWebView = new WebView(mContext); /*mWebView = new WebView(mContext);
mWebView.setWebViewClient(new WebViewClient() { mWebView.setWebViewClient(new WebViewClient() {
@@ -161,8 +161,8 @@ public class WinBollServiceStatusView extends LinearLayout {
addView(mWebView);*/ addView(mWebView);*/
} }
void checkWinBollServerStatusAndUpdateCurrentView() { void checkWinBoLLServerStatusAndUpdateCurrentView() {
LogUtils.d(TAG, "checkWinBollServerStatusAndUpdateCurrentView()"); LogUtils.d(TAG, "checkWinBoLLServerStatusAndUpdateCurrentView()");
/*if (getConnectionStatus() == ConnectionStatus.CONNECTED) { /*if (getConnectionStatus() == ConnectionStatus.CONNECTED) {
mConnectionStatus = ConnectionStatus.CONNECTED; mConnectionStatus = ConnectionStatus.CONNECTED;
} else { } else {
@@ -170,8 +170,8 @@ public class WinBollServiceStatusView extends LinearLayout {
}*/ }*/
} }
public void setServerHost(String szWinBollServerHost) { public void setServerHost(String szWinBoLLServerHost) {
mszServerHost = szWinBollServerHost; mszServerHost = szWinBoLLServerHost;
} }
public void setAuthInfo(String username, String password) { public void setAuthInfo(String username, String password) {
@@ -216,8 +216,8 @@ public class WinBollServiceStatusView extends LinearLayout {
// 按照指定格式格式化时间并输出 // 按照指定格式格式化时间并输出
String formattedDateTime = now.format(formatter); String formattedDateTime = now.format(formatter);
String msg = "ClientIP<" + formattedDateTime + ">: " + text; String msg = "ClientIP<" + formattedDateTime + ">: " + text;
mWinBollServiceViewHandler.postMessageText(msg); mWinBoLLServiceViewHandler.postMessageText(msg);
mWinBollServiceViewHandler.postMessageConnectionStatus(true); mWinBoLLServiceViewHandler.postMessageConnectionStatus(true);
} }
@@ -227,8 +227,8 @@ public class WinBollServiceStatusView extends LinearLayout {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
// 处理网络请求失败 // 处理网络请求失败
setImageViewByConnection(mImageView, false); setImageViewByConnection(mImageView, false);
mWinBollServiceViewHandler.postMessageText(e.getMessage()); mWinBoLLServiceViewHandler.postMessageText(e.getMessage());
mWinBollServiceViewHandler.postMessageConnectionStatus(false); mWinBoLLServiceViewHandler.postMessageConnectionStatus(false);
} }
}; };
@@ -249,12 +249,12 @@ public class WinBollServiceStatusView extends LinearLayout {
username = PrefUtils.getString(mContext, "metDevUserName", ""); username = PrefUtils.getString(mContext, "metDevUserName", "");
password = PrefUtils.getString(mContext, "metDevUserPassword", ""); password = PrefUtils.getString(mContext, "metDevUserPassword", "");
} else { } else {
username = "WinBoll"; username = "WinBoLL";
password = "WinBollPowerByZhanGSKen"; password = "WinBoLLPowerByZhanGSKen";
} }
LogUtils.d(TAG, String.format("Connection Start. targetUrl %s", targetUrl)); LogUtils.d(TAG, String.format("Connection Start. targetUrl %s", targetUrl));
WinBollServerConnectionThread thread = new WinBollServerConnectionThread( WinBoLLServerConnectionThread thread = new WinBoLLServerConnectionThread(
targetUrl, targetUrl,
username, username,
password, password,
@@ -263,7 +263,7 @@ public class WinBollServiceStatusView extends LinearLayout {
thread.start(); thread.start();
} }
/*void requestWithBasicAuth(final WinBollServiceViewHandler textViewHandler, String targetUrl, final String username, final String password) { /*void requestWithBasicAuth(final WinBoLLServiceViewHandler textViewHandler, String targetUrl, final String username, final String password) {
// 用户名和密码替换为实际的认证信息 // 用户名和密码替换为实际的认证信息
//String username = "your_username"; //String username = "your_username";
//String password = "your_password"; //String password = "your_password";
@@ -350,10 +350,10 @@ public class WinBollServiceStatusView extends LinearLayout {
}*/ }*/
class WinBollServiceViewHandler extends Handler { class WinBoLLServiceViewHandler extends Handler {
WinBollServiceStatusView mDevelopHostConnectionStatusView; WinBoLLServiceStatusView mDevelopHostConnectionStatusView;
public WinBollServiceViewHandler(WinBollServiceStatusView view) { public WinBoLLServiceViewHandler(WinBoLLServiceStatusView view) {
mDevelopHostConnectionStatusView = view; mDevelopHostConnectionStatusView = view;
} }
@@ -384,14 +384,14 @@ public class WinBollServiceStatusView extends LinearLayout {
} }
public static void startConnection() { public static void startConnection() {
if (_WinBollServiceStatusView != null) { if (_WinBoLLServiceStatusView != null) {
_WinBollServiceStatusView.startConnectionThread(); _WinBoLLServiceStatusView.startConnectionThread();
} }
} }
public static void stopConnection() { public static void stopConnection() {
if (_WinBollServiceStatusView != null) { if (_WinBoLLServiceStatusView != null) {
_WinBollServiceStatusView.stopConnectionThread(); _WinBoLLServiceStatusView.stopConnectionThread();
} }
} }
@@ -448,7 +448,7 @@ public class WinBollServiceStatusView extends LinearLayout {
requestCIPWithBasicAuth(); requestCIPWithBasicAuth();
} else if (mConnectionStatus == ConnectionStatus.CONNECTED } else if (mConnectionStatus == ConnectionStatus.CONNECTED
|| mConnectionStatus == ConnectionStatus.DISCONNECTED) { || mConnectionStatus == ConnectionStatus.DISCONNECTED) {
//ToastUtils.show("mWinBollServerHostConnectionStatus " + mConnectionStatus); //ToastUtils.show("mWinBoLLServerHostConnectionStatus " + mConnectionStatus);
LogUtils.d(TAG, String.format("mConnectionStatus done %s", mConnectionStatus)); LogUtils.d(TAG, String.format("mConnectionStatus done %s", mConnectionStatus));
} else { } else {
LogUtils.d(TAG, String.format("mConnectionStatus unknow %s", mConnectionStatus)); LogUtils.d(TAG, String.format("mConnectionStatus unknow %s", mConnectionStatus));
@@ -465,7 +465,7 @@ public class WinBollServiceStatusView extends LinearLayout {
} }
} }
/*WinBollService.OnServiceStatusChangeListener mOnServerStatusChangeListener = new WinBollService.OnServiceStatusChangeListener(){ /*WinBoLLService.OnServiceStatusChangeListener mOnServerStatusChangeListener = new WinBoLLService.OnServiceStatusChangeListener(){
@Override @Override
public void onServerStatusChange(boolean isServiceAlive) { public void onServerStatusChange(boolean isServiceAlive) {
} }

View File

@@ -53,10 +53,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal"> android:gravity="center_horizontal">
<cc.winboll.studio.libaes.winboll.WinBollServiceStatusView <cc.winboll.studio.libaes.winboll.WinBoLLServiceStatusView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/viewaboutdevWinBollServiceStatusView1"/> android:id="@+id/viewaboutdevWinBoLLServiceStatusView1"/>
</LinearLayout> </LinearLayout>

View File

@@ -12,10 +12,10 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal"> android:gravity="center_horizontal">
<cc.winboll.studio.libaes.winboll.WinBollServiceStatusView <cc.winboll.studio.libaes.winboll.WinBoLLServiceStatusView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/viewaboutwwwWinBollServiceStatusView1"/> android:id="@+id/viewaboutwwwWinBoLLServiceStatusView1"/>
</LinearLayout> </LinearLayout>

View File

@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:background="@drawable/toast_frame"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textStyle="bold"
android:textColor="#FFFFFFFF"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_launcher"/>
<TextView
android:id="@android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="#FFFFFFFF"/>
</LinearLayout>
</LinearLayout>

View File

@@ -2,7 +2,7 @@
<resources> <resources>
<string name="lib_name">libaes</string> <string name="lib_name">libaes</string>
<string name="lib_description">云宝APP应用安卓元素类库示例。源码仅供调试参考请勿直接引用。(WinBoll APP application Android element class library example. The source is just for demo debug test, Do not quote directly.)</string> <string name="lib_description">云宝APP应用安卓元素类库示例。源码仅供调试参考请勿直接引用。(WinBoLL APP application Android element class library example. The source is just for demo debug test, Do not quote directly.)</string>
<string name="lib_home">https://winboll.cc/aes</string> <string name="lib_home">https://winboll.cc/aes</string>
<string name="text_about">关于</string> <string name="text_about">关于</string>
<string name="text_AppTheme">应用主题</string> <string name="text_AppTheme">应用主题</string>

View File

@@ -2,7 +2,7 @@
<resources> <resources>
<string name="lib_name">libaes</string> <string name="lib_name">libaes</string>
<string name="lib_description">云宝APP应用安卓元素类库示例。源码仅供调试参考请勿直接引用。(WinBoll APP application Android element class library example. The source is just for demo debug test, Do not quote directly.)</string> <string name="lib_description">云宝APP应用安卓元素类库示例。源码仅供调试参考请勿直接引用。(WinBoLL APP application Android element class library example. The source is just for demo debug test, Do not quote directly.)</string>
<string name="lib_home">https://winboll.cc/libaes</string> <string name="lib_home">https://winboll.cc/libaes</string>
<string name="text_about">About</string> <string name="text_about">About</string>
<string name="text_AppTheme">AppTheme</string> <string name="text_AppTheme">AppTheme</string>

View File

@@ -10,7 +10,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 29 targetSdkVersion 30
} }
buildTypes { buildTypes {
release { release {

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Sun Apr 27 10:05:40 HKT 2025 #Tue Apr 29 04:20:48 GMT 2025
stageCount=8 stageCount=4
libraryProject=libappbase libraryProject=libappbase
baseVersion=15.4 baseVersion=15.7
publishVersion=15.4.7 publishVersion=15.7.3
buildCount=0 buildCount=5
baseBetaVersion=15.4.8 baseBetaVersion=15.7.4

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -21,7 +21,28 @@ android {
dependencies { dependencies {
api fileTree(dir: 'libs', include: ['*.jar']) api fileTree(dir: 'libs', include: ['*.jar'])
api 'cc.winboll.studio:libappbase:15.4.8' // Android 类库
//api 'com.android.support:appcompat-v7:28.0.0'
api('com.android.support:appcompat-v7:28.0.0'){
//exclude group: "com.android.support", module: "support-vector-drawable"
exclude group: "com.android.support:animated-vector-drawable:28.0.0"
}
// https://mvnrepository.com/artifact/com.android.support/support-compat
//api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
// https://mvnrepository.com/artifact/com.android.support/support-v4
api 'com.android.support:support-v4:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-media-compat
api 'com.android.support:support-media-compat:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-core-utils
api 'com.android.support:support-core-utils:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-core-ui
api 'com.android.support:support-core-ui:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/support-fragment
api 'com.android.support:support-fragment:28.0.0'
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
api 'com.android.support:recyclerview-v7:28.0.0'
api 'cc.winboll.studio:libappbase:15.2.0'
// 二维码类库 // 二维码类库
api 'com.google.zxing:core:3.4.1' api 'com.google.zxing:core:3.4.1'

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Sun Apr 27 11:19:49 HKT 2025 #Sat Mar 29 12:14:39 HKT 2025
stageCount=1 stageCount=2
libraryProject=libapputils libraryProject=libapputils
baseVersion=15.3 baseVersion=15.2
publishVersion=15.3.0 publishVersion=15.2.1
buildCount=0 buildCount=0
baseBetaVersion=15.3.1 baseBetaVersion=15.2.2

Submodule libjc/jcc/libs deleted from 645058e1e3

Submodule winboll-x deleted from d94d70050f

View File

@@ -1,10 +1,10 @@
## WinBoll Nexus Settings ## WinBoLL Nexus Settings
## These properties is setting for publishing ## These properties is setting for publishing
## library project to WinBoll Nexus Maven Repository. ## library project to WinBoLL Nexus Maven Repository.
## ##
## WinBoll Nexus UserName ## WinBoLL Nexus UserName
#Nexus.name=nexustestuser1 #Nexus.name=nexustestuser1
## WinBoll Nexus Password ## WinBoLL Nexus Password
#Nexus.password=nexustestuserpassword #Nexus.password=nexustestuserpassword

1
winboll/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1 @@

50
winboll/build.gradle Normal file
View File

@@ -0,0 +1,50 @@
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 {
compileSdkVersion 32
buildToolsVersion "32.0.0"
defaultConfig {
applicationId "cc.winboll.studio.appbase"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
versionName "15.2"
if(true) {
versionName = genVersionName("${versionName}")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api project(':libappbase')
api fileTree(dir: 'libs', include: ['*.jar'])
}

8
winboll/build.properties Normal file
View File

@@ -0,0 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Sat Apr 12 15:06:52 HKT 2025
stageCount=6
libraryProject=libappbase
baseVersion=15.2
publishVersion=15.2.5
buildCount=0
baseBetaVersion=15.2.6

17
winboll/proguard-rules.pro vendored Normal file
View File

@@ -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 *;
#}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<application>
<!-- Put flavor specific code here -->
</application>
</manifest>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">AppBase+</string>
</resources>

View File

@@ -0,0 +1,128 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="cc.winboll.studio.appbase">
<application
android:name=".App"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MyAPPBaseTheme"
android:resizeableActivity="true"
android:process=":App">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".activities.NewActivity"
android:label="NewActivity"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
<activity android:name=".activities.New2Activity"
android:label="New2Activity"
android:exported="true"
android:resizeableActivity="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
<service
android:name=".MyTileService"
android:exported="true"
android:label="@string/tileservice_name"
android:icon="@drawable/ic_launcher"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
</intent-filter>
</service>
<service
android:name=".services.MainService"
android:exported="true"/>
<service
android:name="cc.winboll.studio.appbase.services.TestDemoBindService"
android:exported="true"/>
<service
android:name="cc.winboll.studio.appbase.services.TestDemoService"
android:exported="true"/>
<service android:name=".services.AssistantService"/>
<receiver android:name="cc.winboll.studio.appbase.receivers.MainReceiver"
android:exported="true">
<intent-filter>
<action android:name="cc.winboll.studio.appbase.receivers.MainReceiver"/>
</intent-filter>
</receiver>
<receiver
android:name=".widgets.APPNewsWidget"
android:exported="true">
<intent-filter>
<action android:name="cc.winboll.studio.appbase.widgets.APPNewsWidget.ACTION_WAKEUP_SERVICE"/>
<action android:name="cc.winboll.studio.appbase.widgets.APPNewsWidget.ACTION_RELOAD_REPORT"/>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider_info_sos"/>
</receiver>
<receiver android:name=".receivers.APPNewsWidgetClickListener"
android:exported="true">
<intent-filter>
<action android:name="cc.winboll.studio.appbase.receivers.APPNewsWidgetClickListener.ACTION_PRE"/>
<action android:name="cc.winboll.studio.appbase.receivers.APPNewsWidgetClickListener.ACTION_NEXT"/>
</intent-filter>
</receiver>
<meta-data
android:name="android.max_aspect"
android:value="4.0"/>
</application>
</manifest>

View File

@@ -0,0 +1,27 @@
package cc.winboll.studio.appbase;
/**
* @Author ZhanGSKen@QQ.COM
* @Date 2025/01/05 09:54:42
* @Describe APPbase 应用类
*/
import cc.winboll.studio.libappbase.GlobalApplication;
import android.content.IntentFilter;
import cc.winboll.studio.libappbase.sos.SOSCenterServiceReceiver;
import cc.winboll.studio.libappbase.sos.SOS;
public class App extends GlobalApplication {
public static final String TAG = "App";
SOSCenterServiceReceiver mSOSCenterServiceReceiver;
@Override
public void onCreate() {
super.onCreate();
mSOSCenterServiceReceiver = new SOSCenterServiceReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SOS.ACTION_SOS);
registerReceiver(mSOSCenterServiceReceiver, intentFilter);
}
}

View File

@@ -0,0 +1,184 @@
package cc.winboll.studio.appbase;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.activities.NewActivity;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.appbase.services.TestDemoBindService;
import cc.winboll.studio.appbase.services.TestDemoService;
import cc.winboll.studio.libappbase.CrashHandler;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.GlobalCrashActivity;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.SOS;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import cc.winboll.studio.libappbase.widgets.StatusWidget;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
public class MainActivity extends WinBollActivityBase implements IWinBollActivity {
public static final String TAG = "MainActivity";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
Toolbar mToolbar;
//LogView mLogView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ToastUtils.show("onCreate");
setContentView(R.layout.activity_main);
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
//mLogView = findViewById(R.id.activitymainLogView1);
// if (GlobalApplication.isDebuging()) {
// mLogView.start();
// ToastUtils.show("LogView start.");
// }
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu);
getMenuInflater().inflate(R.menu.toolbar_appbase, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
super.onDestroy();
Intent intentAPPWidget = new Intent(this, StatusWidget.class);
intentAPPWidget.setAction(StatusWidget.ACTION_STATUS_UPDATE);
sendBroadcast(intentAPPWidget);
}
public void onSwitchDebugMode(View view) {
boolean isDebuging = ((CheckBox)view).isChecked();
GlobalApplication.setIsDebuging(isDebuging);
GlobalApplication.saveDebugStatus();
}
public void onPreviewGlobalCrashActivity(View view) {
Intent intent = new Intent(this, GlobalCrashActivity.class);
intent.putExtra(CrashHandler.EXTRA_CRASH_INFO, "Demo log...");
startActivity(intent);
}
public void onStartCenter(View view) {
MainService.startMainService(this);
}
public void onStopCenter(View view) {
MainService.stopMainService(this);
}
public void onTestStopMainServiceWithoutSettingEnable(View view) {
LogUtils.d(TAG, "onTestStopMainServiceWithoutSettingEnable");
stopService(new Intent(this, MainService.class));
}
public void onTestUseComponentStartService(View view) {
LogUtils.d(TAG, "onTestUseComponentStartService");
// 目标服务的包名和类名
String packageName = this.getPackageName();
String serviceClassName = TestDemoService.class.getName();
// 构建Intent
Intent intentService = new Intent();
intentService.setComponent(new ComponentName(packageName, serviceClassName));
startService(intentService);
}
public void onTestDemoServiceSOS(View view) {
Intent intent = new Intent(this, TestDemoService.class);
stopService(intent);
if (App.isDebuging()) {
SOS.sosToAppBaseBeta(this, TestDemoService.class.getName());
} else {
SOS.sosToAppBase(this, TestDemoService.class.getName());
}
}
public void onSartTestDemoService(View view) {
Intent intent = new Intent(this, TestDemoService.class);
intent.setAction(TestDemoService.ACTION_ENABLE);
startService(intent);
}
public void onStopTestDemoService(View view) {
Intent intent = new Intent(this, TestDemoService.class);
intent.setAction(TestDemoService.ACTION_DISABLE);
startService(intent);
Intent intentStop = new Intent(this, TestDemoService.class);
stopService(intentStop);
}
public void onStopTestDemoServiceNoSettings(View view) {
Intent intent = new Intent(this, TestDemoService.class);
stopService(intent);
}
public void onSartTestDemoBindService(View view) {
Intent intent = new Intent(this, TestDemoBindService.class);
intent.setAction(TestDemoBindService.ACTION_ENABLE);
startService(intent);
}
public void onStopTestDemoBindService(View view) {
Intent intent = new Intent(this, TestDemoBindService.class);
intent.setAction(TestDemoBindService.ACTION_DISABLE);
startService(intent);
Intent intentStop = new Intent(this, TestDemoBindService.class);
stopService(intentStop);
}
public void onStopTestDemoBindServiceNoSettings(View view) {
Intent intent = new Intent(this, TestDemoBindService.class);
stopService(intent);
}
public void onTestOpenNewActivity(View view) {
GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, NewActivity.class);
}
}

View File

@@ -0,0 +1,79 @@
package cc.winboll.studio.appbase;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/13 19:30:10
*/
import android.content.Context;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import cc.winboll.studio.appbase.models.MainServiceBean;
import cc.winboll.studio.appbase.services.MainService;
public class MyTileService extends TileService {
public static final String TAG = "MyTileService";
volatile static MyTileService _MyTileService;
@Override
public void onStartListening() {
super.onStartListening();
_MyTileService = this;
Tile tile = getQsTile();
MainServiceBean bean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (bean != null && bean.isEnable()) {
//MainService.startMainService(context);
tile.setState(Tile.STATE_ACTIVE);
tile.setIcon(android.graphics.drawable.Icon.createWithResource(this, R.drawable.ic_cloud));
} else {
//MainService.stopMainService(context);
tile.setState(Tile.STATE_INACTIVE);
tile.setIcon(android.graphics.drawable.Icon.createWithResource(this, R.drawable.ic_cloud_outline));
}
tile.updateTile();
// Tile tile = getQsTile();
// tile.setState(Tile.STATE_INACTIVE);
// tile.setLabel(getString(R.string.tileservice_name));
// tile.setIcon(android.graphics.drawable.Icon.createWithResource(this, R.drawable.ic_cloud_outline));
// tile.updateTile();
}
@Override
public void onClick() {
super.onClick();
Tile tile = getQsTile();
MainServiceBean bean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (bean == null) {
bean = new MainServiceBean();
}
if (tile.getState() == Tile.STATE_ACTIVE) {
bean.setIsEnable(false);
MainServiceBean.saveBean(this, bean);
MainService.stopMainService(this);
} else if (tile.getState() == Tile.STATE_INACTIVE) {
bean.setIsEnable(true);
MainServiceBean.saveBean(this, bean);
MainService.startMainService(this);
}
updateServiceIconStatus(this);
}
public static void updateServiceIconStatus(Context context) {
if (_MyTileService == null) {
return;
}
Tile tile = _MyTileService.getQsTile();
MainServiceBean bean = MainServiceBean.loadBean(context, MainServiceBean.class);
if (bean != null && bean.isEnable()) {
tile.setState(Tile.STATE_ACTIVE);
tile.setIcon(android.graphics.drawable.Icon.createWithResource(context, R.drawable.ic_cloud));
} else {
tile.setState(Tile.STATE_INACTIVE);
tile.setIcon(android.graphics.drawable.Icon.createWithResource(context, R.drawable.ic_cloud_outline));
}
tile.updateTile();
}
}

View File

@@ -0,0 +1,82 @@
package cc.winboll.studio.appbase;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/28 15:34:16
* @Describe 应用活动窗口基类
*/
import android.app.Activity;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import cc.winboll.studio.appbase.App;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.dialogs.YesNoAlertDialog;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
import cc.winboll.studio.libappbase.winboll.WinBollActivityManager;
public class WinBollActivityBase extends AppCompatActivity implements IWinBollActivity {
public static final String TAG = "WinBollActivityBase";
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
WinBollActivityManager getWinBollActivityManager() {
return WinBollActivityManager.getInstance(GlobalApplication.getInstance());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWinBollActivityManager().add(this);
}
@Override
public void onPostCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onPostCreate(savedInstanceState, persistentState);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
} else if(item.getItemId() == cc.winboll.studio.appbase.R.id.item_minimal) {
//moveTaskToBack(true);
exit();
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
}
void exit() {
YesNoAlertDialog.show(this, "Exit " + getString(R.string.app_name), "Close all activity and exit?", new YesNoAlertDialog.OnDialogResultListener(){
@Override
public void onYes() {
App.getWinBollActivityManager().finishAll();
}
@Override
public void onNo() {
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
getWinBollActivityManager().registeRemove(this);
}
}

View File

@@ -0,0 +1,83 @@
package cc.winboll.studio.appbase.activities;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/25 11:46:40
* @Describe 测试窗口2
*/
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.WinBollActivityBase;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
public class New2Activity extends WinBollActivityBase implements IWinBollActivity {
public static final String TAG = "New2Activity";
Toolbar mToolbar;
//LogView mLogView;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new2);
// mLogView = findViewById(R.id.logview);
// mLogView.start();
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
}
@Override
protected void onResume() {
super.onResume();
//mLogView.start();
}
public void onCloseThisActivity(View view) {
GlobalApplication.getWinBollActivityManager().finish(this);
}
public void onCloseAllActivity(View view) {
GlobalApplication.getWinBollActivityManager().finishAll();
}
public void onNewActivity(View view) {
GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, NewActivity.class);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu);
getMenuInflater().inflate(R.menu.toolbar_appbase, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
}
}

View File

@@ -0,0 +1,81 @@
package cc.winboll.studio.appbase.activities;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/25 05:04:22
*/
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.WinBollActivityBase;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.winboll.IWinBollActivity;
public class NewActivity extends WinBollActivityBase implements IWinBollActivity {
public static final String TAG = "NewActivity";
Toolbar mToolbar;
//LogView mLogView;
@Override
public Activity getActivity() {
return this;
}
@Override
public String getTag() {
return TAG;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new);
// mLogView = findViewById(R.id.logview);
// mLogView.start();
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
}
@Override
protected void onResume() {
super.onResume();
//mLogView.start();
}
public void onCloseThisActivity(View view) {
GlobalApplication.getWinBollActivityManager().finish(this);
}
public void onCloseAllActivity(View view) {
GlobalApplication.getWinBollActivityManager().finishAll();
}
public void onNew2Activity(View view) {
GlobalApplication.getWinBollActivityManager().startWinBollActivity(this, New2Activity.class);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_main, menu);
getMenuInflater().inflate(R.menu.toolbar_appbase, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == cc.winboll.studio.appbase.R.id.item_log) {
GlobalApplication.getWinBollActivityManager().startLogActivity(this);
return true;
}
// 在switch语句中处理每个ID并在处理完后返回true未处理的情况返回false。
return super.onOptionsItemSelected(item);
}
}

View File

@@ -0,0 +1,38 @@
package cc.winboll.studio.appbase.handlers;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/14 03:51:40
*/
import android.os.Handler;
import android.os.Message;
import cc.winboll.studio.appbase.services.MainService;
import java.lang.ref.WeakReference;
public class MainServiceHandler extends Handler {
public static final String TAG = "MainServiceHandler";
public static final int MSG_REMINDTHREAD = 0;
WeakReference<MainService> serviceWeakReference;
public MainServiceHandler(MainService service) {
serviceWeakReference = new WeakReference<MainService>(service);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REMINDTHREAD: // 处理下载完成消息更新UI
{
// 显示提醒消息
//
//LogUtils.d(TAG, "显示提醒消息");
MainService mainService = serviceWeakReference.get();
if (mainService != null) {
mainService.appenMessage((String)msg.obj);
}
break;
}
}
}
}

View File

@@ -0,0 +1,67 @@
package cc.winboll.studio.appbase.models;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/13 07:06:13
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class MainServiceBean extends BaseBean {
public static final String TAG = "MainServiceBean";
boolean isEnable;
public MainServiceBean() {
this.isEnable = false;
}
public void setIsEnable(boolean isEnable) {
this.isEnable = isEnable;
}
public boolean isEnable() {
return isEnable;
}
@Override
public String getName() {
return MainServiceBean.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("isEnable").value(isEnable());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("isEnable")) {
setIsEnable(jsonReader.nextBoolean());
} else {
return false;
}
}
return true;
}
@Override
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (!initObjectsFromJsonReader(jsonReader, name)) {
jsonReader.skipValue();
}
}
// 结束 JSON 对象
jsonReader.endObject();
return this;
}
}

View File

@@ -0,0 +1,67 @@
package cc.winboll.studio.appbase.models;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/07 12:47:22
* @Describe TestServiceBean
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class TestDemoBindServiceBean extends BaseBean {
public static final String TAG = "TestServiceBean";
boolean isEnable;
public TestDemoBindServiceBean() {
this.isEnable = false;
}
public void setIsEnable(boolean isEnable) {
this.isEnable = isEnable;
}
public boolean isEnable() {
return isEnable;
}
@Override
public String getName() {
return TestDemoBindServiceBean.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("isEnable").value(isEnable());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("isEnable")) {
setIsEnable(jsonReader.nextBoolean());
} else {
return false;
}
}
return true;
}
@Override
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (!initObjectsFromJsonReader(jsonReader, name)) {
jsonReader.skipValue();
}
}
// 结束 JSON 对象
jsonReader.endObject();
return this;
}
}

View File

@@ -0,0 +1,68 @@
package cc.winboll.studio.appbase.models;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/07 12:49:21
* @Describe TestDemoServiceBean
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class TestDemoServiceBean extends BaseBean {
public static final String TAG = "TestDemoServiceBean";
boolean isEnable;
public TestDemoServiceBean() {
this.isEnable = false;
}
public void setIsEnable(boolean isEnable) {
this.isEnable = isEnable;
}
public boolean isEnable() {
return isEnable;
}
@Override
public String getName() {
return TestDemoServiceBean.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("isEnable").value(isEnable());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("isEnable")) {
setIsEnable(jsonReader.nextBoolean());
} else {
return false;
}
}
return true;
}
@Override
public BaseBean readBeanFromJsonReader(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (!initObjectsFromJsonReader(jsonReader, name)) {
jsonReader.skipValue();
}
}
// 结束 JSON 对象
jsonReader.endObject();
return this;
}
}

View File

@@ -0,0 +1,72 @@
package cc.winboll.studio.appbase.models;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/17 10:05:09
* @Describe APPSOSReportBean
*/
import android.util.JsonReader;
import android.util.JsonWriter;
import cc.winboll.studio.libappbase.BaseBean;
import java.io.IOException;
public class WinBollNewsBean extends BaseBean {
public static final String TAG = "WinBollNewsBean";
protected String message;
public WinBollNewsBean() {
this.message = "";
}
public WinBollNewsBean(String message) {
this.message = message;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
@Override
public String getName() {
return WinBollNewsBean.class.getName();
}
@Override
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
super.writeThisToJsonWriter(jsonWriter);
jsonWriter.name("message").value(getMessage());
}
@Override
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
if (name.equals("message")) {
setMessage(jsonReader.nextString());
} 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;
}
}

View File

@@ -0,0 +1,36 @@
package cc.winboll.studio.appbase.receivers;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/24 07:11:44
*/
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
import cc.winboll.studio.libappbase.LogUtils;
public class APPNewsWidgetClickListener extends BroadcastReceiver {
public static final String TAG = "APPNewsWidgetClickListener";
public static final String ACTION_PRE = APPNewsWidgetClickListener.class.getName() + ".ACTION_PRE";
public static final String ACTION_NEXT = APPNewsWidgetClickListener.class.getName() + ".ACTION_NEXT";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null) {
LogUtils.d(TAG, String.format("action %s", action));
return;
}
if (action.equals(ACTION_PRE)) {
LogUtils.d(TAG, "ACTION_PRE");
APPNewsWidget.prePage(context);
} else if (action.equals(ACTION_NEXT)) {
LogUtils.d(TAG, "ACTION_NEXT");
APPNewsWidget.nextPage(context);
} else {
LogUtils.d(TAG, String.format("action %s", action));
}
}
}

View File

@@ -0,0 +1,117 @@
package cc.winboll.studio.appbase.receivers;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/13 06:58:04
* @Describe 主要广播接收器
*/
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import cc.winboll.studio.appbase.models.WinBollNewsBean;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
import cc.winboll.studio.libappbase.AppUtils;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.APPModel;
import cc.winboll.studio.libappbase.sos.SOS;
import cc.winboll.studio.libappbase.sos.SOSObject;
import cc.winboll.studio.libappbase.sos.WinBoll;
import cc.winboll.studio.libappbase.utils.ToastUtils;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainReceiver extends BroadcastReceiver {
public static final String TAG = "MainReceiver";
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
WeakReference<MainService> mwrService;
public MainReceiver(MainService service) {
mwrService = new WeakReference<MainService>(service);
}
@Override
public void onReceive(Context context, Intent intent) {
String szAction = intent.getAction();
if (szAction.equals(ACTION_BOOT_COMPLETED)) {
ToastUtils.show("ACTION_BOOT_COMPLETED");
} else if (szAction.equals(WinBoll.ACTION_BIND)) {
LogUtils.d(TAG, "ACTION_BIND");
LogUtils.d(TAG, String.format("context.getPackageName() %s", context.getPackageName()));
LogUtils.d(TAG, String.format("intent.getAction() %s", intent.getAction()));
String szAPPModel = intent.getStringExtra(WinBoll.EXTRA_APPMODEL);
LogUtils.d(TAG, String.format("szAPPModel %s", szAPPModel));
if (szAPPModel != null && !szAPPModel.equals("")) {
try {
APPModel bean = APPModel.parseStringToBean(szAPPModel, APPModel.class);
if (bean != null) {
String szAppPackageName = bean.getAppPackageName();
LogUtils.d(TAG, String.format("szAppPackageName %s", szAppPackageName));
String szAppMainServiveName = bean.getAppMainServiveName();
LogUtils.d(TAG, String.format("szAppMainServiveName %s", szAppMainServiveName));
mwrService.get().bindAPPModelConnection(bean);
}
} catch (IOException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
} else if (intent.getAction().equals(SOS.ACTION_SOS)) {
LogUtils.d(TAG, "ACTION_SOS");
String sos = intent.getStringExtra(SOS.EXTRA_OBJECT);
LogUtils.d(TAG, String.format("SOS %s", sos));
if (sos != null && !sos.equals("")) {
SOSObject bean = SOS.parseSOSObject(sos);
if (bean != null) {
String szObjectPackageName = bean.getObjectPackageName();
LogUtils.d(TAG, String.format("szObjectPackageName %s", szObjectPackageName));
String szObjectServiveName = bean.getObjectServiveName();
LogUtils.d(TAG, String.format("szObjectServiveName %s", szObjectServiveName));
Intent intentService = new Intent();
intentService.setComponent(new ComponentName(szObjectPackageName, szObjectServiveName));
context.startService(intentService);
String appName = AppUtils.getAppNameByPackageName(context, szObjectPackageName);
LogUtils.d(TAG, String.format("appName %s", appName));
WinBollNewsBean appWinBollNewsBean = new WinBollNewsBean(appName);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currentTime = sdf.format(new Date());
StringBuilder sbLine = new StringBuilder();
sbLine.append("[");
sbLine.append(currentTime);
sbLine.append("] Power to ");
sbLine.append(appName);
appWinBollNewsBean.setMessage(sbLine.toString());
APPNewsWidget.addWinBollNewsBean(context, appWinBollNewsBean);
Intent intentWidget = new Intent(context, APPNewsWidget.class);
intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT);
context.sendBroadcast(intentWidget);
}
}
} else {
ToastUtils.show(szAction);
}
}
// 注册 Receiver
//
public void registerAction(MainService service) {
IntentFilter filter=new IntentFilter();
filter.addAction(ACTION_BOOT_COMPLETED);
filter.addAction(SOS.ACTION_SOS);
filter.addAction(WinBoll.ACTION_BIND);
//filter.addAction(Intent.ACTION_BATTERY_CHANGED);
service.registerReceiver(this, filter);
}
}

View File

@@ -0,0 +1,138 @@
package cc.winboll.studio.appbase.services;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/14 03:38:31
* @Describe 守护进程服务
*/
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import cc.winboll.studio.appbase.models.MainServiceBean;
import cc.winboll.studio.appbase.services.AssistantService;
import cc.winboll.studio.appbase.services.MainService;
import cc.winboll.studio.libappbase.LogUtils;
import android.os.Binder;
public class AssistantService extends Service {
public static final String TAG = "AssistantService";
MainServiceBean mMainServiceBean;
MyServiceConnection mMyServiceConnection;
MainService mMainService;
boolean isBound = false;
volatile boolean isThreadAlive = false;
public synchronized void setIsThreadAlive(boolean isThreadAlive) {
LogUtils.d(TAG, "setIsThreadAlive(...)");
LogUtils.d(TAG, String.format("isThreadAlive %s", isThreadAlive));
this.isThreadAlive = isThreadAlive;
}
public boolean isThreadAlive() {
return isThreadAlive;
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
LogUtils.d(TAG, "onCreate");
super.onCreate();
//mMyBinder = new MyBinder();
if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection();
}
// 设置运行参数
setIsThreadAlive(false);
assistantService();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.d(TAG, "call onStartCommand(...)");
assistantService();
return START_STICKY;
}
@Override
public void onDestroy() {
//LogUtils.d(TAG, "onDestroy");
setIsThreadAlive(false);
// 解除绑定
if (isBound) {
unbindService(mMyServiceConnection);
isBound = false;
}
super.onDestroy();
}
// 运行服务内容
//
void assistantService() {
LogUtils.d(TAG, "assistantService()");
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
LogUtils.d(TAG, String.format("mMainServiceBean.isEnable() %s", mMainServiceBean.isEnable()));
if (mMainServiceBean.isEnable()) {
LogUtils.d(TAG, String.format("mIsThreadAlive %s", isThreadAlive()));
if (isThreadAlive() == false) {
// 设置运行状态
setIsThreadAlive(true);
// 唤醒和绑定主进程
wakeupAndBindMain();
}
}
}
// 唤醒和绑定主进程
//
void wakeupAndBindMain() {
LogUtils.d(TAG, "wakeupAndBindMain()");
// 绑定服务的Intent
Intent intent = new Intent(this, MainService.class);
startService(new Intent(this, MainService.class));
bindService(intent, mMyServiceConnection, Context.BIND_IMPORTANT);
// startService(new Intent(this, MainService.class));
// bindService(new Intent(AssistantService.this, MainService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
}
// 主进程与守护进程连接时需要用到此类
//
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogUtils.d(TAG, "onServiceConnected(...)");
MainService.MyBinder binder = (MainService.MyBinder) service;
mMainService = binder.getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtils.d(TAG, "onServiceDisconnected(...)");
mMainServiceBean = MainServiceBean.loadBean(AssistantService.this, MainServiceBean.class);
if (mMainServiceBean.isEnable()) {
wakeupAndBindMain();
}
isBound = false;
mMainService = null;
}
}
// 用于返回服务实例的Binder
public class MyBinder extends Binder {
AssistantService getService() {
LogUtils.d(TAG, "AssistantService MyBinder getService()");
return AssistantService.this;
}
}
}

View File

@@ -0,0 +1,316 @@
package cc.winboll.studio.appbase.services;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/13 06:56:41
* @Describe 拨号主服务
* 参考:
* 进程保活-双进程守护的正确姿势
* https://blog.csdn.net/sinat_35159441/article/details/75267380
* Android Service之onStartCommand方法研究
* https://blog.csdn.net/cyp331203/article/details/38920491
*/
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.appbase.MyTileService;
import cc.winboll.studio.appbase.models.MainServiceBean;
import cc.winboll.studio.appbase.handlers.MainServiceHandler;
import cc.winboll.studio.appbase.receivers.MainReceiver;
import cc.winboll.studio.appbase.services.AssistantService;
import cc.winboll.studio.appbase.threads.MainServiceThread;
import cc.winboll.studio.appbase.widgets.APPNewsWidget;
import cc.winboll.studio.libappbase.LogUtils;
import java.util.ArrayList;
import cc.winboll.studio.libappbase.sos.APPModel;
public class MainService extends Service {
public static final String TAG = "MainService";
public static final int MSG_UPDATE_STATUS = 0;
static MainService _mControlCenterService;
volatile boolean isServiceRunning;
MainServiceBean mMainServiceBean;
MainServiceThread mMainServiceThread;
MainServiceHandler mMainServiceHandler;
MyServiceConnection mMyServiceConnection;
AssistantService mAssistantService;
boolean isBound = false;
MainReceiver mMainReceiver;
ArrayList<APPConnection> mAPPModelConnectionList;
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public MainServiceThread getRemindThread() {
return mMainServiceThread;
}
@Override
public void onCreate() {
super.onCreate();
LogUtils.d(TAG, "onCreate()");
mAPPModelConnectionList = new ArrayList<APPConnection>();
_mControlCenterService = MainService.this;
isServiceRunning = false;
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (mMyServiceConnection == null) {
mMyServiceConnection = new MyServiceConnection();
}
mMainServiceHandler = new MainServiceHandler(this);
// 运行服务内容
mainService();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.d(TAG, "onStartCommand(...)");
// 运行服务内容
mainService();
return (mMainServiceBean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
}
// 运行服务内容
//
void mainService() {
LogUtils.d(TAG, "mainService()");
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (mMainServiceBean.isEnable() && isServiceRunning == false) {
LogUtils.d(TAG, "mainService() start running");
isServiceRunning = true;
// 唤醒守护进程
wakeupAndBindAssistant();
if (mMainReceiver == null) {
// 注册广播接收器
mMainReceiver = new MainReceiver(this);
mMainReceiver.registerAction(this);
}
// 启动小部件
Intent intentTimeWidget = new Intent(this, APPNewsWidget.class);
intentTimeWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT);
this.sendBroadcast(intentTimeWidget);
startMainServiceThread();
MyTileService.updateServiceIconStatus(this);
LogUtils.i(TAG, "Main Service Is Start.");
}
}
// 唤醒和绑定守护进程
//
void wakeupAndBindAssistant() {
LogUtils.d(TAG, "wakeupAndBindAssistant()");
Intent intent = new Intent(this, AssistantService.class);
startService(intent);
// 绑定服务的Intent
bindService(intent, mMyServiceConnection, Context.BIND_IMPORTANT);
}
// 开启提醒铃声线程
//
public void startMainServiceThread() {
LogUtils.d(TAG, "startMainServiceThread");
if (mMainServiceThread == null) {
mMainServiceThread = new MainServiceThread(this, mMainServiceHandler);
LogUtils.d(TAG, "new MainServiceThread");
} else {
if (mMainServiceThread.isExist() == true) {
mMainServiceThread = new MainServiceThread(this, mMainServiceHandler);
LogUtils.d(TAG, "renew MainServiceThread");
} else {
// 提醒进程正在进行中就更新状态后退出
LogUtils.d(TAG, "A mMainServiceThread running.");
return;
}
}
mMainServiceThread.start();
}
public void stopRemindThread() {
if (mMainServiceThread != null) {
mMainServiceThread.setIsExist(true);
mMainServiceThread = null;
}
}
@Override
public void onDestroy() {
//LogUtils.d(TAG, "onDestroy");
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
if (mMainServiceBean.isEnable() == false) {
// 设置运行状态
isServiceRunning = false;// 解除绑定
if (isBound) {
unbindService(mMyServiceConnection);
isBound = false;
}
// 停止守护进程
Intent intent = new Intent(this, AssistantService.class);
stopService(intent);
// 停止Receiver
if (mMainReceiver != null) {
unregisterReceiver(mMainReceiver);
mMainReceiver = null;
}
// 停止前台通知栏
stopForeground(true);
// 停止消息提醒进程
stopRemindThread();
MyTileService.updateServiceIconStatus(this);
super.onDestroy();
//LogUtils.d(TAG, "onDestroy done");
}
}
public void bindAPPModelConnection(APPModel bean) {
LogUtils.d(TAG, "bindAPPModelConnection(...)");
// 清理旧的绑定链接
for (int i = mAPPModelConnectionList.size() - 1; i > -1; i--) {
APPConnection item = mAPPModelConnectionList.get(i);
if (item.isBindToAPP(bean)) {
LogUtils.d(TAG, "Bind Servive exist.");
unbindService(item);
mAPPModelConnectionList.remove(i);
}
}
// 绑定服务
APPConnection appConnection = new APPConnection();
Intent intentService = new Intent();
intentService.setComponent(new ComponentName(bean.getAppPackageName(), bean.getAppMainServiveName()));
bindService(intentService, appConnection, Context.BIND_IMPORTANT);
mAPPModelConnectionList.add(appConnection);
Intent intentWidget = new Intent(this, APPNewsWidget.class);
intentWidget.setAction(APPNewsWidget.ACTION_WAKEUP_SERVICE);
APPModel appSOSBean = new APPModel(bean.getAppPackageName(), bean.getAppMainServiveName());
intentWidget.putExtra("APPSOSBean", appSOSBean.toString());
sendBroadcast(intentWidget);
}
public class APPConnection implements ServiceConnection {
ComponentName mComponentName;
boolean isBindToAPP(APPModel bean) {
return mComponentName != null
&& mComponentName.getClassName().equals(bean.getAppMainServiveName())
&& mComponentName.getPackageName().equals(bean.getAppPackageName());
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogUtils.d(TAG, "onServiceConnected(...)");
mComponentName = name;
LogUtils.d(TAG, String.format("onServiceConnected : \ngetClassName %s\ngetPackageName %s", name.getClassName(), name.getPackageName()));
}
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtils.d(TAG, "onServiceDisconnected(...)");
LogUtils.d(TAG, String.format("onServiceDisconnected : \ngetClassName %s\ngetPackageName %s", name.getClassName(), name.getPackageName()));
// 尝试无参数启动一下服务
String appPackage = mComponentName.getPackageName();
LogUtils.d(TAG, String.format("appPackage %s", appPackage));
String appMainServiceClassName = mComponentName.getClassName();
LogUtils.d(TAG, String.format("appMainServiceClassName %s", appMainServiceClassName));
Intent intentService = new Intent();
intentService.setComponent(new ComponentName(appPackage, appMainServiceClassName));
startService(intentService);
}
}
// 主进程与守护进程连接时需要用到此类
//
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LogUtils.d(TAG, "onServiceConnected(...)");
AssistantService.MyBinder binder = (AssistantService.MyBinder) service;
mAssistantService = binder.getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
LogUtils.d(TAG, "onServiceDisconnected(...)");
if (mMainServiceBean.isEnable()) {
// 唤醒守护进程
wakeupAndBindAssistant();
}
isBound = false;
mAssistantService = null;
}
}
// 用于返回服务实例的Binder
public class MyBinder extends Binder {
MainService getService() {
LogUtils.d(TAG, "MainService MyBinder getService()");
return MainService.this;
}
}
// //
// // 启动服务
// //
// public static void startControlCenterService(Context context) {
// Intent intent = new Intent(context, MainService.class);
// context.startForegroundService(intent);
// }
//
// //
// // 停止服务
// //
// public static void stopControlCenterService(Context context) {
// Intent intent = new Intent(context, MainService.class);
// context.stopService(intent);
// }
public void appenMessage(String message) {
LogUtils.d(TAG, String.format("Message : %s", message));
}
public static void stopMainService(Context context) {
LogUtils.d(TAG, "stopMainService");
MainServiceBean bean = new MainServiceBean();
bean.setIsEnable(false);
MainServiceBean.saveBean(context, bean);
context.stopService(new Intent(context, MainService.class));
}
public static void startMainService(Context context) {
LogUtils.d(TAG, "startMainService");
MainServiceBean bean = new MainServiceBean();
bean.setIsEnable(true);
MainServiceBean.saveBean(context, bean);
context.startService(new Intent(context, MainService.class));
}
}

View File

@@ -0,0 +1,178 @@
package cc.winboll.studio.appbase.services;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/07 12:45:49
* @Describe 启动时申请绑定到APPBase主服务的服务示例
*/
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.appbase.models.TestDemoBindServiceBean;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.WinBoll;
import cc.winboll.studio.appbase.App;
import cc.winboll.studio.libappbase.sos.SOS;
public class TestDemoBindService extends Service {
public static final String TAG = "TestDemoBindService";
public static final String ACTION_ENABLE = TestDemoBindService.class.getName() + ".ACTION_ENABLE";
public static final String ACTION_DISABLE = TestDemoBindService.class.getName() + ".ACTION_DISABLE";
volatile static TestThread _TestThread;
volatile static boolean _IsRunning;
public synchronized static void setIsRunning(boolean isRunning) {
_IsRunning = isRunning;
}
public static boolean isRunning() {
return _IsRunning;
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public class MyBinder extends Binder {
public TestDemoBindService getService() {
return TestDemoBindService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
LogUtils.d(TAG, "onCreate()");
run();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.d(TAG, "onStartCommand(...)");
TestDemoBindServiceBean bean = TestDemoBindServiceBean.loadBean(this, TestDemoBindServiceBean.class);
if (bean == null) {
bean = new TestDemoBindServiceBean();
}
if (intent.getAction() != null) {
if (intent.getAction().equals(ACTION_ENABLE)) {
bean.setIsEnable(true);
LogUtils.d(TAG, "setIsEnable(true);");
TestDemoBindServiceBean.saveBean(this, bean);
} else if (intent.getAction().equals(ACTION_DISABLE)) {
bean.setIsEnable(false);
LogUtils.d(TAG, "setIsEnable(false);");
TestDemoBindServiceBean.saveBean(this, bean);
}
}
run();
return (bean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
//return super.onStartCommand(intent, flags, startId);
}
void run() {
LogUtils.d(TAG, "run()");
TestDemoBindServiceBean bean = TestDemoBindServiceBean.loadBean(this, TestDemoBindServiceBean.class);
if (bean == null) {
bean = new TestDemoBindServiceBean();
TestDemoBindServiceBean.saveBean(this, bean);
}
if (bean.isEnable()) {
LogUtils.d(TAG, "run() bean.isEnable()");
TestThread.getInstance(this).start();
LogUtils.d(TAG, "_TestThread.start()");
}
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtils.d(TAG, "onDestroy()");
TestDemoBindServiceBean bean = TestDemoBindServiceBean.loadBean(this, TestDemoBindServiceBean.class);
if (bean == null) {
bean = new TestDemoBindServiceBean();
}
TestThread.getInstance(this).setIsExit(true);
// 预防 APPBase 应用重启绑定失效。
// 所以退出时检查本服务是否配置启用,如果启用就发送一个 SOS 信号。
// 这样 APPBase 就会用组件方式启动本服务。
if (bean.isEnable()) {
if (App.isDebuging()) {
SOS.sosToAppBaseBeta(this, TestDemoBindService.class.getName());
} else {
SOS.sosToAppBase(this, TestDemoBindService.class.getName());
}
}
_IsRunning = false;
}
static class TestThread extends Thread {
volatile static TestThread _TestThread;
Context mContext;
volatile boolean isStarted = false;
volatile boolean isExit = false;
TestThread(Context context) {
super();
mContext = context;
}
public static synchronized TestThread getInstance(Context context) {
if (_TestThread != null) {
_TestThread.setIsExit(true);
}
_TestThread = new TestThread(context);
return _TestThread;
}
public synchronized void setIsExit(boolean isExit) {
this.isExit = isExit;
}
public boolean isExit() {
return isExit;
}
@Override
public void run() {
if (isStarted == false) {
isStarted = true;
super.run();
LogUtils.d(TAG, "run() start");
if (App.isDebuging()) {
WinBoll.bindToAPPBaseBeta(mContext, TestDemoBindService.class.getName());
} else {
WinBoll.bindToAPPBase(mContext, TestDemoBindService.class.getName());
}
while (!isExit()) {
LogUtils.d(TAG, "run()");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
LogUtils.d(TAG, "run() exit");
}
}
}
}

View File

@@ -0,0 +1,156 @@
package cc.winboll.studio.appbase.services;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/03/07 12:39:24
* @Describe 普通服务示例
*/
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.appbase.models.TestDemoServiceBean;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.WinBoll;
public class TestDemoService extends Service {
public static final String TAG = "TestDemoService";
public static final String ACTION_ENABLE = TestDemoService.class.getName() + ".ACTION_ENABLE";
public static final String ACTION_DISABLE = TestDemoService.class.getName() + ".ACTION_DISABLE";
volatile static TestThread _TestThread;
volatile static boolean _IsRunning;
public synchronized static void setIsRunning(boolean isRunning) {
_IsRunning = isRunning;
}
public static boolean isRunning() {
return _IsRunning;
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public class MyBinder extends Binder {
public TestDemoService getService() {
return TestDemoService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
LogUtils.d(TAG, "onCreate()");
run();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LogUtils.d(TAG, "onStartCommand(...)");
TestDemoServiceBean bean = TestDemoServiceBean.loadBean(this, TestDemoServiceBean.class);
if (bean == null) {
bean = new TestDemoServiceBean();
}
if (intent.getAction() != null) {
if (intent.getAction().equals(ACTION_ENABLE)) {
bean.setIsEnable(true);
LogUtils.d(TAG, "setIsEnable(true);");
TestDemoServiceBean.saveBean(this, bean);
} else if (intent.getAction().equals(ACTION_DISABLE)) {
bean.setIsEnable(false);
LogUtils.d(TAG, "setIsEnable(false);");
TestDemoServiceBean.saveBean(this, bean);
}
}
run();
return (bean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
//return super.onStartCommand(intent, flags, startId);
}
void run() {
LogUtils.d(TAG, "run()");
TestDemoServiceBean bean = TestDemoServiceBean.loadBean(this, TestDemoServiceBean.class);
if (bean == null) {
bean = new TestDemoServiceBean();
TestDemoServiceBean.saveBean(this, bean);
}
if (bean.isEnable()) {
LogUtils.d(TAG, "run() bean.isEnable()");
TestThread.getInstance(this).start();
LogUtils.d(TAG, "_TestThread.start()");
}
}
@Override
public void onDestroy() {
super.onDestroy();
LogUtils.d(TAG, "onDestroy()");
TestThread.getInstance(this).setIsExit(true);
_IsRunning = false;
}
static class TestThread extends Thread {
volatile static TestThread _TestThread;
Context mContext;
volatile boolean isStarted = false;
volatile boolean isExit = false;
TestThread(Context context) {
super();
mContext = context;
}
public static synchronized TestThread getInstance(Context context) {
if (_TestThread != null) {
_TestThread.setIsExit(true);
}
_TestThread = new TestThread(context);
return _TestThread;
}
public synchronized void setIsExit(boolean isExit) {
this.isExit = isExit;
}
public boolean isExit() {
return isExit;
}
@Override
public void run() {
if (isStarted == false) {
isStarted = true;
super.run();
LogUtils.d(TAG, "run() start");
while (!isExit()) {
LogUtils.d(TAG, "run()");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
LogUtils.d(TAG, "run() exit");
}
}
}
}

View File

@@ -0,0 +1,54 @@
package cc.winboll.studio.appbase.threads;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/14 03:46:44
*/
import android.content.Context;
import cc.winboll.studio.appbase.handlers.MainServiceHandler;
import cc.winboll.studio.libappbase.LogUtils;
import java.lang.ref.WeakReference;
public class MainServiceThread extends Thread {
public static final String TAG = "MainServiceThread";
Context mContext;
// 控制线程是否退出的标志
volatile boolean isExist = false;
// 服务Handler, 用于线程发送消息使用
WeakReference<MainServiceHandler> mwrMainServiceHandler;
public void setIsExist(boolean isExist) {
this.isExist = isExist;
}
public boolean isExist() {
return isExist;
}
public MainServiceThread(Context context, MainServiceHandler handler) {
mContext = context;
mwrMainServiceHandler = new WeakReference<MainServiceHandler>(handler);
}
@Override
public void run() {
LogUtils.d(TAG, "run()");
while (!isExist()) {
//ToastUtils.show("run()");
//LogUtils.d(TAG, "run()");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
LogUtils.d(TAG, "run() exit.");
}
}

View File

@@ -0,0 +1,186 @@
package cc.winboll.studio.appbase.widgets;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/15 14:41:25
* @Describe TimeWidget
*/
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import cc.winboll.studio.appbase.R;
import cc.winboll.studio.appbase.models.WinBollNewsBean;
import cc.winboll.studio.appbase.receivers.APPNewsWidgetClickListener;
import cc.winboll.studio.libappbase.AppUtils;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.sos.APPModel;
import cc.winboll.studio.libappbase.sos.WinBoll;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
public class APPNewsWidget extends AppWidgetProvider {
public static final String TAG = "APPNewsWidget";
public static final String ACTION_WAKEUP_SERVICE = APPNewsWidget.class.getName() + ".ACTION_WAKEUP_SERVICE";
public static final String ACTION_RELOAD_REPORT = APPNewsWidget.class.getName() + ".ACTION_RELOAD_REPORT";
volatile static ArrayList<WinBollNewsBean> _WinBollNewsBeanList;
final static int _MAX_PAGES = 10;
final static int _OnePageLinesCount = 5;
volatile static int _CurrentPageIndex = 0;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
initWinBollNewsBeanList(context);
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
initWinBollNewsBeanList(context);
if (intent.getAction().equals(ACTION_RELOAD_REPORT)) {
LogUtils.d(TAG, "ACTION_RELOAD_REPORT");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPNewsWidget.class));
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}else if (intent.getAction().equals(ACTION_WAKEUP_SERVICE)) {
LogUtils.d(TAG, "ACTION_WAKEUP_SERVICE");
String szAPPModel = intent.getStringExtra(WinBoll.EXTRA_APPMODEL);
LogUtils.d(TAG, String.format("szAPPModel %s", szAPPModel));
if (szAPPModel != null && !szAPPModel.equals("")) {
try {
APPModel bean = APPModel.parseStringToBean(szAPPModel, APPModel.class);
if (bean != null) {
String szAppPackageName = bean.getAppPackageName();
LogUtils.d(TAG, String.format("szAppPackageName %s", szAppPackageName));
String szAppMainServiveName = bean.getAppMainServiveName();
LogUtils.d(TAG, String.format("szAppMainServiveName %s", szAppMainServiveName));
String appName = AppUtils.getAppNameByPackageName(context, szAppPackageName);
LogUtils.d(TAG, String.format("appName %s", appName));
WinBollNewsBean winBollNewsBean = new WinBollNewsBean(appName);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currentTime = sdf.format(new Date());
StringBuilder sbLine = new StringBuilder();
sbLine.append("[");
sbLine.append(currentTime);
sbLine.append("] Wake up ");
sbLine.append(appName);
winBollNewsBean.setMessage(sbLine.toString());
addWinBollNewsBean(context, winBollNewsBean);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPNewsWidget.class));
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
} catch (IOException e) {
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
}
}
}
}
//
// 加入新报告信息
//
public synchronized static void addWinBollNewsBean(Context context, WinBollNewsBean bean) {
initWinBollNewsBeanList(context);
_WinBollNewsBeanList.add(0, bean);
// 控制记录总数
while (_WinBollNewsBeanList.size() > _MAX_PAGES * _OnePageLinesCount) {
_WinBollNewsBeanList.remove(_WinBollNewsBeanList.size() - 1);
}
WinBollNewsBean.saveBeanList(context, _WinBollNewsBeanList, WinBollNewsBean.class);
}
synchronized static void initWinBollNewsBeanList(Context context) {
if (_WinBollNewsBeanList == null) {
_WinBollNewsBeanList = new ArrayList<WinBollNewsBean>();
WinBollNewsBean.loadBeanList(context, _WinBollNewsBeanList, WinBollNewsBean.class);
}
if (_WinBollNewsBeanList == null) {
_WinBollNewsBeanList = new ArrayList<WinBollNewsBean>();
WinBollNewsBean.saveBeanList(context, _WinBollNewsBeanList, WinBollNewsBean.class);
}
}
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
LogUtils.d(TAG, "updateAppWidget(...)");
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_news);
//设置按钮点击事件
Intent intentPre = new Intent(context, APPNewsWidgetClickListener.class);
intentPre.setAction(APPNewsWidgetClickListener.ACTION_PRE);
PendingIntent pendingIntentPre = PendingIntent.getBroadcast(context, 0, intentPre, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_button_pre, pendingIntentPre);
Intent intentNext = new Intent(context, APPNewsWidgetClickListener.class);
intentNext.setAction(APPNewsWidgetClickListener.ACTION_NEXT);
PendingIntent pendingIntentNext = PendingIntent.getBroadcast(context, 0, intentNext, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.widget_button_next, pendingIntentNext);
views.setTextViewText(R.id.tv_msg, getPageInfo());
views.setTextViewText(R.id.tv_news, getMessage());
appWidgetManager.updateAppWidget(appWidgetId, views);
}
public static String getMessage() {
ArrayList<String> msgTemp = new ArrayList<String>();
if (_WinBollNewsBeanList != null) {
int start = _OnePageLinesCount * _CurrentPageIndex;
start = _WinBollNewsBeanList.size() > start ? start : _WinBollNewsBeanList.size() - 1;
for (int i = start, j = 0; i < _WinBollNewsBeanList.size() && j < _OnePageLinesCount && start > -1; i++, j++) {
msgTemp.add(_WinBollNewsBeanList.get(i).getMessage());
}
String message = String.join("\n", msgTemp);
return message;
}
return "";
}
public static void prePage(Context context) {
if (_WinBollNewsBeanList != null) {
if (_CurrentPageIndex > 0) {
_CurrentPageIndex = _CurrentPageIndex - 1;
}
Intent intentWidget = new Intent(context, APPNewsWidget.class);
intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT);
context.sendBroadcast(intentWidget);
}
}
public static void nextPage(Context context) {
if (_WinBollNewsBeanList != null) {
if ((_CurrentPageIndex + 1) * _OnePageLinesCount < _WinBollNewsBeanList.size()) {
_CurrentPageIndex = _CurrentPageIndex + 1;
}
Intent intentWidget = new Intent(context, APPNewsWidget.class);
intentWidget.setAction(APPNewsWidget.ACTION_RELOAD_REPORT);
context.sendBroadcast(intentWidget);
}
}
String getPageInfo() {
if (_WinBollNewsBeanList == null) {
return "0/0";
}
int leftCount = _WinBollNewsBeanList.size() % _OnePageLinesCount;
int currentPageCount = _WinBollNewsBeanList.size() / _OnePageLinesCount + (leftCount == 0 ?0: 1);
return String.format("%d/%d", _CurrentPageIndex + 1, currentPageCount);
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M6.5,20Q4.22,20 2.61,18.43 1,16.85 1,14.58 1,12.63 2.17,11.1 3.35,9.57 5.25,9.15 5.88,6.85 7.75,5.43 9.63,4 12,4 14.93,4 16.96,6.04 19,8.07 19,11 20.73,11.2 21.86,12.5 23,13.78 23,15.5 23,17.38 21.69,18.69 20.38,20 18.5,20Z"/>
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ff000000"
android:pathData="M6.5,20Q4.22,20 2.61,18.43 1,16.85 1,14.58 1,12.63 2.17,11.1 3.35,9.57 5.25,9.15 5.88,6.85 7.75,5.43 9.63,4 12,4 14.93,4 16.96,6.04 19,8.07 19,11 20.73,11.2 21.86,12.5 23,13.78 23,15.5 23,17.38 21.69,18.69 20.38,20 18.5,20M6.5,18H18.5Q19.55,18 20.27,17.27 21,16.55 21,15.5 21,14.45 20.27,13.73 19.55,13 18.5,13H17V11Q17,8.93 15.54,7.46 14.08,6 12,6 9.93,6 8.46,7.46 7,8.93 7,11H6.5Q5.05,11 4.03,12.03 3,13.05 3,14.5 3,15.95 4.03,17 5.05,18 6.5,18M12,12Z"/>
</vector>

View File

@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toolbar"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0">
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, WinBoll!"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android版本10的代号是“Q”API级别是29。 Android 10开始谷歌不再公开使用甜品作为版本代号但内部仍保留了大量与“Q”相关的元素。Android 10本身并没有严格对应某个特定的Java版本但在开发Android 10应用时通常可以使用Java 8或更高版本。 Java 8为Android开发带来了诸如Lambda表达式、方法引用等新特性能提高开发效率和代码可读性与Android 10开发适配良好。Java 9及更高版本也可用于Android 10开发能使用一些新的语言特性和API但可能需要注意兼容性和配置问题。"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:gravity="right|center_vertical"
android:layout_width="wrap_content">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Debug Mode"
android:layout_weight="1.0"
android:onClick="onSwitchDebugMode"
android:id="@+id/activitymainCheckBox1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Application CrashReport"
android:textAllCaps="false"
android:onClick="onTestApplicationCrashReport"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PreviewGlobalCrashActivity"
android:textAllCaps="false"
android:onClick="onPreviewGlobalCrashActivity"/>
</LinearLayout>
</HorizontalScrollView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="400dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StartCenter"
android:textAllCaps="false"
android:onClick="onStartCenter"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopCenter"
android:textAllCaps="false"
android:onClick="onStopCenter"/>
</LinearLayout>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SartTestDemoService"
android:textAllCaps="false"
android:onClick="onSartTestDemoService"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopTestDemoService"
android:textAllCaps="false"
android:onClick="onStopTestDemoService"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopTestDemoServiceNoSettings"
android:textAllCaps="false"
android:onClick="onStopTestDemoServiceNoSettings"/>
</LinearLayout>
</HorizontalScrollView>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SartTestDemoBindService"
android:textAllCaps="false"
android:onClick="onSartTestDemoBindService"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopTestDemoBindService"
android:textAllCaps="false"
android:onClick="onStopTestDemoBindService"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StopTestDemoBindServiceNoSettings"
android:textAllCaps="false"
android:onClick="onStopTestDemoBindServiceNoSettings"/>
</LinearLayout>
</HorizontalScrollView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestStopMainServiceWithoutSettingEnable"
android:textAllCaps="false"
android:onClick="onTestStopMainServiceWithoutSettingEnable"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestUseComponentStartService"
android:textAllCaps="false"
android:onClick="onTestUseComponentStartService"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestDemoServiceSOS"
android:textAllCaps="false"
android:onClick="onTestDemoServiceSOS"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestOpenNewActivity"
android:textAllCaps="false"
android:onClick="onTestOpenNewActivity"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toolbar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NewActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CloseThisActivity"
android:textAllCaps="false"
android:onClick="onCloseThisActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CloseAllActivity"
android:textAllCaps="false"
android:onClick="onCloseAllActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New2Activity"
android:textAllCaps="false"
android:onClick="onNew2Activity"/>
</LinearLayout>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toolbar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New2Activity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CloseThisActivity"
android:textAllCaps="false"
android:onClick="onCloseThisActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CloseAllActivity"
android:textAllCaps="false"
android:onClick="onCloseAllActivity"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NewActivity"
android:textAllCaps="false"
android:onClick="onNewActivity"/>
</LinearLayout>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FFFFFFFF">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right|center_vertical">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/tv_title"
android:layout_weight="1.0"
android:text="WinBollNews"
android:textStyle="bold"
android:textSize="16sp"/>
<Button
android:layout_width="48dp"
android:layout_height="48dp"
android:text="⇦"
android:id="@+id/widget_button_pre"/>
<Button
android:layout_width="48dp"
android:layout_height="48dp"
android:text="⇨"
android:id="@+id/widget_button_next"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv_msg"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/tv_news"
android:layout_weight="1.0"/>
</LinearLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
</menu>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FF00B322</color>
<color name="colorPrimaryDark">#FF005C12</color>
<color name="colorAccent">#FF8DFFA2</color>
<color name="colorText">#FFFFFB8D</color>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">AppBase</string>
<string name="tileservice_name">WinBoll</string>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyAPPBaseTheme" parent="APPBaseTheme">
<item name="attrColorPrimary">@color/colorPrimary</item>
<item name="themeGlobalCrashActivity">@style/MyGlobalCrashActivityTheme</item>
</style>
<style name="MyGlobalCrashActivityTheme" parent="GlobalCrashActivityTheme">
<item name="colorTittle">#FFFFFFFF</item>
<item name="colorTittleBackgound">#FF00A4B3</item>
<item name="colorText">#FFFFFFFF</item>
<item name="colorTextBackgound">#FF000000</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="200dp"
android:minHeight="100dp"
android:updatePeriodMillis="1000"
android:initialLayout="@layout/widget_news">
</appwidget-provider>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<application>
<!-- Put flavor specific code here -->
</application>
</manifest>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Put flavor specific strings here -->
</resources>