diff --git a/sdk-push/consumer-rules.pro b/sdk-push/consumer-rules.pro index dd1ca31..76424ea 100644 --- a/sdk-push/consumer-rules.pro +++ b/sdk-push/consumer-rules.pro @@ -17,6 +17,10 @@ # ── Vendor push services — instantiated via reflection inside PushSDK ───────── -keep class com.xuqm.sdk.push.vendor.** { *; } +# OPPO SDK is initialized from the vendor adapter and also instantiates callback +# services from the manifest. Keep its API and service classes in minified apps. +-keep class com.heytap.msp.** { *; } + # ── Enum values used as strings ─────────────────────────────────────────────── -keepclassmembers enum com.xuqm.sdk.push.model.PushVendor { public static **[] values(); diff --git a/sdk-push/src/main/java/com/xuqm/sdk/push/PushSDK.kt b/sdk-push/src/main/java/com/xuqm/sdk/push/PushSDK.kt index ede4fa1..ffd7c2c 100644 --- a/sdk-push/src/main/java/com/xuqm/sdk/push/PushSDK.kt +++ b/sdk-push/src/main/java/com/xuqm/sdk/push/PushSDK.kt @@ -346,7 +346,7 @@ object PushSDK { 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(), + oppoAppSecret = pushConfig?.getAsJsonObject("oppo")?.get("appSecret")?.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(), @@ -361,4 +361,4 @@ object PushSDK { } private const val CONFIG_CACHE_TTL_MS = 5 * 60 * 1000L -} \ No newline at end of file +} diff --git a/sdk-push/src/main/java/com/xuqm/sdk/push/vendor/OppoPushService.kt b/sdk-push/src/main/java/com/xuqm/sdk/push/vendor/OppoPushService.kt index aa1e1f4..21d7c66 100644 --- a/sdk-push/src/main/java/com/xuqm/sdk/push/vendor/OppoPushService.kt +++ b/sdk-push/src/main/java/com/xuqm/sdk/push/vendor/OppoPushService.kt @@ -1,150 +1,88 @@ package com.xuqm.sdk.push.vendor import android.content.Context -import android.content.pm.PackageManager -import android.os.Bundle import android.util.Log +import com.heytap.msp.push.HeytapPushManager +import com.heytap.msp.push.callback.ICallBackResultService import com.xuqm.sdk.push.PushSDK import com.xuqm.sdk.push.model.PushVendor import com.xuqm.sdk.push.model.PushVendorConfig -import java.lang.reflect.Proxy -/** - * OPPO 推送集成。OPPO Push 依赖由 sdk-push 自身声明,注册参数优先来自租户 PUSH 配置。 - */ +/** OPPO/OnePlus/realme 离线推送注册。凭据来自租户 PUSH 配置。 */ class OppoPushService : PushVendorInterface { override val vendor: PushVendor = PushVendor.OPPO - override fun isAvailable(context: Context): Boolean { - return runCatching { - resolvePushManagerClass() - true - }.getOrDefault(false) - } + override fun isAvailable(context: Context): Boolean = + runCatching { HeytapPushManager.isSupportPush(context.applicationContext) } + .onFailure { Log.w(TAG, "OPPO push availability check failed: ${it.message}") } + .getOrDefault(false) override fun register(context: Context, config: PushVendorConfig) { - runCatching { - val meta = context.packageManager.getApplicationInfo( - context.packageName, PackageManager.GET_META_DATA - ).metaData ?: Bundle.EMPTY - val appKey = config.oppoAppKey.ifBlank { meta.getString("XUQM_OPPO_APP_KEY", "") } - val appSecret = config.oppoAppSecret.ifBlank { meta.getString("XUQM_OPPO_APP_SECRET", "") } + val appContext = context.applicationContext + val appKey = config.oppoAppKey.trim() + val appSecret = config.oppoAppSecret.trim() + if (appKey.isBlank() || appSecret.isBlank()) { + Log.e(TAG, "OPPO appKey/appSecret not configured on control plane, skipping registration") + return + } - if (appKey.isNotBlank() && appSecret.isNotBlank()) { - if (!registerWithHeytapMsp(context, appKey, appSecret)) { - registerWithLegacyMcs(context, appKey, appSecret) - } - Log.i(TAG, "OPPO push registration requested") - } else { - Log.w(TAG, "OPPO appKey/appSecret not configured, skipping registration") + runCatching { + HeytapPushManager.init(appContext, false) + if (!HeytapPushManager.isSupportPush(appContext)) { + Log.w(TAG, "OPPO push is not supported on this device") + return } + HeytapPushManager.register(appContext, appKey, appSecret, callback(appContext)) + runCatching { HeytapPushManager.requestNotificationPermission() } + Log.i(TAG, "OPPO push registration requested") }.onFailure { error -> - Log.w(TAG, "OPPO push registration failed: ${error.message}") + Log.e(TAG, "OPPO push registration failed: ${error.message}", error) } } override fun unregister(context: Context) { runCatching { - val pushManagerClass = resolvePushManagerClass() - if (pushManagerClass.name == "com.heytap.msp.push.HeytapPushManager") { - pushManagerClass.getMethod("unRegister").invoke(null) - } else { - val instance = pushManagerClass.getMethod("getInstance").invoke(null) - pushManagerClass.getMethod("unRegister", Context::class.java).invoke(instance, context) - } + HeytapPushManager.unRegister() Log.i(TAG, "OPPO push unregistered") }.onFailure { error -> Log.w(TAG, "OPPO push unregistration failed: ${error.message}") } } - companion object { - 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 callback(context: Context) = object : ICallBackResultService { + override fun onRegister(code: Int, regId: String?) { + if (code == SUCCESS && !regId.isNullOrBlank()) { + PushSDK.updateNativePushToken(context, vendor, regId) + Log.i(TAG, "OPPO push token acquired") + } else { + Log.e(TAG, "OPPO push register callback failed: code=$code, message=$regId") } } - } - 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) + override fun onUnRegister(code: Int) { + Log.i(TAG, "OPPO push unregister callback: code=$code") } - 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 + override fun onSetPushTime(code: Int, message: String?) { + Log.d(TAG, "OPPO set push time callback: code=$code, message=$message") } - 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 + override fun onGetPushStatus(code: Int, status: Int) { + Log.d(TAG, "OPPO push status callback: code=$code, status=$status") } + + override fun onGetNotificationStatus(code: Int, status: Int) { + Log.d(TAG, "OPPO notification status callback: code=$code, status=$status") + } + + override fun onError(code: Int, message: String?) { + Log.e(TAG, "OPPO push error: code=$code, message=$message") + } + } + + private companion object { + const val TAG = "OppoPushService" + const val SUCCESS = 0 } }