diff --git a/contacts/build.gradle b/contacts/build.gradle
index 86bb581..89322a4 100644
--- a/contacts/build.gradle
+++ b/contacts/build.gradle
@@ -64,7 +64,7 @@ dependencies {
api 'com.google.android.material:material:1.1.0'
api 'cc.winboll.studio:libapputils:9.3.2'
- api 'cc.winboll.studio:libappbase:1.5.1'
+ api 'cc.winboll.studio:libappbase:1.5.5'
api fileTree(dir: 'libs', include: ['*.jar'])
}
diff --git a/contacts/build.properties b/contacts/build.properties
index ed0e69d..d1c9e68 100644
--- a/contacts/build.properties
+++ b/contacts/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Thu Feb 13 19:09:39 GMT 2025
+#Thu Feb 20 03:27:00 GMT 2025
stageCount=0
libraryProject=winboll-shared
baseVersion=1.0
publishVersion=1.0.0
-buildCount=13
+buildCount=91
baseBetaVersion=1.0.1
diff --git a/contacts/src/main/AndroidManifest.xml b/contacts/src/main/AndroidManifest.xml
index 509b1b2..5ccab58 100644
--- a/contacts/src/main/AndroidManifest.xml
+++ b/contacts/src/main/AndroidManifest.xml
@@ -42,7 +42,10 @@
-
+
+
+
@@ -54,6 +57,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java b/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java
index 952e7ba..9177664 100644
--- a/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/MainActivity.java
@@ -1,5 +1,7 @@
package cc.winboll.studio.contacts;
+
+
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
@@ -9,13 +11,15 @@ import android.widget.CheckBox;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.contacts.BuildConfig;
+import cc.winboll.studio.contacts.MainActivity;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.MainServiceBean;
+import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.GlobalApplication;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.LogView;
import cc.winboll.studio.libappbase.SOS;
-import cc.winboll.studio.libapputils.app.AboutActivityFactory;
+import cc.winboll.studio.libappbase.bean.APPSOSBean;
import cc.winboll.studio.libapputils.app.IWinBollActivity;
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
import cc.winboll.studio.libapputils.bean.APPInfo;
@@ -27,7 +31,9 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
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;
@@ -40,21 +46,21 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
@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;
+// 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
@@ -64,11 +70,11 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
// 以下正常创建主窗口
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
+
mLogView = findViewById(R.id.activitymainLogView1);
if (GlobalApplication.isDebuging()) { mLogView.start(); }
-
+
// 初始化工具栏
mToolbar = findViewById(R.id.activitymainToolbar1);
setSupportActionBar(mToolbar);
@@ -90,22 +96,48 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
cbMainService.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
- SOS.sendToWinBoll(MainActivity.this);
-// if (cbMainService.isChecked()) {
-// MainService.startISOSService(MainActivity.this);
-// } else {
-// MainService.stopISOSService(MainActivity.this);
-// }
+ if (cbMainService.isChecked()) {
+ MainService.startMainService(MainActivity.this);
+ } else {
+ MainService.stopMainService(MainActivity.this);
+ }
}
});
}
+// public static void sosToWinBoll(Context context) {
+// Intent intent = new Intent(ACTION_SOS);
+// intent.putExtra("sos", "SOS");
+// intent.putExtra("sosPackage", context.getPackageName());
+// intent.putExtra("sosCalssType", "Service");
+// intent.putExtra("sosClassName", MainService.class.getName());
+// String szToPackage = "";
+// if (GlobalApplication.isDebuging()) {
+// szToPackage = "cc.winboll.studio.appbase.beta";
+// } else {
+// szToPackage = "cc.winboll.studio.appbase";
+// }
+// intent.setPackage(szToPackage);
+// context.sendBroadcast(intent);
+//
+// LogUtils.d(TAG, String.format("SOS Send To WinBoll. (szToPackage : %s)", szToPackage));
+// //ToastUtils.show("SOS Send To WinBoll");
+// }
+
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
//setSubTitle("");
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ LogUtils.d(TAG, "onDestroy() SOS");
+ }
+
+
+
//
// 处理传入的 Intent 数据
//
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/handlers/MainServiceHandler.java b/contacts/src/main/java/cc/winboll/studio/contacts/handlers/MainServiceHandler.java
new file mode 100644
index 0000000..d19cd99
--- /dev/null
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/handlers/MainServiceHandler.java
@@ -0,0 +1,38 @@
+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 serviceWeakReference;
+ public MainServiceHandler(MainService service) {
+ serviceWeakReference = new WeakReference(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;
+ }
+ }
+ }
+}
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/receivers/MainReceiver.java b/contacts/src/main/java/cc/winboll/studio/contacts/receivers/MainReceiver.java
index 6315f2f..7d93891 100644
--- a/contacts/src/main/java/cc/winboll/studio/contacts/receivers/MainReceiver.java
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/receivers/MainReceiver.java
@@ -1,20 +1,32 @@
package cc.winboll.studio.contacts.receivers;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import com.hjq.toast.ToastUtils;
-
/**
* @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 cc.winboll.studio.contacts.services.MainService;
+import com.hjq.toast.ToastUtils;
+import java.lang.ref.WeakReference;
+
public class MainReceiver extends BroadcastReceiver {
-
+
public static final String TAG = "MainReceiver";
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
-
+ WeakReference mwrService;
+ // 存储电量指示值,
+ // 用于校验电量消息时的电量变化
+ static volatile int _mnTheQuantityOfElectricityOld = -1;
+ static volatile boolean _mIsCharging = false;
+
+ public MainReceiver(MainService service) {
+ mwrService = new WeakReference(service);
+ }
+
@Override
public void onReceive(Context context, Intent intent) {
String szAction = intent.getAction();
@@ -24,5 +36,13 @@ public class MainReceiver extends BroadcastReceiver {
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);
+ }
}
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java b/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java
new file mode 100644
index 0000000..a031f4b
--- /dev/null
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/services/AssistantService.java
@@ -0,0 +1,139 @@
+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;
+ }
+ }
+}
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java b/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java
index 4e9d60a..efaf13e 100644
--- a/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/services/MainService.java
@@ -1,162 +1,229 @@
package cc.winboll.studio.contacts.services;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
-import cc.winboll.studio.contacts.beans.MainServiceBean;
-import cc.winboll.studio.libappbase.ISOSAPP;
-import cc.winboll.studio.libappbase.ISOSService;
-import cc.winboll.studio.libappbase.LogUtils;
-import cc.winboll.studio.libappbase.SOSCSBroadcastReceiver;
-import cc.winboll.studio.libappbase.SimpleOperateSignalCenterService;
-import com.hjq.toast.ToastUtils;
-import android.content.ComponentName;
-
/**
* @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
*/
-public class MainService extends Service implements ISOSService {
-
+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.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;
+
+public class MainService extends Service {
+
public static final String TAG = "MainService";
-
- public static final String ACTION_ENABLE = MainService.class.getName() + ".ACTION_ENABLE";
- public static final String ACTION_DISABLE = MainService.class.getName() + ".ACTION_DISABLE";
+
+ public static final int MSG_UPDATE_STATUS = 0;
+
+ static MainService _mControlCenterService;
+
+ volatile boolean isServiceRunning;
MainServiceBean mMainServiceBean;
- static MainThread _MainThread;
- public static synchronized MainThread getMainThreadInstance() {
- if (_MainThread == null) {
- _MainThread = new MainThread();
- }
- return _MainThread;
- }
+ MainServiceThread mMainServiceThread;
+ MainServiceHandler mMainServiceHandler;
+ MyServiceConnection mMyServiceConnection;
+ AssistantService mAssistantService;
+ boolean isBound = false;
+ MainReceiver mMainReceiver;
@Override
public IBinder onBind(Intent intent) {
- return null;
+ return new MyBinder();
+ }
+
+ public MainServiceThread getRemindThread() {
+ return mMainServiceThread;
}
@Override
public void onCreate() {
super.onCreate();
- LogUtils.d(TAG, "onCreate");
+ LogUtils.d(TAG, "onCreate()");
+ _mControlCenterService = MainService.this;
+ isServiceRunning = false;
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
- runMainThread();
+
+ 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");
- if (intent.getBooleanExtra(ISOSService.EXTRA_ENABLE, false)) {
- LogUtils.d(TAG, "onStartCommand enable service");
- mMainServiceBean.setIsEnable(true);
- MainServiceBean.saveBean(this, mMainServiceBean);
- }
-
- runMainThread();
-
- //return super.onStartCommand(intent, flags, startId);
- return mMainServiceBean.isEnable() ? Service.START_STICKY: super.onStartCommand(intent, flags, startId);
+ LogUtils.d(TAG, "onStartCommand(...)");
+ // 运行服务内容
+ mainService();
+ return (mMainServiceBean.isEnable()) ? START_STICKY : super.onStartCommand(intent, flags, startId);
}
- void runMainThread() {
+ // 运行服务内容
+ //
+ void mainService() {
+ LogUtils.d(TAG, "mainService()");
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
- if (mMainServiceBean.isEnable()
- && _MainThread == null) {
- getMainThreadInstance().start();
+ 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);
+ }
+
+
+ MainServiceThread.getInstance(this, mMainServiceHandler).start();
+
+ LogUtils.i(TAG, "Main Service Is Start.");
}
}
- @Override
- public Intent getISOSServiceIntentWhichAskForHelp() {
- Intent intentService = new Intent();
- intentService.putExtra(ISOSAPP.EXTRA_PACKAGE, this.getPackageName());
- intentService.putExtra(ISOSAPP.EXTRA_SERVICE, this.getClass().getName());
- return intentService;
- }
+ // 唤醒和绑定守护进程
+ //
+ 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);
- @Override
- public boolean isEnable() {
- mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
- return mMainServiceBean.isEnable();
+// Intent intent = new Intent(this, AssistantService.class);
+// startService(intent);
+// LogUtils.d(TAG, "startService(intent)");
+// bindService(new Intent(this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT);
}
@Override
public void onDestroy() {
- super.onDestroy();
- LogUtils.d(TAG, "onDestroy");
+ //LogUtils.d(TAG, "onDestroy");
mMainServiceBean = MainServiceBean.loadBean(this, MainServiceBean.class);
- if (mMainServiceBean.isEnable()) {
- LogUtils.d(TAG, "mMainServiceBean.isEnable()");
-// ISOSAPP iSOSAPP = (ISOSAPP)getApplication();
-// iSOSAPP.helpISOSService(getISOSServiceIntentWhichAskForHelp());
- sos();
- }
- if (_MainThread != null) {
- _MainThread.isExist = true;
- _MainThread = null;
+ //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 stopISOSService(Context context) {
- LogUtils.d(TAG, "stopISOSService");
+// //
+// // 启动服务
+// //
+// 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 startISOSService(Context context) {
- LogUtils.d(TAG, "startISOSService");
+ 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));
}
-
- public void sos() {
- // 创建Intent对象,指定广播的action
- Intent intentService = new Intent(SOSCSBroadcastReceiver.ACTION_SOS);
- String packageName = this.getPackageName();
- String serviceClassName = SOSCSBroadcastReceiver.class.getName();
- intentService.setComponent(new ComponentName(packageName, serviceClassName));
-
- // 目标服务的包名和类名
- intentService.putExtra(ISOSAPP.EXTRA_PACKAGE, getPackageName());
- intentService.putExtra(ISOSAPP.EXTRA_SERVICE, MainService.class.getName());
- // 发送广播
- sendBroadcast(intentService);
- LogUtils.d(TAG, "sos");
- ToastUtils.show("sos");
- }
-
- static class MainThread extends Thread {
- volatile boolean isExist = false;
-
- public void setIsExist(boolean isExist) {
- this.isExist = isExist;
- }
-
- public boolean isExist() {
- return isExist;
- }
-
- @Override
- public void run() {
- super.run();
- while (!isExist) {
- LogUtils.d(TAG, "run");
- ToastUtils.show("run");
- try {
- sleep(1000);
- } catch (InterruptedException e) {
- LogUtils.d(TAG, e, Thread.currentThread().getStackTrace());
- }
- }
- }
-
- }
}
+
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/threads/MainServiceThread.java b/contacts/src/main/java/cc/winboll/studio/contacts/threads/MainServiceThread.java
new file mode 100644
index 0000000..0dfd918
--- /dev/null
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/threads/MainServiceThread.java
@@ -0,0 +1,77 @@
+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 mwrMainServiceHandler;
+
+ MainServiceThread(Context context, MainServiceHandler handler) {
+ mContext = context;
+ mwrMainServiceHandler = new WeakReference(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");
+ }
+ }
+
+}
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/widgets/APPStatusWidget.java b/contacts/src/main/java/cc/winboll/studio/contacts/widgets/APPStatusWidget.java
new file mode 100644
index 0000000..8a9b7c0
--- /dev/null
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/widgets/APPStatusWidget.java
@@ -0,0 +1,76 @@
+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");
+ }
+}
diff --git a/contacts/src/main/java/cc/winboll/studio/contacts/widgets/APPStatusWidgetClickListener.java b/contacts/src/main/java/cc/winboll/studio/contacts/widgets/APPStatusWidgetClickListener.java
new file mode 100644
index 0000000..016ccb2
--- /dev/null
+++ b/contacts/src/main/java/cc/winboll/studio/contacts/widgets/APPStatusWidgetClickListener.java
@@ -0,0 +1,32 @@
+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();
+ }
+ }
+}
diff --git a/contacts/src/main/res/drawable/ic_launcher_disable.xml b/contacts/src/main/res/drawable/ic_launcher_disable.xml
new file mode 100644
index 0000000..9a31905
--- /dev/null
+++ b/contacts/src/main/res/drawable/ic_launcher_disable.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/contacts/src/main/res/drawable/ic_launcher_foreground_disable.xml b/contacts/src/main/res/drawable/ic_launcher_foreground_disable.xml
new file mode 100644
index 0000000..763b72c
--- /dev/null
+++ b/contacts/src/main/res/drawable/ic_launcher_foreground_disable.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/contacts/src/main/res/layout/widget_layout.xml b/contacts/src/main/res/layout/widget_layout.xml
new file mode 100644
index 0000000..0dc6b46
--- /dev/null
+++ b/contacts/src/main/res/layout/widget_layout.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/contacts/src/main/res/xml/appwidget_provider_info.xml b/contacts/src/main/res/xml/appwidget_provider_info.xml
new file mode 100644
index 0000000..7dda9ab
--- /dev/null
+++ b/contacts/src/main/res/xml/appwidget_provider_info.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/winboll-shared/build.properties b/winboll-shared/build.properties
index ed0e69d..d1c9e68 100644
--- a/winboll-shared/build.properties
+++ b/winboll-shared/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Thu Feb 13 19:09:39 GMT 2025
+#Thu Feb 20 03:27:00 GMT 2025
stageCount=0
libraryProject=winboll-shared
baseVersion=1.0
publishVersion=1.0.0
-buildCount=13
+buildCount=91
baseBetaVersion=1.0.1