通知服务核心更新
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -8,6 +8,16 @@
|
|||||||
<!-- 添加接收系统启动消息(用于开机启动)权限 -->
|
<!-- 添加接收系统启动消息(用于开机启动)权限 -->
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||||
|
<!-- 前台服务权限 -->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<!-- Android 14+ specialUse 前台服务权限 -->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
|
<!-- Android 13+ 通知权限 -->
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<!-- WorkManager 需要 -->
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<!-- 电池优化白名单请求 -->
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
|
||||||
<!-- 下面这个也必须加,否则 Android 11+ 拿不到列表 -->
|
<!-- 下面这个也必须加,否则 Android 11+ 拿不到列表 -->
|
||||||
<queries>
|
<queries>
|
||||||
@@ -20,6 +30,7 @@
|
|||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
<application
|
<application
|
||||||
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
@@ -31,7 +42,7 @@
|
|||||||
android:roundIcon="@mipmap/app_logo"
|
android:roundIcon="@mipmap/app_logo"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.SmsMessage"
|
android:theme="@style/Theme.SmsMessage"
|
||||||
tools:targetApi="31">
|
tools:targetApi="34">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.MainActivity"
|
android:name=".Activity.MainActivity"
|
||||||
@@ -54,20 +65,41 @@
|
|||||||
android:name=".Activity.AppListActivity"
|
android:name=".Activity.AppListActivity"
|
||||||
android:theme="@style/Theme.SmsMessage1"
|
android:theme="@style/Theme.SmsMessage1"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
|
<activity
|
||||||
|
android:name=".Activity.LoginActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".Activity.ChangePasswordActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".Activity.BankListActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".Activity.PermissionActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
<!--通知栏获取短信-->
|
<!--通知栏获取短信-->
|
||||||
<service
|
<service
|
||||||
android:name=".service.NotificationService"
|
android:name=".service.NotificationService"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:foregroundServiceType="specialUse"
|
||||||
android:label="通知监控"
|
android:label="通知监控"
|
||||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
|
||||||
android:priority="1000">
|
android:priority="1000">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
|
||||||
<action android:name="android.service.notification.NotificationListenerService" />
|
<action android:name="android.service.notification.NotificationListenerService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<!-- 开机自启广播接收器 -->
|
||||||
|
<receiver
|
||||||
|
android:name=".service.BootReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,46 @@
|
|||||||
package com.miraclegarden.smsmessage.service;
|
package com.miraclegarden.smsmessage.service;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.service.notification.NotificationListenerService;
|
import android.service.notification.NotificationListenerService;
|
||||||
import android.service.notification.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
import com.miraclegarden.smsmessage.Activity.NotificationActivity;
|
import com.miraclegarden.smsmessage.Activity.NotificationActivity;
|
||||||
import com.miraclegarden.smsmessage.App;
|
import com.miraclegarden.smsmessage.App;
|
||||||
import com.miraclegarden.smsmessage.MessageInfo;
|
import com.miraclegarden.smsmessage.MessageInfo;
|
||||||
|
import com.miraclegarden.smsmessage.R;
|
||||||
|
import com.miraclegarden.smsmessage.model.ApiError;
|
||||||
|
import com.miraclegarden.smsmessage.model.UploadNotificationResponse;
|
||||||
|
import com.miraclegarden.smsmessage.network.ApiService;
|
||||||
|
import com.miraclegarden.smsmessage.network.TokenManager;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.Callback;
|
import okhttp3.Callback;
|
||||||
import okhttp3.FormBody;
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
@@ -39,119 +49,291 @@ import okhttp3.Response;
|
|||||||
|
|
||||||
public class NotificationService extends NotificationListenerService {
|
public class NotificationService extends NotificationListenerService {
|
||||||
private static final String TAG = "NotificationService";
|
private static final String TAG = "NotificationService";
|
||||||
|
private static final int FOREGROUND_NOTIFICATION_ID = 9001;
|
||||||
|
private static final String CHANNEL_ID = "notification_listener_channel";
|
||||||
|
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||||
|
private static final String WAKELOCK_TAG = "NotificationService:WakeLock";
|
||||||
|
|
||||||
|
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
|
||||||
|
.connectTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private RetryManager retryManager;
|
||||||
|
private PowerManager.WakeLock wakeLock;
|
||||||
|
private static boolean isMonitoring = false;
|
||||||
|
private ApiService apiService;
|
||||||
|
private TokenManager tokenManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
createNotificationChannel();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
|
startForeground(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(0, false), ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
startForeground(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(0, false), ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
|
||||||
|
} else {
|
||||||
|
startForeground(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(0, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
apiService = new ApiService(this);
|
||||||
|
tokenManager = TokenManager.getInstance(this);
|
||||||
|
|
||||||
|
retryManager = new RetryManager(this);
|
||||||
|
retryManager.setUploadCallback(this::performUpload);
|
||||||
|
retryManager.restoreFromPersistence();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
if (intent != null && "ACTION_START_MONITORING".equals(intent.getAction())) {
|
||||||
|
startMonitoring();
|
||||||
|
}
|
||||||
NotificationActivity.sendMessage("监听服务成功!");
|
NotificationActivity.sendMessage("监听服务成功!");
|
||||||
return super.onStartCommand(intent, flags, startId);
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isMonitoring() {
|
||||||
|
return isMonitoring;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startMonitoring() {
|
||||||
|
if (isMonitoring) return;
|
||||||
|
isMonitoring = true;
|
||||||
|
|
||||||
|
toggleNotificationListenerService(this);
|
||||||
|
updateForegroundNotification(retryManager != null ? retryManager.getUploadedCount() : 0);
|
||||||
|
NotificationActivity.sendMessage("已开启持续监听模式");
|
||||||
|
NotificationActivity.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopMonitoring(Context context) {
|
||||||
|
isMonitoring = false;
|
||||||
|
NotificationActivity.sendMessage("已停止监听服务");
|
||||||
|
NotificationActivity.updateUI();
|
||||||
|
Toast.makeText(context, "监听服务已停止", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acquireWakeLockForUpload() {
|
||||||
|
if (wakeLock != null && wakeLock.isHeld()) return;
|
||||||
|
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
|
if (pm != null) {
|
||||||
|
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
|
||||||
|
wakeLock.acquire(30_000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseWakeLockAfterUpload() {
|
||||||
|
if (wakeLock != null && wakeLock.isHeld()) {
|
||||||
|
wakeLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void requestStartMonitoring(Context context) {
|
||||||
|
toggleNotificationListenerService(context);
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(context, NotificationService.class);
|
||||||
|
intent.setAction("ACTION_START_MONITORING");
|
||||||
|
context.startService(intent);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "启动监听失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNotificationPosted(StatusBarNotification sbn) {
|
public void onNotificationPosted(StatusBarNotification sbn) {
|
||||||
getSbnByNotificatinList(sbn);
|
if (sbn == null) return;
|
||||||
|
|
||||||
}
|
if (sbn.getPackageName().equals(getPackageName())) return;
|
||||||
|
|
||||||
public void getSbnByNotificatinList(StatusBarNotification sbn) {
|
|
||||||
MessageInfo messageInfo = App.getMessageByNotiList(this, sbn.getPackageName());
|
MessageInfo messageInfo = App.getMessageByNotiList(this, sbn.getPackageName());
|
||||||
if (messageInfo != null) {
|
if (messageInfo == null) return;
|
||||||
initData(messageInfo, sbn);
|
|
||||||
|
NotificationExtractor.Result result = NotificationExtractor.extract(sbn);
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(result.title) && TextUtils.isEmpty(result.content)) {
|
||||||
|
NotificationActivity.sendMessage("[" + messageInfo.getAppName() + "] 通知内容为空,跳过");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.title.contains("正在运行") || result.title.contains("正在监听")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationActivity.sendMessage(result.title + " " + result.content);
|
||||||
|
submitNotification(messageInfo, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String text = "";
|
private void submitNotification(MessageInfo messageInfo, NotificationExtractor.Result result) {
|
||||||
|
// 检查是否已登录
|
||||||
private void initData(MessageInfo messageInfo, StatusBarNotification sbn) {
|
if (!tokenManager.isLoggedIn()) {
|
||||||
Bundle bundle = sbn.getNotification().extras;
|
NotificationActivity.sendMessage("未登录,请先登录");
|
||||||
String title = bundle.getString(Notification.EXTRA_TITLE, "获取标题失败!");
|
return;
|
||||||
String context = bundle.getString(Notification.EXTRA_TEXT, "获取内容失败!");
|
|
||||||
if (context.equals("获取内容失败!")) {
|
|
||||||
if (sbn.getNotification().tickerText != null) {
|
|
||||||
context = sbn.getNotification().tickerText.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
NotificationActivity.sendMessage(title + " " + context);
|
|
||||||
if (!text.equals(context)) {
|
// 检查是否关联了银行账户
|
||||||
if (!title.equals("获取标题失败!") && !context.equals("获取内容失败!") && !title.contains("正在运行")) {
|
if (TextUtils.isEmpty(messageInfo.getBankInfoId())) {
|
||||||
NotificationActivity.sendMessage("准备发送服务器:成功");
|
NotificationActivity.sendMessage("该应用未关联银行账户,请先配置");
|
||||||
Submit(messageInfo,title, context);
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
|
||||||
|
|
||||||
public void Submit(MessageInfo messageInfo,String title, String context) {
|
|
||||||
OkHttpClient client = new OkHttpClient();
|
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences("server", MODE_PRIVATE);
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
// 根据文档,bankInfoId 是建议字段
|
||||||
|
jsonObject.put("bankInfoId", messageInfo.getBankInfoId());
|
||||||
|
|
||||||
|
// data 字段包含通知内容
|
||||||
|
JSONObject dataObject = new JSONObject();
|
||||||
|
dataObject.put("title", result.title);
|
||||||
|
dataObject.put("context", result.content);
|
||||||
|
dataObject.put("timestamp", result.timestamp);
|
||||||
|
jsonObject.put("data", dataObject);
|
||||||
|
|
||||||
|
// 保留原有字段用于兼容性
|
||||||
jsonObject.put("name", messageInfo.getName());
|
jsonObject.put("name", messageInfo.getName());
|
||||||
jsonObject.put("code", messageInfo.getCode());
|
jsonObject.put("code", messageInfo.getCode());
|
||||||
jsonObject.put("remark", messageInfo.getRemark());
|
jsonObject.put("remark", messageInfo.getRemark());
|
||||||
jsonObject.put("appName", messageInfo.getAppName());
|
jsonObject.put("appName", messageInfo.getAppName());
|
||||||
jsonObject.put("packageName", messageInfo.getPackageName());
|
jsonObject.put("packageName", messageInfo.getPackageName());
|
||||||
|
|
||||||
JSONObject jsonObject1 = new JSONObject();
|
String payload = jsonObject.toString();
|
||||||
jsonObject1.put("title", title+System.currentTimeMillis());
|
NotificationActivity.sendMessage("准备发送服务器:成功");
|
||||||
jsonObject1.put("context", context+System.currentTimeMillis());
|
retryManager.enqueue(payload);
|
||||||
jsonObject.put("data", jsonObject1);
|
|
||||||
|
|
||||||
String json = jsonObject.toString();
|
|
||||||
|
|
||||||
RequestBody body = RequestBody.create(json, JSON);
|
|
||||||
|
|
||||||
// 构建请求
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(sharedPreferences.getString("host", ""))
|
|
||||||
.post(body)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
client.newCall(request).enqueue(new Callback() {
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
|
||||||
NotificationActivity.sendMessage("提交失败:" + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
|
||||||
if (response.isSuccessful()) {
|
|
||||||
String str = response.body().string();
|
|
||||||
NotificationActivity.sendMessage(title + "提交成功:" + str);
|
|
||||||
text = context;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NotificationActivity.sendMessage("提交失败:");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
throw new RuntimeException(e);
|
Log.e(TAG, "JSON构建失败", e);
|
||||||
|
NotificationActivity.sendMessage("JSON构建失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void performUpload(String jsonPayload, RetryManager.UploadResultListener listener) {
|
||||||
* 监听断开
|
acquireWakeLockForUpload();
|
||||||
*/
|
|
||||||
|
// 使用新的API服务上传
|
||||||
|
apiService.uploadNotification(jsonPayload, new ApiService.ApiCallback<UploadNotificationResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(UploadNotificationResponse result) {
|
||||||
|
releaseWakeLockAfterUpload();
|
||||||
|
String message = "提交成功";
|
||||||
|
if (result.getId() != null) {
|
||||||
|
message += " (ID: " + result.getId().substring(0, Math.min(8, result.getId().length())) + "...)";
|
||||||
|
}
|
||||||
|
if (result.getDuplicateOfEmailSyncRecordId() != null) {
|
||||||
|
message += " [已去重]";
|
||||||
|
}
|
||||||
|
NotificationActivity.sendMessage(message);
|
||||||
|
listener.onSuccess();
|
||||||
|
updateForegroundNotification(retryManager.getUploadedCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ApiError error) {
|
||||||
|
releaseWakeLockAfterUpload();
|
||||||
|
String errorMsg = error.getMessage();
|
||||||
|
if (error.isTokenExpired()) {
|
||||||
|
errorMsg = "登录已失效,请重新登录";
|
||||||
|
tokenManager.clear();
|
||||||
|
}
|
||||||
|
NotificationActivity.sendMessage("提交失败: " + errorMsg);
|
||||||
|
listener.onFailure(errorMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onListenerDisconnected() {
|
public void onListenerDisconnected() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
Log.w(TAG, "通知监听断开,尝试恢复");
|
||||||
// 通知侦听器断开连接 - 请求重新绑定
|
NotificationActivity.sendMessage("通知监听断开,尝试恢复...");
|
||||||
requestRebind(new ComponentName(this, NotificationListenerService.class));
|
toggleNotificationListenerService(this);
|
||||||
|
|
||||||
|
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||||
|
if (!isNotificationListenerEnabled()) {
|
||||||
|
notifyNlsDisabled();
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNotificationListenerEnabled() {
|
||||||
|
String flat = Settings.Secure.getString(
|
||||||
|
getContentResolver(),
|
||||||
|
"enabled_notification_listeners");
|
||||||
|
if (TextUtils.isEmpty(flat)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return flat.contains(getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyNlsDisabled() {
|
||||||
|
Log.w(TAG, "通知监听已被禁用,向用户发出警告");
|
||||||
|
NotificationActivity.sendMessage("警告:通知监听已被禁用,请重新开启!");
|
||||||
|
|
||||||
|
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
isMonitoring = false;
|
||||||
|
NotificationActivity.updateUI();
|
||||||
|
if (wakeLock != null && wakeLock.isHeld()) {
|
||||||
|
wakeLock.release();
|
||||||
|
wakeLock = null;
|
||||||
|
}
|
||||||
|
if (retryManager != null) {
|
||||||
|
retryManager.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param context 反正第二次启动失败
|
|
||||||
*/
|
|
||||||
public static void toggleNotificationListenerService(Context context) {
|
public static void toggleNotificationListenerService(Context context) {
|
||||||
|
ComponentName thisComponent = new ComponentName(context, NotificationService.class);
|
||||||
PackageManager pm = context.getPackageManager();
|
PackageManager pm = context.getPackageManager();
|
||||||
pm.setComponentEnabledSetting(new ComponentName(context, NotificationService.class),
|
pm.setComponentEnabledSetting(thisComponent,
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||||
|
PackageManager.DONT_KILL_APP);
|
||||||
pm.setComponentEnabledSetting(new ComponentName(context, NotificationService.class),
|
pm.setComponentEnabledSetting(thisComponent,
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
|
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||||
|
PackageManager.DONT_KILL_APP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createNotificationChannel() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
NotificationChannel channel = new NotificationChannel(
|
||||||
|
CHANNEL_ID,
|
||||||
|
"通知监听服务",
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
);
|
||||||
|
channel.setDescription("保持通知监听服务运行");
|
||||||
|
channel.setShowBadge(false);
|
||||||
|
NotificationManager nm = getSystemService(NotificationManager.class);
|
||||||
|
if (nm != null) {
|
||||||
|
nm.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Notification buildForegroundNotification(int uploadedCount, boolean monitoring) {
|
||||||
|
String title = monitoring ? "持续监听中" : "通知监听服务";
|
||||||
|
String text = monitoring
|
||||||
|
? "已上传 " + uploadedCount + " 条 · 持续运行中"
|
||||||
|
: "已上传 " + uploadedCount + " 条";
|
||||||
|
|
||||||
|
return new NotificationCompat.Builder(this, CHANNEL_ID)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(text)
|
||||||
|
.setSmallIcon(R.mipmap.app_logo)
|
||||||
|
.setOngoing(true)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateForegroundNotification(int uploadedCount) {
|
||||||
|
NotificationManager nm = getSystemService(NotificationManager.class);
|
||||||
|
if (nm != null) {
|
||||||
|
nm.notify(FOREGROUND_NOTIFICATION_ID, buildForegroundNotification(uploadedCount, isMonitoring));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user