diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bdcf39e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.trae/
diff --git a/Kiosk/android/app/src/main/AndroidManifest.xml b/Kiosk/android/app/src/main/AndroidManifest.xml
index 7937524..8748df4 100644
--- a/Kiosk/android/app/src/main/AndroidManifest.xml
+++ b/Kiosk/android/app/src/main/AndroidManifest.xml
@@ -7,6 +7,14 @@
android:label="kiosk"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
+
+
+
+
+
+ when (call.method) {
+ "isNotificationListenerEnabled" -> result.success(isNotificationListenerEnabled())
+ "getAlipayNotificationState" -> result.success(getAlipayNotificationState())
+ "getLatestAlipayNotification" -> result.success(getLatestAlipayNotification())
+ "getLatestAlipayPaymentNotification" -> result.success(getLatestAlipayPaymentNotification())
+ "getActiveAlipayNotificationsSnapshot" -> result.success(getActiveAlipayNotificationsSnapshot())
+ "getWechatNotificationState" -> result.success(getWechatNotificationState())
+ "getLatestWechatNotification" -> result.success(getLatestWechatNotification())
+ "getLatestWechatPaymentNotification" -> result.success(getLatestWechatPaymentNotification())
+ "getActiveWechatNotificationsSnapshot" -> result.success(getActiveWechatNotificationsSnapshot())
+ "openNotificationListenerSettings" -> {
+ startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+ result.success(true)
+ }
+ else -> result.notImplemented()
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: android.os.Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ receiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ when (intent.action) {
+ SecgoNotificationListenerService.ACTION_NOTIFICATION_STATE -> {
+ val hasAlipay = intent.getBooleanExtra(SecgoNotificationListenerService.KEY_HAS_ALIPAY, false)
+ val hasWechat = intent.getBooleanExtra(SecgoNotificationListenerService.KEY_HAS_WECHAT, false)
+ val updatedAt = intent.getLongExtra(SecgoNotificationListenerService.KEY_UPDATED_AT_MS, 0L)
+ val latestAlipayJson = intent.getStringExtra(SecgoNotificationListenerService.KEY_LAST_ALIPAY_JSON)
+ val latestAlipayPaymentJson =
+ intent.getStringExtra(SecgoNotificationListenerService.KEY_LAST_ALIPAY_PAYMENT_JSON)
+ val latestWechatJson = intent.getStringExtra(SecgoNotificationListenerService.KEY_LAST_WECHAT_JSON)
+ val latestWechatPaymentJson =
+ intent.getStringExtra(SecgoNotificationListenerService.KEY_LAST_WECHAT_PAYMENT_JSON)
+ eventSink?.success(
+ mapOf(
+ "type" to "state",
+ "hasAlipay" to hasAlipay,
+ "hasWechat" to hasWechat,
+ "updatedAtMs" to updatedAt,
+ "alipay" to (parseJsonToMap(latestAlipayJson) ?: emptyMap()),
+ "alipayPayment" to (parseJsonToMap(latestAlipayPaymentJson) ?: emptyMap()),
+ "wechat" to (parseJsonToMap(latestWechatJson) ?: emptyMap()),
+ "wechatPayment" to (parseJsonToMap(latestWechatPaymentJson) ?: emptyMap()),
+ ),
+ )
+ }
+ SecgoNotificationListenerService.ACTION_NOTIFICATION_POSTED -> {
+ val postedJson = intent.getStringExtra(SecgoNotificationListenerService.KEY_POSTED_JSON)
+ Log.i("SecgoNotif", "ACTION_NOTIFICATION_POSTED eventSink=${eventSink != null} postedJson=${postedJson != null}")
+ eventSink?.success(
+ mapOf(
+ "type" to "posted",
+ "notification" to (parseJsonToMap(postedJson) ?: emptyMap()),
+ ),
+ )
+ }
+ else -> {
+ }
+ }
+ }
+ }
+
+ val filter =
+ IntentFilter().apply {
+ addAction(SecgoNotificationListenerService.ACTION_NOTIFICATION_STATE)
+ addAction(SecgoNotificationListenerService.ACTION_NOTIFICATION_POSTED)
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED)
+ } else {
+ @Suppress("DEPRECATION")
+ registerReceiver(receiver, filter)
+ }
+ }
+
+ override fun onDestroy() {
+ receiver?.let {
+ try {
+ unregisterReceiver(it)
+ } catch (_: Exception) {
+ }
+ }
+ receiver = null
+ super.onDestroy()
+ }
+
+ private fun isNotificationListenerEnabled(): Boolean {
+ val enabled = Settings.Secure.getString(contentResolver, "enabled_notification_listeners") ?: return false
+ return enabled.contains(packageName)
+ }
+
+ private fun getAlipayNotificationState(): Map {
+ val prefs = getSharedPreferences(SecgoNotificationListenerService.PREFS_NAME, Context.MODE_PRIVATE)
+ val hasAlipay = prefs.getBoolean(SecgoNotificationListenerService.KEY_HAS_ALIPAY, false)
+ val updatedAt = prefs.getLong(SecgoNotificationListenerService.KEY_UPDATED_AT_MS, 0L)
+ return mapOf(
+ "enabled" to isNotificationListenerEnabled(),
+ "hasAlipay" to hasAlipay,
+ "updatedAtMs" to updatedAt,
+ )
+ }
+
+ private fun getLatestAlipayNotification(): Map? {
+ val prefs = getSharedPreferences(SecgoNotificationListenerService.PREFS_NAME, Context.MODE_PRIVATE)
+ val json = prefs.getString(SecgoNotificationListenerService.KEY_LAST_ALIPAY_JSON, null) ?: return null
+ return parseJsonToMap(json)
+ }
+
+ private fun getLatestAlipayPaymentNotification(): Map? {
+ val prefs = getSharedPreferences(SecgoNotificationListenerService.PREFS_NAME, Context.MODE_PRIVATE)
+ val json = prefs.getString(SecgoNotificationListenerService.KEY_LAST_ALIPAY_PAYMENT_JSON, null) ?: return null
+ return parseJsonToMap(json)
+ }
+
+ private fun getActiveAlipayNotificationsSnapshot(): List