Compare commits
66 Commits
appbase-v2
...
apputils-v
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d4ea79b950 | ||
![]() |
06a40a4298 | ||
![]() |
35835d746e | ||
![]() |
5f3d03ba7d | ||
![]() |
1d372ff9ae | ||
![]() |
4a1e398755 | ||
![]() |
107be6d6ad | ||
![]() |
19db567a7d | ||
![]() |
b14add854e | ||
![]() |
104d9fa283 | ||
![]() |
dd041e5d78 | ||
![]() |
2f019ae176 | ||
![]() |
b5b4fbd3f5 | ||
![]() |
548dcf74ed | ||
![]() |
547bf894c6 | ||
![]() |
09e6429726 | ||
![]() |
3ad9bb262e | ||
![]() |
15992da22f | ||
![]() |
7fb4e665f9 | ||
![]() |
6a82889926 | ||
![]() |
7272cc4e5b | ||
![]() |
1f7d112a8a | ||
![]() |
936e214015 | ||
![]() |
46e95d1b1f | ||
![]() |
15173f7af3 | ||
![]() |
6f3b6c40af | ||
![]() |
42ffba69e5 | ||
![]() |
f021e8a1a3 | ||
![]() |
02ce7dedb0 | ||
![]() |
8e290cd5e6 | ||
![]() |
37f2aa5f1b | ||
![]() |
10cc69940b | ||
![]() |
bfdff9ff2f | ||
![]() |
12c6129a61 | ||
![]() |
ea10d1b540 | ||
![]() |
81f6ff592e | ||
![]() |
e6f22e9212 | ||
![]() |
8ce8f383fa | ||
![]() |
35d32b384f | ||
![]() |
85e86ddf05 | ||
![]() |
99bf804625 | ||
![]() |
261259e61e | ||
![]() |
9aaf3433bd | ||
![]() |
b739510951 | ||
![]() |
903359d9a2 | ||
![]() |
69e7e72ed8 | ||
![]() |
a96ba362b4 | ||
![]() |
6447bcf924 | ||
![]() |
18ed325731 | ||
![]() |
16e3d10b63 | ||
![]() |
8b0e8b00ae | ||
![]() |
7f61ff1470 | ||
![]() |
c4e0c23a0c | ||
![]() |
c7d26bbc3d | ||
![]() |
4968bbaeae | ||
![]() |
8e6b06e366 | ||
![]() |
ae7fb2984a | ||
![]() |
a4d009f8fb | ||
![]() |
5a549e9652 | ||
![]() |
e2d71ae088 | ||
![]() |
506d2619f2 | ||
![]() |
17fa805a7f | ||
![]() |
1dcf8cd007 | ||
![]() |
d86d50212e | ||
![]() |
af2e09c02a | ||
![]() |
de6361b19b |
3
.idea/.gitignore
generated
vendored
3
.idea/.gitignore
generated
vendored
@@ -1,3 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
1
.idea/.name
generated
1
.idea/.name
generated
@@ -1 +0,0 @@
|
|||||||
appbase
|
|
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="17" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
.idea/deploymentTargetDropDown.xml
generated
10
.idea/deploymentTargetDropDown.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetDropDown">
|
|
||||||
<value>
|
|
||||||
<entry key="appbase">
|
|
||||||
<State />
|
|
||||||
</entry>
|
|
||||||
</value>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
.idea/migrations.xml
generated
10
.idea/migrations.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectMigrations">
|
|
||||||
<option name="MigrateToGradleLocalJavaHome">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
10
.idea/misc.xml
generated
10
.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectType">
|
|
||||||
<option name="id" value="Android" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@@ -18,18 +18,18 @@ def genVersionName(def versionName){
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 32
|
||||||
buildToolsVersion "30.0.3"
|
buildToolsVersion "33.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "cc.winboll.studio.appbase"
|
applicationId "cc.winboll.studio.appbase"
|
||||||
minSdkVersion 26
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode 1
|
versionCode 1
|
||||||
// versionName 更新后需要手动设置
|
// versionName 更新后需要手动设置
|
||||||
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
|
||||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||||
versionName "2.1"
|
versionName "1.0"
|
||||||
if(true) {
|
if(true) {
|
||||||
versionName = genVersionName("${versionName}")
|
versionName = genVersionName("${versionName}")
|
||||||
}
|
}
|
||||||
@@ -41,32 +41,14 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_11
|
||||||
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':libappbase')
|
api project(':libappbase')
|
||||||
|
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
|
|
||||||
// SSH
|
|
||||||
implementation 'com.jcraft:jsch:0.1.55'
|
|
||||||
// Html 解析
|
|
||||||
implementation 'org.jsoup:jsoup:1.13.1'
|
|
||||||
// 二维码类库
|
|
||||||
implementation 'com.google.zxing:core:3.4.1'
|
|
||||||
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
|
|
||||||
// 应用介绍页类库
|
|
||||||
implementation 'io.github.medyo:android-about-page:2.0.0'
|
|
||||||
// 吐司类库
|
|
||||||
implementation 'com.github.getActivity:ToastUtils:10.5'
|
|
||||||
// 网络连接类库
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
|
|
||||||
|
|
||||||
// Android 类库
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
|
||||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
|
||||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
|
||||||
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
|
|
||||||
implementation 'androidx.fragment:fragment:1.1.0'
|
|
||||||
implementation 'com.google.android.material:material:1.4.0'
|
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sat Mar 08 03:38:29 HKT 2025
|
#Sun Jan 05 02:30:11 GMT 2025
|
||||||
stageCount=3
|
stageCount=0
|
||||||
libraryProject=libappbase
|
libraryProject=
|
||||||
baseVersion=2.1
|
baseVersion=1.0
|
||||||
publishVersion=2.1.2
|
publishVersion=1.0.0
|
||||||
buildCount=0
|
buildCount=2
|
||||||
baseBetaVersion=2.1.3
|
baseBetaVersion=1.0.1
|
||||||
|
@@ -21,87 +21,15 @@
|
|||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<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>
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".GlobalApplication$CrashActivity"/>
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".MyTileService"
|
|
||||||
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=".services.AssistantService"/>
|
|
||||||
|
|
||||||
<receiver android:name="cc.winboll.studio.appbase.receivers.MainReceiver">
|
|
||||||
|
|
||||||
<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=".widgets.APPNewsWidgetClickListener">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="cc.winboll.studio.appbase.widgets.APPNewsWidgetClickListener.ACTION_PRE"/>
|
|
||||||
|
|
||||||
<action android:name="cc.winboll.studio.appbase.widgets.APPNewsWidgetClickListener.ACTION_NEXT"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.max_aspect"
|
android:name="android.max_aspect"
|
||||||
android:value="4.0"/>
|
android:value="4.0"/>
|
||||||
|
|
||||||
<service android:name="cc.winboll.studio.appbase.services.TestDemoBindService"
|
<activity android:name=".GlobalApplication$CrashActivity"/>
|
||||||
android:exported="true"/>
|
|
||||||
|
|
||||||
<service android:name="cc.winboll.studio.appbase.services.TestDemoService"
|
|
||||||
android:exported="true"/>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
@@ -5,24 +5,12 @@ package cc.winboll.studio.appbase;
|
|||||||
* @Date 2025/01/05 09:54:42
|
* @Date 2025/01/05 09:54:42
|
||||||
* @Describe APPbase 应用类
|
* @Describe APPbase 应用类
|
||||||
*/
|
*/
|
||||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
import cc.winboll.studio.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 class App extends GlobalApplication {
|
||||||
|
|
||||||
public static final String TAG = "App";
|
public static final String TAG = "App";
|
||||||
|
|
||||||
SOSCenterServiceReceiver mSOSCenterServiceReceiver;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
GlobalApplication.setIsDebuging(this, BuildConfig.DEBUG);
|
|
||||||
mSOSCenterServiceReceiver = new SOSCenterServiceReceiver();
|
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
|
||||||
intentFilter.addAction(SOS.ACTION_SOS);
|
|
||||||
registerReceiver(mSOSCenterServiceReceiver, intentFilter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,141 +1,15 @@
|
|||||||
package cc.winboll.studio.appbase;
|
package cc.winboll.studio.appbase;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.CheckBox;
|
public class MainActivity extends Activity {
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
@Override
|
||||||
import cc.winboll.studio.appbase.R;
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
import cc.winboll.studio.appbase.services.MainService;
|
super.onCreate(savedInstanceState);
|
||||||
import cc.winboll.studio.appbase.services.TestDemoBindService;
|
setContentView(R.layout.activity_main);
|
||||||
import cc.winboll.studio.appbase.services.TestDemoService;
|
|
||||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
}
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import cc.winboll.studio.libappbase.LogView;
|
}
|
||||||
import cc.winboll.studio.libappbase.widgets.StatusWidget;
|
|
||||||
import com.hjq.toast.ToastUtils;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import cc.winboll.studio.libappbase.sos.SOS;
|
|
||||||
import cc.winboll.studio.libappbase.sos.SOSObject;
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
public static final String TAG = "MainActivity";
|
|
||||||
|
|
||||||
LogView mLogView;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
ToastUtils.show("onCreate");
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.activitymainToolbar1);
|
|
||||||
setSupportActionBar(toolbar);
|
|
||||||
|
|
||||||
CheckBox cbIsDebugMode = findViewById(R.id.activitymainCheckBox1);
|
|
||||||
cbIsDebugMode.setChecked(GlobalApplication.isDebuging());
|
|
||||||
mLogView = findViewById(R.id.activitymainLogView1);
|
|
||||||
|
|
||||||
if (GlobalApplication.isDebuging()) { mLogView.start(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
Intent intentAPPWidget = new Intent(this, StatusWidget.class);
|
|
||||||
intentAPPWidget.setAction(StatusWidget.ACTION_STATUS_UPDATE);
|
|
||||||
sendBroadcast(intentAPPWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
LogUtils.d(TAG, "onResume");
|
|
||||||
super.onResume();
|
|
||||||
mLogView.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSwitchDebugMode(View view) {
|
|
||||||
GlobalApplication.setIsDebuging(this, ((CheckBox)view).isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 onTestSOS(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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,79 +0,0 @@
|
|||||||
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.beans.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();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,67 +0,0 @@
|
|||||||
package cc.winboll.studio.appbase.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,67 +0,0 @@
|
|||||||
package cc.winboll.studio.appbase.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,68 +0,0 @@
|
|||||||
package cc.winboll.studio.appbase.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,72 +0,0 @@
|
|||||||
package cc.winboll.studio.appbase.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,38 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,118 +0,0 @@
|
|||||||
package cc.winboll.studio.appbase.receivers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/13 06:58:04
|
|
||||||
* @Describe 主要广播接收器
|
|
||||||
*/
|
|
||||||
import android.appwidget.AppWidgetManager;
|
|
||||||
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.beans.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 com.hjq.toast.ToastUtils;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import cc.winboll.studio.libappbase.sos.WinBoll;
|
|
||||||
import cc.winboll.studio.libappbase.sos.APPModel;
|
|
||||||
import cc.winboll.studio.libappbase.sos.SOS;
|
|
||||||
import cc.winboll.studio.libappbase.sos.SOSObject;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,138 +0,0 @@
|
|||||||
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.beans.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,316 +0,0 @@
|
|||||||
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.beans.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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,178 +0,0 @@
|
|||||||
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.beans.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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,156 +0,0 @@
|
|||||||
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.beans.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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,54 +0,0 @@
|
|||||||
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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,185 +0,0 @@
|
|||||||
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.beans.WinBollNewsBean;
|
|
||||||
import cc.winboll.studio.libappbase.AppUtils;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import cc.winboll.studio.libappbase.sos.APPModel;
|
|
||||||
import cc.winboll.studio.libappbase.sos.WinBoll;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,36 +0,0 @@
|
|||||||
package cc.winboll.studio.appbase.widgets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/15 17:20:46
|
|
||||||
* @Describe WidgetButtonClickListener
|
|
||||||
*/
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?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>
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?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>
|
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
@@ -1,194 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/activitymainToolbar1"/>
|
android:text="Hello, WinBoll!"
|
||||||
|
android:onClick="onHello"/>
|
||||||
<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,但可能需要注意兼容性和配置问题。"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="right|center_vertical">
|
|
||||||
|
|
||||||
<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"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<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">
|
|
||||||
|
|
||||||
<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="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"/>
|
|
||||||
|
|
||||||
<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="TestSOS"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:onClick="onTestSOS"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
<cc.winboll.studio.libappbase.LogView
|
|
||||||
android:layout_height="500dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/activitymainLogView1"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@@ -1,51 +0,0 @@
|
|||||||
<?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>
|
|
||||||
|
|
9
appbase/src/main/res/values-v21/styles.xml
Normal file
9
appbase/src/main/res/values-v21/styles.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="AppTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
|
||||||
|
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="android:colorAccent">@color/colorAccent</item>
|
||||||
|
<item name="android:navigationBarColor">?android:colorPrimary</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="colorPrimary">#005800FF</color>
|
<color name="colorPrimary">#009688</color>
|
||||||
<color name="colorPrimaryDark">#005800FF</color>
|
<color name="colorPrimaryDark">#00796B</color>
|
||||||
<color name="colorAccent">#005800FF</color>
|
<color name="colorAccent">#FF9800</color>
|
||||||
</resources>
|
</resources>
|
@@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">AppBase</string>
|
<string name="app_name">AppBase</string>
|
||||||
<string name="tileservice_name">WinBoll</string>
|
</resources>
|
||||||
</resources>
|
|
||||||
|
@@ -1,14 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="AppTheme" parent="APPBaseTheme">
|
<style name="AppTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
|
||||||
<item name="attrColorPrimary">@color/colorPrimary</item>
|
</style>
|
||||||
<item name="themeGlobalCrashActivity">@style/MyGlobalCrashActivityTheme</item>
|
</resources>
|
||||||
</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>
|
|
@@ -1,7 +0,0 @@
|
|||||||
<?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>
|
|
@@ -29,7 +29,7 @@ android {
|
|||||||
// versionName 更新后需要手动设置
|
// versionName 更新后需要手动设置
|
||||||
// 项目模块目录的 build.gradle 文件的 stageCount=0
|
// 项目模块目录的 build.gradle 文件的 stageCount=0
|
||||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
||||||
versionName "9.2"
|
versionName "9.3"
|
||||||
if(true) {
|
if(true) {
|
||||||
versionName = genVersionName("${versionName}")
|
versionName = genVersionName("${versionName}")
|
||||||
}
|
}
|
||||||
@@ -50,6 +50,6 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(':libapputils')
|
api project(':libapputils')
|
||||||
api 'cc.winboll.studio:libappbase:1.0.3'
|
|
||||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
api fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sat Jan 18 13:03:10 HKT 2025
|
#Wed Feb 12 19:50:03 HKT 2025
|
||||||
stageCount=2
|
stageCount=3
|
||||||
libraryProject=libapputils
|
libraryProject=libapputils
|
||||||
baseVersion=9.2
|
baseVersion=9.3
|
||||||
publishVersion=9.2.1
|
publishVersion=9.3.2
|
||||||
buildCount=0
|
buildCount=0
|
||||||
baseBetaVersion=9.2.2
|
baseBetaVersion=9.3.3
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@drawable/ic_winboll"
|
android:icon="@drawable/ic_winboll"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/WinBoll.SupportThemeNoActionBar"
|
android:theme="@style/MyAppTheme"
|
||||||
android:supportsRtl="true">
|
android:supportsRtl="true">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
@@ -27,10 +27,8 @@
|
|||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".TestWinBollActivity"/>
|
|
||||||
|
|
||||||
<activity android:name=".TestStringToQrCodeViewActivity"/>
|
<activity android:name=".TestStringToQrCodeViewActivity"/>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@@ -5,27 +5,83 @@ package cc.winboll.studio.apputils;
|
|||||||
* @Date 2024/12/08 15:10:51
|
* @Date 2024/12/08 15:10:51
|
||||||
* @Describe 全局应用类
|
* @Describe 全局应用类
|
||||||
*/
|
*/
|
||||||
import android.view.Gravity;
|
import android.app.Application;
|
||||||
import cc.winboll.studio.libapputils.app.WinBollApplication;
|
import android.content.Context;
|
||||||
import com.hjq.toast.ToastUtils;
|
import android.widget.Toast;
|
||||||
import com.hjq.toast.style.WhiteToastStyle;
|
import cc.winboll.studio.libappbase.GlobalApplication;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.libapputils.app.MyActivityLifecycleCallbacks;
|
||||||
|
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||||
|
import cc.winboll.studio.libapputils.bean.DebugBean;
|
||||||
|
|
||||||
public class App extends WinBollApplication {
|
public class App extends GlobalApplication {
|
||||||
|
|
||||||
public static final String TAG = "App";
|
public static final String TAG = "App";
|
||||||
|
|
||||||
public static final String _ACTION_DEBUGVIEW = WinBollApplication.class.getName() + "_ACTION_DEBUGVIEW";
|
public static final String _ACTION_DEBUGVIEW = App.class.getName() + "_ACTION_DEBUGVIEW";
|
||||||
|
|
||||||
|
//static volatile WinBollApplication _WinBollApplication = null;
|
||||||
|
MyActivityLifecycleCallbacks mMyActivityLifecycleCallbacks;
|
||||||
|
|
||||||
|
// 标记当前应用是否处于调试状态
|
||||||
|
static volatile boolean isDebug = false;
|
||||||
|
|
||||||
|
public synchronized static void setIsDebug(boolean isDebug) {
|
||||||
|
App.isDebug = isDebug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDebug() {
|
||||||
|
return isDebug;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyActivityLifecycleCallbacks getMyActivityLifecycleCallbacks() {
|
||||||
|
return mMyActivityLifecycleCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Context getApplicationContext() {
|
||||||
|
return super.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Application getApplication() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
// 初始化 Toast 框架
|
// 应用环境初始化, 基本调试环境
|
||||||
//
|
//
|
||||||
ToastUtils.init(this);
|
// 初始化日志模块
|
||||||
// 设置 Toast 布局样式
|
//LogUtils.init(this);
|
||||||
//ToastUtils.setView(R.layout.view_toast);
|
|
||||||
ToastUtils.setStyle(new WhiteToastStyle());
|
|
||||||
ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 初始化 Toast 框架
|
||||||
|
// ToastUtils.init(this);
|
||||||
|
// // 设置 Toast 布局样式
|
||||||
|
// //ToastUtils.setView(R.layout.view_toast);
|
||||||
|
// ToastUtils.setStyle(new WhiteToastStyle());
|
||||||
|
// ToastUtils.setGravity(Gravity.BOTTOM, 0, 200);
|
||||||
|
// 设置应用调试标志
|
||||||
|
DebugBean debugBean = DebugBean.loadBean(this, DebugBean.class);
|
||||||
|
if (debugBean == null) {
|
||||||
|
//ToastUtils.show("debugBean == null");
|
||||||
|
setIsDebug(false);
|
||||||
|
} else {
|
||||||
|
//ToastUtils.show("saveDebugStatus(" + String.valueOf(debugBean.isDebuging()) + ")");
|
||||||
|
setIsDebug(debugBean.isDebuging());
|
||||||
|
}
|
||||||
|
// 应用窗口管理模块参数设置
|
||||||
|
//
|
||||||
|
mMyActivityLifecycleCallbacks = new MyActivityLifecycleCallbacks();
|
||||||
|
registerActivityLifecycleCallbacks(mMyActivityLifecycleCallbacks);
|
||||||
|
// 设置默认 WinBoll 应用 UI 类型
|
||||||
|
WinBollActivityManager.getInstance(this).setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Service);
|
||||||
|
//ToastUtils.show("WinBollUI_TYPE " + getWinBollUI_TYPE());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
||||||
|
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,28 +1,81 @@
|
|||||||
package cc.winboll.studio.apputils;
|
package cc.winboll.studio.apputils;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import cc.winboll.studio.apputils.R;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
import cc.winboll.studio.libapputils.activities.AssetsHtmlActivity;
|
import cc.winboll.studio.libapputils.activities.AssetsHtmlActivity;
|
||||||
import cc.winboll.studio.libapputils.activities.QRCodeDecodeActivity;
|
import cc.winboll.studio.libapputils.activities.QRCodeDecodeActivity;
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivity;
|
import cc.winboll.studio.libapputils.app.AboutActivityFactory;
|
||||||
|
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
||||||
|
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||||
import cc.winboll.studio.libapputils.log.LogActivity;
|
import cc.winboll.studio.libapputils.log.LogActivity;
|
||||||
import cc.winboll.studio.libapputils.log.LogUtils;
|
import cc.winboll.studio.libapputils.view.AboutView;
|
||||||
|
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
|
||||||
import com.hjq.toast.ToastUtils;
|
import com.hjq.toast.ToastUtils;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
final public class MainActivity extends WinBollActivity {
|
final public class MainActivity extends AppCompatActivity implements IWinBollActivity {
|
||||||
|
|
||||||
public static final String TAG = "MainActivity";
|
public static final String TAG = "MainActivity";
|
||||||
|
|
||||||
public static final int REQUEST_QRCODEDECODE_ACTIVITY = 0;
|
public static final int REQUEST_QRCODEDECODE_ACTIVITY = 0;
|
||||||
|
|
||||||
|
Toolbar mToolbar;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnableDisplayHomeAsUp() {
|
public AppCompatActivity getActivity() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APPInfo getAppInfo() {
|
||||||
|
String szBranchName = "apputils";
|
||||||
|
|
||||||
|
APPInfo appInfo = AboutActivityFactory.buildDefaultAPPInfo();
|
||||||
|
appInfo.setAppName("APPUtils");
|
||||||
|
appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
|
||||||
|
appInfo.setAppDescription("APPUtils Description");
|
||||||
|
appInfo.setAppGitName("APP");
|
||||||
|
appInfo.setAppGitOwner("Studio");
|
||||||
|
appInfo.setAppGitAPPBranch(szBranchName);
|
||||||
|
appInfo.setAppGitAPPSubProjectFolder(szBranchName);
|
||||||
|
appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=APP");
|
||||||
|
appInfo.setAppAPKName("APPUtils");
|
||||||
|
appInfo.setAppAPKFolderName("APPUtils");
|
||||||
|
return appInfo;
|
||||||
|
//return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAddWinBollToolBar() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Toolbar initToolBar() {
|
||||||
|
return findViewById(R.id.activitymainToolbar1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnableDisplayHomeAsUp() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +84,19 @@ final public class MainActivity extends WinBollActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
//Toolbar toolbar = findViewById(R.id.activitymainToolbar1);
|
// 初始化工具栏
|
||||||
//setActionBar(toolbar);
|
mToolbar = findViewById(R.id.activitymainToolbar1);
|
||||||
|
setSupportActionBar(mToolbar);
|
||||||
|
if (isEnableDisplayHomeAsUp()) {
|
||||||
|
// 显示后退按钮
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
getSupportActionBar().setSubtitle(getTag());
|
||||||
|
|
||||||
|
checkResolveActivity();
|
||||||
|
archiveInstance();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 接收并处理 Intent 数据,函数 Intent 处理接收就直接返回
|
// 接收并处理 Intent 数据,函数 Intent 处理接收就直接返回
|
||||||
//if (prosessIntents(getIntent())) return;
|
//if (prosessIntents(getIntent())) return;
|
||||||
@@ -44,44 +108,94 @@ final public class MainActivity extends WinBollActivity {
|
|||||||
// LogUtils.d(TAG, "BuildConfig.DEBUG : " + Boolean.toString(BuildConfig.DEBUG));
|
// LogUtils.d(TAG, "BuildConfig.DEBUG : " + Boolean.toString(BuildConfig.DEBUG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean checkResolveActivity() {
|
||||||
|
PackageManager packageManager = getPackageManager();
|
||||||
|
//Intent intent = new Intent("your_action_here");
|
||||||
|
Intent intent = getIntent();
|
||||||
|
if (intent != null) {
|
||||||
|
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||||
|
if (resolveInfoList.size() > 0) {
|
||||||
|
// 传入的Intent action在Activity清单的intent-filter的action节点里有定义
|
||||||
|
if (intent.getAction() != null) {
|
||||||
|
if (intent.getAction().equals(cc.winboll.studio.libapputils.intent.action.DEBUGVIEW)) {
|
||||||
|
App.setIsDebug(true);
|
||||||
|
//ToastUtils.show!("WinBollApplication.setIsDebug(true) by action : " + intent.getAction());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// 传入的Intent action在Activity清单的intent-filter的action节点里没有定义
|
||||||
|
//ToastUtils.show("false : " + intent.getAction());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// action在清单文件中没有声明
|
||||||
|
ToastUtils.show("false");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void archiveInstance() {
|
||||||
|
Intent intent = getIntent();
|
||||||
|
StringBuilder sb = new StringBuilder("\n### Archive Instance ###\n");
|
||||||
|
|
||||||
|
if (intent != null) {
|
||||||
|
ComponentName componentName = intent.getComponent();
|
||||||
|
if (componentName != null) {
|
||||||
|
String packageName = componentName.getPackageName();
|
||||||
|
//Log.d("AppStarter", "启动本应用的应用包名: " + packageName);
|
||||||
|
sb.append("启动本应用的应用包名: \n" + packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("\nImplicit Intent Tracker :\n接收到的 Intent 动作: \n" + intent.getAction());
|
||||||
|
Set<String> categories = intent.getCategories();
|
||||||
|
if (categories != null) {
|
||||||
|
for (String category : categories) {
|
||||||
|
sb.append("\n接收到的 Intent 类别 :\n" + category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Uri data = intent.getData();
|
||||||
|
if (data != null) {
|
||||||
|
sb.append("\n接收到的 Intent 数据 :\n" + data.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("Intent is null.");
|
||||||
|
}
|
||||||
|
sb.append("\n\n");
|
||||||
|
LogUtils.d(TAG, sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
|
super.onPostCreate(savedInstanceState);
|
||||||
|
// 缓存当前 activity
|
||||||
|
WinBollActivityManager.getInstance(this).add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
WinBollActivityManager.getInstance(this).registeRemove(this);
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
public void onTestLogClick(View view) {
|
public void onTestLogClick(View view) {
|
||||||
LogUtils.d(TAG, "onTestLogClick");
|
LogUtils.d(TAG, "onTestLogClick");
|
||||||
Toast.makeText(getApplication(), "onTestLogClick", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplication(), "onTestLogClick", Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLogUtilsClick(View view) {
|
public void onLogUtilsClick(View view) {
|
||||||
Intent intent = new Intent(this, LogActivity.class);
|
// Intent intent = new Intent(this, LogActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
// intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||||
startActivity(intent);
|
// startActivity(intent);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
//WinBollActivityManager.getInstance().printAvtivityListInfo();
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
WinBollActivityManager.getInstance(this).startWinBollActivity(this, LogActivity.class);
|
||||||
super.onPostCreate(savedInstanceState);
|
|
||||||
// setSubTitle("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
// exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// void exit() {
|
|
||||||
// YesNoAlertDialog.OnDialogResultListener listener = new YesNoAlertDialog.OnDialogResultListener(){
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onYes() {
|
|
||||||
// WinBollActivityManager.getInstance(getApplicationContext()).finishAll();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onNo() {
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// YesNoAlertDialog.show(this, "[ " + getString(R.string.app_name) + " ]", "Exit(Yes/No).\nIs close all activity?", listener);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 处理传入的 Intent 数据
|
// 处理传入的 Intent 数据
|
||||||
//
|
//
|
||||||
@@ -125,58 +239,108 @@ final public class MainActivity extends WinBollActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTag() {
|
|
||||||
return TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isAddWinBollToolBar() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Toolbar initToolBar() {
|
|
||||||
return findViewById(R.id.activitymainToolbar1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
//ToastUtils.show("onCreateOptionsMenu");
|
||||||
getMenuInflater().inflate(R.menu.toolbar_main, menu);
|
getMenuInflater().inflate(R.menu.toolbar_main, menu);
|
||||||
|
if (isAddWinBollToolBar()) {
|
||||||
|
//ToastUtils.show("mIWinBoll.isAddWinBollToolBar()");
|
||||||
|
getMenuInflater().inflate(R.menu.toolbar_winboll_shared_main, menu);
|
||||||
|
}
|
||||||
|
if (App.isDebug()) {
|
||||||
|
getMenuInflater().inflate(R.menu.toolbar_studio_debug, menu);
|
||||||
|
}
|
||||||
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if (item.getItemId() == R.id.item_testwinboll) {
|
if (item.getItemId() == R.id.item_exit) {
|
||||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, TestWinBollActivity.class);
|
exit();
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.item_about) {
|
||||||
|
AboutActivityFactory.showAboutActivity(this, getAppInfo());
|
||||||
|
return true;
|
||||||
} else if (item.getItemId() == R.id.item_teststringtoqrcodeview) {
|
} else if (item.getItemId() == R.id.item_teststringtoqrcodeview) {
|
||||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, TestStringToQrCodeViewActivity.class);
|
WinBollActivityManager.getInstance(this).startWinBollActivity(this, TestStringToQrCodeViewActivity.class);
|
||||||
} else if (item.getItemId() == R.id.item_testqrcodedecodeactivity) {
|
} else if (item.getItemId() == R.id.item_testqrcodedecodeactivity) {
|
||||||
Intent intent = new Intent(this, QRCodeDecodeActivity.class);
|
Intent intent = new Intent(this, QRCodeDecodeActivity.class);
|
||||||
startActivityForResult(intent, REQUEST_QRCODEDECODE_ACTIVITY);
|
startActivityForResult(intent, REQUEST_QRCODEDECODE_ACTIVITY);
|
||||||
|
} else if (item.getItemId() == R.id.item_testcrashreport) {
|
||||||
|
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
|
||||||
|
getString(i);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.item_log) {
|
||||||
|
WinBollActivityManager.getInstance(this).startWinBollActivity(this, LogActivity.class);
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == R.id.item_exitdebug) {
|
||||||
|
AboutView.setApp2NormalMode(this);
|
||||||
|
return true;
|
||||||
|
} else if (item.getItemId() == android.R.id.home) {
|
||||||
|
WinBollActivityManager.getInstance(this).finish(this);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void about() {
|
||||||
|
// Intent intent = new Intent(this, AboutActivity.class);
|
||||||
|
// intent.putExtra(AboutActivity.EXTRA_APPINFO, AboutActivityFactory.buildAPPBranchInfo(this));
|
||||||
|
// WinBollActivityManager.getInstance(this).startWinBollActivity(this, intent, AboutActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit() {
|
||||||
|
YesNoAlertDialog.OnDialogResultListener listener = new YesNoAlertDialog.OnDialogResultListener(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onYes() {
|
||||||
|
WinBollActivityManager.getInstance(getApplicationContext()).finishAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNo() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
YesNoAlertDialog.show(this, "[ " + getString(R.string.app_name) + " ]", "Exit(Yes/No).\nIs close all activity?", listener);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (WinBollActivityManager.getInstance(getApplicationContext()).isFirstIWinBollActivity(this)) {
|
||||||
|
exit();
|
||||||
|
} else {
|
||||||
|
WinBollActivityManager.getInstance(this).finish(this);
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTestAboutActivity(View view) {
|
||||||
|
about();
|
||||||
|
}
|
||||||
|
|
||||||
public void onTestJavascriptHtmlActivity(View view) {
|
public void onTestJavascriptHtmlActivity(View view) {
|
||||||
Intent intent = new Intent(this, AssetsHtmlActivity.class);
|
Intent intent = new Intent(this, AssetsHtmlActivity.class);
|
||||||
intent.putExtra(AssetsHtmlActivity.EXTRA_HTMLFILENAME, "javascript_test.html");
|
intent.putExtra(AssetsHtmlActivity.EXTRA_HTMLFILENAME, "javascript_test.html");
|
||||||
WinBollActivityManager.getInstance(this).startWinBollActivity(this, intent, AssetsHtmlActivity.class);
|
WinBollActivityManager.getInstance(this).startWinBollActivity(this, intent, AssetsHtmlActivity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/*@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivithyResult(int requestCode, int resultCode, Intent data) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_QRCODEDECODE_ACTIVITY : {
|
case REQUEST_QRCODEDECODE_ACTIVITY : {
|
||||||
String text = data.getStringExtra(QRCodeDecodeActivity.EXTRA_RESULT);
|
if (data != null) {
|
||||||
ToastUtils.show(text);
|
String text = data.getStringExtra(QRCodeDecodeActivity.EXTRA_RESULT);
|
||||||
break;
|
ToastUtils.show(text);
|
||||||
}
|
}
|
||||||
default : {
|
break;
|
||||||
ToastUtils.show(String.format("%d, %d", requestCode, resultCode));
|
}
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
default : {
|
||||||
}
|
//ToastUtils.show(String.format("%d, %d", requestCode, resultCode));
|
||||||
}
|
super.prosessActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
@@ -1,19 +1,31 @@
|
|||||||
package cc.winboll.studio.apputils;
|
package cc.winboll.studio.apputils;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivity;
|
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
||||||
|
import cc.winboll.studio.libapputils.bean.APPInfo;
|
||||||
import cc.winboll.studio.libapputils.view.StringToQrCodeView;
|
import cc.winboll.studio.libapputils.view.StringToQrCodeView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author ZhanGSKen@QQ.COM
|
* @Author ZhanGSKen@QQ.COM
|
||||||
* @Date 2025/01/17 19:50:46
|
* @Date 2025/01/17 19:50:46
|
||||||
*/
|
*/
|
||||||
public class TestStringToQrCodeViewActivity extends WinBollActivity {
|
public class TestStringToQrCodeViewActivity extends AppCompatActivity implements IWinBollActivity {
|
||||||
|
|
||||||
public static final String TAG = "TestStringToQrCodeViewActivity";
|
public static final String TAG = "TestStringToQrCodeViewActivity";
|
||||||
|
|
||||||
StringToQrCodeView mStringToQrCodeView;
|
StringToQrCodeView mStringToQrCodeView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppCompatActivity getActivity() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APPInfo getAppInfo() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTag() {
|
public String getTag() {
|
||||||
@@ -21,17 +33,17 @@ public class TestStringToQrCodeViewActivity extends WinBollActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Toolbar initToolBar() {
|
public Toolbar initToolBar() {
|
||||||
return findViewById(R.id.activityteststringtoqrcodeviewToolbar1);
|
return findViewById(R.id.activityteststringtoqrcodeviewToolbar1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnableDisplayHomeAsUp() {
|
public boolean isEnableDisplayHomeAsUp() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isAddWinBollToolBar() {
|
public boolean isAddWinBollToolBar() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,10 +53,4 @@ public class TestStringToQrCodeViewActivity extends WinBollActivity {
|
|||||||
setContentView(R.layout.activity_teststringtoqrcodeview);
|
setContentView(R.layout.activity_teststringtoqrcodeview);
|
||||||
mStringToQrCodeView = findViewById(R.id.activityteststringtoqrcodeviewStringToQrCodeView1);
|
mStringToQrCodeView = findViewById(R.id.activityteststringtoqrcodeviewStringToQrCodeView1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
|
||||||
super.onPostCreate(savedInstanceState);
|
|
||||||
setSubTitle(TAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,52 +0,0 @@
|
|||||||
package cc.winboll.studio.apputils;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import cc.winboll.studio.libapputils.activities.AssetsHtmlActivity;
|
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivity;
|
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@QQ.COM
|
|
||||||
* @Date 2025/01/13 15:09:46
|
|
||||||
*/
|
|
||||||
public class TestWinBollActivity extends WinBollActivity {
|
|
||||||
|
|
||||||
public static final String TAG = "TestWinBollActivity";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTag() {
|
|
||||||
return TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Toolbar initToolBar() {
|
|
||||||
return findViewById(R.id.activitytestwinbollToolbar1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isEnableDisplayHomeAsUp() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isAddWinBollToolBar() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_testwinboll);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
|
||||||
super.onPostCreate(savedInstanceState);
|
|
||||||
setSubTitle(TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -54,6 +54,20 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right">
|
||||||
|
|
||||||
|
<cc.winboll.studio.libapputils.view.AboutBranchButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="About"
|
||||||
|
android:textAllCaps="false"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -4,7 +4,4 @@
|
|||||||
<color name="colorPrimary">#FF196ABC</color>
|
<color name="colorPrimary">#FF196ABC</color>
|
||||||
<color name="colorPrimaryDark">#FF002B57</color>
|
<color name="colorPrimaryDark">#FF002B57</color>
|
||||||
<color name="colorAccent">#FF80BFFF</color>
|
<color name="colorAccent">#FF80BFFF</color>
|
||||||
<color name="colorToastFrame">#FFA9A9A9</color>
|
|
||||||
<color name="colorToastShadow">#FF000000</color>
|
|
||||||
<color name="colorToastBackgroung">#FFFFFFFF</color>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -1,3 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
<style name="MyAppTheme" parent="APPBaseTheme">
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="GlobalCrashActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
|
||||||
|
<item name="colorTittle">@color/colorAccent</item>
|
||||||
|
<item name="colorTittleBackgound">@color/colorPrimary</item>
|
||||||
|
<item name="colorText">@color/colorAccent</item>
|
||||||
|
<item name="colorTextBackgound">@color/colorPrimaryDark</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
30
build.gradle
30
build.gradle
@@ -1,21 +1,8 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
// Nexus Maven 库地址
|
|
||||||
// "WinBoll Release"
|
|
||||||
maven { url "https://nexus.winboll.cc/repository/maven-public/" }
|
|
||||||
// "WinBoll Snapshot"
|
|
||||||
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
|
|
||||||
|
|
||||||
maven { url 'https://maven.aliyun.com/repository/public/' }
|
|
||||||
maven { url 'https://maven.aliyun.com/repository/google/' }
|
|
||||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
|
|
||||||
maven { url 'https://dl.bintray.com/ppartisan/maven/' }
|
|
||||||
maven { url "https://clojars.org/repo/" }
|
|
||||||
maven { url "https://jitpack.io" }
|
|
||||||
mavenCentral()
|
|
||||||
google()
|
google()
|
||||||
mavenLocal()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.1'
|
classpath 'com.android.tools.build:gradle:7.2.1'
|
||||||
@@ -32,13 +19,6 @@ allprojects {
|
|||||||
// "WinBoll Snapshot"
|
// "WinBoll Snapshot"
|
||||||
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
|
maven { url "https://nexus.winboll.cc/repository/maven-snapshots/" }
|
||||||
|
|
||||||
maven {
|
|
||||||
url "https://mirrors.tencent.com/repository/maven/tencent_public/"
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
url "https://mirrors.tencent.com/repository/maven/tencent_public_snapshots"
|
|
||||||
}
|
|
||||||
|
|
||||||
maven { url 'https://maven.aliyun.com/repository/public/' }
|
maven { url 'https://maven.aliyun.com/repository/public/' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/google/' }
|
maven { url 'https://maven.aliyun.com/repository/google/' }
|
||||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
|
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
|
||||||
@@ -89,14 +69,6 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.compilerArgs << "-parameters"
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
@@ -1,40 +0,0 @@
|
|||||||
# Contacts
|
|
||||||
源码参考自:
|
|
||||||
https://github.com/aJIEw/PhoneCallApp.git
|
|
||||||
|
|
||||||
#### 介绍
|
|
||||||
通讯录与拨号
|
|
||||||
|
|
||||||
#### 软件架构
|
|
||||||
适配安卓应用 [AIDE Pro] 的 Gradle 编译结构。
|
|
||||||
也适配安卓应用 [AndroidIDE] 的 Gradle 编译结构。
|
|
||||||
|
|
||||||
|
|
||||||
#### Gradle 编译说明
|
|
||||||
调试版编译命令 :gradle assembleBetaDebug
|
|
||||||
阶段版编译命令 :gradle assembleStageRelease
|
|
||||||
|
|
||||||
#### 使用说明
|
|
||||||
|
|
||||||
在安卓系统中需要设置两个权限允许。
|
|
||||||
1.自启动权限允许。
|
|
||||||
2.省电策略-无限制权限允许。
|
|
||||||
|
|
||||||
#### 参与贡献
|
|
||||||
|
|
||||||
1. Fork 本仓库
|
|
||||||
2. 新建 Feat_xxx 分支
|
|
||||||
3. 提交代码 : ZhanGSKen(ZhanGSKen@AliYun.Com)
|
|
||||||
4. 新建 Pull Request
|
|
||||||
|
|
||||||
|
|
||||||
#### 特技
|
|
||||||
|
|
||||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
|
||||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
|
||||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
|
||||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
|
||||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
|
||||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
|
||||||
|
|
||||||
#### 参考文档
|
|
@@ -1 +0,0 @@
|
|||||||
|
|
@@ -1,71 +0,0 @@
|
|||||||
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 "33.0.3"
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "cc.winboll.studio.contacts"
|
|
||||||
minSdkVersion 21
|
|
||||||
targetSdkVersion 30
|
|
||||||
versionCode 1
|
|
||||||
// versionName 更新后需要手动设置
|
|
||||||
// 项目模块目录的 build.gradle 文件的 stageCount=0
|
|
||||||
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
|
|
||||||
versionName "1.0"
|
|
||||||
if(true) {
|
|
||||||
versionName = genVersionName("${versionName}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
|
||||||
targetCompatibility JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// 二维码使用的类库
|
|
||||||
api 'com.google.zxing:core:3.4.1'
|
|
||||||
api 'com.journeyapps:zxing-android-embedded:3.6.0'
|
|
||||||
|
|
||||||
api 'io.github.medyo:android-about-page:2.0.0'
|
|
||||||
api 'com.github.getActivity:ToastUtils:10.5'
|
|
||||||
api 'com.jcraft:jsch:0.1.55'
|
|
||||||
api 'org.jsoup:jsoup:1.13.1'
|
|
||||||
api 'com.squareup.okhttp3:okhttp:4.4.1'
|
|
||||||
|
|
||||||
api 'androidx.appcompat:appcompat:1.1.0'
|
|
||||||
api 'androidx.viewpager:viewpager:1.0.0'
|
|
||||||
api 'androidx.fragment:fragment:1.1.0'
|
|
||||||
api 'com.google.android.material:material:1.4.0'
|
|
||||||
|
|
||||||
api 'cc.winboll.studio:libapputils:9.3.2'
|
|
||||||
api 'cc.winboll.studio:libappbase:1.5.6'
|
|
||||||
|
|
||||||
api fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
|
||||||
#Tue Feb 25 00:17:29 HKT 2025
|
|
||||||
stageCount=2
|
|
||||||
libraryProject=
|
|
||||||
baseVersion=1.0
|
|
||||||
publishVersion=1.0.1
|
|
||||||
buildCount=0
|
|
||||||
baseBetaVersion=1.0.2
|
|
17
contacts/proguard-rules.pro
vendored
17
contacts/proguard-rules.pro
vendored
@@ -1,17 +0,0 @@
|
|||||||
# 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 *;
|
|
||||||
#}
|
|
@@ -1,13 +0,0 @@
|
|||||||
<?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
|
|
||||||
tools:replace="android:icon"
|
|
||||||
android:icon="@drawable/ic_winbollbeta">
|
|
||||||
|
|
||||||
<!-- Put flavor specific code here -->
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
|
|
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<string name="app_name">Contacts+</string>
|
|
||||||
|
|
||||||
</resources>
|
|
@@ -1,187 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<manifest
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="cc.winboll.studio.contacts">
|
|
||||||
|
|
||||||
<!-- BIND_AUTOFILL_SERVICE -->
|
|
||||||
<uses-permission android:name="android.permission.BIND_AUTOFILL_SERVICE"/>
|
|
||||||
|
|
||||||
<!-- 拨打电话 -->
|
|
||||||
<uses-permission android:name="android.permission.CALL_PHONE"/>
|
|
||||||
|
|
||||||
<!-- 读取手机状态和身份 -->
|
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
|
||||||
|
|
||||||
<!-- 修改系统设置 -->
|
|
||||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
|
|
||||||
|
|
||||||
<!-- 重新设置外拨电话的路径 -->
|
|
||||||
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
|
|
||||||
|
|
||||||
<!-- 读取联系人 -->
|
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
|
||||||
|
|
||||||
<!-- 修改您的通讯录 -->
|
|
||||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
|
||||||
|
|
||||||
<!-- 此应用可显示在其他应用上方 -->
|
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
|
||||||
|
|
||||||
<!-- 更改您的音频设置 -->
|
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:name=".App"
|
|
||||||
android:allowBackup="true"
|
|
||||||
android:icon="@drawable/ic_winboll"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@style/MyAppTheme"
|
|
||||||
android:supportsRtl="true">
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".MainActivity"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:exported="true">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activities.CallActivity"
|
|
||||||
android:label="CallActivity"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:exported="true">
|
|
||||||
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".phonecallui.PhoneCallActivity"
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:exported="true">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="android.intent.action.DIAL"/>
|
|
||||||
|
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
|
||||||
|
|
||||||
<data android:scheme="tel"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="android.intent.action.DIAL"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity android:name="cc.winboll.studio.contacts.activities.SettingsActivity"/>
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name="cc.winboll.studio.contacts.services.MainService"
|
|
||||||
android:exported="true"/>
|
|
||||||
|
|
||||||
<service android:name="cc.winboll.studio.contacts.services.AssistantService"/>
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".phonecallui.PhoneCallService"
|
|
||||||
android:permission="android.permission.BIND_INCALL_SERVICE"
|
|
||||||
android:exported="false">
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.telecom.IN_CALL_SERVICE_UI"
|
|
||||||
android:value="true"/>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="android.telecom.InCallService"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".listenphonecall.CallListenerService"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="false">
|
|
||||||
|
|
||||||
<intent-filter android:priority="1000">
|
|
||||||
|
|
||||||
<action android:name=".service.CallShowService"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<receiver android:name=".receivers.MainReceiver">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="cc.winboll.studio.contacts.receivers.MainReceiver"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".widgets.APPStatusWidget"
|
|
||||||
android:exported="true">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
|
||||||
|
|
||||||
<action android:name="cc.winboll.studio.contacts.widgets.APPStatusWidget.ACTION_STATUS_ACTIVE"/>
|
|
||||||
|
|
||||||
<action android:name="cc.winboll.studio.contacts.widgets.APPStatusWidget.ACTION_STATUS_NOACTIVE"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.appwidget.provider"
|
|
||||||
android:resource="@xml/appwidget_provider_info"/>
|
|
||||||
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver android:name=".widgets.APPStatusWidgetClickListener">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
|
|
||||||
<action android:name="cc.winboll.studio.contacts.widgets.APPStatusWidgetClickListener.ACTION_APPICON_CLICK"/>
|
|
||||||
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<provider
|
|
||||||
android:name="androidx.core.content.FileProvider"
|
|
||||||
android:authorities="${applicationId}.fileprovider"
|
|
||||||
android:exported="false"
|
|
||||||
android:grantUriPermissions="true">
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
||||||
android:resource="@xml/studio_provider"/>
|
|
||||||
|
|
||||||
</provider>
|
|
||||||
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
@@ -1,59 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class ActivityStack {
|
|
||||||
|
|
||||||
private static final ActivityStack INSTANCE = new ActivityStack();
|
|
||||||
|
|
||||||
private List<Activity> activities = new ArrayList<>();
|
|
||||||
|
|
||||||
public static ActivityStack getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addActivity(Activity activity) {
|
|
||||||
activities.add(activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Activity getTopActivity() {
|
|
||||||
if (activities.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return activities.get(activities.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishTopActivity() {
|
|
||||||
if (!activities.isEmpty()) {
|
|
||||||
activities.remove(activities.size() - 1).finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishActivity(Activity activity) {
|
|
||||||
if (activity != null) {
|
|
||||||
activities.remove(activity);
|
|
||||||
activity.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishActivity(Class activityClass) {
|
|
||||||
for (Activity activity : activities) {
|
|
||||||
if (activity.getClass().equals(activityClass)) {
|
|
||||||
finishActivity(activity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishAllActivity() {
|
|
||||||
if (!activities.isEmpty()) {
|
|
||||||
for (Activity activity : activities) {
|
|
||||||
activity.finish();
|
|
||||||
activities.remove(activity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@QQ.COM
|
|
||||||
* @Date 2024/12/08 15:10:51
|
|
||||||
* @Describe 全局应用类
|
|
||||||
*/
|
|
||||||
import cc.winboll.studio.libappbase.GlobalApplication;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
|
||||||
|
|
||||||
public class App extends GlobalApplication {
|
|
||||||
|
|
||||||
public static final String TAG = "App";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
// 必须在调用基类前设置应用调试标志,
|
|
||||||
// 这样可以预先设置日志与数据的存储根目录。
|
|
||||||
setIsDebuging(this, BuildConfig.DEBUG);
|
|
||||||
super.onCreate();
|
|
||||||
// 设置 WinBoll 应用 UI 类型
|
|
||||||
WinBollActivityManager.getInstance(this).setWinBollUI_TYPE(WinBollActivityManager.WinBollUI_TYPE.Aplication);
|
|
||||||
|
|
||||||
LogUtils.d(TAG, "onCreate");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,406 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts;
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.role.RoleManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.telecom.TelecomManager;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Switch;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.viewpager.widget.ViewPager;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
import cc.winboll.studio.contacts.activities.CallActivity;
|
|
||||||
import cc.winboll.studio.contacts.adapters.MyPagerAdapter;
|
|
||||||
import cc.winboll.studio.contacts.beans.MainServiceBean;
|
|
||||||
import cc.winboll.studio.contacts.services.MainService;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import cc.winboll.studio.libappbase.LogView;
|
|
||||||
import cc.winboll.studio.libapputils.app.IWinBollActivity;
|
|
||||||
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
|
|
||||||
import cc.winboll.studio.libapputils.bean.APPInfo;
|
|
||||||
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
|
|
||||||
import cc.winboll.studio.contacts.listenphonecall.CallListenerService;
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import cc.winboll.studio.contacts.activities.SettingsActivity;
|
|
||||||
|
|
||||||
final public class MainActivity extends AppCompatActivity implements IWinBollActivity, ViewPager.OnPageChangeListener, View.OnClickListener {
|
|
||||||
|
|
||||||
public static final String TAG = "MainActivity";
|
|
||||||
|
|
||||||
public static final int REQUEST_HOME_ACTIVITY = 0;
|
|
||||||
public static final int REQUEST_ABOUT_ACTIVITY = 1;
|
|
||||||
|
|
||||||
public static final String ACTION_SOS = "cc.winboll.studio.libappbase.WinBoll.ACTION_SOS";
|
|
||||||
|
|
||||||
LogView mLogView;
|
|
||||||
Toolbar mToolbar;
|
|
||||||
CheckBox cbMainService;
|
|
||||||
MainServiceBean mMainServiceBean;
|
|
||||||
ViewPager viewPager;
|
|
||||||
private List<View> views; //用来存放放进ViewPager里面的布局
|
|
||||||
//实例化存储imageView(导航原点)的集合
|
|
||||||
ImageView[] imageViews;
|
|
||||||
//MyPagerAdapter adapter;//适配器
|
|
||||||
MyPagerAdapter pagerAdapter;
|
|
||||||
LinearLayout linearLayout;//下标所在在LinearLayout布局里
|
|
||||||
int currentPoint = 0;//当前被选中中页面的下标
|
|
||||||
|
|
||||||
private static final int DIALER_REQUEST_CODE = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AppCompatActivity getActivity() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public APPInfo getAppInfo() {
|
|
||||||
// String szBranchName = "contacts";
|
|
||||||
//
|
|
||||||
// APPInfo appInfo = AboutActivityFactory.buildDefaultAPPInfo();
|
|
||||||
// appInfo.setAppName("Contacts");
|
|
||||||
// appInfo.setAppIcon(cc.winboll.studio.libapputils.R.drawable.ic_winboll);
|
|
||||||
// appInfo.setAppDescription("Contacts Description");
|
|
||||||
// appInfo.setAppGitName("APP");
|
|
||||||
// appInfo.setAppGitOwner("Studio");
|
|
||||||
// appInfo.setAppGitAPPBranch(szBranchName);
|
|
||||||
// appInfo.setAppGitAPPSubProjectFolder(szBranchName);
|
|
||||||
// appInfo.setAppHomePage("https://www.winboll.cc/studio/details.php?app=Contacts");
|
|
||||||
// appInfo.setAppAPKName("Contacts");
|
|
||||||
// appInfo.setAppAPKFolderName("Contacts");
|
|
||||||
// return appInfo;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
// 接收并处理 Intent 数据,函数 Intent 处理接收就直接返回
|
|
||||||
//if (prosessIntents(getIntent())) return;
|
|
||||||
// 以下正常创建主窗口
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
|
|
||||||
// 初始化工具栏
|
|
||||||
mToolbar = findViewById(R.id.activitymainToolbar1);
|
|
||||||
setSupportActionBar(mToolbar);
|
|
||||||
if (isEnableDisplayHomeAsUp()) {
|
|
||||||
// 显示后退按钮
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
}
|
|
||||||
getSupportActionBar().setSubtitle(getTag());
|
|
||||||
|
|
||||||
initData();
|
|
||||||
initView();
|
|
||||||
//initPoint();//调用初始化导航原点的方法
|
|
||||||
viewPager.addOnPageChangeListener(this);//滑动事件
|
|
||||||
|
|
||||||
ViewPager viewPager = findViewById(R.id.activitymainViewPager1);
|
|
||||||
MyPagerAdapter pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
|
|
||||||
viewPager.setAdapter(pagerAdapter);
|
|
||||||
TabLayout tabLayout = findViewById(R.id.activitymainTabLayout1);
|
|
||||||
tabLayout.setupWithViewPager(viewPager);
|
|
||||||
|
|
||||||
// mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
|
||||||
// if (mMainServiceBean == null) {
|
|
||||||
// mMainServiceBean = new MainServiceBean();
|
|
||||||
// }
|
|
||||||
// cbMainService = findViewById(R.id.activitymainCheckBox1);
|
|
||||||
// cbMainService.setChecked(mMainServiceBean.isEnable());
|
|
||||||
// cbMainService.setOnClickListener(new View.OnClickListener(){
|
|
||||||
// @Override
|
|
||||||
// public void onClick(View view) {
|
|
||||||
// if (cbMainService.isChecked()) {
|
|
||||||
// MainService.startMainService(MainActivity.this);
|
|
||||||
// } else {
|
|
||||||
// MainService.stopMainService(MainActivity.this);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
MainService.startMainService(MainActivity.this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//初始化view,即显示的图片
|
|
||||||
void initView() {
|
|
||||||
viewPager = findViewById(R.id.activitymainViewPager1);
|
|
||||||
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
|
|
||||||
viewPager.setAdapter(pagerAdapter);
|
|
||||||
//adapter = new MyPagerAdapter(views);
|
|
||||||
//viewPager = findViewById(R.id.activitymainViewPager1);
|
|
||||||
//viewPager.setAdapter(adapter);
|
|
||||||
//linearLayout = findViewById(R.id.activitymainLinearLayout1);
|
|
||||||
//initPoint();//初始化页面下方的点
|
|
||||||
viewPager.setOnPageChangeListener(this);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//初始化所要显示的布局
|
|
||||||
void initData() {
|
|
||||||
ViewPager viewPager = findViewById(R.id.activitymainViewPager1);
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
|
||||||
View view1 = inflater.inflate(R.layout.fragment_call, viewPager, false);
|
|
||||||
View view2 = inflater.inflate(R.layout.fragment_contacts, viewPager, false);
|
|
||||||
View view3 = inflater.inflate(R.layout.fragment_log, viewPager, false);
|
|
||||||
|
|
||||||
views = new ArrayList<>();
|
|
||||||
views.add(view1);
|
|
||||||
views.add(view2);
|
|
||||||
views.add(view3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// void initPoint() {
|
|
||||||
// imageViews = new ImageView[5];//实例化5个图片
|
|
||||||
// for (int i = 0; i < linearLayout.getChildCount(); i++) {
|
|
||||||
// imageViews[i] = (ImageView) linearLayout.getChildAt(i);
|
|
||||||
// imageViews[i].setImageResource(R.drawable.ic_launcher);
|
|
||||||
// imageViews[i].setOnClickListener(this);//点击导航点,即可跳转
|
|
||||||
// imageViews[i].setTag(i);//重复利用实例化的对象
|
|
||||||
// }
|
|
||||||
// currentPoint = 0;//默认第一个坐标
|
|
||||||
// imageViews[currentPoint].setImageResource(R.drawable.ic_launcher);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//OnPageChangeListener接口要实现的三个方法
|
|
||||||
/* onPageScrollStateChanged(int state)
|
|
||||||
此方法是在状态改变的时候调用,其中state这个参数有三种状态:
|
|
||||||
SCROLL_STATE_DRAGGING(1)表示用户手指“按在屏幕上并且开始拖动”的状态
|
|
||||||
(手指按下但是还没有拖动的时候还不是这个状态,只有按下并且手指开始拖动后log才打出。)
|
|
||||||
SCROLL_STATE_IDLE(0)滑动动画做完的状态。
|
|
||||||
SCROLL_STATE_SETTLING(2)在“手指离开屏幕”的状态。*/
|
|
||||||
@Override
|
|
||||||
public void onPageScrollStateChanged(int state) {
|
|
||||||
|
|
||||||
}
|
|
||||||
/* onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
|
|
||||||
当页面在滑动的时候会调用此方法,在滑动被停止之前,此方法回一直得到调用。其中三个参数的含义分别为:
|
|
||||||
|
|
||||||
position :当前页面,即你点击滑动的页面(从A滑B,则是A页面的position。
|
|
||||||
positionOffset:当前页面偏移的百分比
|
|
||||||
positionOffsetPixels:当前页面偏移的像素位置*/
|
|
||||||
@Override
|
|
||||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
|
||||||
|
|
||||||
}
|
|
||||||
/* onPageSelected(int position)
|
|
||||||
此方法是页面滑动完后得到调用,position是你当前选中的页面的Position(位置编号)
|
|
||||||
(从A滑动到B,就是B的position)*/
|
|
||||||
public void onPageSelected(int position) {
|
|
||||||
|
|
||||||
// ImageView preView = imageViews[currentPoint];
|
|
||||||
// preView.setImageResource(R.drawable.ic_launcher);
|
|
||||||
// ImageView currView = imageViews[position];
|
|
||||||
// currView.setImageResource(R.drawable.ic_launcher);
|
|
||||||
// currentPoint = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
//小圆点点击事件
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
//通过getTag(),可以判断是哪个控件
|
|
||||||
// int i = (Integer) v.getTag();
|
|
||||||
// viewPager.setCurrentItem(i);//直接跳转到某一个页面的情况
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
|
||||||
super.onPostCreate(savedInstanceState);
|
|
||||||
//setSubTitle("");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
LogUtils.d(TAG, "onDestroy() SOS");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 处理传入的 Intent 数据
|
|
||||||
//
|
|
||||||
// boolean prosessIntents(Intent intent) {
|
|
||||||
// if (intent == null
|
|
||||||
// || intent.getAction() == null
|
|
||||||
// || intent.getAction().equals(""))
|
|
||||||
// return false;
|
|
||||||
//
|
|
||||||
// if (intent.getAction().equals(StringToQrCodeView.ACTION_UNITTEST_QRCODE)) {
|
|
||||||
// try {
|
|
||||||
// WinBollActivity clazzActivity = UnitTestActivity.class.newInstance();
|
|
||||||
// String tag = clazzActivity.getTag();
|
|
||||||
// LogUtils.d(TAG, "String tag = clazzActivity.getTag(); tag " + tag);
|
|
||||||
// Intent subIntent = new Intent(this, UnitTestActivity.class);
|
|
||||||
// subIntent.setAction(intent.getAction());
|
|
||||||
// File file = new File(getCacheDir(), UUID.randomUUID().toString());
|
|
||||||
// //取出文件uri
|
|
||||||
// Uri uri = intent.getData();
|
|
||||||
// if (uri == null) {
|
|
||||||
// uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
|
||||||
// }
|
|
||||||
// //获取文件真实地址
|
|
||||||
// String szSrcPath = UriUtils.getFileFromUri(getApplication(), uri);
|
|
||||||
// if (TextUtils.isEmpty(szSrcPath)) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Files.copy(Paths.get(szSrcPath), Paths.get(file.getPath()));
|
|
||||||
// //startWinBollActivity(subIntent, tag);
|
|
||||||
// WinBollActivityManager.getInstance(this).startWinBollActivity(this, subIntent, UnitTestActivity.class);
|
|
||||||
// } catch (IllegalAccessException | InstantiationException | IOException e) {
|
|
||||||
// LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
|
||||||
// // 函数处理异常返回失败
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// LogUtils.d(TAG, "prosessIntents|" + intent.getAction() + "|yet");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTag() {
|
|
||||||
return TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Toolbar initToolBar() {
|
|
||||||
return findViewById(R.id.activitymainToolbar1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAddWinBollToolBar() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnableDisplayHomeAsUp() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void exit() {
|
|
||||||
YesNoAlertDialog.OnDialogResultListener listener = new YesNoAlertDialog.OnDialogResultListener(){
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onYes() {
|
|
||||||
WinBollActivityManager.getInstance(getApplicationContext()).finishAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNo() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
YesNoAlertDialog.show(this, "[ " + getString(R.string.app_name) + " ]", "Exit(Yes/No).\nIs close all activity?", listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
getMenuInflater().inflate(R.menu.toolbar_main, menu);
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == R.id.item_call) {
|
|
||||||
Intent intent = new Intent(this, CallActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
|
||||||
} else if (item.getItemId() == R.id.item_settings) {
|
|
||||||
Intent intent = new Intent(this, SettingsActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
//WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class);
|
|
||||||
}
|
|
||||||
// } else
|
|
||||||
// if (item.getItemId() == R.id.item_exit) {
|
|
||||||
// exit();
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Android M 及以上检查是否是系统默认电话应用
|
|
||||||
*/
|
|
||||||
public boolean isDefaultPhoneCallApp() {
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
TelecomManager manger = (TelecomManager) getSystemService(TELECOM_SERVICE);
|
|
||||||
if (manger != null && manger.getDefaultDialerPackage() != null) {
|
|
||||||
return manger.getDefaultDialerPackage().equals(getPackageName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isServiceRunning(Class<?> serviceClass) {
|
|
||||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
|
||||||
if (manager == null) return false;
|
|
||||||
|
|
||||||
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
|
|
||||||
Integer.MAX_VALUE)) {
|
|
||||||
if (serviceClass.getName().equals(service.service.getClassName())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
// switch (resultCode) {
|
|
||||||
// case REQUEST_HOME_ACTIVITY : {
|
|
||||||
// LogUtils.d(TAG, "REQUEST_HOME_ACTIVITY");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case REQUEST_ABOUT_ACTIVITY : {
|
|
||||||
// LogUtils.d(TAG, "REQUEST_ABOUT_ACTIVITY");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default : {
|
|
||||||
// super.onActivityResult(requestCode, resultCode, data);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (requestCode == DIALER_REQUEST_CODE) {
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
Toast.makeText(MainActivity.this, getString(R.string.app_name) + " 已成为默认电话应用",
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,35 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 21:14:52
|
|
||||||
* @Describe PhoneCallManager
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.telecom.Call;
|
|
||||||
import android.telecom.VideoProfile;
|
|
||||||
|
|
||||||
public class PhoneCallManager {
|
|
||||||
|
|
||||||
public static final String TAG = "PhoneCallManager";
|
|
||||||
|
|
||||||
public static Call call;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接听电话
|
|
||||||
*/
|
|
||||||
public void answer() {
|
|
||||||
if (call != null) {
|
|
||||||
call.answer(VideoProfile.STATE_AUDIO_ONLY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断开电话,包括来电时的拒接以及接听后的挂断
|
|
||||||
*/
|
|
||||||
public void disconnect() {
|
|
||||||
if (call != null) {
|
|
||||||
call.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,118 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.activities;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 17:15:46
|
|
||||||
* @Describe 拨号窗口
|
|
||||||
*/
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.telephony.PhoneStateListener;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import cc.winboll.studio.contacts.MainActivity;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
|
|
||||||
public class CallActivity extends AppCompatActivity {
|
|
||||||
public static final String TAG = "CallActivity";
|
|
||||||
|
|
||||||
private static final int REQUEST_CALL_PHONE = 1;
|
|
||||||
private EditText phoneNumberEditText;
|
|
||||||
private TextView callStatusTextView;
|
|
||||||
private TelephonyManager telephonyManager;
|
|
||||||
private MyPhoneStateListener phoneStateListener;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
//setContentView(R.layout.activity_main);
|
|
||||||
setContentView(R.layout.activity_call);
|
|
||||||
|
|
||||||
phoneNumberEditText = findViewById(R.id.phone_number);
|
|
||||||
Button dialButton = findViewById(R.id.dial_button);
|
|
||||||
callStatusTextView = findViewById(R.id.call_status);
|
|
||||||
|
|
||||||
dialButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
String phoneNumber = phoneNumberEditText.getText().toString().trim();
|
|
||||||
if (!phoneNumber.isEmpty()) {
|
|
||||||
if (ContextCompat.checkSelfPermission(CallActivity.this, Manifest.permission.CALL_PHONE)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
|
||||||
ActivityCompat.requestPermissions(CallActivity.this,
|
|
||||||
new String[]{Manifest.permission.CALL_PHONE},
|
|
||||||
REQUEST_CALL_PHONE);
|
|
||||||
} else {
|
|
||||||
dialPhoneNumber(phoneNumber);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Toast.makeText(CallActivity.this, "请输入电话号码", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 初始化TelephonyManager和PhoneStateListener
|
|
||||||
telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
|
|
||||||
phoneStateListener = new MyPhoneStateListener();
|
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
if (requestCode == REQUEST_CALL_PHONE) {
|
|
||||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
String phoneNumber = phoneNumberEditText.getText().toString().trim();
|
|
||||||
dialPhoneNumber(phoneNumber);
|
|
||||||
} else {
|
|
||||||
Toast.makeText(this, "未授予拨打电话权限", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dialPhoneNumber(String phoneNumber) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_CALL);
|
|
||||||
intent.setData(android.net.Uri.parse("tel:" + phoneNumber));
|
|
||||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MyPhoneStateListener extends PhoneStateListener {
|
|
||||||
@Override
|
|
||||||
public void onCallStateChanged(int state, String incomingNumber) {
|
|
||||||
switch (state) {
|
|
||||||
case TelephonyManager.CALL_STATE_IDLE:
|
|
||||||
callStatusTextView.setText("电话已挂断");
|
|
||||||
break;
|
|
||||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
|
||||||
callStatusTextView.setText("正在通话中");
|
|
||||||
break;
|
|
||||||
case TelephonyManager.CALL_STATE_RINGING:
|
|
||||||
callStatusTextView.setText("来电: " + incomingNumber);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
// 取消监听
|
|
||||||
if (telephonyManager != null) {
|
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,40 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.activities;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 20:18:26
|
|
||||||
*/
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
|
|
||||||
public class DialerActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
public static final String TAG = "DialerActivity";
|
|
||||||
|
|
||||||
private EditText phoneNumberEditText;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_dialer);
|
|
||||||
|
|
||||||
phoneNumberEditText = findViewById(R.id.phone_number_edit_text);
|
|
||||||
Button dialButton = findViewById(R.id.dial_button);
|
|
||||||
|
|
||||||
dialButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
String phoneNumber = phoneNumberEditText.getText().toString();
|
|
||||||
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber));
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,143 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.activities;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/21 05:37:42
|
|
||||||
*/
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Switch;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
import cc.winboll.studio.contacts.beans.RingTongBean;
|
|
||||||
import cc.winboll.studio.libappbase.IWinBollActivity;
|
|
||||||
import cc.winboll.studio.libappbase.bean.APPInfo;
|
|
||||||
import com.hjq.toast.ToastUtils;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
public class SettingsActivity extends AppCompatActivity implements IWinBollActivity {
|
|
||||||
|
|
||||||
public static final String TAG = "SettingsActivity";
|
|
||||||
|
|
||||||
Toolbar mToolbar;
|
|
||||||
Switch swSilent;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public APPInfo getAppInfo() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AppCompatActivity getActivity() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTag() {
|
|
||||||
return TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Toolbar initToolBar() {
|
|
||||||
return findViewById(R.id.activitymainToolbar1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAddWinBollToolBar() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnableDisplayHomeAsUp() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_settings);
|
|
||||||
|
|
||||||
// 初始化工具栏
|
|
||||||
mToolbar = findViewById(R.id.activitymainToolbar1);
|
|
||||||
setSupportActionBar(mToolbar);
|
|
||||||
if (isEnableDisplayHomeAsUp()) {
|
|
||||||
// 显示后退按钮
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
}
|
|
||||||
getSupportActionBar().setSubtitle(getTag());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDefaultPhone(View view) {
|
|
||||||
Intent intent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCanDrawOverlays(View view) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
|
||||||
&& !Settings.canDrawOverlays(this)) {
|
|
||||||
// 请求 悬浮框 权限
|
|
||||||
askForDrawOverlay();
|
|
||||||
} else {
|
|
||||||
ToastUtils.show("悬浮窗已开启");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void askForDrawOverlay() {
|
|
||||||
AlertDialog alertDialog = new AlertDialog.Builder(this)
|
|
||||||
.setTitle("允许显示悬浮框")
|
|
||||||
.setMessage("为了使电话监听服务正常工作,请允许这项权限")
|
|
||||||
.setPositiveButton("去设置", new DialogInterface.OnClickListener(){
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
openDrawOverlaySettings();
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton("稍后再说", new DialogInterface.OnClickListener(){
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.create();
|
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
alertDialog.getWindow().setFlags(
|
|
||||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
|
||||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
|
||||||
alertDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳转悬浮窗管理设置界面
|
|
||||||
*/
|
|
||||||
private void openDrawOverlaySettings() {
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
// Android M 以上引导用户去系统设置中打开允许悬浮窗
|
|
||||||
// 使用反射是为了用尽可能少的代码保证在大部分机型上都可用
|
|
||||||
try {
|
|
||||||
Context context = this;
|
|
||||||
Class clazz = Settings.class;
|
|
||||||
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
|
|
||||||
Intent intent = new Intent(field.get(null).toString());
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
intent.setData(Uri.parse("package:" + context.getPackageName()));
|
|
||||||
context.startActivity(intent);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Toast.makeText(this, "请在悬浮窗管理中打开权限", Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.adapters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 14:20:38
|
|
||||||
* @Describe ImagePagerAdapter
|
|
||||||
*/
|
|
||||||
public class ImagePagerAdapter {
|
|
||||||
|
|
||||||
public static final String TAG = "ImagePagerAdapter";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.adapters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 13:33:04
|
|
||||||
* @Describe MyPagerAdapter
|
|
||||||
*/
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
import androidx.fragment.app.FragmentPagerAdapter;
|
|
||||||
import cc.winboll.studio.contacts.fragments.CallFragment;
|
|
||||||
import cc.winboll.studio.contacts.fragments.ContactsFragment;
|
|
||||||
import cc.winboll.studio.contacts.fragments.LogFragment;
|
|
||||||
|
|
||||||
public class MyPagerAdapter extends FragmentPagerAdapter {
|
|
||||||
public static final String TAG = "MyPagerAdapter";
|
|
||||||
|
|
||||||
private static final int PAGE_COUNT = 3;
|
|
||||||
|
|
||||||
public MyPagerAdapter(@NonNull FragmentManager fm) {
|
|
||||||
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Fragment getItem(int position) {
|
|
||||||
if(position == 1) {
|
|
||||||
return ContactsFragment.newInstance(position);
|
|
||||||
} else if(position == 2) {
|
|
||||||
return LogFragment.newInstance(position);
|
|
||||||
} else {
|
|
||||||
return CallFragment.newInstance(position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return PAGE_COUNT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,68 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
MainServiceBean bean = this;
|
|
||||||
jsonWriter.name("isEnable").value(bean.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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,88 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/21 09:52:10
|
|
||||||
* @Describe 电话黑名单规则
|
|
||||||
*/
|
|
||||||
import android.util.JsonReader;
|
|
||||||
import android.util.JsonWriter;
|
|
||||||
import cc.winboll.studio.libappbase.BaseBean;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class PhoneBlackRuleBean extends BaseBean {
|
|
||||||
|
|
||||||
public static final String TAG = "PhoneBlackRuleBean";
|
|
||||||
|
|
||||||
String ruleText;
|
|
||||||
boolean isEnable;
|
|
||||||
|
|
||||||
public PhoneBlackRuleBean() {
|
|
||||||
this.ruleText = "";
|
|
||||||
this.isEnable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PhoneBlackRuleBean(String ruleText, boolean isEnable) {
|
|
||||||
this.ruleText = ruleText;
|
|
||||||
this.isEnable = isEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRuleText(String ruleText) {
|
|
||||||
this.ruleText = ruleText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRuleText() {
|
|
||||||
return ruleText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsEnable(boolean isEnable) {
|
|
||||||
this.isEnable = isEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnable() {
|
|
||||||
return isEnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return PhoneBlackRuleBean.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
|
||||||
super.writeThisToJsonWriter(jsonWriter);
|
|
||||||
jsonWriter.name("ruleText").value(getRuleText());
|
|
||||||
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("ruleText")) {
|
|
||||||
setRuleText(jsonReader.nextString());
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@@ -1,74 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.beans;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/24 18:47:11
|
|
||||||
* @Describe 手机铃声设置参数类
|
|
||||||
*/
|
|
||||||
import cc.winboll.studio.libappbase.BaseBean;
|
|
||||||
import android.util.JsonWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.util.JsonReader;
|
|
||||||
|
|
||||||
public class RingTongBean extends BaseBean {
|
|
||||||
|
|
||||||
public static final String TAG = "AudioRingTongBean";
|
|
||||||
|
|
||||||
// 模式
|
|
||||||
int ringerMode;
|
|
||||||
|
|
||||||
public RingTongBean() {
|
|
||||||
this.ringerMode = AudioManager.RINGER_MODE_NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RingTongBean(int ringerMode) {
|
|
||||||
this.ringerMode = ringerMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRingerMode(int ringerMode) {
|
|
||||||
this.ringerMode = ringerMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRingerMode() {
|
|
||||||
return ringerMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return RingTongBean.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeThisToJsonWriter(JsonWriter jsonWriter) throws IOException {
|
|
||||||
super.writeThisToJsonWriter(jsonWriter);
|
|
||||||
jsonWriter.name("ringerMode").value(getRingerMode());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean initObjectsFromJsonReader(JsonReader jsonReader, String name) throws IOException {
|
|
||||||
if (super.initObjectsFromJsonReader(jsonReader, name)) { return true; } else {
|
|
||||||
if (name.equals("ringerMode")) {
|
|
||||||
setRingerMode(jsonReader.nextInt());
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,76 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.dun;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/21 06:15:10
|
|
||||||
* @Describe 云盾防御规则
|
|
||||||
*/
|
|
||||||
import cc.winboll.studio.contacts.beans.PhoneBlackRuleBean;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
public class Rules {
|
|
||||||
|
|
||||||
public static final String TAG = "Rules";
|
|
||||||
|
|
||||||
ArrayList<PhoneBlackRuleBean> _PhoneBlacRuleBeanList;
|
|
||||||
static volatile Rules _Rules;
|
|
||||||
Context mContext;
|
|
||||||
|
|
||||||
Rules(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
_PhoneBlacRuleBeanList = new ArrayList<PhoneBlackRuleBean>();
|
|
||||||
PhoneBlackRuleBean.loadBeanList(mContext, _PhoneBlacRuleBeanList, PhoneBlackRuleBean.class);
|
|
||||||
|
|
||||||
}
|
|
||||||
public static synchronized Rules getInstance(Context context) {
|
|
||||||
if (_Rules == null) {
|
|
||||||
_Rules = new Rules(context);
|
|
||||||
}
|
|
||||||
return _Rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAllowed(String phoneNumber) {
|
|
||||||
// 黑名单拒接
|
|
||||||
for (int i = 0; i < _PhoneBlacRuleBeanList.size(); i++) {
|
|
||||||
if (_PhoneBlacRuleBeanList.get(i).isEnable()) {
|
|
||||||
String regex = _PhoneBlacRuleBeanList.get(i).getRuleText();
|
|
||||||
if (Pattern.matches(regex, phoneNumber)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 手机号码允许
|
|
||||||
// 中国手机号码正则表达式,以1开头,第二位可以是3、4、5、6、7、8、9,后面跟9位数字
|
|
||||||
String regex = "^1[3-9]\\d{9}$";
|
|
||||||
if (Pattern.matches(regex, phoneNumber)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 指定区号号码允许
|
|
||||||
regex = "^0660\\d+$";
|
|
||||||
if (Pattern.matches(regex, phoneNumber)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 指定区号号码允许
|
|
||||||
regex = "^020\\d+$";
|
|
||||||
if (Pattern.matches(regex, phoneNumber)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他拒接
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(String phoneRuleBlack, boolean isEnable) {
|
|
||||||
_PhoneBlacRuleBeanList.add(new PhoneBlackRuleBean(phoneRuleBlack, isEnable));
|
|
||||||
PhoneBlackRuleBean.saveBeanList(mContext, _PhoneBlacRuleBeanList, PhoneBlackRuleBean.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<PhoneBlackRuleBean> getPhoneBlacRuleBeanList() {
|
|
||||||
return _PhoneBlacRuleBeanList;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,51 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.fragments;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 12:57:00
|
|
||||||
* @Describe 拨号
|
|
||||||
*/
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
import cc.winboll.studio.libappbase.LogView;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
public class CallFragment extends Fragment {
|
|
||||||
|
|
||||||
public static final String TAG = "CallFragment";
|
|
||||||
|
|
||||||
private static final String ARG_PAGE = "ARG_PAGE";
|
|
||||||
private int mPage;
|
|
||||||
|
|
||||||
public static CallFragment newInstance(int page) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putInt(ARG_PAGE, page);
|
|
||||||
CallFragment fragment = new CallFragment();
|
|
||||||
fragment.setArguments(args);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
if (getArguments()!= null) {
|
|
||||||
mPage = getArguments().getInt(ARG_PAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
View view = inflater.inflate(R.layout.fragment_call, container, false);
|
|
||||||
TextView textView = view.findViewById(R.id.page_text);
|
|
||||||
textView.setText("这是第 " + mPage + " 页");
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,50 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.fragments;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 12:57:50
|
|
||||||
* @Describe 联系人
|
|
||||||
*/
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
|
|
||||||
public class ContactsFragment extends Fragment {
|
|
||||||
|
|
||||||
public static final String TAG = "ContactsFragment";
|
|
||||||
|
|
||||||
private static final String ARG_PAGE = "ARG_PAGE";
|
|
||||||
private int mPage;
|
|
||||||
|
|
||||||
public static ContactsFragment newInstance(int page) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putInt(ARG_PAGE, page);
|
|
||||||
ContactsFragment fragment = new ContactsFragment();
|
|
||||||
fragment.setArguments(args);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
if (getArguments()!= null) {
|
|
||||||
mPage = getArguments().getInt(ARG_PAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
View view = inflater.inflate(R.layout.fragment_contacts, container, false);
|
|
||||||
TextView textView = view.findViewById(R.id.page_text);
|
|
||||||
textView.setText("这是第 " + mPage + " 页");
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,50 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.fragments;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/20 12:58:15
|
|
||||||
* @Describe 应用日志
|
|
||||||
*/
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
import cc.winboll.studio.libappbase.LogView;
|
|
||||||
|
|
||||||
public class LogFragment extends Fragment {
|
|
||||||
|
|
||||||
public static final String TAG = "LogFragment";
|
|
||||||
|
|
||||||
private static final String ARG_PAGE = "ARG_PAGE";
|
|
||||||
private int mPage;
|
|
||||||
|
|
||||||
public static LogFragment newInstance(int page) {
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putInt(ARG_PAGE, page);
|
|
||||||
LogFragment fragment = new LogFragment();
|
|
||||||
fragment.setArguments(args);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
if (getArguments() != null) {
|
|
||||||
mPage = getArguments().getInt(ARG_PAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
View view = inflater.inflate(R.layout.fragment_log, container, false);
|
|
||||||
LogView logView = view.findViewById(R.id.logview);
|
|
||||||
logView.start();
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,38 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.handlers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/14 03:51:40
|
|
||||||
*/
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Message;
|
|
||||||
import cc.winboll.studio.contacts.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,206 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.listenphonecall;
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.telephony.PhoneStateListener;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import cc.winboll.studio.contacts.MainActivity;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
|
|
||||||
|
|
||||||
public class CallListenerService extends Service {
|
|
||||||
|
|
||||||
private View phoneCallView;
|
|
||||||
private TextView tvCallNumber;
|
|
||||||
private Button btnOpenApp;
|
|
||||||
|
|
||||||
private WindowManager windowManager;
|
|
||||||
private WindowManager.LayoutParams params;
|
|
||||||
|
|
||||||
private PhoneStateListener phoneStateListener;
|
|
||||||
private TelephonyManager telephonyManager;
|
|
||||||
|
|
||||||
private String callNumber;
|
|
||||||
private boolean hasShown;
|
|
||||||
private boolean isCallingIn;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
|
|
||||||
initPhoneStateListener();
|
|
||||||
|
|
||||||
initPhoneCallView();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化来电状态监听器
|
|
||||||
*/
|
|
||||||
private void initPhoneStateListener() {
|
|
||||||
phoneStateListener = new PhoneStateListener() {
|
|
||||||
@Override
|
|
||||||
public void onCallStateChanged(int state, String incomingNumber) {
|
|
||||||
super.onCallStateChanged(state, incomingNumber);
|
|
||||||
|
|
||||||
callNumber = incomingNumber;
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case TelephonyManager.CALL_STATE_IDLE: // 待机,即无电话时,挂断时触发
|
|
||||||
dismiss();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TelephonyManager.CALL_STATE_RINGING: // 响铃,来电时触发
|
|
||||||
isCallingIn = true;
|
|
||||||
updateUI();
|
|
||||||
show();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TelephonyManager.CALL_STATE_OFFHOOK: // 摘机,接听或拨出电话时触发
|
|
||||||
updateUI();
|
|
||||||
show();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 设置来电监听器
|
|
||||||
telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
|
|
||||||
if (telephonyManager != null) {
|
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initPhoneCallView() {
|
|
||||||
windowManager = (WindowManager) getApplicationContext()
|
|
||||||
.getSystemService(Context.WINDOW_SERVICE);
|
|
||||||
int width = windowManager.getDefaultDisplay().getWidth();
|
|
||||||
int height = windowManager.getDefaultDisplay().getHeight();
|
|
||||||
|
|
||||||
params = new WindowManager.LayoutParams();
|
|
||||||
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
|
|
||||||
params.width = width;
|
|
||||||
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
|
||||||
params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
|
||||||
|
|
||||||
// 设置图片格式,效果为背景透明
|
|
||||||
params.format = PixelFormat.TRANSLUCENT;
|
|
||||||
// 设置 Window flag 为系统级弹框 | 覆盖表层
|
|
||||||
params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
|
|
||||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
|
|
||||||
WindowManager.LayoutParams.TYPE_PHONE;
|
|
||||||
|
|
||||||
// 不可聚集(不响应返回键)| 全屏
|
|
||||||
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
|
||||||
| WindowManager.LayoutParams.FLAG_FULLSCREEN
|
|
||||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
|
||||||
// API 19 以上则还可以开启透明状态栏与导航栏
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
params.flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
|
|
||||||
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
|
|
||||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
|
||||||
| WindowManager.LayoutParams.FLAG_FULLSCREEN
|
|
||||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameLayout interceptorLayout = new FrameLayout(this) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
||||||
|
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
||||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.dispatchKeyEvent(event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
phoneCallView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
|
|
||||||
.inflate(R.layout.view_phone_call, interceptorLayout);
|
|
||||||
tvCallNumber = phoneCallView.findViewById(R.id.tv_call_number);
|
|
||||||
btnOpenApp = phoneCallView.findViewById(R.id.btn_open_app);
|
|
||||||
btnOpenApp.setOnClickListener(new View.OnClickListener(){
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
CallListenerService.this.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示顶级弹框展示通话信息
|
|
||||||
*/
|
|
||||||
private void show() {
|
|
||||||
if (!hasShown) {
|
|
||||||
windowManager.addView(phoneCallView, params);
|
|
||||||
hasShown = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消显示
|
|
||||||
*/
|
|
||||||
private void dismiss() {
|
|
||||||
if (hasShown) {
|
|
||||||
windowManager.removeView(phoneCallView);
|
|
||||||
isCallingIn = false;
|
|
||||||
hasShown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateUI() {
|
|
||||||
tvCallNumber.setText(formatPhoneNumber(callNumber));
|
|
||||||
|
|
||||||
int callTypeDrawable = isCallingIn ? R.drawable.ic_phone_call_in : R.drawable.ic_phone_call_out;
|
|
||||||
tvCallNumber.setCompoundDrawablesWithIntrinsicBounds(null, null,
|
|
||||||
getResources().getDrawable(callTypeDrawable), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String formatPhoneNumber(String phoneNum) {
|
|
||||||
if (!TextUtils.isEmpty(phoneNum) && phoneNum.length() == 11) {
|
|
||||||
return phoneNum.substring(0, 3) + "-"
|
|
||||||
+ phoneNum.substring(3, 7) + "-"
|
|
||||||
+ phoneNum.substring(7);
|
|
||||||
}
|
|
||||||
return phoneNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
|
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,166 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.phonecallui;
|
|
||||||
|
|
||||||
import static cc.winboll.studio.contacts.listenphonecall.CallListenerService.formatPhoneNumber;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import cc.winboll.studio.contacts.ActivityStack;
|
|
||||||
import cc.winboll.studio.contacts.R;
|
|
||||||
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 提供接打电话的界面,仅支持 Android M (6.0, API 23) 及以上的系统
|
|
||||||
*
|
|
||||||
* @author aJIEw
|
|
||||||
*/
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
|
||||||
public class PhoneCallActivity extends AppCompatActivity implements View.OnClickListener {
|
|
||||||
|
|
||||||
private TextView tvCallNumberLabel;
|
|
||||||
private TextView tvCallNumber;
|
|
||||||
private TextView tvPickUp;
|
|
||||||
private TextView tvCallingTime;
|
|
||||||
private TextView tvHangUp;
|
|
||||||
|
|
||||||
private PhoneCallManager phoneCallManager;
|
|
||||||
private PhoneCallService.CallType callType;
|
|
||||||
private String phoneNumber;
|
|
||||||
|
|
||||||
private Timer onGoingCallTimer;
|
|
||||||
private int callingTime;
|
|
||||||
|
|
||||||
public static void actionStart(Context context, String phoneNumber,
|
|
||||||
PhoneCallService.CallType callType) {
|
|
||||||
Intent intent = new Intent(context, PhoneCallActivity.class);
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
intent.putExtra(Intent.EXTRA_MIME_TYPES, callType);
|
|
||||||
intent.putExtra(Intent.EXTRA_PHONE_NUMBER, phoneNumber);
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_phone_call);
|
|
||||||
|
|
||||||
ActivityStack.getInstance().addActivity(this);
|
|
||||||
|
|
||||||
initData();
|
|
||||||
|
|
||||||
initView();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initData() {
|
|
||||||
phoneCallManager = new PhoneCallManager(this);
|
|
||||||
onGoingCallTimer = new Timer();
|
|
||||||
if (getIntent() != null) {
|
|
||||||
phoneNumber = getIntent().getStringExtra(Intent.EXTRA_PHONE_NUMBER);
|
|
||||||
callType = (PhoneCallService.CallType) getIntent().getSerializableExtra(Intent.EXTRA_MIME_TYPES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initView() {
|
|
||||||
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
||||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //hide navigationBar
|
|
||||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
|
||||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
|
|
||||||
getWindow().getDecorView().setSystemUiVisibility(uiOptions);
|
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
|
||||||
|
|
||||||
tvCallNumberLabel = findViewById(R.id.tv_call_number_label);
|
|
||||||
tvCallNumber = findViewById(R.id.tv_call_number);
|
|
||||||
tvPickUp = findViewById(R.id.tv_phone_pick_up);
|
|
||||||
tvCallingTime = findViewById(R.id.tv_phone_calling_time);
|
|
||||||
tvHangUp = findViewById(R.id.tv_phone_hang_up);
|
|
||||||
|
|
||||||
tvCallNumber.setText(formatPhoneNumber(phoneNumber));
|
|
||||||
tvPickUp.setOnClickListener(this);
|
|
||||||
tvHangUp.setOnClickListener(this);
|
|
||||||
|
|
||||||
// 打进的电话
|
|
||||||
if (callType == PhoneCallService.CallType.CALL_IN) {
|
|
||||||
tvCallNumberLabel.setText("来电号码");
|
|
||||||
tvPickUp.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
// 打出的电话
|
|
||||||
else if (callType == PhoneCallService.CallType.CALL_OUT) {
|
|
||||||
tvCallNumberLabel.setText("呼叫号码");
|
|
||||||
tvPickUp.setVisibility(View.GONE);
|
|
||||||
phoneCallManager.openSpeaker();
|
|
||||||
}
|
|
||||||
|
|
||||||
showOnLockScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showOnLockScreen() {
|
|
||||||
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
|
|
||||||
WindowManager.LayoutParams.FLAG_FULLSCREEN |
|
|
||||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
|
||||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
|
|
||||||
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
|
|
||||||
WindowManager.LayoutParams.FLAG_FULLSCREEN |
|
|
||||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
|
||||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v.getId() == R.id.tv_phone_pick_up) {
|
|
||||||
phoneCallManager.answer();
|
|
||||||
tvPickUp.setVisibility(View.GONE);
|
|
||||||
tvCallingTime.setVisibility(View.VISIBLE);
|
|
||||||
onGoingCallTimer.schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
callingTime++;
|
|
||||||
tvCallingTime.setText("通话中:" + getCallingTime());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
} else if (v.getId() == R.id.tv_phone_hang_up) {
|
|
||||||
phoneCallManager.disconnect();
|
|
||||||
stopTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCallingTime() {
|
|
||||||
int minute = callingTime / 60;
|
|
||||||
int second = callingTime % 60;
|
|
||||||
return (minute < 10 ? "0" + minute : minute) +
|
|
||||||
":" +
|
|
||||||
(second < 10 ? "0" + second : second);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopTimer() {
|
|
||||||
if (onGoingCallTimer != null) {
|
|
||||||
onGoingCallTimer.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
callingTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
|
|
||||||
phoneCallManager.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,62 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.phonecallui;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.telecom.Call;
|
|
||||||
import android.telecom.VideoProfile;
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import cc.winboll.studio.contacts.dun.Rules;
|
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
|
||||||
public class PhoneCallManager {
|
|
||||||
|
|
||||||
public static Call call;
|
|
||||||
|
|
||||||
private Context context;
|
|
||||||
private AudioManager audioManager;
|
|
||||||
|
|
||||||
public PhoneCallManager(Context context) {
|
|
||||||
this.context = context;
|
|
||||||
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接听电话
|
|
||||||
*/
|
|
||||||
public void answer() {
|
|
||||||
if (call != null) {
|
|
||||||
call.answer(VideoProfile.STATE_AUDIO_ONLY);
|
|
||||||
openSpeaker();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断开电话,包括来电时的拒接以及接听后的挂断
|
|
||||||
*/
|
|
||||||
public void disconnect() {
|
|
||||||
if (call != null) {
|
|
||||||
call.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开免提
|
|
||||||
*/
|
|
||||||
public void openSpeaker() {
|
|
||||||
if (audioManager != null) {
|
|
||||||
audioManager.setMode(AudioManager.MODE_IN_CALL);
|
|
||||||
audioManager.setSpeakerphoneOn(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 销毁资源
|
|
||||||
*/
|
|
||||||
public void destroy() {
|
|
||||||
call = null;
|
|
||||||
context = null;
|
|
||||||
audioManager = null;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,103 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.phonecallui;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 监听电话通信状态的服务,实现该类的同时必须提供电话管理的 UI
|
|
||||||
*
|
|
||||||
* @author aJIEw
|
|
||||||
* @see PhoneCallActivity
|
|
||||||
* @see android.telecom.InCallService
|
|
||||||
*/
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.telecom.Call;
|
|
||||||
import android.telecom.InCallService;
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import cc.winboll.studio.contacts.ActivityStack;
|
|
||||||
import cc.winboll.studio.contacts.beans.RingTongBean;
|
|
||||||
import cc.winboll.studio.contacts.dun.Rules;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
|
||||||
public class PhoneCallService extends InCallService {
|
|
||||||
|
|
||||||
public static final String TAG = "PhoneCallService";
|
|
||||||
|
|
||||||
private volatile int originalRingVolume;
|
|
||||||
|
|
||||||
private final Call.Callback callback = new Call.Callback() {
|
|
||||||
@Override
|
|
||||||
public void onStateChanged(Call call, int state) {
|
|
||||||
super.onStateChanged(call, state);
|
|
||||||
switch (state) {
|
|
||||||
case Call.STATE_ACTIVE: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Call.STATE_DISCONNECTED: {
|
|
||||||
ActivityStack.getInstance().finishActivity(PhoneCallActivity.class);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCallAdded(Call call) {
|
|
||||||
super.onCallAdded(call);
|
|
||||||
|
|
||||||
call.registerCallback(callback);
|
|
||||||
PhoneCallManager.call = call;
|
|
||||||
CallType callType = null;
|
|
||||||
|
|
||||||
if (call.getState() == Call.STATE_RINGING) {
|
|
||||||
callType = CallType.CALL_IN;
|
|
||||||
} else if (call.getState() == Call.STATE_CONNECTING) {
|
|
||||||
callType = CallType.CALL_OUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callType != null) {
|
|
||||||
Call.Details details = call.getDetails();
|
|
||||||
String phoneNumber = details.getHandle().getSchemeSpecificPart();
|
|
||||||
|
|
||||||
// 记录原始铃声音量
|
|
||||||
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
|
|
||||||
originalRingVolume = audioManager.getStreamVolume(AudioManager.STREAM_RING);
|
|
||||||
// 检查电话接收规则
|
|
||||||
if (!Rules.getInstance(this).isAllowed(phoneNumber)) {
|
|
||||||
// 预先静音
|
|
||||||
audioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
|
|
||||||
// 断开电话
|
|
||||||
call.disconnect();
|
|
||||||
// 停顿1秒,预防第一声铃声响动
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LogUtils.d(TAG, "");
|
|
||||||
}
|
|
||||||
// 恢复铃声音量
|
|
||||||
audioManager.setStreamVolume(AudioManager.STREAM_RING, originalRingVolume, 0);
|
|
||||||
// 屏蔽电话结束
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 正常接听电话
|
|
||||||
PhoneCallActivity.actionStart(this, phoneNumber, callType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCallRemoved(Call call) {
|
|
||||||
super.onCallRemoved(call);
|
|
||||||
|
|
||||||
call.unregisterCallback(callback);
|
|
||||||
PhoneCallManager.call = null;
|
|
||||||
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
|
|
||||||
// 恢复铃声音量
|
|
||||||
audioManager.setStreamVolume(AudioManager.STREAM_RING, originalRingVolume, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum CallType {
|
|
||||||
CALL_IN,
|
|
||||||
CALL_OUT,
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,49 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.receivers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/13 06:58:04
|
|
||||||
* @Describe 主要广播接收器
|
|
||||||
*/
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
|
||||||
import cc.winboll.studio.contacts.services.MainService;
|
|
||||||
import com.hjq.toast.ToastUtils;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
|
|
||||||
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");
|
|
||||||
MainService.startMainService(context);
|
|
||||||
} else {
|
|
||||||
ToastUtils.show(szAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册 Receiver
|
|
||||||
//
|
|
||||||
public void registerAction(Context context) {
|
|
||||||
IntentFilter filter=new IntentFilter();
|
|
||||||
filter.addAction(ACTION_BOOT_COMPLETED);
|
|
||||||
//filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
|
||||||
context.registerReceiver(this, filter);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,139 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.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.Binder;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import cc.winboll.studio.contacts.beans.MainServiceBean;
|
|
||||||
import cc.winboll.studio.contacts.services.MainService;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import cc.winboll.studio.libappbase.SOS;
|
|
||||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,247 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.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 cc.winboll.studio.contacts.listenphonecall.CallListenerService;
|
|
||||||
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.contacts.beans.MainServiceBean;
|
|
||||||
import cc.winboll.studio.contacts.handlers.MainServiceHandler;
|
|
||||||
import cc.winboll.studio.contacts.receivers.MainReceiver;
|
|
||||||
import cc.winboll.studio.contacts.services.MainService;
|
|
||||||
import cc.winboll.studio.contacts.threads.MainServiceThread;
|
|
||||||
import cc.winboll.studio.contacts.widgets.APPStatusWidget;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import cc.winboll.studio.libappbase.SOS;
|
|
||||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
|
||||||
import cc.winboll.studio.contacts.dun.Rules;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import com.hjq.toast.ToastUtils;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return new MyBinder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MainServiceThread getRemindThread() {
|
|
||||||
return mMainServiceThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
LogUtils.d(TAG, "onCreate()");
|
|
||||||
_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();
|
|
||||||
// 召唤 WinBoll APP 绑定本服务
|
|
||||||
SOS.bindToAPPService(this, new APPSOSBean(getPackageName(), MainService.class.getName()));
|
|
||||||
|
|
||||||
if (mMainReceiver == null) {
|
|
||||||
// 注册广播接收器
|
|
||||||
mMainReceiver = new MainReceiver(this);
|
|
||||||
mMainReceiver.registerAction(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rules.getInstance(this);
|
|
||||||
//Rules.getInstance(this).add("18888888888", true);
|
|
||||||
//Rules.getInstance(this).add("16769764848", true);
|
|
||||||
|
|
||||||
startPhoneCallListener();
|
|
||||||
|
|
||||||
MainServiceThread.getInstance(this, mMainServiceHandler).start();
|
|
||||||
|
|
||||||
LogUtils.i(TAG, "Main Service Is Start.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 唤醒和绑定守护进程
|
|
||||||
//
|
|
||||||
void wakeupAndBindAssistant() {
|
|
||||||
LogUtils.d(TAG, "wakeupAndBindAssistant()");
|
|
||||||
// if (ServiceUtils.isServiceAlive(getApplicationContext(), AssistantService.class.getName()) == false) {
|
|
||||||
// startService(new Intent(MainService.this, AssistantService.class));
|
|
||||||
// //LogUtils.d(TAG, "call wakeupAndBindAssistant() : Binding... AssistantService");
|
|
||||||
// bindService(new Intent(MainService.this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
|
||||||
// }
|
|
||||||
Intent intent = new Intent(this, AssistantService.class);
|
|
||||||
startService(intent);
|
|
||||||
// 绑定服务的Intent
|
|
||||||
//Intent intent = new Intent(this, AssistantService.class);
|
|
||||||
bindService(intent, mMyServiceConnection, Context.BIND_IMPORTANT);
|
|
||||||
|
|
||||||
// Intent intent = new Intent(this, AssistantService.class);
|
|
||||||
// startService(intent);
|
|
||||||
// LogUtils.d(TAG, "startService(intent)");
|
|
||||||
// bindService(new Intent(this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void startPhoneCallListener() {
|
|
||||||
Intent callListener = new Intent(this, CallListenerService.class);
|
|
||||||
startService(callListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
//LogUtils.d(TAG, "onDestroy");
|
|
||||||
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
|
|
||||||
//LogUtils.d(TAG, "onDestroy done");
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 停止主要进程
|
|
||||||
MainServiceThread.getInstance(this, mMainServiceHandler).setIsExit(true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主进程与守护进程连接时需要用到此类
|
|
||||||
//
|
|
||||||
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();
|
|
||||||
SOS.sosWinBollService(getApplicationContext(), new APPSOSBean(getPackageName(), MainService.class.getName()));
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,77 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.threads;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/14 03:46:44
|
|
||||||
*/
|
|
||||||
import android.content.Context;
|
|
||||||
import cc.winboll.studio.contacts.handlers.MainServiceHandler;
|
|
||||||
import cc.winboll.studio.contacts.services.MainService;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import cc.winboll.studio.libappbase.SOS;
|
|
||||||
import cc.winboll.studio.libappbase.bean.APPSOSBean;
|
|
||||||
import com.hjq.toast.ToastUtils;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
public class MainServiceThread extends Thread {
|
|
||||||
|
|
||||||
public static final String TAG = "MainServiceThread";
|
|
||||||
|
|
||||||
volatile static MainServiceThread _MainServiceThread;
|
|
||||||
// 控制线程是否退出的标志
|
|
||||||
volatile boolean isExit = false;
|
|
||||||
volatile boolean isStarted = false;
|
|
||||||
Context mContext;
|
|
||||||
// 服务Handler, 用于线程发送消息使用
|
|
||||||
WeakReference<MainServiceHandler> mwrMainServiceHandler;
|
|
||||||
|
|
||||||
MainServiceThread(Context context, MainServiceHandler handler) {
|
|
||||||
mContext = context;
|
|
||||||
mwrMainServiceHandler = new WeakReference<MainServiceHandler>(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsExit(boolean isExit) {
|
|
||||||
this.isExit = isExit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExit() {
|
|
||||||
return isExit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsStarted(boolean isStarted) {
|
|
||||||
this.isStarted = isStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isStarted() {
|
|
||||||
return isStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MainServiceThread getInstance(Context context, MainServiceHandler handler) {
|
|
||||||
if (_MainServiceThread != null) {
|
|
||||||
_MainServiceThread.setIsExit(true);
|
|
||||||
}
|
|
||||||
_MainServiceThread = new MainServiceThread(context, handler);
|
|
||||||
return _MainServiceThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (isStarted == false) {
|
|
||||||
isStarted = true;
|
|
||||||
LogUtils.d(TAG, "run()");
|
|
||||||
|
|
||||||
while (!isExit()) {
|
|
||||||
//ToastUtils.show("run");
|
|
||||||
//LogUtils.d(TAG, "run()");
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_MainServiceThread = null;
|
|
||||||
LogUtils.d(TAG, "run() exit");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,76 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.widgets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/17 14:49:31
|
|
||||||
* @Describe APPStatusWidget
|
|
||||||
*/
|
|
||||||
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.contacts.R;
|
|
||||||
import cc.winboll.studio.contacts.threads.MainServiceThread;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import com.hjq.toast.ToastUtils;
|
|
||||||
|
|
||||||
public class APPStatusWidget extends AppWidgetProvider {
|
|
||||||
|
|
||||||
public static final String TAG = "APPSOSReportWidget";
|
|
||||||
|
|
||||||
public static final String ACTION_STATUS_ACTIVE = "cc.winboll.studio.contacts.widgets.APPStatusWidget.ACTION_STATUS_ACTIVE";
|
|
||||||
public static final String ACTION_STATUS_NOACTIVE = "cc.winboll.studio.contacts.widgets.APPStatusWidget.ACTION_STATUS_NOACTIVE";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
|
||||||
for (int appWidgetId : appWidgetIds) {
|
|
||||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
super.onReceive(context, intent);
|
|
||||||
if (intent.getAction().equals(ACTION_STATUS_ACTIVE)) {
|
|
||||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
|
||||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPStatusWidget.class));
|
|
||||||
for (int appWidgetId : appWidgetIds) {
|
|
||||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
|
||||||
}
|
|
||||||
} else if (intent.getAction().equals(ACTION_STATUS_NOACTIVE)) {
|
|
||||||
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
|
|
||||||
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, APPStatusWidget.class));
|
|
||||||
for (int appWidgetId : appWidgetIds) {
|
|
||||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
|
||||||
LogUtils.d(TAG, "updateAppWidget(...)");
|
|
||||||
|
|
||||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
|
|
||||||
//设置按钮点击事件
|
|
||||||
Intent intentAppButton = new Intent(context, APPStatusWidgetClickListener.class);
|
|
||||||
intentAppButton.setAction(APPStatusWidgetClickListener.ACTION_APPICON_CLICK);
|
|
||||||
PendingIntent pendingIntentAppButton = PendingIntent.getBroadcast(context, 0, intentAppButton, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
views.setOnClickPendingIntent(R.id.widgetlayoutImageView1, pendingIntentAppButton);
|
|
||||||
|
|
||||||
// boolean isActive = !MainServiceThread.isExist();
|
|
||||||
// if (isActive) {
|
|
||||||
// views.setImageViewResource(R.id.widgetlayoutImageView1, R.drawable.ic_launcher);
|
|
||||||
// } else {
|
|
||||||
// views.setImageViewResource(R.id.widgetlayoutImageView1, R.drawable.ic_launcher_disable);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onAPPStatusWidgetClick(Context context) {
|
|
||||||
ToastUtils.show("onAPPStatusWidgetClick");
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
package cc.winboll.studio.contacts.widgets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author ZhanGSKen@AliYun.Com
|
|
||||||
* @Date 2025/02/17 14:59:55
|
|
||||||
* @Describe WidgetButtonClickListener
|
|
||||||
*/
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
|
|
||||||
public class APPStatusWidgetClickListener extends BroadcastReceiver {
|
|
||||||
|
|
||||||
public static final String TAG = "APPStatusWidgetClickListener";
|
|
||||||
|
|
||||||
public static final String ACTION_APPICON_CLICK = "cc.winboll.studio.contacts.widgets.APPStatusWidgetClickListener.ACTION_APPICON_CLICK";
|
|
||||||
|
|
||||||
@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_APPICON_CLICK)) {
|
|
||||||
LogUtils.d(TAG, "ACTION_APPICON_CLICK");
|
|
||||||
Toast.makeText(context, "ACTION_APPICON_CLICK", Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:clickable="true">
|
|
||||||
<item android:drawable="@drawable/ic_launcher_background"/>
|
|
||||||
<item
|
|
||||||
android:left="15dp"
|
|
||||||
android:top="15dp"
|
|
||||||
android:right="15dp"
|
|
||||||
android:bottom="15dp"
|
|
||||||
android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</layer-list>
|
|
@@ -1,170 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="@color/colorPrimary"
|
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M9,0L9,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,0L19,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,0L29,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
|
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:clickable="true">
|
|
||||||
<item android:drawable="@drawable/ic_launcher_background"/>
|
|
||||||
<item
|
|
||||||
android:left="15dp"
|
|
||||||
android:top="15dp"
|
|
||||||
android:right="15dp"
|
|
||||||
android:bottom="15dp"
|
|
||||||
android:drawable="@drawable/ic_launcher_foreground_disable"/>
|
|
||||||
</layer-list>
|
|
@@ -1,10 +0,0 @@
|
|||||||
<?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="#FFFFFFFF"
|
|
||||||
android:pathData="M16.61,15.15C16.15,15.15 15.77,14.78 15.77,14.32S16.15,13.5 16.61,13.5H16.61C17.07,13.5 17.45,13.86 17.45,14.32C17.45,14.78 17.07,15.15 16.61,15.15M7.41,15.15C6.95,15.15 6.57,14.78 6.57,14.32C6.57,13.86 6.95,13.5 7.41,13.5H7.41C7.87,13.5 8.24,13.86 8.24,14.32C8.24,14.78 7.87,15.15 7.41,15.15M16.91,10.14L18.58,7.26C18.67,7.09 18.61,6.88 18.45,6.79C18.28,6.69 18.07,6.75 18,6.92L16.29,9.83C14.95,9.22 13.5,8.9 12,8.91C10.47,8.91 9,9.24 7.73,9.82L6.04,6.91C5.95,6.74 5.74,6.68 5.57,6.78C5.4,6.87 5.35,7.08 5.44,7.25L7.1,10.13C4.25,11.69 2.29,14.58 2,18H22C21.72,14.59 19.77,11.7 16.91,10.14H16.91Z"/>
|
|
||||||
</vector>
|
|
@@ -1,10 +0,0 @@
|
|||||||
<?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="#FFAAAAAA"
|
|
||||||
android:pathData="M16.61,15.15C16.15,15.15 15.77,14.78 15.77,14.32S16.15,13.5 16.61,13.5H16.61C17.07,13.5 17.45,13.86 17.45,14.32C17.45,14.78 17.07,15.15 16.61,15.15M7.41,15.15C6.95,15.15 6.57,14.78 6.57,14.32C6.57,13.86 6.95,13.5 7.41,13.5H7.41C7.87,13.5 8.24,13.86 8.24,14.32C8.24,14.78 7.87,15.15 7.41,15.15M16.91,10.14L18.58,7.26C18.67,7.09 18.61,6.88 18.45,6.79C18.28,6.69 18.07,6.75 18,6.92L16.29,9.83C14.95,9.22 13.5,8.9 12,8.91C10.47,8.91 9,9.24 7.73,9.82L6.04,6.91C5.95,6.74 5.74,6.68 5.57,6.78C5.4,6.87 5.35,7.08 5.44,7.25L7.1,10.13C4.25,11.69 2.29,14.58 2,18H22C21.72,14.59 19.77,11.7 16.91,10.14H16.91Z"/>
|
|
||||||
</vector>
|
|
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportHeight="1024"
|
|
||||||
android:viewportWidth="1024">
|
|
||||||
<path
|
|
||||||
android:fillColor="#fff"
|
|
||||||
android:pathData="M847.53,307.03L597.5,307.03c-8.54,0.17 -13.66,-11.26 -13.66,-19.97 0.17,-8.7 5.12,-14.17 13.66,-14.17h250.02c30.21,-0.34 31.41,34.14 0,34.14zM736.6,428.71c-6.14,6.32 -16.05,6.32 -22.02,0.17l-128.34,-130.56c-5.98,-6.14 -5.8,-16.22 0.17,-22.53l122.37,-124.76c6.14,-6.31 16.05,-6.31 22.02,-0.34 5.98,6.14 5.81,16.22 -0.34,22.36L623.1,289.62l113.5,116.22a16.33,16.33 0,0 1,0 22.87zM833.02,717.99c-18.78,-12.63 -122.37,-64.85 -141.99,-77.14 -2.05,0 -7.34,0.68 -14.85,4.43 -8.02,4.1 -31.23,16.9 -63.66,34.99l-25.26,14.16 -23.9,-16.38c-17.75,-12.11 -56.32,-41.3 -115.03,-98.64 -58.88,-57.69 -88.58,-95.23 -101.04,-112.47l-16.72,-23.38L345.09,418.82c13.99,-23.9 30.72,-52.9 35.84,-62.46 4.1,-7.51 4.44,-12.63 4.44,-14.17v-0.51C374.27,324.44 303.27,219.65 290.3,201.22c-1.88,-0.34 -5.8,0 -10.75,3.42 -40.28,28.5 -82.43,68.95 -88.41,84.65C195.24,373.42 270.85,491.52 404.48,622.25c133.8,130.73 251.22,205.49 336.9,209.41 16.22,-5.63 62.81,-52.05 91.65,-91.14 2.05,-2.9 3.24,-3.58 3.24,-6.99 0,-0.51 -3.07,-15.02 -3.24,-15.53zM867.5,770.73c-0.68,1.02 -81.58,108.03 -126.12,106.67 -125.1,-3.93 -265.73,-128.86 -366.94,-227.84 -101.38,-98.99 -225.45,-238.25 -229.38,-360.96v-1.02c0,-43.01 124.76,-128 125.78,-128.69 19.62,-13.14 36.35,-13.82 52.39,10.41 7.85,10.92 87.73,123.9 96.94,138.58 3.92,6.49 11.09,25.94 11.09,34.48 0,10.92 -3.24,23.21 -9.73,34.98 -6.31,11.61 -26.62,46.59 -36.69,63.83 10.92,15.19 46.76,61.44 103.94,117.25 56.83,55.63 85.16,72.19 100.69,82.77 17.58,-9.73 53.42,-29.7 65.2,-35.67 22.18,-11.44 44.37,-12.8 59.39,-3.42 14.16,8.7 136.02,88.41 147.79,96.6 10.93,7.68 16.9,21.67 16.9,36.69 0.17,11.78 -3.58,24.41 -11.26,35.33z" />
|
|
||||||
</vector>
|
|
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportHeight="1024"
|
|
||||||
android:viewportWidth="1024">
|
|
||||||
<path
|
|
||||||
android:fillColor="#fff"
|
|
||||||
android:pathData="M861.86,307.03L614.4,307.03c-31.06,-0.17 -29.86,-34.48 0,-34.14h247.46c8.54,0.17 13.31,5.46 13.49,14.17 0,8.87 -4.95,20.14 -13.49,19.97zM872.96,298.5l-126.98,130.56c-5.98,6.14 -15.7,5.98 -21.85,-0.17 -6.14,-6.32 -6.14,-16.38 -0.17,-22.36l112.3,-116.22L730.11,173.74c-6.14,-6.31 -6.14,-16.38 -0.17,-22.35 5.97,-6.14 15.7,-5.98 21.84,0.34L872.96,276.48c5.8,5.8 5.98,15.87 0,22.02zM833.02,717.99c-18.78,-12.63 -122.37,-64.85 -141.99,-77.14 -2.05,0 -7.34,0.68 -14.85,4.43 -8.02,4.1 -31.23,16.9 -63.66,34.99l-25.26,14.16 -23.9,-16.38c-17.75,-12.11 -56.32,-41.3 -115.03,-98.64 -58.88,-57.69 -88.41,-95.23 -100.86,-112.47L330.75,443.56l14.5,-24.74c14,-23.9 30.72,-52.9 35.84,-62.46 4.1,-7.51 4.44,-12.63 4.44,-14.17v-0.51C374.44,324.44 303.45,219.65 290.3,201.22c-1.88,-0.34 -5.8,0 -10.75,3.42 -40.28,28.5 -82.43,68.95 -88.41,84.65C195.24,373.42 270.85,491.52 404.48,622.25c133.63,130.73 251.05,205.49 336.9,209.41 16.22,-5.63 62.81,-52.05 91.65,-91.14 2.05,-2.9 3.24,-3.58 3.24,-6.99 0,-0.51 -3.07,-15.02 -3.24,-15.53zM867.5,770.73c-0.68,1.02 -81.58,108.03 -126.12,106.67 -125.1,-3.93 -265.56,-128.86 -366.94,-227.84 -101.38,-98.99 -225.45,-238.25 -229.38,-360.96v-1.02c0,-43.01 124.76,-128 125.78,-128.69 19.62,-13.14 36.35,-13.82 52.39,10.41 7.85,10.92 87.73,123.9 96.94,138.58 4.1,6.49 11.09,25.94 11.09,34.48 0,10.92 -3.24,23.21 -9.73,34.98 -6.14,11.61 -26.62,46.59 -36.69,63.83 10.75,15.19 46.76,61.44 103.94,117.25 56.83,55.63 85.16,72.19 100.69,82.77 17.58,-9.73 53.42,-29.7 65.2,-35.67 22.18,-11.44 44.37,-12.8 59.39,-3.42 14.16,8.7 136.19,88.41 147.79,96.6 10.93,7.68 16.9,21.67 16.9,36.69 0.17,11.78 -3.58,24.41 -11.26,35.33z" />
|
|
||||||
</vector>
|
|
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="64dp"
|
|
||||||
android:height="64dp"
|
|
||||||
android:viewportHeight="1024"
|
|
||||||
android:viewportWidth="1024">
|
|
||||||
<path
|
|
||||||
android:fillColor="#201f1f"
|
|
||||||
android:pathData="M841.22,856.06c185.86,-185.86 185.86,-487.42 0,-673.79C655.36,-3.58 353.79,-3.58 167.42,182.27c-185.86,185.86 -185.86,487.42 0,673.79 186.37,185.86 487.94,185.86 673.79,0zM218.62,495.1c0,-47.62 111.1,-113.66 285.7,-113.66 175.1,0 285.7,66.05 285.7,113.66 0,40.96 10.75,102.4 -73.73,93.18 -84.48,-9.22 -78.85,-40.96 -78.85,-83.46 0,-29.7 -68.61,-36.35 -133.12,-36.35 -65.02,0 -133.12,6.66 -133.12,36.35 0,42.5 5.63,74.24 -78.85,83.46 -84.99,9.22 -73.73,-51.71 -73.73,-93.18z" />
|
|
||||||
</vector>
|
|
@@ -1,30 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="64dp"
|
|
||||||
android:height="64dp"
|
|
||||||
android:viewportHeight="1024"
|
|
||||||
android:viewportWidth="1024">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M277.9,742s167.9,-294.1 465.3,-465.3C575.7,577.8 277.9,742 277.9,742z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M743.1,742S575.2,447.9 277.8,276.7C445.3,577.8 743.1,742 743.1,742z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M284.1,343m-49,0a49,49 0,1 0,98 0,49 49,0 1,0 -98,0Z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M284.1,515.5m-49,0a49,49 0,1 0,98 0,49 49,0 1,0 -98,0Z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M284.1,683.5m-49,0a49,49 0,1 0,98 0,49 49,0 1,0 -98,0Z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M808.4,341.6s-208.5,-61.2 -420,0c211.5,64.8 420,0 420,0zM808.4,516.6s-208.5,-61.2 -420,0c211.5,64.8 420,0 420,0zM808.4,684.6s-208.5,-61.2 -420,0c211.5,64.8 420,0 420,0z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#0EC469"
|
|
||||||
android:pathData="M512,512m-448,0a448,448 0,1 0,896 0,448 448,0 1,0 -896,0Z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M701.4,786.8h-0.3c-3.2,-0.3 -6.4,-0.8 -9.5,-1.4C290,725.2 237.2,331.5 237.2,331.5h0.1c-5.9,-27.8 0.8,-56.8 22.5,-78.5 9.5,-9.5 22.5,-18.1 31.3,-19.2l111.6,111.6c-1.1,8.8 -9.6,21.7 -19.1,31.2 -8.5,8.5 -17.9,14.4 -28.4,18.6 57.7,214.5 272.1,271.5 272.1,271.5l0.3,0.2c4.2,-10.5 9.6,-19.3 18.1,-27.8 9.5,-9.5 22.6,-18.1 31.4,-19.2l111.6,111.6c-1.1,8.8 -9.6,21.7 -19.1,31.2 -18.9,19 -43.4,26.3 -68.2,24.1z" />
|
|
||||||
</vector>
|
|
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<gradient
|
|
||||||
android:angle="180"
|
|
||||||
android:endColor="#FFFFFFFF"
|
|
||||||
android:startColor="#FFFFFFFF"
|
|
||||||
android:type="linear" />
|
|
||||||
|
|
||||||
<corners android:radius="10dp" />
|
|
||||||
</shape>
|
|
@@ -1,28 +0,0 @@
|
|||||||
<?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:padding="16dp">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/phone_number"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="请输入电话号码"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/dial_button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="拨号"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/call_status"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="16dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@@ -1,22 +0,0 @@
|
|||||||
<?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:padding="16dp">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/phone_number_edit_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="Enter phone number" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/dial_button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Dial" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@@ -1,27 +0,0 @@
|
|||||||
<?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"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/activitymainToolbar1"/>
|
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1.0"
|
|
||||||
android:id="@+id/activitymainViewPager1"/>
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
android:id="@+id/activitymainTabLayout1"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@@ -1,95 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".phonecallui.PhoneCallActivity">
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/rl_user_info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="300dp"
|
|
||||||
android:background="@color/colorPrimaryDark">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_call_number_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_above="@+id/tv_call_number"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="来电号码"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="18sp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_call_number"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="28sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
tools:text="133-9527-9527" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@android:color/white">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_phone_calling_time"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:text="通话中:01:33"
|
|
||||||
android:textColor="@android:color/black"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_phone_hang_up"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:drawableTop="@drawable/ic_phone_hang_up"
|
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:text="挂 断"
|
|
||||||
android:textColor="@android:color/black"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_phone_pick_up"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="50dp"
|
|
||||||
android:layout_toRightOf="@id/tv_phone_hang_up"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:drawableTop="@drawable/ic_phone_pick_up"
|
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:text="接 听"
|
|
||||||
android:textColor="@android:color/black"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
|
@@ -1,51 +0,0 @@
|
|||||||
<?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"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/activitymainToolbar1"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1.0">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="应用权限设置:"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="right">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="悬浮窗设置"
|
|
||||||
android:id="@+id/activitysettingsButton2"
|
|
||||||
android:onClick="onCanDrawOverlays"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="默认拨号设置"
|
|
||||||
android:id="@+id/activitysettingsButton1"
|
|
||||||
android:onClick="onDefaultPhone"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@@ -1,29 +0,0 @@
|
|||||||
<?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">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:ems="10"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1.0"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Text"
|
|
||||||
android:id="@+id/page_text"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@@ -1,15 +0,0 @@
|
|||||||
<?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">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Text"
|
|
||||||
android:id="@+id/page_text"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@@ -1,12 +0,0 @@
|
|||||||
<?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">
|
|
||||||
<cc.winboll.studio.libappbase.LogView
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/logview"/>
|
|
||||||
</LinearLayout>
|
|
@@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/rl_user_info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@color/colorPrimary">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_call_number"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="30dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="18sp"
|
|
||||||
tools:text="133-8892-9579" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_open_app"
|
|
||||||
style="@style/Base.Widget.AppCompat.Button.Borderless.Colored"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/tv_call_number"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="打开 Phone Call App"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user