feat: 添加原生通知监听功能,自动同步通知和交易列表

This commit is contained in:
2025-11-28 10:55:03 +08:00
parent cc2c376e9d
commit a2c5525a2e
8 changed files with 1271 additions and 15 deletions

View File

@@ -17,6 +17,17 @@ android {
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
}
}
// <20><>ʽͳһ Java / Kotlin <20>ı<EFBFBD><C4B1><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Capacitor <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>£<EFBFBD>Java 21<32><31>
compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
kotlinOptions {
jvmTarget = '21'
}
buildTypes {
release {
minifyEnabled false
@@ -41,4 +52,4 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
apply from: 'capacitor.build.gradle'
apply from: 'capacitor.build.gradle'

View File

@@ -2,5 +2,9 @@
{
"pkg": "@capacitor-community/sqlite",
"classpath": "com.getcapacitor.community.database.sqlite.CapacitorSQLitePlugin"
},
{
"pkg": "@capacitor/app",
"classpath": "com.capacitorjs.plugins.app.AppPlugin"
}
]

View File

@@ -1,17 +1,46 @@
package com.echo.app.notification
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.core.app.NotificationManagerCompat
import com.getcapacitor.JSArray
import com.getcapacitor.JSObject
import com.getcapacitor.Plugin
import com.getcapacitor.PluginCall
import com.getcapacitor.annotation.CapacitorPlugin
import com.getcapacitor.PluginMethod
import com.getcapacitor.annotation.CapacitorPlugin
// Capacitor <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>˱<EFBFBD>¶֪ͨȨ<D6AA>޼<EFBFBD><DEBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>д<EFBFBD><EFBFBD>??
// Capacitor <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>˱<EFBFBD>¶֪ͨȨ<D6AA>޼<EFBFBD><DEBC><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
@CapacitorPlugin(name = "NotificationBridge")
class NotificationBridgePlugin : Plugin() {
private var notificationPostedReceiver: BroadcastReceiver? = null
override fun load() {
super.load()
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> NotificationBridgeService <20><>Ӧ<EFBFBD><D3A6><EFBFBD>ڹ㲥<DAB9><E3B2A5><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ JS <20>¼<EFBFBD>
val filter = IntentFilter("com.echo.app.NOTIFICATION_POSTED")
notificationPostedReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val payload = JSObject()
payload.put("id", intent.getStringExtra("id"))
notifyListeners("notificationPosted", payload)
}
}
context.registerReceiver(notificationPostedReceiver, filter)
}
override fun handleOnDestroy() {
notificationPostedReceiver?.let { receiver ->
context.unregisterReceiver(receiver)
}
notificationPostedReceiver = null
super.handleOnDestroy()
}
@PluginMethod
fun hasPermission(call: PluginCall) {
val enabled = NotificationManagerCompat.getEnabledListenerPackages(context)
@@ -23,7 +52,7 @@ class NotificationBridgePlugin : Plugin() {
@PluginMethod
fun requestPermission(call: PluginCall) {
// <20><><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ǰ״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> App <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>
// <20><>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
hasPermission(call)
}
@@ -51,4 +80,4 @@ class NotificationBridgePlugin : Plugin() {
NotificationStorage.clear(context)
call.resolve()
}
}
}

View File

@@ -1,6 +1,7 @@
package com.echo.app.notification
import android.app.Notification
import android.content.Intent
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import java.text.SimpleDateFormat
@@ -9,7 +10,7 @@ import java.util.Locale
import java.util.TimeZone
import org.json.JSONObject
// Android ֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>񣺰<EFBFBD>ϵͳ֪ͨת<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Echo <20><><EFBFBD><EFBFBD><EFBFBD>ѵ<EFBFBD> JSON <20><>д<EFBFBD><EFBFBD>ض<EFBFBD><D8B6><EFBFBD>
// Android notification listener: persist notifications to local storage and notify app via broadcast
class NotificationBridgeService : NotificationListenerService() {
override fun onNotificationPosted(sbn: StatusBarNotification) {
val notification = sbn.notification ?: return
@@ -22,11 +23,11 @@ class NotificationBridgeService : NotificationListenerService() {
val builder = StringBuilder()
fun appendValue(value: CharSequence?) {
val safe = value?.toString()?.takeIf { it.isNotBlank() }
if (!safe.isNullOrEmpty()) {
if (builder.isNotEmpty()) builder.append(' ')
builder.append(safe)
}
val safe = value?.toString()?.takeIf { it.isNotBlank() }
if (!safe.isNullOrEmpty()) {
if (builder.isNotEmpty()) builder.append(' ')
builder.append(safe)
}
}
appendValue(text)
@@ -34,14 +35,22 @@ class NotificationBridgeService : NotificationListenerService() {
appendValue(subText)
lines?.forEach { appendValue(it) }
val id = sbn.key ?: sbn.id.toString()
val payload = JSONObject()
payload.put("id", sbn.key ?: sbn.id.toString())
payload.put("id", id)
payload.put("channel", title ?: sbn.packageName)
payload.put("text", if (builder.isNotEmpty()) builder.toString() else text.orEmpty())
payload.put("createdAt", isoNow())
payload.put("packageName", sbn.packageName)
// Persist notification in local queue for JS side to fetch via NotificationBridge
NotificationStorage.add(applicationContext, payload)
// Broadcast an in-app event so the Capacitor plugin can notify JS listeners
val intent = Intent("com.echo.app.NOTIFICATION_POSTED")
intent.setPackage(packageName)
intent.putExtra("id", id)
sendBroadcast(intent)
}
override fun onNotificationRemoved(sbn: StatusBarNotification) {
@@ -53,4 +62,4 @@ class NotificationBridgeService : NotificationListenerService() {
formatter.timeZone = TimeZone.getTimeZone("UTC")
return formatter.format(Date())
}
}
}