feat(push): 通知点击事件通过回调给 App,不在 SDK 内解析业务逻辑
- 新增 PushNotificationClickEvent(vendor/title/content/params/skipContent) - PushSDK.setNotificationClickListener 供 App 注册通知点击回调 - PushSDK.dispatchNotificationClick(internal):触发回调 + 启动宿主 Activity 携带原始 extras(EXTRA_PUSH_PARAMS/EXTRA_PUSH_SKIP_CONTENT/EXTRA_PUSH_VENDOR), 冷启动场景由 App 自行从 Intent extras 解析 - XuqmVivoPushReceiver 仅负责把 UPSNotificationMessage 转为 event 后分发, 不做任何业务层解析(URL 跳转逻辑由 App 实现) - 删除 PushDeepLinkHandler(职责越界) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
f63ae07bcb
当前提交
fc43885f1e
@ -1,20 +0,0 @@
|
||||
package com.xuqm.sdk.push
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
|
||||
object PushDeepLinkHandler {
|
||||
|
||||
const val EXTRA_PUSH_URL = "xuqm_push_url"
|
||||
private const val TAG = "PushDeepLinkHandler"
|
||||
|
||||
fun open(context: Context, url: String) {
|
||||
val pm = context.packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(context.packageName) ?: return
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
intent.putExtra(EXTRA_PUSH_URL, url)
|
||||
Log.d(TAG, "Opening app with push URL: $url")
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import com.xuqm.sdk.push.model.PushNotificationClickEvent
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
object PushSDK {
|
||||
@ -37,9 +38,27 @@ object PushSDK {
|
||||
private val lastRegisteredDeviceKey = AtomicReference<String?>(null)
|
||||
@Volatile private var cachedVendorConfig: PushVendorConfig? = null
|
||||
@Volatile private var cachedConfigAt: Long = 0L
|
||||
@Volatile private var notificationClickListener: ((PushNotificationClickEvent) -> Unit)? = null
|
||||
|
||||
/** 推送通知点击 Intent extras 的键:原始 params JSON */
|
||||
const val EXTRA_PUSH_PARAMS = "xuqm_push_params"
|
||||
/** 推送通知点击 Intent extras 的键:skipContent */
|
||||
const val EXTRA_PUSH_SKIP_CONTENT = "xuqm_push_skip_content"
|
||||
/** 推送通知点击 Intent extras 的键:厂商名 */
|
||||
const val EXTRA_PUSH_VENDOR = "xuqm_push_vendor"
|
||||
|
||||
// ── Public API (spec-aligned) ──────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 注册推送通知点击回调。
|
||||
* App 在运行时会通过此回调收到通知点击事件;
|
||||
* 若 App 未运行(冷启动),通知数据通过 Intent extras 传递到启动 Activity。
|
||||
* Intent extras 键:[EXTRA_PUSH_PARAMS]、[EXTRA_PUSH_SKIP_CONTENT]、[EXTRA_PUSH_VENDOR]。
|
||||
*/
|
||||
fun setNotificationClickListener(listener: ((PushNotificationClickEvent) -> Unit)?) {
|
||||
notificationClickListener = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置离线推送开关。
|
||||
* 关闭后用户不会收到离线推送,但在线消息仍正常接收。
|
||||
@ -91,6 +110,27 @@ object PushSDK {
|
||||
fun notificationChannelIdFor(context: Context, routeType: String): String? =
|
||||
PushNotificationChannelManager.channelIdFor(context.applicationContext, routeType)
|
||||
|
||||
// ── Internal notification click dispatch ──────────────────────────────────
|
||||
|
||||
/**
|
||||
* 由各厂商 Receiver 在通知被点击时调用。
|
||||
* 优先触发已注册的 [notificationClickListener](App 在前台/后台均有效);
|
||||
* 同时启动宿主 App,携带原始 params extras 供冷启动场景下读取。
|
||||
*/
|
||||
internal fun dispatchNotificationClick(context: Context, event: PushNotificationClickEvent) {
|
||||
Log.d("XuqmPushSDK", "Notification clicked: vendor=${event.vendor}, params=${event.params}")
|
||||
notificationClickListener?.invoke(event)
|
||||
val pm = context.packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(context.packageName) ?: return
|
||||
intent.flags = android.content.Intent.FLAG_ACTIVITY_NEW_TASK or android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
intent.putExtra(EXTRA_PUSH_VENDOR, event.vendor.name)
|
||||
intent.putExtra(EXTRA_PUSH_SKIP_CONTENT, event.skipContent)
|
||||
if (event.params.isNotEmpty()) {
|
||||
intent.putExtra(EXTRA_PUSH_PARAMS, HashMap(event.params))
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
// ── Internal hooks called by XuqmSDK via reflection ───────────────────────
|
||||
|
||||
fun onSdkLogin(session: XuqmLoginSession) {
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
package com.xuqm.sdk.push.model
|
||||
|
||||
data class PushNotificationClickEvent(
|
||||
val vendor: PushVendor,
|
||||
val title: String?,
|
||||
val content: String?,
|
||||
val params: Map<String, String>,
|
||||
val skipContent: String?,
|
||||
)
|
||||
@ -1,13 +1,12 @@
|
||||
package com.xuqm.sdk.push.vivo
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import com.vivo.push.model.UnvarnishedMessage
|
||||
import com.vivo.push.model.UPSNotificationMessage
|
||||
import com.vivo.push.sdk.OpenClientPushMessageReceiver
|
||||
import com.xuqm.sdk.push.PushDeepLinkHandler
|
||||
import com.xuqm.sdk.push.PushSDK
|
||||
import com.xuqm.sdk.push.model.PushNotificationClickEvent
|
||||
import com.xuqm.sdk.push.model.PushVendor
|
||||
|
||||
class XuqmVivoPushReceiver : OpenClientPushMessageReceiver() {
|
||||
@ -27,12 +26,14 @@ class XuqmVivoPushReceiver : OpenClientPushMessageReceiver() {
|
||||
}
|
||||
|
||||
override fun onNotificationMessageClicked(context: Context, message: UPSNotificationMessage) {
|
||||
val url = message.params?.get("url")?.takeIf { it.isNotBlank() }
|
||||
?: message.skipContent?.takeIf { it.isNotBlank() }
|
||||
Log.d(TAG, "Vivo notification clicked: ${message.title}, url=$url")
|
||||
if (url != null) {
|
||||
PushDeepLinkHandler.open(context, url)
|
||||
}
|
||||
val event = PushNotificationClickEvent(
|
||||
vendor = PushVendor.VIVO,
|
||||
title = message.title,
|
||||
content = message.content,
|
||||
params = message.params?.toMap() ?: emptyMap(),
|
||||
skipContent = message.skipContent,
|
||||
)
|
||||
PushSDK.dispatchNotificationClick(context, event)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户