6.7.0 - Alpha18 - 读取通知权限支持自动重连机制 (requestRebind) 以增强通知监听相关功能的稳定性

This commit is contained in:
SuperMonster003
2026-01-28 18:11:45 +08:00
parent 6e6d288c34
commit 2f223d1d67
5 changed files with 73 additions and 5 deletions

View File

@@ -1,13 +1,17 @@
package org.autojs.autojs.core.notification
import android.content.ComponentName
import android.content.Context
import android.provider.Settings
import android.service.notification.StatusBarNotification
import org.autojs.autojs.core.accessibility.NotificationListener
import java.util.concurrent.CopyOnWriteArrayList
import android.service.notification.NotificationListenerService as AndroidNotificationListenerService
/**
* Created by Stardust on Oct 30, 2017.
*/
class NotificationListenerService : android.service.notification.NotificationListenerService() {
class NotificationListenerService : AndroidNotificationListenerService() {
private val mNotificationListeners = CopyOnWriteArrayList<NotificationListener>()
@@ -44,8 +48,31 @@ class NotificationListenerService : android.service.notification.NotificationLis
}
companion object {
@JvmStatic
var instance: NotificationListenerService? = null
private set
@JvmStatic
fun isNotificationListenerEnabled(context: Context): Boolean {
val enabled = Settings.Secure.getString(
context.contentResolver,
"enabled_notification_listeners",
) ?: return false
val cn = ComponentName(context, NotificationListenerService::class.java).flattenToString()
return enabled.contains(cn)
}
@JvmStatic
fun requestRebindIfPossible(context: Context): Boolean {
if (!isNotificationListenerEnabled(context)) return false
return runCatching {
val cn = ComponentName(context, NotificationListenerService::class.java)
requestRebind(cn)
true
}.isSuccess
}
}
}

View File

@@ -40,6 +40,8 @@ import java.util.Set;
/**
* Created by Stardust on Jul 18, 2017.
* Modified by JetBrains AI Assistant (GPT-5.2) as of Jan 28, 2026.
* Modified by SuperMonster003 as of Jan 28, 2026.
*/
public class Events extends EventEmitter implements OnKeyListener, TouchObserver.OnTouchEventListener, NotificationListener, AccessibilityNotificationObserver.ToastListener, AccessibilityService.Companion.GestureListener {
@@ -72,8 +74,14 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
private boolean mListeningKey = false;
private final Loopers mLoopers;
private Handler mHandler;
private boolean mListeningNotification = false;
private boolean mListeningToast = false;
private int mNotificationBindRetryCount = 0;
private static final int NOTIFICATION_BIND_MAX_RETRY = 5;
private static final long NOTIFICATION_BIND_RETRY_DELAY_MS = 400L;
private final ScriptRuntime mScriptRuntime;
private volatile boolean mInterceptsAllKey = false;
private KeyInterceptor mKeyInterceptor;
@@ -237,21 +245,53 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
mListeningNotification = true;
ensureHandler();
mLoopers.waitWhenIdle(true);
if (NotificationListenerService.getInstance() != null) {
NotificationListenerService.getInstance().addListener(this);
return;
}
// Permission enabled but service not bound (common on some ROMs): try to rebind automatically.
// zh-CN: 权限已启用但服务未绑定 (在某些 ROM 上常见): 尝试自动重新绑定.
if (NotificationListenerService.isNotificationListenerEnabled(mContext)) {
mNotificationBindRetryCount = 0;
NotificationListenerService.requestRebindIfPossible(mContext);
retryAttachNotificationListener();
return;
}
// Permission not enabled: guide user to settings page.
// zh-CN: 权限未启用: 引导用户前往设置页面.
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
IntentUtils.startSafely(intent, mContext);
throw new ScriptException(mContext.getString(R.string.text_notification_service_disabled));
}
private void retryAttachNotificationListener() {
if (!mListeningNotification) {
return;
}
if (NotificationListenerService.getInstance() != null) {
NotificationListenerService.getInstance().addListener(this);
return;
}
if (mNotificationBindRetryCount++ >= NOTIFICATION_BIND_MAX_RETRY) {
// Still not bound: last resort, open settings page to let user re-toggle.
// zh-CN: 仍未绑定: 最后的手段, 打开设置页面让用户重新切换.
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
IntentUtils.startSafely(intent, mContext);
return;
}
mHandler.postDelayed(this::retryAttachNotificationListener, NOTIFICATION_BIND_RETRY_DELAY_MS);
}
public void removeNotificationObserver() {
mAccessibilityBridge.getNotificationObserver().removeNotificationListener(this);
if (NotificationListenerService.getInstance() != null) {
NotificationListenerService.getInstance().removeListener(this);
}
mListeningNotification = false;
mNotificationBindRetryCount = 0;
if (!mListeningToast) {
mLoopers.waitWhenIdle(false);
}

View File

@@ -10,7 +10,7 @@ import org.autojs.autojs.util.IntentUtils.startSafely
class NotificationService(override val context: Context) : ServiceItemHelper {
override val isRunning: Boolean
get() = NotificationListenerService.instance != null
get() = NotificationListenerService.isNotificationListenerEnabled(context)
override fun start(): Boolean = false.also { config() }