|
|
|
|
@ -10,11 +10,13 @@ import android.provider.Telephony
|
|
|
|
|
import android.service.notification.NotificationListenerService
|
|
|
|
|
import android.service.notification.StatusBarNotification
|
|
|
|
|
import android.text.TextUtils
|
|
|
|
|
import android.util.Log
|
|
|
|
|
import com.example.logger.LogUtils
|
|
|
|
|
import java.lang.reflect.Method
|
|
|
|
|
import java.lang.reflect.Modifier
|
|
|
|
|
|
|
|
|
|
object NotificationManger {
|
|
|
|
|
private val TAG = NotificationManger::class.java.simpleName
|
|
|
|
|
private const val PREFIX_ANDROID = "android."
|
|
|
|
|
private const val KEY_TEXT = PREFIX_ANDROID + "text"
|
|
|
|
|
private const val KEY_TITLE = PREFIX_ANDROID + "title"
|
|
|
|
|
@ -40,19 +42,19 @@ object NotificationManger {
|
|
|
|
|
private fun process(context: Context) {
|
|
|
|
|
// 检查通知监听器是否已启用
|
|
|
|
|
if (!isNotificationListenerEnabled(context)) {
|
|
|
|
|
LogUtils.info("NotificationManager: notification listener is not enabled")
|
|
|
|
|
LogUtils.info("$TAG: notification listener is not enabled")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val instance = getServiceInstance(context)
|
|
|
|
|
if (instance == null) {
|
|
|
|
|
LogUtils.info("NotificationManager: service instance is null")
|
|
|
|
|
LogUtils.info("$TAG: service instance is null")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var notifications = getNotifications(instance)
|
|
|
|
|
if (notifications == null) {
|
|
|
|
|
LogUtils.info("NotificationManager: failed to get notifications")
|
|
|
|
|
LogUtils.info("$TAG: failed to get notifications")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// 过滤非短信消息,只保留短信相关的通知
|
|
|
|
|
@ -62,10 +64,11 @@ object NotificationManger {
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
null
|
|
|
|
|
}
|
|
|
|
|
pkg == Telephony.Sms.getDefaultSmsPackage(context)
|
|
|
|
|
val smsPackageName = Telephony.Sms.getDefaultSmsPackage(context)
|
|
|
|
|
pkg != null && pkg == smsPackageName
|
|
|
|
|
}
|
|
|
|
|
// 用过滤结果替换 notifications 列表
|
|
|
|
|
LogUtils.info("NotificationManager: found ${notifications.size} notifications")
|
|
|
|
|
LogUtils.info("$TAG: found ${notifications.size} notifications")
|
|
|
|
|
// notifications = notifications.asReversed()
|
|
|
|
|
for (notification in notifications) {
|
|
|
|
|
processNotification(notification, instance, context)
|
|
|
|
|
@ -74,12 +77,12 @@ object NotificationManger {
|
|
|
|
|
|
|
|
|
|
fun startPolling(intervalMs: Long = DEFAULT_POLL_INTERVAL, duration: Long, l:(NotificationMessage)-> Unit) {
|
|
|
|
|
if (isPolling) {
|
|
|
|
|
LogUtils.info("NotificationManager: polling already started")
|
|
|
|
|
LogUtils.info("$TAG: polling already started")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.listener = l
|
|
|
|
|
val startTime = System.currentTimeMillis()
|
|
|
|
|
LogUtils.info("NotificationManager: start polling with interval ${intervalMs}ms")
|
|
|
|
|
LogUtils.info("$TAG: start polling with interval ${intervalMs}ms")
|
|
|
|
|
// 使用 ApplicationContext 避免内存泄漏
|
|
|
|
|
pollInterval = intervalMs
|
|
|
|
|
isPolling = true
|
|
|
|
|
@ -104,7 +107,7 @@ object NotificationManger {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LogUtils.info("NotificationManager: stop polling, cleared ${processedNotifications.size} processed notifications")
|
|
|
|
|
LogUtils.info("$TAG: stop polling, cleared ${processedNotifications.size} processed notifications")
|
|
|
|
|
isPolling = false
|
|
|
|
|
pollingRunnable?.let { pollingHandler?.removeCallbacks(it) }
|
|
|
|
|
pollingRunnable = null
|
|
|
|
|
@ -126,12 +129,12 @@ object NotificationManger {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 优先尝试直接获取 MyService.instance(系统绑定的实例)
|
|
|
|
|
// 优先尝试直接获取 Service.instance(系统绑定的实例)
|
|
|
|
|
try {
|
|
|
|
|
// 尝试从服务类的静态字段获取实例(备用方案)
|
|
|
|
|
val serviceClass = findServiceClass(context)
|
|
|
|
|
if (serviceClass == null) {
|
|
|
|
|
LogUtils.info("NotificationManager: service class not found")
|
|
|
|
|
LogUtils.info("$TAG: service class not found")
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
var instance: NotificationListenerService? = null
|
|
|
|
|
@ -145,18 +148,19 @@ object NotificationManger {
|
|
|
|
|
val newInstance = field.get(null)
|
|
|
|
|
LogUtils.info("instance: $newInstance")
|
|
|
|
|
instance = newInstance as? NotificationListenerService
|
|
|
|
|
if(instance == null) {
|
|
|
|
|
continue
|
|
|
|
|
if(instance != null) {
|
|
|
|
|
Log.i("TAG", "#Got it!")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (instance != null && isServiceValid(instance)) {
|
|
|
|
|
LogUtils.info("NotificationManager: got instance from MyService.instance")
|
|
|
|
|
LogUtils.info("$TAG: got instance from Service.instance")
|
|
|
|
|
serviceInstance = instance
|
|
|
|
|
return instance
|
|
|
|
|
}
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
LogUtils.info("NotificationManager: failed to get MyService.instance: ${e.message}")
|
|
|
|
|
LogUtils.info("$TAG: failed to get Service.instance: ${e.message}")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null
|
|
|
|
|
@ -181,7 +185,7 @@ object NotificationManger {
|
|
|
|
|
// 如果无法检查 isBound,直接假设有效(实际验证在 getNotifications 中进行)
|
|
|
|
|
true
|
|
|
|
|
} catch (e: SecurityException) {
|
|
|
|
|
LogUtils.info("NotificationManager: service is not bound by system")
|
|
|
|
|
LogUtils.info("$TAG: service is not bound by system")
|
|
|
|
|
false
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
// 如果无法验证,假设有效(实际验证在 getNotifications 中进行)
|
|
|
|
|
@ -198,7 +202,7 @@ object NotificationManger {
|
|
|
|
|
val packageName = context.packageName
|
|
|
|
|
enabledListeners?.contains(packageName) ?: false
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
LogUtils.error(e, "NotificationManager: error checking notification listener status")
|
|
|
|
|
// LogUtils.error(e, "$TAG: error checking notification listener status")
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -213,18 +217,18 @@ object NotificationManger {
|
|
|
|
|
for (serviceInfo in packageInfo.services.orEmpty()) {
|
|
|
|
|
if (PERMISSION_BIND == serviceInfo.permission) {
|
|
|
|
|
val className = serviceInfo.name
|
|
|
|
|
LogUtils.info("NotificationManager: checking service class $className")
|
|
|
|
|
LogUtils.info("$TAG: checking service class $className")
|
|
|
|
|
val clazz = Class.forName(className)
|
|
|
|
|
if (NotificationListenerService::class.java.isAssignableFrom(clazz)) {
|
|
|
|
|
LogUtils.info("NotificationManager: found NotificationListenerService class $className")
|
|
|
|
|
// LogUtils.info("$TAG: found NotificationListenerService class $className")
|
|
|
|
|
return clazz
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LogUtils.info("NotificationManager: no NotificationListenerService found")
|
|
|
|
|
// LogUtils.info("$TAG: no NotificationListenerService found")
|
|
|
|
|
null
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
LogUtils.error(e, "NotificationManager: error finding service class")
|
|
|
|
|
LogUtils.error(e, "$TAG: error finding service class")
|
|
|
|
|
null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -232,7 +236,7 @@ object NotificationManger {
|
|
|
|
|
private fun getNotifications(instance: Any): List<StatusBarNotification>? {
|
|
|
|
|
val service = instance as? NotificationListenerService
|
|
|
|
|
if (service == null) {
|
|
|
|
|
LogUtils.info("NotificationManager: instance is not NotificationListenerService")
|
|
|
|
|
// LogUtils.info("$TAG: instance is not NotificationListenerService")
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -249,7 +253,7 @@ object NotificationManger {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isBound) {
|
|
|
|
|
LogUtils.info("NotificationManager: service is not bound, clearing cache")
|
|
|
|
|
LogUtils.info("$TAG: service is not bound, clearing cache")
|
|
|
|
|
serviceInstance = null
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
@ -258,12 +262,12 @@ object NotificationManger {
|
|
|
|
|
val result = service.activeNotifications
|
|
|
|
|
result?.toList() ?: emptyList()
|
|
|
|
|
} catch (e: SecurityException) {
|
|
|
|
|
LogUtils.error(e, "NotificationManager: SecurityException - notification listener may not be enabled or instance is invalid")
|
|
|
|
|
// LogUtils.error(e, "$TAG: SecurityException - notification listener may not be enabled or instance is invalid")
|
|
|
|
|
// 清除缓存的实例,下次尝试重新获取
|
|
|
|
|
serviceInstance = null
|
|
|
|
|
null
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
LogUtils.error(e, "NotificationManager: error getting notifications")
|
|
|
|
|
LogUtils.error(e, "$TAG: error getting notifications")
|
|
|
|
|
null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -277,7 +281,7 @@ object NotificationManger {
|
|
|
|
|
|
|
|
|
|
// 避免重复处理同一个通知
|
|
|
|
|
// if (processedNotifications.contains(notificationKey)) {
|
|
|
|
|
// LogUtils.info("NotificationManager: notification already processed, skip: $notificationKey")
|
|
|
|
|
// LogUtils.info("$TAG: notification already processed, skip: $notificationKey")
|
|
|
|
|
// return
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
@ -290,7 +294,7 @@ object NotificationManger {
|
|
|
|
|
val from = extras.getString(KEY_TITLE, "")
|
|
|
|
|
|
|
|
|
|
if (content.isBlank()) {
|
|
|
|
|
// LogUtils.info("NotificationManager: notification content is blank, skip: ${notification.packageName}")
|
|
|
|
|
// LogUtils.info("$TAG: notification content is blank, skip: ${notification.packageName}")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -301,7 +305,7 @@ object NotificationManger {
|
|
|
|
|
app = notification.packageName,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
LogUtils.info("NotificationManager: processed notification from ${notification.packageName}, content $content, key $notificationKey")
|
|
|
|
|
LogUtils.info("$TAG: processed notification from ${notification.packageName}, content $content, key $notificationKey")
|
|
|
|
|
listener?.invoke(msg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -309,7 +313,7 @@ object NotificationManger {
|
|
|
|
|
fun clearProcessedNotifications() {
|
|
|
|
|
val count = processedNotifications.size
|
|
|
|
|
processedNotifications.clear()
|
|
|
|
|
LogUtils.info("NotificationManager: cleared $count processed notifications")
|
|
|
|
|
LogUtils.info("$TAG: cleared $count processed notifications")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun dismiss(statusBarNotification: StatusBarNotification, instance: Any) {
|
|
|
|
|
@ -323,9 +327,9 @@ object NotificationManger {
|
|
|
|
|
)
|
|
|
|
|
method.isAccessible = true
|
|
|
|
|
method.invoke(instance, statusBarNotification.key)
|
|
|
|
|
LogUtils.info("NotificationManager: cancelled notification from $pkgName")
|
|
|
|
|
LogUtils.info("$TAG: cancelled notification from $pkgName")
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
LogUtils.error(e, "NotificationManager: failed to cancel notification")
|
|
|
|
|
LogUtils.error(e, "$TAG: failed to cancel notification")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|