Compare commits
	
		
			170 Commits
		
	
	
		
			appbase-v1
			...
			androiddem
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 3c36ed589a | ||
|   | 9768103741 | ||
|   | 787b8f0d77 | ||
|   | 1d58126fd8 | ||
|   | 7b5a3d2d71 | ||
|   | a988a9d4f6 | ||
|   | 04a67e666b | ||
|   | 348edc8aaf | ||
|   | 5970ae33c8 | ||
|   | 91a44f48ef | ||
|   | c66e9a090b | ||
|   | 7a14b55247 | ||
|   | fab68f16c8 | ||
|   | 3a97c6135f | ||
|   | cdad017d8c | ||
|   | bf84382963 | ||
|   | 34601fc5b1 | ||
|   | a40dbcfb61 | ||
|   | 4d344b299b | ||
|   | 37b0867d34 | ||
|   | cdfbb082d2 | ||
|   | 7e476894a7 | ||
|   | 0e8ae2e020 | ||
|   | 48623a2805 | ||
|   | b505156211 | ||
|   | 91b30fb576 | ||
|   | ab3ac72d54 | ||
|   | 73285c8779 | ||
|   | fa338ec8c7 | ||
|   | 7a3a1f4bcd | ||
|   | ea65810e7d | ||
|   | ad991e3da2 | ||
|   | 7e263447c8 | ||
|   | 80201e8370 | ||
|   | ea0473606a | ||
|   | 870e9a94fb | ||
|   | 2421ecb943 | ||
|   | 687fff7216 | ||
|   | 50d4cd830b | ||
|   | 2079822c00 | ||
|   | 297c76f328 | ||
|   | 43b18ee662 | ||
|   | 3ec3a4cfc2 | ||
|   | 2c10a9f38c | ||
|   | e62888636e | ||
|   | 364980dd02 | ||
|   | 0e155e4f3a | ||
|   | 89febba5a9 | ||
|   | 653330f8e1 | ||
|   | 386c73effc | ||
|   | b385583c5a | ||
|   | e7a9be2f56 | ||
|   | b27f7b0080 | ||
|   | 0a440419ff | ||
|   | 9e189ed5ac | ||
|   | 0fb6aadc72 | ||
|   | 46f3315b02 | ||
|   | c0ff228845 | ||
|   | a0fe8f17a8 | ||
|   | 16bd40fc59 | ||
|   | ffaf683c54 | ||
|   | 26f5f8d3db | ||
|   | 917e25cdc8 | ||
|   | 707bed52c7 | ||
|   | 3795cf8631 | ||
|   | b374f3117a | ||
|   | d581cd9842 | ||
|   | cef50d087d | ||
|   | 6d9adc124e | ||
|   | 52f738b45b | ||
|   | 9ece6778b7 | ||
|   | b7f8b76ace | ||
|   | 326e5fa68e | ||
|   | e9c8f9029e | ||
|   | c00bfa1292 | ||
|   | 11ee4dcf27 | ||
|   | 8974e24dce | ||
|   | 89142e379c | ||
|   | dabc671c27 | ||
|   | ed849e92d1 | ||
|   | 42d2522927 | ||
|   | 6a52b2a8c3 | ||
|   | 02ed5bd5d1 | ||
|   | b685665d0c | ||
|   | 1b030a2855 | ||
|   | dd577f1765 | ||
|   | 0f8350600d | ||
|   | 1777ebb8dc | ||
|   | 2b99f707e7 | ||
|   | 068c94e749 | ||
|   | 0b3bc7e296 | ||
|   | 6ef747bcf8 | ||
|   | a8e843c388 | ||
|   | d3fd593cb0 | ||
|   | 3aec176b8b | ||
|   | 5960f76238 | ||
|   | 1a118da827 | ||
|   | f73cad6f3e | ||
|   | 7130ecf023 | ||
|   | 953c8f08cd | ||
|   | 87b7557f72 | ||
|   | 77f5a156f8 | ||
|   | b34ea40536 | ||
|   | d202a3443d | ||
|   | 8c532c885f | ||
|   | 5fc4cb5f74 | ||
|   | 2a590a99fb | ||
|   | c6ad707ca2 | ||
|   | ee13a43fb6 | ||
|   | 5fbe1d8f71 | ||
|   | 38fe941a8b | ||
|   | e13c8e7af0 | ||
|   | a4988b5b68 | ||
|   | 04df902b6b | ||
|   | 33c71ea868 | ||
|   | 5507126f6b | ||
|   | d381c29452 | ||
|   | ba861d910e | ||
|   | f5d9aafe43 | ||
|   | eb61eb7306 | ||
|   | 31ad66685c | ||
|   | beb561ad6a | ||
|   | 8869265d60 | ||
|   | 2739627aff | ||
|   | 58e0be9cf4 | ||
|   | 9e9402f84e | ||
|   | ec18330022 | ||
|   | 8bb80ef575 | ||
|   | c1e6e32809 | ||
|   | 3e7722e2c0 | ||
|   | a1707e73b5 | ||
|   | 9dcbaa0d75 | ||
|   | 07b5e66875 | ||
|   | 91f5cf9051 | ||
|   | 0e3b9dc760 | ||
|   | 8730f434dd | ||
|   | f8944490f8 | ||
|   | 733af004f6 | ||
|   | c03568e1f5 | ||
|   | a0575a5e8b | ||
|   | 0e57ce679e | ||
|   | f9211a8eb4 | ||
|   | 4c31ff9b54 | ||
|   | 8cf610962e | ||
|   | 3071d186ec | ||
|   | df10306059 | ||
|   | ccdb9c5abd | ||
|   | f27209ab87 | ||
|   | 2a819e94e4 | ||
|   | 6635358ec5 | ||
|   | f53b222b7f | ||
|   | 0c0cde8406 | ||
|   | 46967065c0 | ||
|   | 8edbff5ac1 | ||
|   | 434f8a8549 | ||
|   | c04be60b13 | ||
|   | 641098f8fb | ||
|   | dba54ac4b2 | ||
|   | c6cd779889 | ||
|   | dfb1692a04 | ||
|   | c83c8f66b3 | ||
|   | cd7b5f38bf | ||
|   | 0c2e73b82e | ||
|   | 7b1838ff8e | ||
|   | 73ff3d1726 | ||
|   | a69572e216 | ||
|   | fa79c3f807 | ||
|   | fde4b275f7 | ||
|   | d66d9373ff | ||
|   | f32ed94e4e | 
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Sat Jun 28 12:59:51 HKT 2025 | ||||
| stageCount=3 | ||||
| #Sun Aug 31 23:40:17 HKT 2025 | ||||
| stageCount=4 | ||||
| libraryProject=libaes | ||||
| baseVersion=15.9 | ||||
| publishVersion=15.9.2 | ||||
| publishVersion=15.9.3 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.9.3 | ||||
| baseBetaVersion=15.9.4 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.aes; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/24 23:52:29 | ||||
|  * @Describe AES应用介绍窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.aes; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/13 19:03:58 | ||||
|  * @Describe AES应用类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.aes; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/13 19:05:52 | ||||
|  * @Describe 应用主窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -0,0 +1 @@ | ||||
|  | ||||
|   | ||||
| @@ -67,6 +67,6 @@ dependencies { | ||||
|     // https://mvnrepository.com/artifact/com.android.support/recyclerview-v7 | ||||
|     api 'com.android.support:recyclerview-v7:28.0.0' | ||||
|      | ||||
|     api 'cc.winboll.studio:libapputils:15.8.2' | ||||
|     api 'cc.winboll.studio:libappbase:15.8.2' | ||||
|     api 'cc.winboll.studio:libapputils:15.8.5' | ||||
|     api 'cc.winboll.studio:libappbase:15.9.5' | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Sun Jun 01 08:02:46 GMT 2025 | ||||
| stageCount=0 | ||||
| #Sun Aug 31 05:11:26 CST 2025 | ||||
| stageCount=1 | ||||
| libraryProject= | ||||
| baseVersion=15.0 | ||||
| publishVersion=15.0.0 | ||||
| buildCount=27 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.0.1 | ||||
|   | ||||
| @@ -0,0 +1 @@ | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ android { | ||||
|         // versionName 更新后需要手动设置  | ||||
|         // .winboll/winbollBuildProps.properties 文件的 stageCount=0 | ||||
|         // Gradle编译环境下合起来的 versionName 就是 "${versionName}.0" | ||||
|         versionName "15.0" | ||||
|         versionName "15.1" | ||||
|         if(true) { | ||||
|             versionName = genVersionName("${versionName}") | ||||
|         } | ||||
| @@ -67,7 +67,7 @@ dependencies { | ||||
|     //api 'androidx.vectordrawable:vectordrawable-animated:1.1.0' | ||||
|     //api 'androidx.fragment:fragment:1.1.0' | ||||
|      | ||||
|     api 'cc.winboll.studio:libaes:15.9.2' | ||||
|     api 'cc.winboll.studio:libapputils:15.8.4' | ||||
|     api 'cc.winboll.studio:libappbase:15.8.4' | ||||
|     api 'cc.winboll.studio:libaes:15.9.3' | ||||
|     api 'cc.winboll.studio:libapputils:15.8.5' | ||||
|     api 'cc.winboll.studio:libappbase:15.9.5' | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Sat Jun 28 05:02:54 GMT 2025 | ||||
| stageCount=0 | ||||
| #Sun Aug 31 05:42:50 CST 2025 | ||||
| stageCount=2 | ||||
| libraryProject= | ||||
| baseVersion=15.0 | ||||
| publishVersion=15.0.0 | ||||
| buildCount=27 | ||||
| baseBetaVersion=15.0.1 | ||||
| baseVersion=15.1 | ||||
| publishVersion=15.1.1 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.1.2 | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Mon Aug 18 03:56:26 HKT 2025 | ||||
| #Sun Aug 31 23:37:38 HKT 2025 | ||||
| stageCount=6 | ||||
| libraryProject=libappbase | ||||
| baseVersion=15.9 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/01/05 09:54:42 | ||||
|  * @Describe APPbase 应用类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 19:30:10 | ||||
|  */ | ||||
| import android.content.Context; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/25 11:46:40 | ||||
|  * @Describe 测试窗口2 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/25 05:04:22 | ||||
|  */ | ||||
| import android.app.Activity; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/05/10 09:48 | ||||
|  * @Describe WinBoLL 窗口基础类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.handlers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/14 03:51:40 | ||||
|  */ | ||||
| import android.os.Handler; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.models; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 07:06:13 | ||||
|  */ | ||||
| import android.util.JsonReader; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.models; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/07 12:47:22 | ||||
|  * @Describe TestServiceBean | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.models; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/07 12:49:21 | ||||
|  * @Describe TestDemoServiceBean | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.receivers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/24 07:11:44 | ||||
|  */ | ||||
| import android.content.BroadcastReceiver; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.receivers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 06:58:04 | ||||
|  * @Describe 主要广播接收器 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/14 03:38:31 | ||||
|  * @Describe 守护进程服务 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 06:56:41 | ||||
|  * @Describe 拨号主服务 | ||||
|  * 参考: | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/07 12:45:49 | ||||
|  * @Describe 启动时申请绑定到APPBase主服务的服务示例 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/07 12:39:24 | ||||
|  * @Describe 普通服务示例 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.appbase.threads; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/14 03:46:44 | ||||
|  */ | ||||
| import android.content.Context; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| package cc.winboll.studio.appbase.widgets; | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/15 14:41:25 | ||||
|  * @Describe TimeWidget | ||||
|  */ | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Tue Jun 03 15:05:48 HKT 2025 | ||||
| stageCount=5 | ||||
| #Mon Sep 01 07:56:33 HKT 2025 | ||||
| stageCount=7 | ||||
| libraryProject=libapputils | ||||
| baseVersion=15.8 | ||||
| publishVersion=15.8.4 | ||||
| publishVersion=15.8.6 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.8.5 | ||||
| baseBetaVersion=15.8.7 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.apputils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/12/08 15:10:51 | ||||
|  * @Describe 全局应用类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.apputils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/01/03 11:02:49 | ||||
|  * @Describe 一个可以浏览随 APP 附带的 Html 文档的窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.apputils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/01/18 10:32:21 | ||||
|  * @Describe 二维码扫码解码窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.apputils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/23 16:14:45 | ||||
|  */ | ||||
| import android.app.Activity; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.apputils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/05/13 11:15 | ||||
|  * @Describe WinBoLLActivity | ||||
|  */ | ||||
|   | ||||
							
								
								
									
										35
									
								
								autoinstaller/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								autoinstaller/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| # AutoInstaller | ||||
|  | ||||
| #### 介绍 | ||||
| APK 文件监控,监控指定文件路径的 APK 文件。 | ||||
| 在 APK 文件改变后自动调用系统安装命令安装,或者调用[应用信息查看器]打开。 | ||||
|  | ||||
| #### 软件架构 | ||||
| 适配安卓应用 [AIDE Pro] 的 Gradle 编译结构。 | ||||
| 也适配安卓应用 [AndroidIDE] 的 Gradle 编译结构。 | ||||
|  | ||||
|  | ||||
| #### Gradle 编译说明 | ||||
| 调试版编译命令 :gradle assembleBetaDebug | ||||
| 阶段版编译命令 :bash .winboll/bashPublishAPKAddTag.sh autoinstaller | ||||
|  | ||||
| #### 使用说明 | ||||
|  | ||||
| #### 参与贡献 | ||||
|  | ||||
| 1.  Fork 本仓库 | ||||
| 2.  新建 Feat_xxx 分支 | ||||
| 3.  提交代码 : ZhanGSKen(ZhanGSKen<zhangsken@188.com>) | ||||
| 4.  新建 Pull Request | ||||
|  | ||||
|  | ||||
| #### 特技 | ||||
|  | ||||
| 1.  使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md | ||||
| 2.  Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) | ||||
| 3.  你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 | ||||
| 4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 | ||||
| 5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) | ||||
| 6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) | ||||
|  | ||||
| #### 参考文档 | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/04/28 02:39:58 | ||||
|  * @Describe 全局应用类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/04/15 09:24:46 | ||||
|  * @Describe 磁贴工具服务类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller.models; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/04/02 20:50:29 | ||||
|  * @Describe 监控的 APK 安装文件对应的应用信息数据模型 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller.models; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/05/27 17:36:01 | ||||
|  * @Describe 应用配置数据类 | ||||
|  */ | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import cc.winboll.studio.libappbase.BaseBean; | ||||
| import java.io.IOException; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/04/15 09:27:39 | ||||
|  * @Describe MainServiceBean | ||||
|  */ | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import cc.winboll.studio.autoinstaller.services.MainService; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/06 13:19:38 | ||||
|  * @Describe 应用消息接收类 | ||||
|  */ | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import cc.winboll.studio.autoinstaller.models.AppConfigs; | ||||
| import cc.winboll.studio.autoinstaller.utils.ServiceUtil; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/05/27 20:16:00 | ||||
|  * @Describe MainService 守护进程服务 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/05/27 17:56:31 | ||||
|  * @Describe 文件管理类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/12/11 06:28:50 | ||||
|  * @Describe 一个获取安卓APK安装文件的应用包名的函数 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.autoinstaller.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/05/27 20:20:03 | ||||
|  * @Describe 服务类工具 | ||||
|  */ | ||||
|   | ||||
| @@ -45,9 +45,9 @@ android { | ||||
|  | ||||
| dependencies { | ||||
|     api fileTree(dir: 'libs', include: ['*.jar']) | ||||
|     api 'cc.winboll.studio:libaes:15.9.2' | ||||
|     api 'cc.winboll.studio:libapputils:15.8.4' | ||||
|     api 'cc.winboll.studio:libappbase:15.8.4' | ||||
|     api 'cc.winboll.studio:libaes:15.9.3' | ||||
|     api 'cc.winboll.studio:libapputils:15.8.5' | ||||
|     api 'cc.winboll.studio:libappbase:15.9.5' | ||||
|      | ||||
|     // 权限请求框架:https://github.com/getActivity/XXPermissions | ||||
|     api 'com.github.getActivity:XXPermissions:18.63' | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Thu Jul 17 09:57:24 HKT 2025 | ||||
| stageCount=12 | ||||
| #Sun Aug 31 06:05:42 CST 2025 | ||||
| stageCount=17 | ||||
| libraryProject= | ||||
| baseVersion=15.3 | ||||
| publishVersion=15.3.11 | ||||
| publishVersion=15.3.16 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.3.12 | ||||
| baseBetaVersion=15.3.17 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/12/08 15:10:51 | ||||
|  * @Describe 全局应用类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,5 +1,10 @@ | ||||
| package cc.winboll.studio.contacts; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||
|  * @Date 2025/08/30 14:32 | ||||
|  * @Describe 主窗口 | ||||
|  */ | ||||
| import android.Manifest; | ||||
| import android.app.Activity; | ||||
| import android.app.ActivityManager; | ||||
| @@ -8,6 +13,7 @@ import android.content.Intent; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.os.Build; | ||||
| import android.os.Bundle; | ||||
| import android.os.Handler; | ||||
| import android.telecom.TelecomManager; | ||||
| import android.telephony.PhoneStateListener; | ||||
| import android.telephony.TelephonyManager; | ||||
| @@ -41,7 +47,7 @@ import java.util.List; | ||||
|  | ||||
| final public class MainActivity extends AppCompatActivity implements IWinBoLLActivity, ViewPager.OnPageChangeListener, View.OnClickListener { | ||||
|  | ||||
| 	public static final String TAG = "MainActivity"; | ||||
|     public static final String TAG = "MainActivity"; | ||||
|  | ||||
|     public static final int REQUEST_HOME_ACTIVITY = 0; | ||||
|     public static final int REQUEST_ABOUT_ACTIVITY = 1; | ||||
| @@ -55,13 +61,10 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct | ||||
|     MainServiceBean mMainServiceBean; | ||||
|     private TabLayout tabLayout; | ||||
|     private ViewPager viewPager; | ||||
|     private List<View> views; //用来存放放进ViewPager里面的布局 | ||||
|     //实例化存储imageView(导航原点)的集合 | ||||
|     private List<View> views;  | ||||
|     ImageView[] imageViews; | ||||
|     //MyPagerAdapter adapter;//适配器 | ||||
|     MyPagerAdapter pagerAdapter; | ||||
|     LinearLayout linearLayout;//下标所在在LinearLayout布局里 | ||||
|     int currentPoint = 0;//当前被选中中页面的下标 | ||||
|     LinearLayout linearLayout; | ||||
|     int currentPoint = 0; | ||||
|  | ||||
|     private TelephonyManager telephonyManager; | ||||
|     private MyPhoneStateListener phoneStateListener; | ||||
| @@ -70,30 +73,6 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct | ||||
|  | ||||
|     private static final int DIALER_REQUEST_CODE = 1; | ||||
|  | ||||
| //    @Override | ||||
| //    public Activity getActivity() { | ||||
| //        return this; | ||||
| //    } | ||||
|  | ||||
| //    @Override | ||||
| //    public APPInfo getAppInfo() { | ||||
| //        String szBranchName = "contacts"; | ||||
| // | ||||
| //        APPInfo appInfo = AboutActivityFactory.buildDefaultAPPInfo(); | ||||
| //        appInfo.setAppName("Contacts"); | ||||
| //        appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll); | ||||
| //        appInfo.setAppDescription("Contacts Description"); | ||||
| //        appInfo.setAppGitName("APP"); | ||||
| //        appInfo.setAppGitOwner("Studio"); | ||||
| //        appInfo.setAppGitAPPBranch(szBranchName); | ||||
| //        appInfo.setAppGitAPPSubProjectFolder(szBranchName); | ||||
| //        appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=Contacts"); | ||||
| //        appInfo.setAppAPKName("Contacts"); | ||||
| //        appInfo.setAppAPKFolderName("Contacts"); | ||||
| //        return appInfo; | ||||
| //        return null; | ||||
| //    } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     public Activity getActivity() { | ||||
| @@ -107,89 +86,62 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct | ||||
|  | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         // 接收并处理 Intent 数据,函数 Intent 处理接收就直接返回 | ||||
|         //if (prosessIntents(getIntent())) return; | ||||
|         // 以下正常创建主窗口 | ||||
|         super.onCreate(savedInstanceState); | ||||
|         _MainActivity = this; | ||||
|         setContentView(R.layout.activity_main); | ||||
|  | ||||
|         // 初始化工具栏 | ||||
|         mToolbar = findViewById(R.id.activitymainToolbar1); | ||||
|         // 初始化工具栏(仅加载基础UI) | ||||
|         mToolbar = (Toolbar) findViewById(R.id.activitymainToolbar1); | ||||
|         setSupportActionBar(mToolbar); | ||||
| //        if (isEnableDisplayHomeAsUp()) { | ||||
| //            // 显示后退按钮 | ||||
| //            getSupportActionBar().setDisplayHomeAsUpEnabled(true); | ||||
| //        } | ||||
|         getSupportActionBar().setSubtitle(TAG); | ||||
|  | ||||
|         tabLayout = findViewById(R.id.tabLayout); | ||||
|         viewPager = findViewById(R.id.viewPager); | ||||
|         tabLayout = (TabLayout) findViewById(R.id.tabLayout); | ||||
|         viewPager = (ViewPager) findViewById(R.id.viewPager); | ||||
|  | ||||
|         // 创建Fragment列表和标题列表 | ||||
|         fragmentList = new ArrayList<>(); | ||||
|         tabTitleList = new ArrayList<>(); | ||||
|         // 创建Fragment列表(仅实例化,不加载数据) | ||||
|         fragmentList = new ArrayList<Fragment>(); | ||||
|         tabTitleList = new ArrayList<String>(); | ||||
|         fragmentList.add(CallLogFragment.newInstance(0)); | ||||
|         fragmentList.add(ContactsFragment.newInstance(1)); | ||||
|         fragmentList.add(ContactsFragment.newInstance(1)); // 延迟加载联系人数据 | ||||
|         fragmentList.add(LogFragment.newInstance(2)); | ||||
|         tabTitleList.add("通话记录"); | ||||
|         tabTitleList.add("联系人"); | ||||
|         tabTitleList.add("应用日志"); | ||||
|  | ||||
|         // 设置ViewPager的适配器 | ||||
|         // 设置ViewPager适配器 | ||||
|         MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), fragmentList, tabTitleList); | ||||
|         viewPager.setAdapter(adapter); | ||||
|  | ||||
|         // 关键:关闭预加载,仅当前页初始化 | ||||
|         viewPager.setOffscreenPageLimit(0); | ||||
|  | ||||
|         // 关联TabLayout和ViewPager | ||||
|         tabLayout.setupWithViewPager(viewPager); | ||||
|  | ||||
|  | ||||
|  | ||||
| //        initData(); | ||||
| //        initView(); | ||||
| //        //initPoint();//调用初始化导航原点的方法 | ||||
| //        viewPager.addOnPageChangeListener(this);//滑动事件 | ||||
|  | ||||
|         //ViewPager viewPager = findViewById(R.id.activitymainViewPager1); | ||||
|         //MyPagerAdapter pagerAdapter = new MyPagerAdapter(getSupportFragmentManager()); | ||||
|         //viewPager.setAdapter(pagerAdapter); | ||||
|         //TabLayout tabLayout = findViewById(R.id.activitymainTabLayout1); | ||||
|         //tabLayout.setupWithViewPager(viewPager); | ||||
|  | ||||
| //        mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class); | ||||
| //        if (mMainServiceBean == null) { | ||||
| //            mMainServiceBean = new MainServiceBean(); | ||||
| //        } | ||||
| //        cbMainService = findViewById(R.id.activitymainCheckBox1); | ||||
| //        cbMainService.setChecked(mMainServiceBean.isEnable()); | ||||
| //        cbMainService.setOnClickListener(new View.OnClickListener(){ | ||||
| //                @Override | ||||
| //                public void onClick(View view) { | ||||
| //                    if (cbMainService.isChecked()) { | ||||
| //                        MainService.startMainService(MainActivity.this); | ||||
| //                    } else { | ||||
| //                        MainService.stopMainService(MainActivity.this); | ||||
| //                    } | ||||
| //                } | ||||
| //            }); | ||||
|  | ||||
|         // 初始化服务状态(延迟启动非核心服务) | ||||
|         MainServiceBean mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class); | ||||
|         if (mMainServiceBean == null) { | ||||
|             mMainServiceBean = new MainServiceBean(); | ||||
|             MainServiceBean.saveBean(this, mMainServiceBean); | ||||
|         } | ||||
|         if (mMainServiceBean.isEnable()) { | ||||
|             MainService.startMainService(this); | ||||
|             // 延迟1秒启动服务,避免阻塞启动 | ||||
|             new Handler().postDelayed(new Runnable() { | ||||
| 					@Override | ||||
| 					public void run() { | ||||
| 						MainService.startMainService(MainActivity.this); | ||||
| 					} | ||||
| 				}, 1000); | ||||
|         } | ||||
|  | ||||
|         // 初始化TelephonyManager和PhoneStateListener | ||||
|         // 初始化电话状态监听(基础功能保留) | ||||
|         telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); | ||||
|         phoneStateListener = new MyPhoneStateListener(); | ||||
|         telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // ViewPager的适配器 | ||||
|     // ViewPager适配器(Java 7语法) | ||||
|     private class MyPagerAdapter extends FragmentPagerAdapter { | ||||
|  | ||||
|         private List<Fragment> fragmentList; | ||||
| @@ -226,91 +178,22 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct | ||||
|         _MainActivity.startActivity(intent); | ||||
|     } | ||||
|  | ||||
|     //初始化view,即显示的图片 | ||||
| //    void initView() { | ||||
| //        viewPager = findViewById(R.id.activitymainViewPager1); | ||||
| //        pagerAdapter = new MyPagerAdapter(getSupportFragmentManager()); | ||||
| //        viewPager.setAdapter(pagerAdapter); | ||||
| //        //adapter = new MyPagerAdapter(views); | ||||
| //        //viewPager = findViewById(R.id.activitymainViewPager1); | ||||
| //        //viewPager.setAdapter(adapter); | ||||
| //        //linearLayout = findViewById(R.id.activitymainLinearLayout1); | ||||
| //        //initPoint();//初始化页面下方的点 | ||||
| //        viewPager.setOnPageChangeListener(this); | ||||
| // | ||||
| //    } | ||||
|  | ||||
|     //初始化所要显示的布局 | ||||
| //    void initData() { | ||||
| //        LayoutInflater inflater = LayoutInflater.from(getActivity()); | ||||
| //        View view1 = inflater.inflate(R.layout.fragment_call_log, viewPager, false); | ||||
| //        View view2 = inflater.inflate(R.layout.fragment_contacts, viewPager, false); | ||||
| //        View view3 = inflater.inflate(R.layout.fragment_log, viewPager, false); | ||||
| // | ||||
| //        views = new ArrayList<>(); | ||||
| //        views.add(view1); | ||||
| //        views.add(view2); | ||||
| //        views.add(view3); | ||||
| //    } | ||||
|  | ||||
| //    void initPoint() { | ||||
| //        imageViews = new ImageView[5];//实例化5个图片 | ||||
| //        for (int i = 0; i < linearLayout.getChildCount(); i++) { | ||||
| //            imageViews[i] = (ImageView) linearLayout.getChildAt(i); | ||||
| //            imageViews[i].setImageResource(R.drawable.ic_launcher); | ||||
| //            imageViews[i].setOnClickListener(this);//点击导航点,即可跳转 | ||||
| //            imageViews[i].setTag(i);//重复利用实例化的对象 | ||||
| //        } | ||||
| //        currentPoint = 0;//默认第一个坐标 | ||||
| //        imageViews[currentPoint].setImageResource(R.drawable.ic_launcher); | ||||
| //    } | ||||
|  | ||||
|     //OnPageChangeListener接口要实现的三个方法 | ||||
|     /*    onPageScrollStateChanged(int state) | ||||
|      此方法是在状态改变的时候调用,其中state这个参数有三种状态: | ||||
|      SCROLL_STATE_DRAGGING(1)表示用户手指“按在屏幕上并且开始拖动”的状态 | ||||
|      (手指按下但是还没有拖动的时候还不是这个状态,只有按下并且手指开始拖动后log才打出。) | ||||
|      SCROLL_STATE_IDLE(0)滑动动画做完的状态。 | ||||
|      SCROLL_STATE_SETTLING(2)在“手指离开屏幕”的状态。*/ | ||||
|     // OnPageChangeListener接口实现 | ||||
|     @Override | ||||
|     public void onPageScrollStateChanged(int state) { | ||||
|     public void onPageScrollStateChanged(int state) {} | ||||
|  | ||||
|     } | ||||
|     /*    onPageScrolled(int position, float positionOffset, int positionOffsetPixels) | ||||
|      当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用。其中三个参数的含义分别为: | ||||
|  | ||||
|      position :当前页面,即你点击滑动的页面(从A滑B,则是A页面的position。 | ||||
|      positionOffset:当前页面偏移的百分比 | ||||
|      positionOffsetPixels:当前页面偏移的像素位置*/ | ||||
|     @Override | ||||
|     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { | ||||
|     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} | ||||
|  | ||||
|     } | ||||
|     /*    onPageSelected(int position) | ||||
|      此方法是页面滑动完后得到调用,position是你当前选中的页面的Position(位置编号) | ||||
|      (从A滑动到B,就是B的position)*/ | ||||
|     public void onPageSelected(int position) { | ||||
|  | ||||
| //        ImageView preView = imageViews[currentPoint]; | ||||
| //        preView.setImageResource(R.drawable.ic_launcher); | ||||
| //        ImageView currView = imageViews[position]; | ||||
| //        currView.setImageResource(R.drawable.ic_launcher); | ||||
| //        currentPoint = position; | ||||
|     } | ||||
|  | ||||
|     //小圆点点击事件 | ||||
|     @Override | ||||
|     public void onClick(View v) { | ||||
|         // TODO Auto-generated method stub | ||||
|         //通过getTag(),可以判断是哪个控件 | ||||
| //        int i = (Integer) v.getTag(); | ||||
| //        viewPager.setCurrentItem(i);//直接跳转到某一个页面的情况 | ||||
|     } | ||||
|     public void onPageSelected(int position) {} | ||||
|  | ||||
|     @Override | ||||
|     public void onClick(View v) {} | ||||
|  | ||||
|     @Override | ||||
|     protected void onPostCreate(Bundle savedInstanceState) { | ||||
|         super.onPostCreate(savedInstanceState); | ||||
|         //setSubTitle(""); | ||||
|     } | ||||
|  | ||||
|     private class MyPhoneStateListener extends PhoneStateListener { | ||||
| @@ -336,109 +219,31 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct | ||||
|         LogUtils.d(TAG, "onDestroy() SOS"); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     // | ||||
|     // 处理传入的 Intent 数据 | ||||
|     // | ||||
| //    boolean prosessIntents(Intent intent) { | ||||
| //        if (intent == null  | ||||
| //            || intent.getAction() == null | ||||
| //            || intent.getAction().equals("")) | ||||
| //            return false; | ||||
| // | ||||
| //        if (intent.getAction().equals(StringToQrCodeView.ACTION_UNITTEST_QRCODE)) { | ||||
| //            try { | ||||
| //                WinBoLLActivity clazzActivity = UnitTestActivity.class.newInstance(); | ||||
| //                String tag = clazzActivity.getTag(); | ||||
| //                LogUtils.d(TAG, "String tag = clazzActivity.getTag(); tag " + tag); | ||||
| //                Intent subIntent = new Intent(this, UnitTestActivity.class); | ||||
| //                subIntent.setAction(intent.getAction()); | ||||
| //                File file = new File(getCacheDir(), UUID.randomUUID().toString()); | ||||
| //                //取出文件uri | ||||
| //                Uri uri = intent.getData(); | ||||
| //                if (uri == null) { | ||||
| //                    uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); | ||||
| //                } | ||||
| //                //获取文件真实地址 | ||||
| //                String szSrcPath = UriUtils.getFileFromUri(getApplication(), uri); | ||||
| //                if (TextUtils.isEmpty(szSrcPath)) { | ||||
| //                    return false; | ||||
| //                } | ||||
| // | ||||
| //                Files.copy(Paths.get(szSrcPath), Paths.get(file.getPath())); | ||||
| //                //startWinBoLLActivity(subIntent, tag); | ||||
| //                WinBoLLActivityManager.getInstance(this).startWinBoLLActivity(this, subIntent, UnitTestActivity.class); | ||||
| //            } catch (IllegalAccessException | InstantiationException | IOException e) { | ||||
| //                LogUtils.d(TAG, e, Thread.currentThread().getStackTrace()); | ||||
| //                // 函数处理异常返回失败 | ||||
| //                return false; | ||||
| //            } | ||||
| //        } else { | ||||
| //            LogUtils.d(TAG, "prosessIntents|" + intent.getAction() + "|yet"); | ||||
| //            return false; | ||||
| //        } | ||||
| //        return true; | ||||
| //    } | ||||
|  | ||||
| //    @Override | ||||
| //    public String getTag() { | ||||
| //        return TAG; | ||||
| //    } | ||||
|  | ||||
| //    @Override | ||||
| //    public void onBackPressed() { | ||||
| //        exit(); | ||||
| //    } | ||||
| // | ||||
| //    void exit() { | ||||
| //        YesNoAlertDialog.OnDialogResultListener listener = new YesNoAlertDialog.OnDialogResultListener(){ | ||||
| // | ||||
| //            @Override | ||||
| //            public void onYes() { | ||||
| //                WinBoLLActivityManager.getInstance(getApplicationContext()).finishAll(); | ||||
| //            } | ||||
| // | ||||
| //            @Override | ||||
| //            public void onNo() { | ||||
| //            } | ||||
| //        }; | ||||
| //        YesNoAlertDialog.show(this, "[ " + getString(R.string.app_name) + " ]", "Exit(Yes/No).\nIs close all activity?", listener); | ||||
| //    } | ||||
|  | ||||
|     @Override | ||||
|     public boolean onCreateOptionsMenu(Menu menu) { | ||||
|         getMenuInflater().inflate(R.menu.toolbar_main, menu); | ||||
|         return super.onCreateOptionsMenu(menu); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     public boolean onOptionsItemSelected(MenuItem item) { | ||||
|         if (item.getItemId() == R.id.item_settings) { | ||||
|             Intent intent = new Intent(this, SettingsActivity.class); | ||||
|             startActivity(intent); | ||||
|             //WinBoLLActivityManager.getInstance(this).startWinBoLLActivity(this, CallActivity.class); | ||||
|         } | ||||
| //        } else  | ||||
| //        if (item.getItemId() == R.id.item_exit) { | ||||
| //            exit(); | ||||
| //            return true; | ||||
| //        } | ||||
|         return super.onOptionsItemSelected(item); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     protected void onResume() { | ||||
|         super.onResume(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Android M 及以上检查是否是系统默认电话应用 | ||||
|      * 检查是否是系统默认电话应用 | ||||
|      */ | ||||
|     public boolean isDefaultPhoneCallApp() { | ||||
|         if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|             TelecomManager manger = (TelecomManager) getSystemService(TELECOM_SERVICE); | ||||
|             if (manger != null && manger.getDefaultDialerPackage() != null) { | ||||
|                 return manger.getDefaultDialerPackage().equals(getPackageName()); | ||||
| @@ -452,35 +257,22 @@ final public class MainActivity extends AppCompatActivity implements IWinBoLLAct | ||||
|         if (manager == null) return false; | ||||
|  | ||||
|         for (ActivityManager.RunningServiceInfo service : manager.getRunningServices( | ||||
|             Integer.MAX_VALUE)) { | ||||
| 			Integer.MAX_VALUE)) { | ||||
|             if (serviceClass.getName().equals(service.service.getClassName())) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onActivityResult(int requestCode, int resultCode, Intent data) { | ||||
| //        switch (resultCode) { | ||||
| //            case REQUEST_HOME_ACTIVITY : { | ||||
| //                    LogUtils.d(TAG, "REQUEST_HOME_ACTIVITY"); | ||||
| //                    break; | ||||
| //                } | ||||
| //            case REQUEST_ABOUT_ACTIVITY : { | ||||
| //                    LogUtils.d(TAG, "REQUEST_ABOUT_ACTIVITY"); | ||||
| //                    break; | ||||
| //                } | ||||
| //            default : { | ||||
| //                    super.onActivityResult(requestCode, resultCode, data); | ||||
| //                } | ||||
| //        } | ||||
|         if (requestCode == DIALER_REQUEST_CODE) { | ||||
|             if (resultCode == Activity.RESULT_OK) { | ||||
|                 Toast.makeText(MainActivity.this, getString(R.string.app_name) + " 已成为默认电话应用", | ||||
|                                Toast.LENGTH_SHORT).show(); | ||||
| 							   Toast.LENGTH_SHORT).show(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/31 15:15:54 | ||||
|  * @Describe 应用介绍窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/20 17:15:46 | ||||
|  * @Describe 拨号窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/20 20:18:26 | ||||
|  */ | ||||
| import android.content.Intent; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/21 05:37:42 | ||||
|  */ | ||||
| import android.content.Context; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import cc.winboll.studio.libappbase.LogUtils; | ||||
| import cc.winboll.studio.libappbase.LogView; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/02 16:07:04 | ||||
|  */ | ||||
| public class UnitTestActivity extends Activity { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/31 15:16:45 | ||||
|  * @Describe 应用窗口基类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.adapters; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/26 13:09:32 | ||||
|  * @Describe CallLogAdapter | ||||
|  */ | ||||
| @@ -40,6 +40,10 @@ public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.CallLogV | ||||
|         this.mContactUtils = ContactUtils.getInstance(mContext); | ||||
|         this.callLogList = callLogList; | ||||
|     } | ||||
| 	 | ||||
| 	public void relaodContacts() { | ||||
| 		this.mContactUtils.relaodContacts(); | ||||
| 	} | ||||
|  | ||||
|     @NonNull | ||||
|     @Override | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.adapters; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/26 13:35:44 | ||||
|  * @Describe ContactAdapter | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.adapters; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/20 14:20:38 | ||||
|  * @Describe ImagePagerAdapter | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.adapters; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/02 17:27:41 | ||||
|  * @Describe PhoneConnectRuleAdapter | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/26 13:10:57 | ||||
|  * @Describe CallLogModel | ||||
|  */ | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package cc.winboll.studio.contacts.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Date 2025/02/26 13:37:00 | ||||
|  * @Describe ContactModel | ||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||
|  * @Date 2025/08/30 14:32 | ||||
|  * @Describe 联系人信息数据模型 | ||||
|  */ | ||||
| import net.sourceforge.pinyin4j.PinyinHelper; | ||||
| import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; | ||||
| @@ -18,13 +18,18 @@ public class ContactModel { | ||||
|     private String name; | ||||
|     private String number; | ||||
|     private String pinyin; | ||||
|     // 新增:存储姓名的拼音首字母(如"啊牛"→"an") | ||||
|     private String pinyinFirstLetter; | ||||
|  | ||||
|     public ContactModel(String name, String number) { | ||||
|         this.name = name; | ||||
|         this.number = number.replaceAll("\\s", ""); | ||||
|         this.pinyin = convertToPinyin(name); | ||||
|         // 初始化时生成拼音首字母 | ||||
|         this.pinyinFirstLetter = convertToPinyinFirstLetter(name); | ||||
|     } | ||||
|  | ||||
|     // 原方法:转换为全拼(如"啊牛"→"aniu") | ||||
|     private String convertToPinyin(String chinese) { | ||||
|         HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); | ||||
|         format.setCaseType(HanyuPinyinCaseType.LOWERCASE); | ||||
| @@ -33,22 +38,55 @@ public class ContactModel { | ||||
|         StringBuilder pinyin = new StringBuilder(); | ||||
|         for (int i = 0; i < chinese.length(); i++) { | ||||
|             char ch = chinese.charAt(i); | ||||
|             if (Character.toString(ch).matches("[\\u4e00-\\u9fa5]")) { | ||||
|             if (Character.toString(ch).matches("[\\u4e00-\\u9fa5]")) { // 仅处理汉字 | ||||
|                 try { | ||||
|                     String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, format); | ||||
|                     if (pinyinArray != null) { | ||||
|                         pinyin.append(pinyinArray[0]); | ||||
|                     if (pinyinArray != null && pinyinArray.length > 0) { | ||||
|                         pinyin.append(pinyinArray[0]); // 取第一个拼音(多音字默认首选项) | ||||
|                     } | ||||
|                 } catch (BadHanyuPinyinOutputFormatCombination e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } else { | ||||
|                 pinyin.append(ch); | ||||
|                 pinyin.append(ch); // 非汉字直接拼接(如字母、数字、符号) | ||||
|             } | ||||
|         } | ||||
|         return pinyin.toString(); | ||||
|     } | ||||
|  | ||||
|     // 新增:转换为拼音首字母(如"啊牛"→"an") | ||||
|     private String convertToPinyinFirstLetter(String chinese) { | ||||
|         HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); | ||||
|         format.setCaseType(HanyuPinyinCaseType.LOWERCASE); | ||||
|         format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); | ||||
|  | ||||
|         StringBuilder firstLetters = new StringBuilder(); | ||||
|         for (int i = 0; i < chinese.length(); i++) { | ||||
|             char ch = chinese.charAt(i); | ||||
|             if (Character.toString(ch).matches("[\\u4e00-\\u9fa5]")) { // 仅处理汉字 | ||||
|                 try { | ||||
|                     String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, format); | ||||
|                     if (pinyinArray != null && pinyinArray.length > 0) { | ||||
|                         // 取拼音的第一个字母(如"a"、"niu"→"a"、"n") | ||||
|                         firstLetters.append(pinyinArray[0].charAt(0)); | ||||
|                     } | ||||
|                 } catch (BadHanyuPinyinOutputFormatCombination e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } else { | ||||
|                 // 非汉字可根据需求处理:此处保留原字符(如"李3"→"l3","张A"→"za") | ||||
|                 firstLetters.append(ch); | ||||
|             } | ||||
|         } | ||||
|         return firstLetters.toString(); | ||||
|     } | ||||
|  | ||||
|     // 新增:获取拼音首字母 | ||||
|     public String getPinyinFirstLetter() { | ||||
|         return pinyinFirstLetter; | ||||
|     } | ||||
|  | ||||
|     // 原有getter方法 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 07:06:13 | ||||
|  */ | ||||
| import android.util.JsonReader; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/21 09:52:10 | ||||
|  * @Describe 电话黑名单规则 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/24 18:47:11 | ||||
|  * @Describe 手机铃声设置参数类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/02 19:51:40 | ||||
|  * @Describe SettingsModel | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.bobulltoon; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/02 13:47:48 | ||||
|  * @Describe 汤姆猫管家 :使用 BoBullToon 项目,对通讯地址进行筛选判断的好朋友。 | ||||
|  */ | ||||
| @@ -11,6 +11,7 @@ import cc.winboll.studio.contacts.dun.Rules; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
| import com.hjq.toast.ToastUtils; | ||||
| import java.io.File; | ||||
| import java.io.FileFilter; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| @@ -154,6 +155,62 @@ public class TomCat { | ||||
|     File getWorkingFolder() { | ||||
|         return mContext.getExternalFilesDir(TAG); | ||||
|     } | ||||
| 	 | ||||
| 	public File getBoBullToonDataFolder() { | ||||
| 		File fCheckRoot = getWorkingFolder(); | ||||
| 		if (fCheckRoot == null || !fCheckRoot.exists()) { | ||||
| 			return fCheckRoot; | ||||
| 		} | ||||
|  | ||||
| 		// 递归查找符合条件的文件夹 | ||||
| 		File targetFolder = findTargetFolder(fCheckRoot); | ||||
| 		return targetFolder != null ? targetFolder : fCheckRoot; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 递归查找同时包含LICENSE和README.md文件的文件夹 | ||||
| 	 */ | ||||
| 	private File findTargetFolder(File currentFolder) { | ||||
| 		// 检查当前文件夹是否符合条件 | ||||
| 		if (hasRequiredFiles(currentFolder)) { | ||||
| 			return currentFolder; | ||||
| 		} | ||||
|  | ||||
| 		// 查找子文件夹(Java 7不支持方法引用,用匿名内部类过滤) | ||||
| 		File[] subFolders = currentFolder.listFiles(new FileFilter() { | ||||
| 				@Override | ||||
| 				public boolean accept(File file) { | ||||
| 					return file.isDirectory(); // 仅保留子文件夹 | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
| 		if (subFolders != null) { | ||||
| 			for (File subFolder : subFolders) { | ||||
| 				File result = findTargetFolder(subFolder); | ||||
| 				if (result != null) { | ||||
| 					return result; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return null; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 检查文件夹中是否同时存在LICENSE和README.md文件 | ||||
| 	 */ | ||||
| 	private boolean hasRequiredFiles(File folder) { | ||||
| 		if (folder == null || !folder.isDirectory()) { | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		// 检查两个文件是否同时存在且均为文件(非文件夹) | ||||
| 		File licenseFile = new File(folder, "LICENSE"); | ||||
| 		File readmeFile = new File(folder, "README.md"); | ||||
|  | ||||
| 		return licenseFile.exists() && licenseFile.isFile() | ||||
| 			&& readmeFile.exists() && readmeFile.isFile(); | ||||
| 	} | ||||
|  | ||||
| 	public void cleanBoBullToon() { | ||||
| 		String destinationFolder = getWorkingFolder().getPath(); // 替换为实际的目标文件夹路径 | ||||
| @@ -170,9 +227,9 @@ public class TomCat { | ||||
|  | ||||
|     public boolean loadPhoneBoBullToon() { | ||||
|         listPhoneBoBullToon.clear(); | ||||
|         File fBoBullToon = new File(getWorkingFolder(), "bobulltoon"); | ||||
|         File fBoBullToon = getBoBullToonDataFolder(); | ||||
|         if (fBoBullToon.exists()) { | ||||
|             LogUtils.d(TAG, String.format("getWorkingFolder() %s", getWorkingFolder())); | ||||
|             LogUtils.d(TAG, String.format("getBoBullToonDataFolder() %s", getWorkingFolder())); | ||||
|             for (File userFolder : fBoBullToon.listFiles()) { | ||||
|                 if (userFolder.isDirectory()) { | ||||
|                     for (File recordFile : userFolder.listFiles()) { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.dun; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/21 06:15:10 | ||||
|  * @Describe 云盾防御规则 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.fragments; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/20 12:57:00 | ||||
|  * @Describe 拨号 | ||||
|  */ | ||||
| @@ -161,4 +161,12 @@ public class CallLogFragment extends Fragment { | ||||
|             _CallLogFragment.triggerUpdate(); | ||||
|         } | ||||
|     } | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void onResume() { | ||||
| 		super.onResume(); | ||||
| 		//ToastUtils.show("onResume"); | ||||
| 		callLogAdapter.relaodContacts(); | ||||
| 		readCallLog();  // 窗口回显时更新通话记录 | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,15 +1,18 @@ | ||||
| package cc.winboll.studio.contacts.fragments; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Date 2025/02/20 12:57:50 | ||||
|  * @Describe 联系人 | ||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||
|  * @Date 2025/08/30 14:32 | ||||
|  * @Describe 联系人视图 | ||||
|  */ | ||||
| import android.Manifest; | ||||
| import android.content.Intent; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.database.Cursor; | ||||
| import android.os.Bundle; | ||||
| import android.os.Handler; | ||||
| import android.os.Looper; | ||||
| import android.provider.ContactsContract; | ||||
| import android.text.Editable; | ||||
| import android.text.TextWatcher; | ||||
| @@ -27,24 +30,39 @@ import androidx.recyclerview.widget.RecyclerView; | ||||
| import cc.winboll.studio.contacts.R; | ||||
| import cc.winboll.studio.contacts.adapters.ContactAdapter; | ||||
| import cc.winboll.studio.contacts.beans.ContactModel; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
| import com.hjq.toast.ToastUtils; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import java.util.concurrent.ExecutorService; | ||||
| import java.util.concurrent.Executors; | ||||
|  | ||||
| public class ContactsFragment extends Fragment { | ||||
|  | ||||
|     public static final String TAG = "ContactsFragment"; | ||||
|  | ||||
|     private static final String ARG_PAGE = "ARG_PAGE"; | ||||
|     private int mPage; | ||||
|  | ||||
|     private static final int REQUEST_READ_CONTACTS = 1; | ||||
|  | ||||
|     private int mPage; | ||||
|     private RecyclerView recyclerView; | ||||
|     private ContactAdapter contactAdapter; | ||||
|     private List<ContactModel> contactList = new ArrayList<>(); | ||||
|     private List<ContactModel> originalContactList = new ArrayList<>(); | ||||
|     private EditText searchEditText; | ||||
|     private Button btnDial; | ||||
|     private boolean isViewInitialized = false; // 标记视图是否已初始化 | ||||
|  | ||||
|     // 静态缓存:全局复用联系人数据 | ||||
|     private static List<ContactModel> sCachedOriginalList = new ArrayList<ContactModel>(); | ||||
|     private static List<ContactModel> sCachedFilteredList = new ArrayList<ContactModel>(); | ||||
|  | ||||
|     // 当前页面数据容器 | ||||
|     private List<ContactModel> contactList = new ArrayList<ContactModel>(); | ||||
|     private List<ContactModel> originalContactList = new ArrayList<ContactModel>(); | ||||
|  | ||||
|     // 异步工具 | ||||
|     private final ExecutorService executor = Executors.newSingleThreadExecutor(); | ||||
|     private final Handler mainHandler = new Handler(Looper.getMainLooper()); | ||||
|     private boolean isDataLoaded = false; | ||||
|  | ||||
|  | ||||
|     public static ContactsFragment newInstance(int page) { | ||||
|         Bundle args = new Bundle(); | ||||
| @@ -65,103 +83,272 @@ public class ContactsFragment extends Fragment { | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
|         return inflater.inflate(R.layout.fragment_contacts, container, false); | ||||
|         // 加载布局(已移除进度条相关代码) | ||||
|         View view = inflater.inflate(R.layout.fragment_contacts, container, false); | ||||
|         return view; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { | ||||
|         super.onViewCreated(view, savedInstanceState); | ||||
|         recyclerView = view.findViewById(R.id.contacts_recycler_view); | ||||
|         // 初始化RecyclerView | ||||
|         recyclerView = (RecyclerView) view.findViewById(R.id.contacts_recycler_view); | ||||
|         recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); | ||||
|         contactList = new ArrayList<ContactModel>(); | ||||
|         contactAdapter = new ContactAdapter(getContext(), contactList); | ||||
|         recyclerView.setAdapter(contactAdapter); | ||||
|         // 初始隐藏列表,数据加载后显示 | ||||
|         recyclerView.setVisibility(View.GONE); | ||||
|  | ||||
|         searchEditText = view.findViewById(R.id.search_edit_text); | ||||
|         searchEditText.addTextChangedListener(new TextWatcher() { | ||||
|                 @Override | ||||
|                 public void beforeTextChanged(CharSequence s, int start, int count, int after) { | ||||
|                 } | ||||
|         // 绑定搜索框和拨号按钮 | ||||
|         searchEditText = (EditText) view.findViewById(R.id.search_edit_text); | ||||
|         btnDial = (Button) view.findViewById(R.id.btn_dial); | ||||
|         // 初始隐藏搜索相关控件,延迟到首次可见时显示 | ||||
|         searchEditText.setVisibility(View.GONE); | ||||
|         btnDial.setVisibility(View.GONE); | ||||
|     } | ||||
|  | ||||
|                 @Override | ||||
|                 public void onTextChanged(CharSequence s, int start, int before, int count) { | ||||
|                     filterContacts(s.toString()); | ||||
|                 } | ||||
|     // 首次可见时初始化资源 | ||||
|     @Override | ||||
|     public void onResume() { | ||||
|         super.onResume(); | ||||
|         if (!isViewInitialized) { | ||||
|             initSearchAndDial(); // 初始化搜索和拨号功能 | ||||
|             checkContactPermission(); // 检查权限并加载数据 | ||||
|             isViewInitialized = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|                 @Override | ||||
|                 public void afterTextChanged(Editable s) { | ||||
|                 } | ||||
|             }); | ||||
|     // 初始化搜索框和拨号按钮 | ||||
|     private void initSearchAndDial() { | ||||
|         // 显示搜索相关控件 | ||||
|         searchEditText.setVisibility(View.VISIBLE); | ||||
|         btnDial.setVisibility(View.VISIBLE); | ||||
|  | ||||
|         // 搜索框防抖监听 | ||||
|         searchEditText.addTextChangedListener(new DebounceTextWatcher(300) { | ||||
| 				@Override | ||||
| 				public void onDebounceTextChanged(String query) { | ||||
| 					filterContacts(query); | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
|         // 拨号按钮点击事件 | ||||
|         btnDial.setOnClickListener(new View.OnClickListener() { | ||||
| 				@Override | ||||
| 				public void onClick(View v) { | ||||
| 					String phoneNumber = searchEditText.getText().toString().replaceAll("\\s", ""); | ||||
| 					if (phoneNumber.isEmpty()) { | ||||
| 						ToastUtils.show("请输入号码"); | ||||
| 						return; | ||||
| 					} | ||||
| 					Intent intent = new Intent(Intent.ACTION_CALL); | ||||
| 					intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); | ||||
| 					intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
| 					startActivity(intent); | ||||
| 				} | ||||
| 			}); | ||||
|     } | ||||
|  | ||||
|     // 权限检查 | ||||
|     private void checkContactPermission() { | ||||
|         if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { | ||||
|             ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS); | ||||
|         } else { | ||||
|             readContacts(); | ||||
|             loadContacts(); | ||||
|         } | ||||
|  | ||||
|         Button btnDial = view.findViewById(R.id.btn_dial); | ||||
|         btnDial.setOnClickListener(new View.OnClickListener(){ | ||||
|                 @Override | ||||
|                 public void onClick(View p1) { | ||||
|  | ||||
|                     String phoneNumber = searchEditText.getText().toString().replaceAll("\\s", ""); | ||||
|                     //phoneNumber = "+8616769764848"; | ||||
|                     ToastUtils.show(phoneNumber); | ||||
|                     Intent intent = new Intent(Intent.ACTION_CALL); | ||||
|                     intent.setData(android.net.Uri.parse("tel:" + phoneNumber)); | ||||
|                     // 添加 FLAG_ACTIVITY_NEW_TASK 标志 | ||||
|                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|                     startActivity(intent); | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     // 加载联系人(延迟到首次可见时) | ||||
|     private void loadContacts() { | ||||
|         // 若有缓存,直接复用 | ||||
|         if (!sCachedOriginalList.isEmpty() && !sCachedFilteredList.isEmpty()) { | ||||
|             originalContactList.clear(); | ||||
|             originalContactList.addAll(sCachedOriginalList); | ||||
|             contactList.clear(); | ||||
|             contactList.addAll(sCachedFilteredList); | ||||
|             contactAdapter.notifyDataSetChanged(); | ||||
|             recyclerView.setVisibility(View.VISIBLE); // 显示列表 | ||||
|             isDataLoaded = true; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // 无缓存时异步加载 | ||||
|         if (!isDataLoaded) { | ||||
|             recyclerView.setVisibility(View.GONE); // 加载中隐藏列表 | ||||
|  | ||||
|             executor.execute(new Runnable() { | ||||
| 					@Override | ||||
| 					public void run() { | ||||
| 						// 子线程读取联系人 | ||||
| 						final List<ContactModel> tempList = readContactsInBackground(); | ||||
|  | ||||
| 						// 主线程更新UI | ||||
| 						mainHandler.post(new Runnable() { | ||||
| 								@Override | ||||
| 								public void run() { | ||||
| 									// 更新缓存 | ||||
| 									sCachedOriginalList.clear(); | ||||
| 									sCachedOriginalList.addAll(tempList); | ||||
| 									sCachedFilteredList.clear(); | ||||
| 									sCachedFilteredList.addAll(tempList); | ||||
|  | ||||
| 									// 更新当前列表 | ||||
| 									originalContactList.clear(); | ||||
| 									originalContactList.addAll(sCachedOriginalList); | ||||
| 									contactList.clear(); | ||||
| 									contactList.addAll(sCachedFilteredList); | ||||
| 									contactAdapter.notifyDataSetChanged(); | ||||
| 									LogUtils.d(TAG, String.format("联系人加载完成,共%d条数据", contactList.size())); | ||||
|  | ||||
| 									// 数据加载后显示列表 | ||||
| 									recyclerView.setVisibility(View.VISIBLE); | ||||
| 									isDataLoaded = true; | ||||
| 								} | ||||
| 							}); | ||||
| 					} | ||||
| 				}); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // 子线程读取联系人 | ||||
|     private List<ContactModel> readContactsInBackground() { | ||||
|         List<ContactModel> tempList = new ArrayList<ContactModel>(); | ||||
|         Cursor cursor = null; | ||||
|         try { | ||||
|             // 查询联系人姓名和号码 | ||||
|             cursor = requireContext().getContentResolver().query( | ||||
|                 ContactsContract.CommonDataKinds.Phone.CONTENT_URI, | ||||
|                 new String[]{ | ||||
|                     ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, | ||||
|                     ContactsContract.CommonDataKinds.Phone.NUMBER | ||||
|                 }, | ||||
|                 null, | ||||
|                 null, | ||||
|                 ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC" | ||||
|             ); | ||||
|  | ||||
|             if (cursor != null && cursor.moveToFirst()) { | ||||
|                 int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); | ||||
|                 int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); | ||||
|  | ||||
|                 do { | ||||
|                     String name = cursor.getString(nameIndex); | ||||
|                     String number = cursor.getString(numberIndex).replaceAll("\\s", ""); // 去除空格 | ||||
|                     tempList.add(new ContactModel(name, number)); | ||||
|                 } while (cursor.moveToNext()); | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|             LogUtils.d(TAG, "读取联系人失败:" + e); | ||||
|         } finally { | ||||
|             if (cursor != null) { | ||||
|                 cursor.close(); // 关闭游标,避免内存泄漏 | ||||
|             } | ||||
|         } | ||||
|         return tempList; | ||||
|     } | ||||
|  | ||||
|     // 过滤联系人 | ||||
|     private void filterContacts(String query) { | ||||
|         contactList.clear(); | ||||
|         if (query.isEmpty()) { | ||||
|             contactList.addAll(originalContactList); | ||||
|             sCachedFilteredList.clear(); | ||||
|             sCachedFilteredList.addAll(originalContactList); | ||||
|         } else { | ||||
|             String lowerQuery = query.toLowerCase(); | ||||
|             for (ContactModel contact : originalContactList) { | ||||
|                 // 匹配姓名、全拼、简拼、号码 | ||||
|                 boolean matchName = contact.getName().toLowerCase().contains(lowerQuery); | ||||
|                 boolean matchPinyin = contact.getPinyin().toLowerCase().contains(lowerQuery); | ||||
|                 boolean matchFirstLetter = contact.getPinyinFirstLetter().toLowerCase().contains(lowerQuery); | ||||
|                 boolean matchNumber = contact.getNumber().contains(lowerQuery); | ||||
|  | ||||
|                 if (matchName || matchPinyin || matchFirstLetter || matchNumber) { | ||||
|                     contactList.add(contact); | ||||
|                 } | ||||
|             } | ||||
|             sCachedFilteredList.clear(); | ||||
|             sCachedFilteredList.addAll(contactList); | ||||
|         } | ||||
|         contactAdapter.notifyDataSetChanged(); | ||||
|         // 过滤后确保列表可见 | ||||
|         recyclerView.setVisibility(View.VISIBLE); | ||||
|     } | ||||
|  | ||||
|     // 权限回调 | ||||
|     @Override | ||||
|     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { | ||||
|         super.onRequestPermissionsResult(requestCode, permissions, grantResults); | ||||
|         if (requestCode == REQUEST_READ_CONTACTS) { | ||||
|             if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | ||||
|                 readContacts(); | ||||
|                 loadContacts(); // 授权后加载联系人 | ||||
|             } else { | ||||
|                 ToastUtils.show("请授予联系人权限以查看联系人列表"); | ||||
|                 recyclerView.setVisibility(View.VISIBLE); // 显示空列表 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void readContacts() { | ||||
|         contactList.clear(); | ||||
|         originalContactList.clear(); | ||||
|         Cursor cursor = requireContext().getContentResolver().query( | ||||
|             ContactsContract.CommonDataKinds.Phone.CONTENT_URI, | ||||
|             null, | ||||
|             null, | ||||
|             null, | ||||
|             ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"); | ||||
|     // 防抖TextWatcher(Java 7实现) | ||||
|     public abstract static class DebounceTextWatcher implements TextWatcher { | ||||
|         private final long debounceDelay; | ||||
|         private Handler handler = new Handler(Looper.getMainLooper()); | ||||
|         private Runnable pendingRunnable; | ||||
|  | ||||
|         if (cursor != null) { | ||||
|             while (cursor.moveToNext()) { | ||||
|                 String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); | ||||
|                 String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); | ||||
|                 ContactModel contact = new ContactModel(name, number); | ||||
|                 contactList.add(contact); | ||||
|                 originalContactList.add(contact); | ||||
|             } | ||||
|             cursor.close(); | ||||
|             contactAdapter.notifyDataSetChanged(); | ||||
|         public DebounceTextWatcher(long debounceDelay) { | ||||
|             this.debounceDelay = debounceDelay; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void filterContacts(String query) { | ||||
|         contactList.clear(); | ||||
|         if (query.isEmpty()) { | ||||
|             contactList.addAll(originalContactList); | ||||
|         } else { | ||||
|             for (ContactModel contact : originalContactList) { | ||||
|                 if (contact.getName().toLowerCase().contains(query.toLowerCase()) || | ||||
|                     contact.getPinyin().toLowerCase().contains(query.toLowerCase()) || | ||||
|                     contact.getNumber().toLowerCase().contains(query.toLowerCase())) { | ||||
|                     contactList.add(contact); | ||||
|         @Override | ||||
|         public void beforeTextChanged(CharSequence s, int start, int count, int after) { | ||||
|             // 无需处理 | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onTextChanged(final CharSequence s, int start, int before, int count) { | ||||
|             // 移除之前的延迟任务 | ||||
|             if (pendingRunnable != null) { | ||||
|                 handler.removeCallbacks(pendingRunnable); | ||||
|             } | ||||
|             // 延迟执行过滤 | ||||
|             pendingRunnable = new Runnable() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     onDebounceTextChanged(s.toString()); | ||||
|                 } | ||||
|             } | ||||
|             }; | ||||
|             handler.postDelayed(pendingRunnable, debounceDelay); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void afterTextChanged(Editable s) { | ||||
|             // 无需处理 | ||||
|         } | ||||
|  | ||||
|         // 抽象方法:防抖后的回调 | ||||
|         public abstract void onDebounceTextChanged(String query); | ||||
|     } | ||||
|  | ||||
|     // 资源释放 | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|         executor.shutdown(); // 关闭线程池 | ||||
|         mainHandler.removeCallbacksAndMessages(null); // 清除未执行任务 | ||||
|     } | ||||
|  | ||||
|     // Fragment隐藏/显示时的处理 | ||||
|     @Override | ||||
|     public void onHiddenChanged(boolean hidden) { | ||||
|         super.onHiddenChanged(hidden); | ||||
|         if (!hidden && isDataLoaded) { | ||||
|             // 复用缓存数据并显示列表 | ||||
|             contactList.clear(); | ||||
|             contactList.addAll(sCachedFilteredList); | ||||
|             contactAdapter.notifyDataSetChanged(); | ||||
|             recyclerView.setVisibility(View.VISIBLE); | ||||
|         } | ||||
|         contactAdapter.notifyDataSetChanged(); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.fragments; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/20 12:58:15 | ||||
|  * @Describe 应用日志 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.handlers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/14 03:51:40 | ||||
|  */ | ||||
| import android.os.Handler; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.receivers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 06:58:04 | ||||
|  * @Describe 主要广播接收器 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/14 03:38:31 | ||||
|  * @Describe 守护进程服务 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/13 06:56:41 | ||||
|  * @Describe 拨号主服务 | ||||
|  * 参考: | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.threads; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/14 03:46:44 | ||||
|  */ | ||||
| import android.content.Context; | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package cc.winboll.studio.contacts.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Date 2025/03/06 21:08:16 | ||||
|  * @Describe ContactUtils | ||||
|  * @Author ZhanGSKen&豆包大模型<zhangsken@qq.com> | ||||
|  * @Date 2025/08/30 14:32 | ||||
|  * @Describe 联系人工具集 | ||||
|  */ | ||||
| import android.content.ContentResolver; | ||||
| import android.content.Context; | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import android.widget.EditText; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/04/13 00:59:13 | ||||
|  * @Describe Int类型数字输入框工具集 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/04/13 01:16:28 | ||||
|  * @Describe Int数字操作工具集 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/26 15:21:48 | ||||
|  * @Describe PhoneUtils | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.utils; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/12/09 19:00:21 | ||||
|  * @Describe .* 前置预防针 | ||||
|  regex pointer preventive injection | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.views; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/02 21:11:03 | ||||
|  * @Describe 云盾防御信息 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.views; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/04 10:51:50 | ||||
|  * @Describe CustomHorizontalScrollView | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.views; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/03/19 14:04:20 | ||||
|  * @Describe 云盾滑视度热备控件 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.widgets; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/17 14:49:31 | ||||
|  * @Describe APPStatusWidget | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.contacts.widgets; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/02/17 14:59:55 | ||||
|  * @Describe WidgetButtonClickListener | ||||
|  */ | ||||
|   | ||||
| @@ -2,6 +2,6 @@ | ||||
| <resources> | ||||
|  | ||||
|     <string name="app_name">Contacts</string> | ||||
|     <string name="default_bobulltoon_url">https://gitea.winboll.cc/Studio/BoBullToon/archive/main.zip</string> | ||||
|     <string name="default_bobulltoon_url">https://gitee.com/zhangsken/bobulltoon/repository/archive/main.zip</string> | ||||
|  | ||||
| </resources> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.jc; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/11/28 15:42:47 | ||||
|  * @Describe 全局应用类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.jcndk; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/01/08 16:31:28 | ||||
|  * @Describe 文件工具类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.jcndk.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2025/01/09 11:19:28 | ||||
|  * @Describe JC 主服务类 | ||||
|  */ | ||||
|   | ||||
| @@ -21,8 +21,8 @@ android { | ||||
|  | ||||
| dependencies { | ||||
|     api fileTree(dir: 'libs', include: ['*.jar']) | ||||
|     api 'cc.winboll.studio:libapputils:15.8.4' | ||||
|     api 'cc.winboll.studio:libappbase:15.8.4' | ||||
|     api 'cc.winboll.studio:libapputils:15.8.5' | ||||
| 	api 'cc.winboll.studio:libappbase:15.9.5' | ||||
|      | ||||
|     // 吐司类库 | ||||
|     api 'com.github.getActivity:ToastUtils:10.5' | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Sat Jun 28 12:59:30 HKT 2025 | ||||
| stageCount=3 | ||||
| #Sun Aug 31 05:00:43 CST 2025 | ||||
| stageCount=4 | ||||
| libraryProject=libaes | ||||
| baseVersion=15.9 | ||||
| publishVersion=15.9.2 | ||||
| publishVersion=15.9.3 | ||||
| buildCount=0 | ||||
| baseBetaVersion=15.9.3 | ||||
| baseBetaVersion=15.9.4 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.activitys; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/13 18:58:54 | ||||
|  * @Describe 可以加入Fragment的有抽屉的活动窗口抽象类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/14 02:42:57 | ||||
|  * @Describe 主题元素项目类 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.beans; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/14 01:53:34 | ||||
|  * @Describe 抽屉菜单项目类 | ||||
|  */ | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import cc.winboll.studio.libaes.activitys.DrawerFragmentActivity; | ||||
| import cc.winboll.studio.libappbase.winboll.IWinBoLLActivity; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/15 00:58:10 | ||||
|  * @Describe 第二级窗口 | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.unittests; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/07/16 02:36:34 | ||||
|  * @Describe SecondaryLibraryFragment | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.unittests; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/07/16 01:27:50 | ||||
|  * @Describe TestAButtonFragment | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.unittests; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/07/16 01:14:00 | ||||
|  * @Describe TestASupportToolbarActivity | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.unittests; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/07/16 01:16:07 | ||||
|  * @Describe TestAToolbarActivity | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package cc.winboll.studio.libaes.unittests; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen<zhangsken@188.com> | ||||
|  * @Author ZhanGSKen<zhangsken@qq.com> | ||||
|  * @Date 2024/06/30 15:00:51 | ||||
|  */ | ||||
| import android.app.Activity; | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user