feat(push): 添加多厂商推送集成支持

- 实现了华为 HMS 推送服务集成
- 实现了小米推送服务集成
- 实现了 OPPO 推送服务集成
- 实现了 vivo 推送服务集成
- 实现了荣耀推送服务集成
- 实现了 FCM 推送服务集成
- 添加了统一的厂商推送接口和检测机制
- 添加了推送配置 API 和存储管理
- 添加了推送令牌管理和设备注册功能
- 添加了模拟器环境的推送测试用例
这个提交包含在:
XuqmGroup 2026-05-05 17:54:59 +08:00
父节点 19e7b27d6e
当前提交 ea693d5c66
共有 21 个文件被更改,包括 698 次插入98 次删除

查看文件

@ -76,8 +76,11 @@ class PushSdkTest {
val expected = when (manufacturer) { val expected = when (manufacturer) {
"HUAWEI" -> PushVendor.HUAWEI "HUAWEI" -> PushVendor.HUAWEI
"XIAOMI" -> PushVendor.XIAOMI "XIAOMI" -> PushVendor.XIAOMI
"REDMI", "POCO" -> PushVendor.XIAOMI
"OPPO" -> PushVendor.OPPO "OPPO" -> PushVendor.OPPO
"REALME", "ONEPLUS" -> PushVendor.OPPO
"VIVO" -> PushVendor.VIVO "VIVO" -> PushVendor.VIVO
"IQOO" -> PushVendor.VIVO
"HONOR" -> PushVendor.HONOR "HONOR" -> PushVendor.HONOR
else -> PushVendor.FCM else -> PushVendor.FCM
} }
@ -102,11 +105,17 @@ class PushSdkTest {
// 1. initializeVendors 不应抛出任何异常 // 1. initializeVendors 不应抛出任何异常
PushSDK.initializeVendors(appCtx) PushSDK.initializeVendors(appCtx)
// 2. 模拟器上 FCM token 通常为 null // 2. 模拟器上 FCM token 通常为 null;真机只校验厂商映射和流程不崩溃
val reg = PushSDK.currentRegistration(appCtx)
val vendor = PushSDK.detectVendor() val vendor = PushSDK.detectVendor()
// 不做 pushToken 非空断言emulator 无 Firebase,仅验证 vendor 正确 val expected = when (Build.MANUFACTURER.uppercase()) {
assertEquals("模拟器应检测到 FCM", PushVendor.FCM, vendor) "HUAWEI" -> PushVendor.HUAWEI
"XIAOMI", "REDMI", "POCO" -> PushVendor.XIAOMI
"OPPO", "REALME", "ONEPLUS" -> PushVendor.OPPO
"VIVO", "IQOO" -> PushVendor.VIVO
"HONOR" -> PushVendor.HONOR
else -> PushVendor.FCM
}
assertEquals("MANUFACTURER=${Build.MANUFACTURER} 应检测到 $expected", expected, vendor)
// 3. setReceivePush 调用不应崩溃 // 3. setReceivePush 调用不应崩溃
PushSDK.setReceivePush(appCtx, USER_A, enabled = false) PushSDK.setReceivePush(appCtx, USER_A, enabled = false)

查看文件

@ -11,6 +11,9 @@ android {
defaultConfig { defaultConfig {
minSdk = libs.versions.minSdk.get().toInt() minSdk = libs.versions.minSdk.get().toInt()
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
manifestPlaceholders["XUQM_VIVO_APP_ID"] = ""
manifestPlaceholders["XUQM_VIVO_APP_KEY"] = ""
manifestPlaceholders["XUQM_HONOR_APP_ID"] = ""
} }
compileOptions { compileOptions {
@ -25,14 +28,12 @@ android {
dependencies { dependencies {
api(project(":sdk-core")) api(project(":sdk-core"))
api(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
implementation(platform(libs.firebase.bom)) implementation(platform(libs.firebase.bom))
implementation(libs.firebase.messaging) implementation(libs.firebase.messaging)
api("com.huawei.hms:push:6.12.0.300")
// Optional vendor push SDKs — add the ones you need in your app module. api("com.hihonor.mcs:push:7.0.41.301")
// These are NOT declared here because they require proprietary Maven repos: api("io.github.hebeiliang.mipush:Push:2.0.0")
// Huawei: com.huawei.hms:push (via Huawei Maven repo) api("com.umeng.umsdk:oppo-push:3.0.0")
// Xiaomi: com.xiaomi.mipush:mipush (via Xiaomi Maven repo) api("com.umeng.umsdk:vivo-push:4.0.6.0")
// OPPO: com.heytap.mcs:push (via OPPO Maven repo)
// vivo: com.vivo.pushsdk:pushsdk (via vivo Maven repo)
// Honor: com.hihonor.mcs:push (via Honor Maven repo)
} }

查看文件

@ -9,6 +9,10 @@
# ── Firebase Messaging Service Android resolves it by class name ──────────── # ── Firebase Messaging Service Android resolves it by class name ────────────
-keep class com.xuqm.sdk.push.fcm.XuqmFirebaseMessagingService { *; } -keep class com.xuqm.sdk.push.fcm.XuqmFirebaseMessagingService { *; }
-keep class com.xuqm.sdk.push.huawei.XuqmHuaweiPushService { *; }
-keep class com.xuqm.sdk.push.honor.XuqmHonorPushService { *; }
-keep class com.xuqm.sdk.push.vivo.XuqmVivoPushReceiver { *; }
-keep class com.xuqm.sdk.push.xiaomi.XuqmXiaomiPushReceiver { *; }
# ── Vendor push services instantiated via reflection inside PushSDK ───────── # ── Vendor push services instantiated via reflection inside PushSDK ─────────
-keep class com.xuqm.sdk.push.vendor.** { *; } -keep class com.xuqm.sdk.push.vendor.** { *; }

20
sdk-push/libs/README.md 普通文件
查看文件

@ -0,0 +1,20 @@
Vendor push SDK binaries can live here when a vendor only provides a console
download.
The Xuqm push SDK owns the vendor dependency graph. Huawei, Honor, Xiaomi,
OPPO, and vivo dependencies are declared by `sdk-push/build.gradle.kts`, so app
integrators do not need to add vendor SDKs themselves.
If a vendor SDK must be pinned to an official console-only binary for a tenant,
put the vendor `*.aar` or `*.jar` here before publishing the Xuqm push SDK.
Those binaries are picked up by `api(fileTree(...))`.
Xiaomi's official current AAR download page requires a Xiaomi Push console login
session. If an app must use that exact official package, download it from the
tenant's Xiaomi console and publish this SDK with the AAR in this directory.
`sdk-push` owns the Android manifest integration: permissions, push services,
notification click activity, vendor receivers and metadata placeholders are
declared in `src/main/AndroidManifest.xml`. Host apps should integrate the Xuqm
push SDK; vendor credentials are loaded from the tenant platform when the vendor
SDK supports runtime configuration.

查看文件

@ -1,6 +1,50 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.coloros.mcs.permission.RECIEVE_MCS_MESSAGE" />
<uses-permission android:name="com.heytap.mcs.permission.RECIEVE_MCS_MESSAGE" />
<uses-permission android:name="com.hihonor.push.permission.READ_PUSH_NOTIFICATION_INFO" />
<uses-permission android:name="${applicationId}.permission.MIPUSH_RECEIVE" />
<permission
android:name="${applicationId}.permission.MIPUSH_RECEIVE"
android:protectionLevel="signature" />
<permission
android:name="${applicationId}.hihonor.permission.PROCESS_PUSH_MSG"
android:protectionLevel="signatureOrSystem" />
<queries>
<package android:name="com.huawei.hwid" />
<package android:name="com.huawei.hms" />
<package android:name="com.huawei.android.pushagent" />
<package android:name="com.hihonor.id" />
<package android:name="com.hihonor.appmarket" />
<intent>
<action android:name="com.hihonor.push.action.BIND_PUSH_SERVICE" />
</intent>
</queries>
<application> <application>
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="true" />
<meta-data
android:name="com.vivo.push.app_id"
android:value="${XUQM_VIVO_APP_ID}" />
<meta-data
android:name="com.vivo.push.api_key"
android:value="${XUQM_VIVO_APP_KEY}" />
<meta-data
android:name="com.hihonor.push.app_id"
android:value="${XUQM_HONOR_APP_ID}" />
<meta-data
android:name="com.hihonor.push.sdk_version"
android:value="7.0.41.301" />
<service <service
android:name="com.xuqm.sdk.push.fcm.XuqmFirebaseMessagingService" android:name="com.xuqm.sdk.push.fcm.XuqmFirebaseMessagingService"
android:exported="false"> android:exported="false">
@ -8,5 +52,102 @@
<action android:name="com.google.firebase.MESSAGING_EVENT" /> <action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter> </intent-filter>
</service> </service>
<service
android:name="com.xuqm.sdk.push.huawei.XuqmHuaweiPushService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name="com.xuqm.sdk.push.honor.XuqmHonorPushService"
android:exported="false">
<intent-filter>
<action android:name="com.hihonor.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name="com.xiaomi.push.service.XMPushService"
android:enabled="true"
android:process=":pushservice" />
<service
android:name="com.xiaomi.push.service.XMJobService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"
android:process=":pushservice" />
<service
android:name="com.xiaomi.mipush.sdk.PushMessageHandler"
android:enabled="true"
android:exported="true"
android:permission="com.xiaomi.xmsf.permission.MIPUSH_RECEIVE" />
<service
android:name="com.xiaomi.mipush.sdk.MessageHandleService"
android:enabled="true" />
<receiver
android:name="com.xiaomi.push.service.receivers.PingReceiver"
android:exported="false"
android:process=":pushservice">
<intent-filter>
<action android:name="com.xiaomi.push.PING_TIMER" />
</intent-filter>
</receiver>
<activity
android:name="com.xiaomi.mipush.sdk.NotificationClickedActivity"
android:enabled="true"
android:excludeFromRecents="true"
android:exported="true"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<meta-data
android:name="supportStyle"
android:value="scene|voip" />
</activity>
<receiver
android:name="com.xuqm.sdk.push.xiaomi.XuqmXiaomiPushReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" />
</intent-filter>
<intent-filter>
<action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" />
</intent-filter>
<intent-filter>
<action android:name="com.xiaomi.mipush.ERROR" />
</intent-filter>
</receiver>
<service
android:name="com.heytap.msp.push.service.CompatibleDataMessageCallbackService"
android:exported="true"
android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE">
<intent-filter>
<action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE" />
</intent-filter>
</service>
<service
android:name="com.heytap.msp.push.service.DataMessageCallbackService"
android:exported="true"
android:permission="com.heytap.mcs.permission.SEND_PUSH_MESSAGE">
<intent-filter>
<action android:name="com.heytap.mcs.action.RECEIVE_MCS_MESSAGE" />
<action android:name="com.heytap.msp.push.RECEIVE_MCS_MESSAGE" />
</intent-filter>
</service>
<service
android:name="com.vivo.push.sdk.service.CommandClientService"
android:exported="true" />
<receiver
android:name="com.xuqm.sdk.push.vivo.XuqmVivoPushReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.vivo.pushclient.action.RECEIVE" />
</intent-filter>
</receiver>
</application> </application>
</manifest> </manifest>

查看文件

@ -9,8 +9,10 @@ import com.xuqm.sdk.XuqmSDK
import com.xuqm.sdk.core.ServiceEndpointRegistry import com.xuqm.sdk.core.ServiceEndpointRegistry
import com.xuqm.sdk.network.ApiClient import com.xuqm.sdk.network.ApiClient
import com.xuqm.sdk.push.api.PushApi import com.xuqm.sdk.push.api.PushApi
import com.xuqm.sdk.push.api.PushConfigApi
import com.xuqm.sdk.push.model.PushRegistrationSnapshot import com.xuqm.sdk.push.model.PushRegistrationSnapshot
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
import com.xuqm.sdk.push.storage.PushRegistrationStore import com.xuqm.sdk.push.storage.PushRegistrationStore
import com.xuqm.sdk.push.vendor.FcmPushService import com.xuqm.sdk.push.vendor.FcmPushService
import com.xuqm.sdk.push.vendor.HonorPushService import com.xuqm.sdk.push.vendor.HonorPushService
@ -29,8 +31,11 @@ import java.util.concurrent.atomic.AtomicReference
object PushSDK { object PushSDK {
private val api: PushApi get() = ApiClient.create(PushApi::class.java, ServiceEndpointRegistry.pushBaseUrl) private val api: PushApi get() = ApiClient.create(PushApi::class.java, ServiceEndpointRegistry.pushBaseUrl)
private val configApi: PushConfigApi get() = ApiClient.create(PushConfigApi::class.java, ServiceEndpointRegistry.controlBaseUrl)
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val registeredUserId = AtomicReference<String?>(null) private val registeredUserId = AtomicReference<String?>(null)
@Volatile
private var cachedVendorConfig: PushVendorConfig? = null
fun currentRegistration(context: Context): PushRegistrationSnapshot? { fun currentRegistration(context: Context): PushRegistrationSnapshot? {
XuqmSDK.requireInit() XuqmSDK.requireInit()
@ -59,6 +64,14 @@ object PushSDK {
registerDevice(context, userId) registerDevice(context, userId)
} }
fun refreshNativePushToken(
context: Context,
vendor: PushVendor = detectVendor(),
) {
XuqmSDK.requireInit()
ensureNativePushToken(context.applicationContext, vendor)
}
fun unbindImUser(userId: String) { fun unbindImUser(userId: String) {
unregisterDevice(userId) unregisterDevice(userId)
} }
@ -77,6 +90,7 @@ object PushSDK {
api.setReceivePush( api.setReceivePush(
appId = XuqmSDK.appKey, appId = XuqmSDK.appKey,
userId = resolvedUserId, userId = resolvedUserId,
deviceId = DeviceUtils.getDeviceId(context),
enabled = enabled, enabled = enabled,
) )
if (enabled) { if (enabled) {
@ -107,6 +121,11 @@ object PushSDK {
userId = userId, userId = userId,
vendor = vendor.name, vendor = vendor.name,
token = pushToken, token = pushToken,
deviceId = DeviceUtils.getDeviceId(context),
brand = Build.MANUFACTURER.orEmpty(),
model = Build.MODEL.orEmpty(),
osVersion = DeviceUtils.getOsVersion(),
appVersion = appVersion(context),
) )
registeredUserId.set(userId) registeredUserId.set(userId)
store(context).updateLastUserId(userId) store(context).updateLastUserId(userId)
@ -126,7 +145,12 @@ object PushSDK {
deviceId = DeviceUtils.getDeviceId(XuqmSDK.appContext), deviceId = DeviceUtils.getDeviceId(XuqmSDK.appContext),
fallbackVendor = detectVendor(), fallbackVendor = detectVendor(),
) )
api.unregisterDevice(XuqmSDK.appKey, userId, reg?.vendor?.name ?: detectVendor().name) api.unregisterDevice(
XuqmSDK.appKey,
userId,
reg?.vendor?.name ?: detectVendor().name,
DeviceUtils.getDeviceId(XuqmSDK.appContext),
)
registeredUserId.compareAndSet(userId, null) registeredUserId.compareAndSet(userId, null)
store(XuqmSDK.appContext).updateLastUserId(null) store(XuqmSDK.appContext).updateLastUserId(null)
} }
@ -146,8 +170,11 @@ object PushSDK {
return when (Build.MANUFACTURER.uppercase()) { return when (Build.MANUFACTURER.uppercase()) {
"HUAWEI" -> PushVendor.HUAWEI "HUAWEI" -> PushVendor.HUAWEI
"XIAOMI" -> PushVendor.XIAOMI "XIAOMI" -> PushVendor.XIAOMI
"REDMI", "POCO" -> PushVendor.XIAOMI
"OPPO" -> PushVendor.OPPO "OPPO" -> PushVendor.OPPO
"REALME", "ONEPLUS" -> PushVendor.OPPO
"VIVO" -> PushVendor.VIVO "VIVO" -> PushVendor.VIVO
"IQOO" -> PushVendor.VIVO
"HONOR" -> PushVendor.HONOR "HONOR" -> PushVendor.HONOR
else -> PushVendor.FCM else -> PushVendor.FCM
} }
@ -156,16 +183,19 @@ object PushSDK {
fun initializeVendors(context: Context) { fun initializeVendors(context: Context) {
val detectedVendor = detectVendor() val detectedVendor = detectVendor()
Log.i("XuqmPushSDK", "Detected push vendor: ${detectedVendor.name}") Log.i("XuqmPushSDK", "Detected push vendor: ${detectedVendor.name}")
scope.launch {
val config = loadVendorConfig()
vendorServices.forEach { service -> vendorServices.forEach { service ->
if (service.vendor == detectedVendor && service.isAvailable(context)) { if (service.vendor == detectedVendor && service.isAvailable(context)) {
Log.i("XuqmPushSDK", "Initializing push vendor: ${service.vendor.name}") Log.i("XuqmPushSDK", "Initializing push vendor: ${service.vendor.name}")
service.register(context) service.register(context, config)
} }
} }
if (detectedVendor == PushVendor.FCM) { if (detectedVendor == PushVendor.FCM) {
ensureNativePushToken(context) ensureNativePushToken(context)
} }
} }
}
fun onSdkLogin(session: XuqmLoginSession) { fun onSdkLogin(session: XuqmLoginSession) {
val context = runCatching { XuqmSDK.appContext }.getOrNull() ?: return val context = runCatching { XuqmSDK.appContext }.getOrNull() ?: return
@ -189,7 +219,13 @@ object PushSDK {
)?.receivePush ?: true )?.receivePush ?: true
private fun ensureNativePushToken(context: Context) { private fun ensureNativePushToken(context: Context) {
val vendor = detectVendor() ensureNativePushToken(context, detectVendor())
}
private fun ensureNativePushToken(
context: Context,
vendor: PushVendor,
) {
val registration = currentRegistration(context) val registration = currentRegistration(context)
if (registration?.pushToken?.isNotBlank() == true) return if (registration?.pushToken?.isNotBlank() == true) return
@ -216,7 +252,9 @@ object PushSDK {
} else { } else {
val service = vendorServices.firstOrNull { it.vendor == vendor } val service = vendorServices.firstOrNull { it.vendor == vendor }
if (service != null && service.isAvailable(context)) { if (service != null && service.isAvailable(context)) {
service.register(context) scope.launch {
service.register(context, loadVendorConfig())
}
} else { } else {
Log.w( Log.w(
"XuqmPushSDK", "XuqmPushSDK",
@ -244,4 +282,37 @@ object PushSDK {
} }
} }
} }
private fun appVersion(context: Context): String? =
runCatching {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
"${packageInfo.versionName ?: ""}(${packageInfo.longVersionCode})"
} else {
@Suppress("DEPRECATION")
"${packageInfo.versionName ?: ""}(${packageInfo.versionCode})"
}
}.getOrNull()
private suspend fun loadVendorConfig(): PushVendorConfig {
cachedVendorConfig?.let { return it }
val loaded = runCatching {
val pushConfig = configApi.sdkConfig(XuqmSDK.appKey).data?.pushConfig
PushVendorConfig(
huaweiAppId = pushConfig?.getAsJsonObject("huawei")?.get("appId")?.asString.orEmpty(),
xiaomiAppId = pushConfig?.getAsJsonObject("xiaomi")?.get("appId")?.asString.orEmpty(),
xiaomiAppKey = pushConfig?.getAsJsonObject("xiaomi")?.get("appKey")?.asString.orEmpty(),
oppoAppKey = pushConfig?.getAsJsonObject("oppo")?.get("appKey")?.asString.orEmpty(),
oppoAppSecret = pushConfig?.getAsJsonObject("oppo")?.get("masterSecret")?.asString.orEmpty(),
vivoAppId = pushConfig?.getAsJsonObject("vivo")?.get("appId")?.asString.orEmpty(),
vivoAppKey = pushConfig?.getAsJsonObject("vivo")?.get("appKey")?.asString.orEmpty(),
honorAppId = pushConfig?.getAsJsonObject("honor")?.get("appId")?.asString.orEmpty(),
)
}.getOrElse { error ->
Log.w("XuqmPushSDK", "Unable to load tenant push config: ${error.message}")
PushVendorConfig()
}
cachedVendorConfig = loaded
return loaded
}
} }

查看文件

@ -12,6 +12,12 @@ interface PushApi {
@Query("userId") userId: String, @Query("userId") userId: String,
@Query("vendor") vendor: String, @Query("vendor") vendor: String,
@Query("token") token: String, @Query("token") token: String,
@Query("deviceId") deviceId: String,
@Query("brand") brand: String,
@Query("model") model: String,
@Query("osVersion") osVersion: String,
@Query("platform") platform: String = "ANDROID",
@Query("appVersion") appVersion: String? = null,
) )
@DELETE("api/push/unregister") @DELETE("api/push/unregister")
@ -19,12 +25,14 @@ interface PushApi {
@Query("appId") appId: String, @Query("appId") appId: String,
@Query("userId") userId: String, @Query("userId") userId: String,
@Query("vendor") vendor: String, @Query("vendor") vendor: String,
@Query("deviceId") deviceId: String? = null,
) )
@POST("api/push/receive-push") @POST("api/push/receive-push")
suspend fun setReceivePush( suspend fun setReceivePush(
@Query("appId") appId: String, @Query("appId") appId: String,
@Query("userId") userId: String, @Query("userId") userId: String,
@Query("deviceId") deviceId: String? = null,
@Query("enabled") enabled: Boolean, @Query("enabled") enabled: Boolean,
) )
} }

查看文件

@ -0,0 +1,21 @@
package com.xuqm.sdk.push.api
import com.google.gson.JsonObject
import retrofit2.http.GET
import retrofit2.http.Query
interface PushConfigApi {
@GET("api/sdk/config")
suspend fun sdkConfig(
@Query("appId") appId: String,
@Query("platform") platform: String = "ANDROID",
): SdkConfigResponse
}
data class SdkConfigResponse(
val data: SdkConfigData? = null,
)
data class SdkConfigData(
val pushConfig: JsonObject? = null,
)

查看文件

@ -0,0 +1,23 @@
package com.xuqm.sdk.push.honor
import android.util.Log
import com.hihonor.push.sdk.HonorMessageService
import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor
class XuqmHonorPushService : HonorMessageService() {
override fun onNewToken(token: String?) {
super.onNewToken(token)
if (token.isNullOrBlank()) return
runCatching {
PushSDK.updateNativePushToken(applicationContext, PushVendor.HONOR, token)
}.onFailure { error ->
Log.w(TAG, "Unable to persist Honor push token: ${error.message}")
}
}
companion object {
private const val TAG = "XuqmHonorPush"
}
}

查看文件

@ -0,0 +1,39 @@
package com.xuqm.sdk.push.huawei
import android.os.Bundle
import android.util.Log
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage
import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor
class XuqmHuaweiPushService : HmsMessageService() {
override fun onNewToken(token: String?) {
super.onNewToken(token)
persistToken(token)
}
override fun onNewToken(token: String?, bundle: Bundle?) {
super.onNewToken(token, bundle)
persistToken(token)
}
override fun onMessageReceived(message: RemoteMessage?) {
super.onMessageReceived(message)
Log.d(TAG, "Huawei push message received")
}
private fun persistToken(token: String?) {
if (token.isNullOrBlank()) return
runCatching {
PushSDK.updateNativePushToken(applicationContext, PushVendor.HUAWEI, token)
}.onFailure { error ->
Log.w(TAG, "Unable to persist Huawei push token: ${error.message}")
}
}
companion object {
private const val TAG = "XuqmHuaweiPush"
}
}

查看文件

@ -0,0 +1,12 @@
package com.xuqm.sdk.push.model
data class PushVendorConfig(
val huaweiAppId: String = "",
val xiaomiAppId: String = "",
val xiaomiAppKey: String = "",
val oppoAppKey: String = "",
val oppoAppSecret: String = "",
val vivoAppId: String = "",
val vivoAppKey: String = "",
val honorAppId: String = "",
)

查看文件

@ -4,6 +4,7 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
/** /**
* FCM (Firebase Cloud Messaging) push integration. * FCM (Firebase Cloud Messaging) push integration.
@ -23,7 +24,7 @@ class FcmPushService : PushVendorInterface {
}.getOrDefault(false) }.getOrDefault(false)
} }
override fun register(context: Context) { override fun register(context: Context, config: PushVendorConfig) {
runCatching { runCatching {
val fcmClass = Class.forName("com.google.firebase.messaging.FirebaseMessaging") val fcmClass = Class.forName("com.google.firebase.messaging.FirebaseMessaging")
val instance = fcmClass.getMethod("getInstance").invoke(null) val instance = fcmClass.getMethod("getInstance").invoke(null)

查看文件

@ -4,6 +4,8 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
import java.lang.reflect.Proxy
/** /**
* 荣耀推送集成框架 * 荣耀推送集成框架
@ -31,13 +33,21 @@ class HonorPushService : PushVendorInterface {
}.getOrDefault(false) }.getOrDefault(false)
} }
override fun register(context: Context) { override fun register(context: Context, config: PushVendorConfig) {
runCatching { runCatching {
val honorPushClass = Class.forName("com.hihonor.push.sdk.HonorPushClient") val honorPushClass = Class.forName("com.hihonor.push.sdk.HonorPushClient")
val instance = honorPushClass.getMethod("getInstance").invoke(null) val instance = honorPushClass.getMethod("getInstance").invoke(null)
// HonorPushClient.getInstance().init(context, true) val supported = runCatching {
honorPushClass.getMethod("checkSupportHonorPush", Context::class.java)
.invoke(instance, context) as? Boolean
}.getOrDefault(true)
if (supported != true) {
Log.w(TAG, "Honor push is not supported on this device")
return
}
honorPushClass.getMethod("init", Context::class.java, Boolean::class.javaPrimitiveType) honorPushClass.getMethod("init", Context::class.java, Boolean::class.javaPrimitiveType)
.invoke(instance, context, true) .invoke(instance, context, false)
requestToken(context, honorPushClass, instance)
Log.i(TAG, "Honor push registration requested") Log.i(TAG, "Honor push registration requested")
}.onFailure { error -> }.onFailure { error ->
Log.w(TAG, "Honor push registration failed: ${error.message}") Log.w(TAG, "Honor push registration failed: ${error.message}")
@ -58,4 +68,36 @@ class HonorPushService : PushVendorInterface {
companion object { companion object {
private const val TAG = "HonorPushService" private const val TAG = "HonorPushService"
} }
private fun requestToken(
context: Context,
honorPushClass: Class<*>,
instance: Any,
) {
runCatching {
val callbackClass = Class.forName("com.hihonor.push.sdk.HonorPushCallback")
val callback = Proxy.newProxyInstance(
callbackClass.classLoader,
arrayOf(callbackClass),
) { _, method, args ->
when (method.name) {
"onSuccess" -> {
val token = args?.firstOrNull() as? String
if (!token.isNullOrBlank()) {
PushSDK.updateNativePushToken(context, vendor, token)
Log.i(TAG, "Honor push token acquired")
}
}
"onFailure" -> {
Log.w(TAG, "Honor push token failed: ${args?.joinToString()}")
}
}
null
}
honorPushClass.getMethod("getPushToken", callbackClass)
.invoke(instance, callback)
}.onFailure { error ->
Log.w(TAG, "Honor push token request failed: ${error.message}")
}
}
} }

查看文件

@ -4,9 +4,10 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
/** /**
* 华为推送集成框架 * Android 华为 HMS 推送集成框架
* *
* 需要添加 HMS Push SDK 依赖 * 需要添加 HMS Push SDK 依赖
* ```groovy * ```groovy
@ -36,12 +37,12 @@ class HuaweiPushService : PushVendorInterface {
}.getOrDefault(false) }.getOrDefault(false)
} }
override fun register(context: Context) { override fun register(context: Context, config: PushVendorConfig) {
runCatching { runCatching {
val hmsClass = Class.forName("com.huawei.hms.aaid.HmsInstanceId") val hmsClass = Class.forName("com.huawei.hms.aaid.HmsInstanceId")
val instance = hmsClass.getMethod("getInstance", Context::class.java) val instance = hmsClass.getMethod("getInstance", Context::class.java)
.invoke(null, context) .invoke(null, context)
val appId = getAppId(context) val appId = config.huaweiAppId.ifBlank { getAppId(context) }
if (appId.isNotBlank()) { if (appId.isNotBlank()) {
val token = hmsClass.getMethod( val token = hmsClass.getMethod(
"getToken", "getToken",

查看文件

@ -6,21 +6,11 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
import java.lang.reflect.Proxy import java.lang.reflect.Proxy
/** /**
* OPPO 推送集成框架 * OPPO 推送集成OPPO Push 依赖由 sdk-push 自身声明注册参数优先来自租户 PUSH 配置
*
* 需要添加 OPPO Push SDK 依赖
* ```groovy
* implementation 'com.heytap.mcs:push:3.x.x'
* ```
*
* `AndroidManifest.xml` `<application>` 下配置
* ```xml
* <meta-data android:name="XUQM_OPPO_APP_KEY" android:value="xxxxxxxx" />
* <meta-data android:name="XUQM_OPPO_APP_SECRET" android:value="xxxxxxxx" />
* ```
*/ */
class OppoPushService : PushVendorInterface { class OppoPushService : PushVendorInterface {
@ -28,49 +18,26 @@ class OppoPushService : PushVendorInterface {
override fun isAvailable(context: Context): Boolean { override fun isAvailable(context: Context): Boolean {
return runCatching { return runCatching {
Class.forName("com.heytap.mcssdk.PushManager") resolvePushManagerClass()
true true
}.getOrDefault(false) }.getOrDefault(false)
} }
override fun register(context: Context) { override fun register(context: Context, config: PushVendorConfig) {
runCatching { runCatching {
val pushManagerClass = Class.forName("com.heytap.mcssdk.PushManager")
val instance = pushManagerClass.getMethod("getInstance").invoke(null)
val meta = context.packageManager.getApplicationInfo( val meta = context.packageManager.getApplicationInfo(
context.packageName, PackageManager.GET_META_DATA context.packageName, PackageManager.GET_META_DATA
).metaData ?: Bundle.EMPTY ).metaData ?: Bundle.EMPTY
val appKey = meta.getString("XUQM_OPPO_APP_KEY", "") val appKey = config.oppoAppKey.ifBlank { meta.getString("XUQM_OPPO_APP_KEY", "") }
val appSecret = meta.getString("XUQM_OPPO_APP_SECRET", "") val appSecret = config.oppoAppSecret.ifBlank { meta.getString("XUQM_OPPO_APP_SECRET", "") }
if (appKey.isNotBlank() && appSecret.isNotBlank()) { if (appKey.isNotBlank() && appSecret.isNotBlank()) {
val callbackClass = Class.forName("com.heytap.mcssdk.callback.PushCallback") if (!registerWithHeytapMsp(context, appKey, appSecret)) {
val proxy = Proxy.newProxyInstance( registerWithLegacyMcs(context, appKey, appSecret)
callbackClass.classLoader,
arrayOf(callbackClass)
) { _, method, args ->
when (method.name) {
"onRegister" -> {
val regId = args?.getOrNull(1) as? String
if (!regId.isNullOrBlank()) {
PushSDK.updateNativePushToken(context, vendor, regId)
Log.i(TAG, "OPPO push token acquired")
} }
}
}
null
}
pushManagerClass.getMethod(
"register",
Context::class.java,
String::class.java,
String::class.java,
callbackClass,
).invoke(instance, context, appKey, appSecret, proxy)
Log.i(TAG, "OPPO push registration requested") Log.i(TAG, "OPPO push registration requested")
} else { } else {
Log.w(TAG, "OPPO appKey/appSecret not configured in meta-data, skipping registration") Log.w(TAG, "OPPO appKey/appSecret not configured, skipping registration")
} }
}.onFailure { error -> }.onFailure { error ->
Log.w(TAG, "OPPO push registration failed: ${error.message}") Log.w(TAG, "OPPO push registration failed: ${error.message}")
@ -79,10 +46,13 @@ class OppoPushService : PushVendorInterface {
override fun unregister(context: Context) { override fun unregister(context: Context) {
runCatching { runCatching {
val pushManagerClass = Class.forName("com.heytap.mcssdk.PushManager") val pushManagerClass = resolvePushManagerClass()
if (pushManagerClass.name == "com.heytap.msp.push.HeytapPushManager") {
pushManagerClass.getMethod("unRegister").invoke(null)
} else {
val instance = pushManagerClass.getMethod("getInstance").invoke(null) val instance = pushManagerClass.getMethod("getInstance").invoke(null)
pushManagerClass.getMethod("unRegister", Context::class.java) pushManagerClass.getMethod("unRegister", Context::class.java).invoke(instance, context)
.invoke(instance, context) }
Log.i(TAG, "OPPO push unregistered") Log.i(TAG, "OPPO push unregistered")
}.onFailure { error -> }.onFailure { error ->
Log.w(TAG, "OPPO push unregistration failed: ${error.message}") Log.w(TAG, "OPPO push unregistration failed: ${error.message}")
@ -91,5 +61,90 @@ class OppoPushService : PushVendorInterface {
companion object { companion object {
private const val TAG = "OppoPushService" private const val TAG = "OppoPushService"
private fun resolvePushManagerClass(): Class<*> {
return runCatching {
Class.forName("com.heytap.msp.push.HeytapPushManager")
}.getOrElse {
Class.forName("com.heytap.mcssdk.PushManager")
}
}
}
private fun registerWithHeytapMsp(
context: Context,
appKey: String,
appSecret: String,
): Boolean {
val pushManagerClass = runCatching {
Class.forName("com.heytap.msp.push.HeytapPushManager")
}.getOrNull() ?: return false
runCatching {
pushManagerClass.getMethod("init", Context::class.java, java.lang.Boolean.TYPE)
.invoke(null, context, false)
}
val supported = runCatching {
pushManagerClass.getMethod("isSupportPush", Context::class.java)
.invoke(null, context) as? Boolean
}.getOrElse {
runCatching { pushManagerClass.getMethod("isSupportPush").invoke(null) as? Boolean }
.getOrDefault(true)
} ?: true
if (!supported) {
Log.w(TAG, "OPPO push is not supported on this device")
return true
}
val callbackClass = Class.forName("com.heytap.msp.push.callback.ICallBackResultService")
val callback = buildCallback(context.applicationContext, callbackClass)
pushManagerClass.getMethod(
"register",
Context::class.java,
String::class.java,
String::class.java,
callbackClass,
).invoke(null, context, appKey, appSecret, callback)
runCatching { pushManagerClass.getMethod("requestNotificationPermission").invoke(null) }
return true
}
private fun registerWithLegacyMcs(
context: Context,
appKey: String,
appSecret: String,
) {
val pushManagerClass = Class.forName("com.heytap.mcssdk.PushManager")
val instance = pushManagerClass.getMethod("getInstance").invoke(null)
val callbackClass = Class.forName("com.heytap.mcssdk.callback.PushCallback")
val callback = buildCallback(context.applicationContext, callbackClass)
pushManagerClass.getMethod(
"register",
Context::class.java,
String::class.java,
String::class.java,
callbackClass,
).invoke(instance, context, appKey, appSecret, callback)
}
private fun buildCallback(context: Context, callbackClass: Class<*>): Any {
return Proxy.newProxyInstance(
callbackClass.classLoader,
arrayOf(callbackClass)
) { _, method, args ->
if (method.name == "onRegister") {
val code = args?.getOrNull(0) as? Int
val regId = args?.getOrNull(1) as? String
if ((code == null || code == 0) && !regId.isNullOrBlank()) {
PushSDK.updateNativePushToken(context, vendor, regId)
Log.i(TAG, "OPPO push token acquired")
} else {
Log.w(TAG, "OPPO push register callback code=$code")
}
}
null
}
} }
} }

查看文件

@ -2,6 +2,7 @@ package com.xuqm.sdk.push.vendor
import android.content.Context import android.content.Context
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
/** /**
* 厂商推送服务接口 * 厂商推送服务接口
@ -22,7 +23,7 @@ interface PushVendorInterface {
/** /**
* 注册厂商推送服务触发获取推送 Token 的流程 * 注册厂商推送服务触发获取推送 Token 的流程
*/ */
fun register(context: Context) fun register(context: Context, config: PushVendorConfig = PushVendorConfig())
/** /**
* 注销厂商推送服务 * 注销厂商推送服务

查看文件

@ -4,6 +4,8 @@ import android.content.Context
import android.util.Log import android.util.Log
import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
import java.lang.reflect.Proxy
/** /**
* vivo 推送集成框架 * vivo 推送集成框架
@ -31,13 +33,33 @@ class VivoPushService : PushVendorInterface {
}.getOrDefault(false) }.getOrDefault(false)
} }
override fun register(context: Context) { override fun register(context: Context, config: PushVendorConfig) {
runCatching { runCatching {
val pushClientClass = Class.forName("com.vivo.push.PushClient") val pushClientClass = Class.forName("com.vivo.push.PushClient")
val instance = pushClientClass.getMethod("getInstance", Context::class.java) val instance = pushClientClass.getMethod("getInstance", Context::class.java)
.invoke(null, context) .invoke(null, context)
// PushClient.getInstance(context).initialize()
pushClientClass.getMethod("initialize").invoke(instance) pushClientClass.getMethod("initialize").invoke(instance)
val listenerClass = Class.forName("com.vivo.push.IPushActionListener")
val listener = Proxy.newProxyInstance(
listenerClass.classLoader,
arrayOf(listenerClass),
) { _, method, args ->
if (method.name == "onStateChanged") {
val state = args?.firstOrNull() as? Int
if (state == 0) {
persistRegId(context, pushClientClass, instance)
} else {
Log.w(TAG, "Vivo push turnOnPush state=$state")
}
}
null
}
runCatching {
pushClientClass.getMethod("turnOnPush", listenerClass)
.invoke(instance, listener)
}.onFailure {
persistRegId(context, pushClientClass, instance)
}
Log.i(TAG, "Vivo push registration requested") Log.i(TAG, "Vivo push registration requested")
}.onFailure { error -> }.onFailure { error ->
Log.w(TAG, "Vivo push registration failed: ${error.message}") Log.w(TAG, "Vivo push registration failed: ${error.message}")
@ -59,4 +81,18 @@ class VivoPushService : PushVendorInterface {
companion object { companion object {
private const val TAG = "VivoPushService" private const val TAG = "VivoPushService"
} }
private fun persistRegId(
context: Context,
pushClientClass: Class<*>,
instance: Any,
) {
val regId = runCatching {
pushClientClass.getMethod("getRegId").invoke(instance) as? String
}.getOrNull()
if (!regId.isNullOrBlank()) {
PushSDK.updateNativePushToken(context, vendor, regId)
Log.i(TAG, "Vivo push token acquired")
}
}
} }

查看文件

@ -6,26 +6,13 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendor
import com.xuqm.sdk.push.model.PushVendorConfig
/** /**
* 小米推送集成框架 * 小米推送集成框架
* *
* 需要添加 MiPush SDK 依赖 * MiPush AAR 需要随 sdk-push 发布注册参数优先来自租户 PUSH 配置
* ```groovy * 旧版本 manifest meta-data 仅作为兼容兜底
* implementation 'com.xiaomi.mipush:mipush:5.x.x'
* ```
*
* `AndroidManifest.xml` `<application>` 下配置
* ```xml
* <meta-data android:name="XUQM_XIAOMI_APP_ID" android:value="288230376xxxxxxxx" />
* <meta-data android:name="XUQM_XIAOMI_APP_KEY" android:value="xxxxxxxxxxxx" />
* ```
*
* 并在自定义 `PushMessageReceiver` `onReceiveRegisterResult()` 回调中获取 token
* 然后调用
* ```kotlin
* PushSDK.updateNativePushToken(context, PushVendor.XIAOMI, token)
* ```
*/ */
class XiaomiPushService : PushVendorInterface { class XiaomiPushService : PushVendorInterface {
@ -38,14 +25,14 @@ class XiaomiPushService : PushVendorInterface {
}.getOrDefault(false) }.getOrDefault(false)
} }
override fun register(context: Context) { override fun register(context: Context, config: PushVendorConfig) {
runCatching { runCatching {
val miPushClass = Class.forName("com.xiaomi.mipush.sdk.MiPushClient") val miPushClass = Class.forName("com.xiaomi.mipush.sdk.MiPushClient")
val meta = context.packageManager.getApplicationInfo( val meta = context.packageManager.getApplicationInfo(
context.packageName, PackageManager.GET_META_DATA context.packageName, PackageManager.GET_META_DATA
).metaData ?: Bundle.EMPTY ).metaData ?: Bundle.EMPTY
val appId = meta.getString("XUQM_XIAOMI_APP_ID", "") val appId = config.xiaomiAppId.ifBlank { meta.getString("XUQM_XIAOMI_APP_ID", "") }
val appKey = meta.getString("XUQM_XIAOMI_APP_KEY", "") val appKey = config.xiaomiAppKey.ifBlank { meta.getString("XUQM_XIAOMI_APP_KEY", "") }
if (appId.isNotBlank() && appKey.isNotBlank()) { if (appId.isNotBlank() && appKey.isNotBlank()) {
miPushClass.getMethod( miPushClass.getMethod(
"registerPush", "registerPush",
@ -54,8 +41,9 @@ class XiaomiPushService : PushVendorInterface {
String::class.java, String::class.java,
).invoke(null, context, appId, appKey) ).invoke(null, context, appId, appKey)
Log.i(TAG, "Xiaomi push registration requested") Log.i(TAG, "Xiaomi push registration requested")
pollRegId(context, miPushClass)
} else { } else {
Log.w(TAG, "Xiaomi appId/appKey not configured in meta-data, skipping registration") Log.w(TAG, "Xiaomi appId/appKey not configured, skipping registration")
} }
}.onFailure { error -> }.onFailure { error ->
Log.w(TAG, "Xiaomi push registration failed: ${error.message}") Log.w(TAG, "Xiaomi push registration failed: ${error.message}")
@ -73,6 +61,24 @@ class XiaomiPushService : PushVendorInterface {
} }
} }
private fun pollRegId(context: Context, miPushClass: Class<*>) {
Thread {
repeat(8) {
val regId = runCatching {
miPushClass.getMethod("getRegId", Context::class.java)
.invoke(null, context) as? String
}.getOrNull()
if (!regId.isNullOrBlank()) {
PushSDK.updateNativePushToken(context, vendor, regId)
Log.i(TAG, "Xiaomi push token acquired")
return@Thread
}
Thread.sleep(1000)
}
Log.w(TAG, "Xiaomi push token not ready after registration")
}.start()
}
companion object { companion object {
private const val TAG = "XiaomiPushService" private const val TAG = "XiaomiPushService"
} }

查看文件

@ -0,0 +1,47 @@
package com.xuqm.sdk.push.vivo
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor
class XuqmVivoPushReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (intent == null) return
val appContext = context.applicationContext
val regId = extractRegId(intent) ?: currentRegId(appContext)
if (regId.isNullOrBlank()) return
runCatching {
PushSDK.updateNativePushToken(appContext, PushVendor.VIVO, regId)
}.onFailure { error ->
Log.w(TAG, "Unable to persist vivo push token: ${error.message}")
}
}
private fun extractRegId(intent: Intent): String? {
val extras = intent.extras ?: return null
for (key in extras.keySet()) {
val value = extras.get(key) as? String ?: continue
if (key.contains("reg", ignoreCase = true) || key.contains("token", ignoreCase = true)) {
return value.takeIf { it.isNotBlank() }
}
}
return null
}
private fun currentRegId(context: Context): String? {
return runCatching {
val pushClientClass = Class.forName("com.vivo.push.PushClient")
val instance = pushClientClass.getMethod("getInstance", Context::class.java)
.invoke(null, context)
pushClientClass.getMethod("getRegId").invoke(instance) as? String
}.getOrNull()
}
companion object {
private const val TAG = "XuqmVivoPush"
}
}

查看文件

@ -0,0 +1,60 @@
package com.xuqm.sdk.push.xiaomi
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.xuqm.sdk.push.PushSDK
import com.xuqm.sdk.push.model.PushVendor
class XuqmXiaomiPushReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (intent == null) return
val appContext = context.applicationContext
val regId = extractRegId(intent)
if (!regId.isNullOrBlank()) {
runCatching {
PushSDK.updateNativePushToken(appContext, PushVendor.XIAOMI, regId)
}.onFailure { error ->
Log.w(TAG, "Unable to persist Xiaomi push token: ${error.message}")
}
return
}
runCatching {
PushSDK.refreshNativePushToken(appContext, PushVendor.XIAOMI)
}.onFailure { error ->
Log.d(TAG, "Xiaomi push callback ignored before SDK init: ${error.message}")
}
}
private fun extractRegId(intent: Intent): String? {
val extras = intent.extras ?: return null
for (key in extras.keySet()) {
val value = extras.get(key) ?: continue
if (value is String && key.contains("reg", ignoreCase = true)) {
return value.takeIf { it.isNotBlank() }
}
if (value.javaClass.name == "com.xiaomi.mipush.sdk.MiPushCommandMessage") {
val resultCode = runCatching {
value.javaClass.getMethod("getResultCode").invoke(value) as? Long
}.getOrNull()
val command = runCatching {
value.javaClass.getMethod("getCommand").invoke(value) as? String
}.getOrNull()
val arguments = runCatching {
@Suppress("UNCHECKED_CAST")
value.javaClass.getMethod("getCommandArguments").invoke(value) as? List<String>
}.getOrNull()
if ((resultCode == null || resultCode == 0L) && command.equals("register", ignoreCase = true)) {
return arguments?.firstOrNull { it.isNotBlank() }
}
}
}
return null
}
companion object {
private const val TAG = "XuqmMiPushReceiver"
}
}

查看文件

@ -1,6 +1,7 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven(url = "https://nexus.xuqinmin.com/repository/android/") maven(url = "https://nexus.xuqinmin.com/repository/android/")
maven(url = "https://developer.hihonor.com/repo")
google() google()
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
@ -11,6 +12,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories { repositories {
maven(url = "https://nexus.xuqinmin.com/repository/android/") maven(url = "https://nexus.xuqinmin.com/repository/android/")
maven(url = "https://developer.hihonor.com/repo")
google() google()
mavenCentral() mavenCentral()
} }