合并appbase
This commit is contained in:
commit
b34d777c9f
@ -14,7 +14,7 @@ def DefaultGroupId = 'cc.winboll.studio' // 类库所有者groupId
|
||||
def DefaultVersion = getDefaultVersion() // 版本号
|
||||
def DeveloperId='zhangsken' // 开发者账号
|
||||
def DeveloperName='ZhanGSKen' // 开发者名称
|
||||
def DeveloperEMail='ZhanGSKen@QQ.COM' // 开发者邮箱地址
|
||||
def DeveloperEMail='zhangsken@188.com' // 开发者邮箱地址
|
||||
def LicenseName='The Apache Software License, Version 2.0'
|
||||
def LicenseUrl='http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
|
||||
|
13
README.md
13
README.md
@ -1,6 +1,6 @@
|
||||
# ☁ ☁ ☁ WinBoll APP ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||
# ☁ ☁ 这是 WinBoll 系列 APP 汇总项目。☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||
# ☁ ☁ ☁ WinBoll 网站地址 https://www.winboll.cc/studio/app/ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||
# ☁ ☁ ☁ WinBoLL APP ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||
# ☁ ☁ WinBoLL Studio Android 应用开源项目。☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||
# ☁ ☁ ☁ WinBoLL 网站地址 https://www.winboll.cc/ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
||||
|
||||
## WinBoll 提问
|
||||
同样是 /sdcard 目录,在开发 Android 应用时,
|
||||
@ -92,7 +92,12 @@
|
||||
|
||||
### ☁ 云游四方 ☁ ###
|
||||
### ☁ 呔! ☁ WinBoll-APP 应用需求规划
|
||||
☁ WinBoll-APP 提供手机目录 /sdcard/WinBollStudio/Sources 的 WinBoll 项目源码管理功能。
|
||||
☁ 如要使用 WinBoLL Android 项目的 Gradle 编译功能,则需要设置以下两个文件夹。
|
||||
☁ 1. 则需要建立数据存储目录 /sdcard/WinBoLLStudio/APKs。
|
||||
WinBoLL 项目源码编译出来的安装包会拷贝一份到 /sdcard/WinBoLLStudio/APKs 目录下。
|
||||
☁ 2. 则需要建立数据存储目录 /sdcard/AppProjects。
|
||||
WinBoLL 项目源码编译出来的安装包会拷贝一份并命名 "app.apk" 的安装文件为到 /sdcard/AppProjects 目录下。
|
||||
|
||||
|
||||
### ☁ 吁! ☁ WinBoll-APP 共享计划前景
|
||||
☁ WinBoll-APP 将会实现 https://winboll.cc/api 访问功能。
|
||||
|
@ -30,7 +30,7 @@ android {
|
||||
// versionName 更新后需要手动设置
|
||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||
versionName "15.4"
|
||||
versionName "15.2"
|
||||
if(true) {
|
||||
versionName = genVersionName("${versionName}")
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Apr 27 17:36:17 HKT 2025
|
||||
stageCount=9
|
||||
#Sat Apr 26 12:27:57 GMT 2025
|
||||
stageCount=6
|
||||
libraryProject=libappbase
|
||||
baseVersion=15.4
|
||||
publishVersion=15.4.8
|
||||
buildCount=0
|
||||
baseBetaVersion=15.4.9
|
||||
baseVersion=15.2
|
||||
publishVersion=15.2.5
|
||||
buildCount=4
|
||||
baseBetaVersion=15.2.6
|
||||
|
@ -4,11 +4,11 @@ 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 android.widget.Toolbar;
|
||||
import cc.winboll.studio.appbase.R;
|
||||
import cc.winboll.studio.appbase.activities.NewActivity;
|
||||
import cc.winboll.studio.appbase.services.MainService;
|
||||
@ -22,6 +22,7 @@ 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 {
|
||||
|
||||
@ -47,7 +48,7 @@ public class MainActivity extends WinBollActivityBase implements IWinBollActivit
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
mToolbar = findViewById(R.id.toolbar);
|
||||
setActionBar(mToolbar);
|
||||
setSupportActionBar(mToolbar);
|
||||
|
||||
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
|
||||
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
|
||||
|
@ -8,6 +8,7 @@ package cc.winboll.studio.appbase;
|
||||
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;
|
||||
@ -16,7 +17,7 @@ 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 Activity implements IWinBollActivity {
|
||||
public class WinBollActivityBase extends AppCompatActivity implements IWinBollActivity {
|
||||
|
||||
public static final String TAG = "WinBollActivityBase";
|
||||
|
||||
|
@ -7,10 +7,10 @@ package cc.winboll.studio.appbase.activities;
|
||||
*/
|
||||
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 android.widget.Toolbar;
|
||||
import cc.winboll.studio.appbase.R;
|
||||
import cc.winboll.studio.appbase.WinBollActivityBase;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
@ -41,7 +41,7 @@ public class New2Activity extends WinBollActivityBase implements IWinBollActivit
|
||||
// mLogView = findViewById(R.id.logview);
|
||||
// mLogView.start();
|
||||
mToolbar = findViewById(R.id.toolbar);
|
||||
setActionBar(mToolbar);
|
||||
setSupportActionBar(mToolbar);
|
||||
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,10 @@ package cc.winboll.studio.appbase.activities;
|
||||
*/
|
||||
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 android.widget.Toolbar;
|
||||
import cc.winboll.studio.appbase.R;
|
||||
import cc.winboll.studio.appbase.WinBollActivityBase;
|
||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||
@ -39,7 +39,7 @@ public class NewActivity extends WinBollActivityBase implements IWinBollActivity
|
||||
// mLogView = findViewById(R.id.logview);
|
||||
// mLogView.start();
|
||||
mToolbar = findViewById(R.id.toolbar);
|
||||
setActionBar(mToolbar);
|
||||
setSupportActionBar(mToolbar);
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.widget.Toolbar
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/toolbar"/>
|
||||
|
@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.widget.Toolbar
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/toolbar"/>
|
||||
|
@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.widget.Toolbar
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/toolbar"/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Apr 27 11:14:39 HKT 2025
|
||||
#Sat Mar 29 12:14:55 HKT 2025
|
||||
stageCount=2
|
||||
libraryProject=libapputils
|
||||
baseVersion=15.2
|
||||
|
@ -22,4 +22,25 @@ android {
|
||||
|
||||
dependencies {
|
||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
// Android 类库
|
||||
//api 'com.android.support:appcompat-v7:28.0.0'
|
||||
api('com.android.support:appcompat-v7:28.0.0'){
|
||||
//exclude group: "com.android.support", module: "support-vector-drawable"
|
||||
exclude group: "com.android.support:animated-vector-drawable:28.0.0"
|
||||
}
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-compat
|
||||
//api 'com.android.support:support-compat:28.0.0' // 保留原有依赖(可选)
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-v4
|
||||
api 'com.android.support:support-v4:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-media-compat
|
||||
api 'com.android.support:support-media-compat:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-core-utils
|
||||
api 'com.android.support:support-core-utils:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-core-ui
|
||||
api 'com.android.support:support-core-ui:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/support-fragment
|
||||
api 'com.android.support:support-fragment:28.0.0'
|
||||
// https://mvnrepository.com/artifact/com.android.support/recyclerview-v7
|
||||
api 'com.android.support:recyclerview-v7:28.0.0'
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sun Apr 27 11:03:35 HKT 2025
|
||||
stageCount=9
|
||||
#Sat Apr 26 12:27:57 GMT 2025
|
||||
stageCount=6
|
||||
libraryProject=libappbase
|
||||
baseVersion=15.4
|
||||
publishVersion=15.4.8
|
||||
buildCount=0
|
||||
baseBetaVersion=15.4.9
|
||||
baseVersion=15.2
|
||||
publishVersion=15.2.5
|
||||
buildCount=4
|
||||
baseBetaVersion=15.2.6
|
||||
|
@ -4,19 +4,20 @@ package cc.winboll.studio.libappbase;
|
||||
* @Author ZhanGSKen@AliYun.Com
|
||||
* @Date 2025/02/11 00:14:05
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
|
||||
public final class GlobalCrashActivity extends Activity implements MenuItem.OnMenuItemClickListener {
|
||||
public final class GlobalCrashActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
|
||||
|
||||
private static final int MENUITEM_COPY = 0;
|
||||
private static final int MENUITEM_RESTART = 1;
|
||||
@ -38,10 +39,10 @@ public final class GlobalCrashActivity extends Activity implements MenuItem.OnMe
|
||||
setContentView(R.layout.activity_globalcrash);
|
||||
mGlobalCrashReportView = findViewById(R.id.activityglobalcrashGlobalCrashReportView1);
|
||||
mGlobalCrashReportView.setReport(mLog);
|
||||
setActionBar(mGlobalCrashReportView.getToolbar());
|
||||
setSupportActionBar(mGlobalCrashReportView.getToolbar());
|
||||
|
||||
getActionBar().setTitle(CrashHandler.TITTLE);
|
||||
getActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
|
||||
getSupportActionBar().setTitle(CrashHandler.TITTLE);
|
||||
getSupportActionBar().setSubtitle(GlobalApplication.getAppName(getApplicationContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -8,6 +8,7 @@ package cc.winboll.studio.libappbase;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.AttributeSet;
|
||||
@ -15,7 +16,6 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
import cc.winboll.studio.libappbase.R;
|
||||
|
||||
public class GlobalCrashReportView extends LinearLayout {
|
||||
|
@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/viewglobalcrashreportLinearLayout1">
|
||||
|
||||
<android.widget.Toolbar
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/viewglobalcrashreportToolbar1"/>
|
||||
|
@ -4,18 +4,22 @@
|
||||
<item
|
||||
android:id="@+id/item_minimal"
|
||||
android:title="MINIMAL"
|
||||
android:icon="@drawable/ic_winboll_point"/>
|
||||
android:icon="@drawable/ic_winboll_point"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/item_about"
|
||||
android:title="ABOUT"
|
||||
android:icon="@drawable/ic_winboll_logo"/>
|
||||
android:icon="@drawable/ic_winboll_logo"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/item_help"
|
||||
android:title="HELP"
|
||||
android:icon="@drawable/ic_winboll_help"/>
|
||||
android:icon="@drawable/ic_winboll_help"
|
||||
app:showAsAction="always"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/item_log"
|
||||
android:title="LOG"
|
||||
android:icon="@drawable/ic_winboll_log"/>
|
||||
android:icon="@drawable/ic_winboll_log"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="APPBaseTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
|
||||
<style name="APPBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="themeGlobalCrashActivity">@style/GlobalCrashActivityTheme</item>
|
||||
</style>
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit d94d70050f92a24b407f35cbd93a8e9ed8b007d8
|
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>
|
Loading…
x
Reference in New Issue
Block a user