Merge remote-tracking branch 'origin/appbase' into apputils
This commit is contained in:
		@@ -14,7 +14,7 @@ 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'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
# ☁ ☁ ☁ 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 应用时,
 | 
				
			||||||
@@ -92,7 +92,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### ☁ 云游四方 ☁ ###
 | 
					### ☁ 云游四方 ☁ ###
 | 
				
			||||||
### ☁ 呔! ☁ 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 共享计划前景
 | 
				
			||||||
☁ WinBoll-APP 将会实现 https://winboll.cc/api 访问功能。
 | 
					☁ WinBoll-APP 将会实现 https://winboll.cc/api 访问功能。
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ android {
 | 
				
			|||||||
        // 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.2"
 | 
				
			||||||
        if(true) {
 | 
					        if(true) {
 | 
				
			||||||
            versionName = genVersionName("${versionName}")
 | 
					            versionName = genVersionName("${versionName}")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					#Sat Apr 26 12:27:57 GMT 2025
 | 
				
			||||||
stageCount=8
 | 
					stageCount=6
 | 
				
			||||||
libraryProject=libappbase
 | 
					libraryProject=libappbase
 | 
				
			||||||
baseVersion=15.4
 | 
					baseVersion=15.2
 | 
				
			||||||
publishVersion=15.4.7
 | 
					publishVersion=15.2.5
 | 
				
			||||||
buildCount=0
 | 
					buildCount=4
 | 
				
			||||||
baseBetaVersion=15.4.8
 | 
					baseBetaVersion=15.2.6
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					#Sat Apr 26 12:27:57 GMT 2025
 | 
				
			||||||
stageCount=8
 | 
					stageCount=6
 | 
				
			||||||
libraryProject=libappbase
 | 
					libraryProject=libappbase
 | 
				
			||||||
baseVersion=15.4
 | 
					baseVersion=15.2
 | 
				
			||||||
publishVersion=15.4.7
 | 
					publishVersion=15.2.5
 | 
				
			||||||
buildCount=0
 | 
					buildCount=4
 | 
				
			||||||
baseBetaVersion=15.4.8
 | 
					baseBetaVersion=15.2.6
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule winboll-x deleted from d94d70050f
									
								
							
							
								
								
									
										1
									
								
								winboll/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								winboll/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					/build
 | 
				
			||||||
							
								
								
									
										1
									
								
								winboll/app_update_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								winboll/app_update_description.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										50
									
								
								winboll/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								winboll/build.gradle
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										8
									
								
								winboll/build.properties
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										17
									
								
								winboll/proguard-rules.pro
									
									
									
									
										vendored
									
									
										Normal 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 *;
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
							
								
								
									
										12
									
								
								winboll/src/beta/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								winboll/src/beta/AndroidManifest.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								winboll/src/beta/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								winboll/src/beta/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<resources>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <string name="app_name">AppBase+</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</resources>
 | 
				
			||||||
							
								
								
									
										128
									
								
								winboll/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								winboll/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										27
									
								
								winboll/src/main/java/cc/winboll/studio/appbase/App.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								winboll/src/main/java/cc/winboll/studio/appbase/App.java
									
									
									
									
									
										Normal 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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								winboll/src/main/res/drawable/ic_cloud.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								winboll/src/main/res/drawable/ic_cloud.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										11
									
								
								winboll/src/main/res/drawable/ic_cloud_outline.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								winboll/src/main/res/drawable/ic_cloud_outline.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										216
									
								
								winboll/src/main/res/layout/activity_main.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								winboll/src/main/res/layout/activity_main.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								winboll/src/main/res/layout/activity_new.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								winboll/src/main/res/layout/activity_new.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								winboll/src/main/res/layout/activity_new2.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								winboll/src/main/res/layout/activity_new2.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										51
									
								
								winboll/src/main/res/layout/widget_news.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								winboll/src/main/res/layout/widget_news.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								winboll/src/main/res/menu/toolbar_main.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								winboll/src/main/res/menu/toolbar_main.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										7
									
								
								winboll/src/main/res/values/colors.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								winboll/src/main/res/values/colors.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										5
									
								
								winboll/src/main/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								winboll/src/main/res/values/strings.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										14
									
								
								winboll/src/main/res/values/styles.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								winboll/src/main/res/values/styles.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										7
									
								
								winboll/src/main/res/xml/widget_provider_info_sos.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								winboll/src/main/res/xml/widget_provider_info_sos.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
							
								
								
									
										12
									
								
								winboll/src/stage/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								winboll/src/stage/AndroidManifest.xml
									
									
									
									
									
										Normal 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								winboll/src/stage/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								winboll/src/stage/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<resources>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Put flavor specific strings here -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</resources>
 | 
				
			||||||
		Reference in New Issue
	
	Block a user