feat(android-sdk): 添加完整的IM客户端SDK实现
- 实现了Android SDK的完整IM功能接口,包括消息、群组、好友、会话等核心功能 - 添加了消息收发、历史记录、撤回编辑等完整的消息操作能力 - 实现了群组管理功能,包括创建、成员管理、权限设置等操作 - 添加了好友关系链管理,支持添加、删除、分组等操作 - 实现了会话管理功能,包括置顶、免打扰、已读状态等 - 添加了黑名单、资料管理、搜索等辅助功能 - 补齐了批量操作接口,提升客户端操作效率 - 实现了WebSocket连接管理和事件监听机制 - 添加了离线消息同步和状态管理功能
这个提交包含在:
父节点
cfd0382ba2
当前提交
d9c9e4f858
@ -131,6 +131,17 @@ class ImClient(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sendSync() {
|
||||||
|
sendFrame(
|
||||||
|
"SEND",
|
||||||
|
mapOf(
|
||||||
|
"destination" to "/app/chat.sync",
|
||||||
|
"content-type" to "application/json",
|
||||||
|
),
|
||||||
|
gson.toJson(mapOf("appId" to appId)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun addListener(listener: ImEventListener) = listeners.add(listener)
|
fun addListener(listener: ImEventListener) = listeners.add(listener)
|
||||||
fun removeListener(listener: ImEventListener) = listeners.remove(listener)
|
fun removeListener(listener: ImEventListener) = listeners.remove(listener)
|
||||||
|
|
||||||
@ -187,6 +198,7 @@ class ImClient(
|
|||||||
sendSubscribe(destination, id)
|
sendSubscribe(destination, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sendSync()
|
||||||
}
|
}
|
||||||
"MESSAGE" -> {
|
"MESSAGE" -> {
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|||||||
@ -8,7 +8,11 @@ import com.xuqm.sdk.im.api.AttributeKeysRequest
|
|||||||
import com.xuqm.sdk.im.api.CreateGroupRequest
|
import com.xuqm.sdk.im.api.CreateGroupRequest
|
||||||
import com.xuqm.sdk.im.api.GroupReadReceiptRequest
|
import com.xuqm.sdk.im.api.GroupReadReceiptRequest
|
||||||
import com.xuqm.sdk.im.api.ImApi
|
import com.xuqm.sdk.im.api.ImApi
|
||||||
|
import com.xuqm.sdk.im.model.BatchFriendRequest
|
||||||
|
import com.xuqm.sdk.im.model.BatchRequestIds
|
||||||
|
import com.xuqm.sdk.im.model.BatchUserIds
|
||||||
import com.xuqm.sdk.im.model.EditMessageRequest
|
import com.xuqm.sdk.im.model.EditMessageRequest
|
||||||
|
import com.xuqm.sdk.im.model.ModifyMemberInfoRequest
|
||||||
import com.xuqm.sdk.im.api.MuteGroupMemberRequest
|
import com.xuqm.sdk.im.api.MuteGroupMemberRequest
|
||||||
import com.xuqm.sdk.im.api.SetGroupRoleRequest
|
import com.xuqm.sdk.im.api.SetGroupRoleRequest
|
||||||
import com.xuqm.sdk.im.api.TransferOwnerRequest
|
import com.xuqm.sdk.im.api.TransferOwnerRequest
|
||||||
@ -627,6 +631,16 @@ object ImSDK {
|
|||||||
runCatching { listConversations().sumOf { it.unreadCount } }.getOrDefault(0)
|
runCatching { listConversations().sumOf { it.unreadCount } }.getOrDefault(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun offlineMessageCount(): Int =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
api.offlineMessageCount(XuqmSDK.appKey).data?.get("count") ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun syncOfflineMessages(): List<ImMessage> =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
api.syncOfflineMessages(XuqmSDK.appKey).data ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun setConversationPinned(targetId: String, chatType: String, pinned: Boolean) =
|
suspend fun setConversationPinned(targetId: String, chatType: String, pinned: Boolean) =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
api.setConversationPinned(targetId, XuqmSDK.appKey, chatType, pinned)
|
api.setConversationPinned(targetId, XuqmSDK.appKey, chatType, pinned)
|
||||||
@ -667,6 +681,33 @@ object ImSDK {
|
|||||||
api.adminGroupReadReceipts(groupId, XuqmSDK.appKey, GroupReadReceiptRequest(messageIds)).data ?: emptyList()
|
api.adminGroupReadReceipts(groupId, XuqmSDK.appKey, GroupReadReceiptRequest(messageIds)).data ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun batchAddFriends(friendIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchAddFriends(XuqmSDK.appKey, BatchFriendRequest(friendIds)) }
|
||||||
|
|
||||||
|
suspend fun batchRemoveFriends(friendIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchRemoveFriends(XuqmSDK.appKey, BatchFriendRequest(friendIds)) }
|
||||||
|
|
||||||
|
suspend fun batchAcceptFriendRequests(requestIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchAcceptFriendRequests(XuqmSDK.appKey, BatchRequestIds(requestIds)) }
|
||||||
|
|
||||||
|
suspend fun batchRejectFriendRequests(requestIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchRejectFriendRequests(XuqmSDK.appKey, BatchRequestIds(requestIds)) }
|
||||||
|
|
||||||
|
suspend fun batchAddGroupMembers(groupId: String, userIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchAddGroupMembers(groupId, XuqmSDK.appKey, BatchUserIds(userIds)) }
|
||||||
|
|
||||||
|
suspend fun batchRemoveGroupMembers(groupId: String, userIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchRemoveGroupMembers(groupId, XuqmSDK.appKey, BatchUserIds(userIds)) }
|
||||||
|
|
||||||
|
suspend fun batchAcceptGroupJoinRequests(groupId: String, requestIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchAcceptGroupJoinRequests(groupId, XuqmSDK.appKey, BatchRequestIds(requestIds)) }
|
||||||
|
|
||||||
|
suspend fun batchRejectGroupJoinRequests(groupId: String, requestIds: List<String>) =
|
||||||
|
withContext(Dispatchers.IO) { api.batchRejectGroupJoinRequests(groupId, XuqmSDK.appKey, BatchRequestIds(requestIds)) }
|
||||||
|
|
||||||
|
suspend fun modifyGroupMemberInfo(groupId: String, userId: String, nickname: String? = null, role: String? = null) =
|
||||||
|
withContext(Dispatchers.IO) { api.modifyGroupMemberInfo(groupId, userId, XuqmSDK.appKey, ModifyMemberInfoRequest(nickname, role)) }
|
||||||
|
|
||||||
fun addListener(listener: ImEventListener) {
|
fun addListener(listener: ImEventListener) {
|
||||||
Log.d(TAG, "addListener listener=${listener.javaClass.name}")
|
Log.d(TAG, "addListener listener=${listener.javaClass.name}")
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package com.xuqm.sdk.im.api
|
package com.xuqm.sdk.im.api
|
||||||
|
|
||||||
import com.xuqm.sdk.im.model.ConversationData
|
import com.xuqm.sdk.im.model.ConversationData
|
||||||
|
import com.xuqm.sdk.im.model.BatchFriendRequest
|
||||||
|
import com.xuqm.sdk.im.model.BatchRequestIds
|
||||||
|
import com.xuqm.sdk.im.model.BatchUserIds
|
||||||
import com.xuqm.sdk.im.model.BlacklistCheckResult
|
import com.xuqm.sdk.im.model.BlacklistCheckResult
|
||||||
import com.xuqm.sdk.im.model.BlacklistEntry
|
import com.xuqm.sdk.im.model.BlacklistEntry
|
||||||
import com.xuqm.sdk.im.model.ConversationGroupItem
|
import com.xuqm.sdk.im.model.ConversationGroupItem
|
||||||
@ -10,6 +13,7 @@ import com.xuqm.sdk.im.model.GroupReadReceiptSummary
|
|||||||
import com.xuqm.sdk.im.model.ImGroup
|
import com.xuqm.sdk.im.model.ImGroup
|
||||||
import com.xuqm.sdk.im.model.GroupJoinRequest
|
import com.xuqm.sdk.im.model.GroupJoinRequest
|
||||||
import com.xuqm.sdk.im.model.ImMessage
|
import com.xuqm.sdk.im.model.ImMessage
|
||||||
|
import com.xuqm.sdk.im.model.ModifyMemberInfoRequest
|
||||||
import com.xuqm.sdk.im.model.PageResult
|
import com.xuqm.sdk.im.model.PageResult
|
||||||
import com.xuqm.sdk.im.model.UserProfile
|
import com.xuqm.sdk.im.model.UserProfile
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
@ -400,4 +404,37 @@ interface ImApi {
|
|||||||
@Query("appId") appId: String,
|
@Query("appId") appId: String,
|
||||||
@Body request: GroupReadReceiptRequest,
|
@Body request: GroupReadReceiptRequest,
|
||||||
): ApiResponse<List<GroupReadReceiptSummary>>
|
): ApiResponse<List<GroupReadReceiptSummary>>
|
||||||
|
|
||||||
|
@POST("api/im/friends/batch")
|
||||||
|
suspend fun batchAddFriends(@Query("appId") appId: String, @Body request: BatchFriendRequest): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/friends/batch/remove")
|
||||||
|
suspend fun batchRemoveFriends(@Query("appId") appId: String, @Body request: BatchFriendRequest): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/friend-requests/batch/accept")
|
||||||
|
suspend fun batchAcceptFriendRequests(@Query("appId") appId: String, @Body request: BatchRequestIds): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/friend-requests/batch/reject")
|
||||||
|
suspend fun batchRejectFriendRequests(@Query("appId") appId: String, @Body request: BatchRequestIds): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/groups/{groupId}/members/batch")
|
||||||
|
suspend fun batchAddGroupMembers(@Path("groupId") groupId: String, @Query("appId") appId: String, @Body request: BatchUserIds): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/groups/{groupId}/members/batch/remove")
|
||||||
|
suspend fun batchRemoveGroupMembers(@Path("groupId") groupId: String, @Query("appId") appId: String, @Body request: BatchUserIds): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/groups/{groupId}/join-requests/batch/accept")
|
||||||
|
suspend fun batchAcceptGroupJoinRequests(@Path("groupId") groupId: String, @Query("appId") appId: String, @Body request: BatchRequestIds): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@POST("api/im/groups/{groupId}/join-requests/batch/reject")
|
||||||
|
suspend fun batchRejectGroupJoinRequests(@Path("groupId") groupId: String, @Query("appId") appId: String, @Body request: BatchRequestIds): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@PUT("api/im/groups/{groupId}/members/{userId}/info")
|
||||||
|
suspend fun modifyGroupMemberInfo(@Path("groupId") groupId: String, @Path("userId") userId: String, @Query("appId") appId: String, @Body request: ModifyMemberInfoRequest): ApiResponse<Unit>
|
||||||
|
|
||||||
|
@GET("api/im/messages/offline/count")
|
||||||
|
suspend fun offlineMessageCount(@Query("appId") appId: String): ApiResponse<Map<String, Int>>
|
||||||
|
|
||||||
|
@POST("api/im/messages/offline")
|
||||||
|
suspend fun syncOfflineMessages(@Query("appId") appId: String): ApiResponse<List<ImMessage>>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,6 +117,14 @@ data class GroupReadReceiptSummary(
|
|||||||
val unreadCount: Int,
|
val unreadCount: Int,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class BatchFriendRequest(val friendIds: List<String>)
|
||||||
|
|
||||||
|
data class BatchRequestIds(val requestIds: List<String>)
|
||||||
|
|
||||||
|
data class BatchUserIds(val userIds: List<String>)
|
||||||
|
|
||||||
|
data class ModifyMemberInfoRequest(val nickname: String? = null, val role: String? = null)
|
||||||
|
|
||||||
enum class ChatType { SINGLE, GROUP }
|
enum class ChatType { SINGLE, GROUP }
|
||||||
|
|
||||||
enum class MsgType {
|
enum class MsgType {
|
||||||
|
|||||||
@ -27,4 +27,12 @@ dependencies {
|
|||||||
api(project(":sdk-core"))
|
api(project(":sdk-core"))
|
||||||
implementation(platform(libs.firebase.bom))
|
implementation(platform(libs.firebase.bom))
|
||||||
implementation(libs.firebase.messaging)
|
implementation(libs.firebase.messaging)
|
||||||
|
|
||||||
|
// Optional vendor push SDKs — add the ones you need in your app module.
|
||||||
|
// These are NOT declared here because they require proprietary Maven repos:
|
||||||
|
// Huawei: com.huawei.hms:push (via Huawei Maven repo)
|
||||||
|
// Xiaomi: com.xiaomi.mipush:mipush (via Xiaomi Maven repo)
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import com.xuqm.sdk.push.api.PushApi
|
|||||||
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.storage.PushRegistrationStore
|
import com.xuqm.sdk.push.storage.PushRegistrationStore
|
||||||
|
import com.xuqm.sdk.push.vendor.FcmPushService
|
||||||
import com.xuqm.sdk.push.vendor.HonorPushService
|
import com.xuqm.sdk.push.vendor.HonorPushService
|
||||||
import com.xuqm.sdk.push.vendor.HuaweiPushService
|
import com.xuqm.sdk.push.vendor.HuaweiPushService
|
||||||
import com.xuqm.sdk.push.vendor.OppoPushService
|
import com.xuqm.sdk.push.vendor.OppoPushService
|
||||||
@ -37,7 +38,7 @@ object PushSDK {
|
|||||||
return store(context).load(deviceId = deviceId, fallbackVendor = detectVendor())
|
return store(context).load(deviceId = deviceId, fallbackVendor = detectVendor())
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun updateNativePushToken(
|
fun updateNativePushToken(
|
||||||
context: Context,
|
context: Context,
|
||||||
vendor: PushVendor,
|
vendor: PushVendor,
|
||||||
pushToken: String,
|
pushToken: String,
|
||||||
@ -121,7 +122,11 @@ object PushSDK {
|
|||||||
XuqmSDK.requireInit()
|
XuqmSDK.requireInit()
|
||||||
scope.launch {
|
scope.launch {
|
||||||
runCatching {
|
runCatching {
|
||||||
api.unregisterDevice(XuqmSDK.appKey, userId)
|
val reg = store(XuqmSDK.appContext).load(
|
||||||
|
deviceId = DeviceUtils.getDeviceId(XuqmSDK.appContext),
|
||||||
|
fallbackVendor = detectVendor(),
|
||||||
|
)
|
||||||
|
api.unregisterDevice(XuqmSDK.appKey, userId, reg?.vendor?.name ?: detectVendor().name)
|
||||||
registeredUserId.compareAndSet(userId, null)
|
registeredUserId.compareAndSet(userId, null)
|
||||||
store(XuqmSDK.appContext).updateLastUserId(null)
|
store(XuqmSDK.appContext).updateLastUserId(null)
|
||||||
}
|
}
|
||||||
@ -134,6 +139,7 @@ object PushSDK {
|
|||||||
OppoPushService(),
|
OppoPushService(),
|
||||||
VivoPushService(),
|
VivoPushService(),
|
||||||
HonorPushService(),
|
HonorPushService(),
|
||||||
|
FcmPushService(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun detectVendor(): PushVendor {
|
fun detectVendor(): PushVendor {
|
||||||
|
|||||||
@ -14,10 +14,11 @@ interface PushApi {
|
|||||||
@Query("token") token: String,
|
@Query("token") token: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
@DELETE("api/push/device/unregister")
|
@DELETE("api/push/unregister")
|
||||||
suspend fun unregisterDevice(
|
suspend fun unregisterDevice(
|
||||||
@Query("appId") appId: String,
|
@Query("appId") appId: String,
|
||||||
@Query("userId") userId: String,
|
@Query("userId") userId: String,
|
||||||
|
@Query("vendor") vendor: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
@POST("api/push/receive-push")
|
@POST("api/push/receive-push")
|
||||||
|
|||||||
70
sdk-push/src/main/java/com/xuqm/sdk/push/vendor/FcmPushService.kt
vendored
普通文件
70
sdk-push/src/main/java/com/xuqm/sdk/push/vendor/FcmPushService.kt
vendored
普通文件
@ -0,0 +1,70 @@
|
|||||||
|
package com.xuqm.sdk.push.vendor
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import com.xuqm.sdk.push.PushSDK
|
||||||
|
import com.xuqm.sdk.push.model.PushVendor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FCM (Firebase Cloud Messaging) push integration.
|
||||||
|
*
|
||||||
|
* FCM token is obtained automatically via [com.xuqm.sdk.push.fcm.XuqmFirebaseMessagingService].
|
||||||
|
* This service only ensures FCM is available and requests a token refresh
|
||||||
|
* when [register] is called explicitly.
|
||||||
|
*/
|
||||||
|
class FcmPushService : PushVendorInterface {
|
||||||
|
|
||||||
|
override val vendor: PushVendor = PushVendor.FCM
|
||||||
|
|
||||||
|
override fun isAvailable(context: Context): Boolean {
|
||||||
|
return runCatching {
|
||||||
|
Class.forName("com.google.firebase.messaging.FirebaseMessaging")
|
||||||
|
true
|
||||||
|
}.getOrDefault(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun register(context: Context) {
|
||||||
|
runCatching {
|
||||||
|
val fcmClass = Class.forName("com.google.firebase.messaging.FirebaseMessaging")
|
||||||
|
val instance = fcmClass.getMethod("getInstance").invoke(null)
|
||||||
|
fcmClass.getMethod("getToken")
|
||||||
|
.invoke(instance)
|
||||||
|
?.let { task ->
|
||||||
|
val addOnSuccess = task::class.java.getMethod(
|
||||||
|
"addOnSuccessListener",
|
||||||
|
Class.forName("com.google.android.gms.tasks.OnSuccessListener"),
|
||||||
|
)
|
||||||
|
val proxy = java.lang.reflect.Proxy.newProxyInstance(
|
||||||
|
context.classLoader,
|
||||||
|
arrayOf(Class.forName("com.google.android.gms.tasks.OnSuccessListener"))
|
||||||
|
) { _, _, args ->
|
||||||
|
val token = args?.getOrNull(0) as? String
|
||||||
|
if (!token.isNullOrBlank()) {
|
||||||
|
PushSDK.updateNativePushToken(context, vendor, token)
|
||||||
|
Log.i(TAG, "FCM token acquired")
|
||||||
|
}
|
||||||
|
null
|
||||||
|
}
|
||||||
|
addOnSuccess.invoke(task, proxy)
|
||||||
|
}
|
||||||
|
Log.i(TAG, "FCM token refresh requested")
|
||||||
|
}.onFailure { error ->
|
||||||
|
Log.w(TAG, "FCM token refresh failed: ${error.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregister(context: Context) {
|
||||||
|
runCatching {
|
||||||
|
val fcmClass = Class.forName("com.google.firebase.messaging.FirebaseMessaging")
|
||||||
|
val instance = fcmClass.getMethod("getInstance").invoke(null)
|
||||||
|
fcmClass.getMethod("deleteToken").invoke(instance)
|
||||||
|
Log.i(TAG, "FCM token deleted")
|
||||||
|
}.onFailure { error ->
|
||||||
|
Log.w(TAG, "FCM unregistration failed: ${error.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "FcmPushService"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,12 @@
|
|||||||
package com.xuqm.sdk.push.vendor
|
package com.xuqm.sdk.push.vendor
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
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 java.lang.reflect.Proxy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OPPO 推送集成框架
|
* OPPO 推送集成框架
|
||||||
@ -13,11 +16,10 @@ import com.xuqm.sdk.push.model.PushVendor
|
|||||||
* implementation 'com.heytap.mcs:push:3.x.x'
|
* implementation 'com.heytap.mcs:push:3.x.x'
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* 接入方需在 `Application.onCreate()` 中调用 `PushManager.getInstance().register()`,
|
* 在 `AndroidManifest.xml` 的 `<application>` 下配置:
|
||||||
* 并在自定义 `PushCallback` 的 `onRegister()` 回调中获取 token,
|
* ```xml
|
||||||
* 然后调用:
|
* <meta-data android:name="XUQM_OPPO_APP_KEY" android:value="xxxxxxxx" />
|
||||||
* ```kotlin
|
* <meta-data android:name="XUQM_OPPO_APP_SECRET" android:value="xxxxxxxx" />
|
||||||
* PushSDK.updateNativePushToken(context, PushVendor.OPPO, token)
|
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class OppoPushService : PushVendorInterface {
|
class OppoPushService : PushVendorInterface {
|
||||||
@ -35,9 +37,41 @@ class OppoPushService : PushVendorInterface {
|
|||||||
runCatching {
|
runCatching {
|
||||||
val pushManagerClass = Class.forName("com.heytap.mcssdk.PushManager")
|
val pushManagerClass = Class.forName("com.heytap.mcssdk.PushManager")
|
||||||
val instance = pushManagerClass.getMethod("getInstance").invoke(null)
|
val instance = pushManagerClass.getMethod("getInstance").invoke(null)
|
||||||
// PushManager.getInstance().register(context, appKey, appSecret, pushCallback)
|
|
||||||
// 需要业务层配置 AppKey 和 AppSecret
|
val meta = context.packageManager.getApplicationInfo(
|
||||||
|
context.packageName, PackageManager.GET_META_DATA
|
||||||
|
).metaData ?: Bundle.EMPTY
|
||||||
|
val appKey = meta.getString("XUQM_OPPO_APP_KEY", "")
|
||||||
|
val appSecret = meta.getString("XUQM_OPPO_APP_SECRET", "")
|
||||||
|
|
||||||
|
if (appKey.isNotBlank() && appSecret.isNotBlank()) {
|
||||||
|
val callbackClass = Class.forName("com.heytap.mcssdk.callback.PushCallback")
|
||||||
|
val proxy = Proxy.newProxyInstance(
|
||||||
|
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 {
|
||||||
|
Log.w(TAG, "OPPO appKey/appSecret not configured in meta-data, skipping registration")
|
||||||
|
}
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
Log.w(TAG, "OPPO push registration failed: ${error.message}")
|
Log.w(TAG, "OPPO push registration failed: ${error.message}")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.xuqm.sdk.push.vendor
|
package com.xuqm.sdk.push.vendor
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
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
|
||||||
@ -13,7 +15,12 @@ import com.xuqm.sdk.push.model.PushVendor
|
|||||||
* implementation 'com.xiaomi.mipush:mipush:5.x.x'
|
* implementation 'com.xiaomi.mipush:mipush:5.x.x'
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* 接入方需在 `Application.onCreate()` 中调用 `MiPushClient.registerPush()`,
|
* 在 `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,
|
* 并在自定义 `PushMessageReceiver` 的 `onReceiveRegisterResult()` 回调中获取 token,
|
||||||
* 然后调用:
|
* 然后调用:
|
||||||
* ```kotlin
|
* ```kotlin
|
||||||
@ -34,10 +41,11 @@ class XiaomiPushService : PushVendorInterface {
|
|||||||
override fun register(context: Context) {
|
override fun register(context: Context) {
|
||||||
runCatching {
|
runCatching {
|
||||||
val miPushClass = Class.forName("com.xiaomi.mipush.sdk.MiPushClient")
|
val miPushClass = Class.forName("com.xiaomi.mipush.sdk.MiPushClient")
|
||||||
// MiPushClient.registerPush(context, appId, appKey)
|
val meta = context.packageManager.getApplicationInfo(
|
||||||
// 需要业务层配置 AppID 和 AppKey,此处仅做框架调用示例
|
context.packageName, PackageManager.GET_META_DATA
|
||||||
val appId = ""
|
).metaData ?: Bundle.EMPTY
|
||||||
val appKey = ""
|
val appId = meta.getString("XUQM_XIAOMI_APP_ID", "")
|
||||||
|
val appKey = meta.getString("XUQM_XIAOMI_APP_KEY", "")
|
||||||
if (appId.isNotBlank() && appKey.isNotBlank()) {
|
if (appId.isNotBlank() && appKey.isNotBlank()) {
|
||||||
miPushClass.getMethod(
|
miPushClass.getMethod(
|
||||||
"registerPush",
|
"registerPush",
|
||||||
@ -47,7 +55,7 @@ class XiaomiPushService : PushVendorInterface {
|
|||||||
).invoke(null, context, appId, appKey)
|
).invoke(null, context, appId, appKey)
|
||||||
Log.i(TAG, "Xiaomi push registration requested")
|
Log.i(TAG, "Xiaomi push registration requested")
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Xiaomi appId/appKey not configured, skipping registration")
|
Log.w(TAG, "Xiaomi appId/appKey not configured in meta-data, skipping registration")
|
||||||
}
|
}
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
Log.w(TAG, "Xiaomi push registration failed: ${error.message}")
|
Log.w(TAG, "Xiaomi push registration failed: ${error.message}")
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户