feat(android-sdk): 添加完整的IM客户端SDK实现
- 实现了Android SDK的完整IM功能接口,包括消息、群组、好友、会话等核心功能 - 添加了消息收发、历史记录、撤回编辑等完整的消息操作能力 - 实现了群组管理功能,包括创建、成员管理、权限设置等操作 - 添加了好友关系链管理,支持添加、删除、分组等操作 - 实现了会话管理功能,包括置顶、免打扰、已读状态等 - 添加了黑名单、资料管理、搜索等辅助功能 - 补齐了批量操作接口,提升客户端操作效率 - 实现了WebSocket连接管理和事件监听机制 - 添加了离线消息同步和状态管理功能
这个提交包含在:
父节点
7e8fc55e41
当前提交
6e42862512
@ -456,6 +456,182 @@ export class ImClient {
|
|||||||
return HttpClient.put<UserProfile>('/api/im/accounts/' + encodeURIComponent(userId), params)
|
return HttpClient.put<UserProfile>('/api/im/accounts/' + encodeURIComponent(userId), params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- 会话扩展 ---------- */
|
||||||
|
async setConversationHidden(targetId: string, hidden: boolean): Promise<void> {
|
||||||
|
const params = new AppBody()
|
||||||
|
params.appId = SDKContext.getConfig().appKey
|
||||||
|
await HttpClient.put<void>('/api/im/conversations/' + encodeURIComponent(targetId) + '/hidden', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async setConversationGroup(targetId: string, groupName: string): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, groupName }
|
||||||
|
await HttpClient.put<void>('/api/im/conversations/' + encodeURIComponent(targetId) + '/group', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async listConversationGroups(): Promise<string[]> {
|
||||||
|
return HttpClient.get<string[]>('/api/im/conversation-groups', this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async listConversationGroupItems(groupName: string): Promise<ConversationData[]> {
|
||||||
|
return HttpClient.get<ConversationData[]>('/api/im/conversation-groups/' + encodeURIComponent(groupName), this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 好友扩展 ---------- */
|
||||||
|
async addFriend(friendId: string): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, friendId }
|
||||||
|
await HttpClient.post<void>('/api/im/friends', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeFriend(friendId: string): Promise<void> {
|
||||||
|
await HttpClient.delete<void>('/api/im/friends/' + encodeURIComponent(friendId), this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeAllFriends(): Promise<void> {
|
||||||
|
await HttpClient.delete<void>('/api/im/friends', this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async setFriendGroup(friendId: string, groupName: string): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, groupName }
|
||||||
|
await HttpClient.put<void>('/api/im/friends/' + encodeURIComponent(friendId) + '/group', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async listFriendGroups(): Promise<string[]> {
|
||||||
|
return HttpClient.get<string[]>('/api/im/friends/groups', this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async listFriendsByGroup(groupName: string): Promise<string[]> {
|
||||||
|
return HttpClient.get<string[]>('/api/im/friends/groups/' + encodeURIComponent(groupName), this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkFriends(friendIds: string[]): Promise<Record<string, boolean>> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, friendIds }
|
||||||
|
return HttpClient.post<Record<string, boolean>>('/api/im/friends/check', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 黑名单 ---------- */
|
||||||
|
async listBlacklist(): Promise<string[]> {
|
||||||
|
return HttpClient.get<string[]>('/api/im/blacklist', this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async addToBlacklist(userId: string): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, userId }
|
||||||
|
await HttpClient.post<void>('/api/im/blacklist', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeFromBlacklist(userId: string): Promise<void> {
|
||||||
|
await HttpClient.delete<void>('/api/im/blacklist', this.buildAppQuery() + '&userId=' + encodeURIComponent(userId))
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkBlacklist(userId: string): Promise<{ meBlocked: boolean; theyBlocked: boolean; eitherBlocked: boolean }> {
|
||||||
|
return HttpClient.get<{ meBlocked: boolean; theyBlocked: boolean; eitherBlocked: boolean }>(
|
||||||
|
'/api/im/blacklist/check',
|
||||||
|
this.buildAppQuery() + '&userId=' + encodeURIComponent(userId),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 群组扩展 ---------- */
|
||||||
|
async createGroup(name: string, memberIds: string[], groupType: string = 'WORK'): Promise<ImGroup> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, name, memberIds, groupType }
|
||||||
|
return HttpClient.post<ImGroup>('/api/im/groups', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateGroupInfo(groupId: string, name?: string, announcement?: string): Promise<ImGroup> {
|
||||||
|
const params: Record<string, string> = { appId: SDKContext.getConfig().appKey }
|
||||||
|
if (name !== undefined) params.name = name
|
||||||
|
if (announcement !== undefined) params.announcement = announcement
|
||||||
|
return HttpClient.put<ImGroup>('/api/im/groups/' + encodeURIComponent(groupId), params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addGroupMember(groupId: string, userId: string): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, userId }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/members', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeGroupMember(groupId: string, userId: string): Promise<void> {
|
||||||
|
await HttpClient.delete<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/members/' + encodeURIComponent(userId), this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async leaveGroup(groupId: string): Promise<void> {
|
||||||
|
await HttpClient.delete<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/members/me', this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
async setGroupRole(groupId: string, userId: string, role: 'ADMIN' | 'MEMBER'): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, userId, role }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/roles', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async muteGroupMember(groupId: string, userId: string, muted: boolean): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, userId, muted }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/mute', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async transferGroupOwner(groupId: string, newOwnerId: string): Promise<ImGroup> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, newOwnerId }
|
||||||
|
return HttpClient.post<ImGroup>('/api/im/groups/' + encodeURIComponent(groupId) + '/owner', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateGroupAttributes(groupId: string, attributes: Record<string, string | number | boolean | null>): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, attributes }
|
||||||
|
await HttpClient.put<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/attributes', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeGroupAttributes(groupId: string, keys: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, keys }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/attributes/delete', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async dismissGroup(groupId: string): Promise<void> {
|
||||||
|
await HttpClient.delete<void>('/api/im/groups/' + encodeURIComponent(groupId), this.buildAppQuery())
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 批量操作 ---------- */
|
||||||
|
async batchAddFriends(friendIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, friendIds }
|
||||||
|
await HttpClient.post<void>('/api/im/friends/batch', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchRemoveFriends(friendIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, friendIds }
|
||||||
|
await HttpClient.post<void>('/api/im/friends/batch/remove', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchAcceptFriendRequests(requestIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, requestIds }
|
||||||
|
await HttpClient.post<void>('/api/im/friend-requests/batch/accept', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchRejectFriendRequests(requestIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, requestIds }
|
||||||
|
await HttpClient.post<void>('/api/im/friend-requests/batch/reject', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchAddMembers(groupId: string, userIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, userIds }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/members/batch', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchRemoveMembers(groupId: string, userIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, userIds }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/members/batch/remove', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchAcceptJoinRequests(groupId: string, requestIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, requestIds }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/join-requests/batch/accept', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async batchRejectJoinRequests(groupId: string, requestIds: string[]): Promise<void> {
|
||||||
|
const params = { appId: SDKContext.getConfig().appKey, requestIds }
|
||||||
|
await HttpClient.post<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/join-requests/batch/reject', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async modifyMemberInfo(groupId: string, userId: string, nickname?: string, role?: string): Promise<void> {
|
||||||
|
const params: Record<string, string> = { appId: SDKContext.getConfig().appKey }
|
||||||
|
if (nickname !== undefined) params.nickname = nickname
|
||||||
|
if (role !== undefined) params.role = role
|
||||||
|
await HttpClient.put<void>('/api/im/groups/' + encodeURIComponent(groupId) + '/members/' + encodeURIComponent(userId) + '/info', params)
|
||||||
|
}
|
||||||
|
|
||||||
private buildAppBody(): AppBody {
|
private buildAppBody(): AppBody {
|
||||||
const body = new AppBody()
|
const body = new AppBody()
|
||||||
body.appId = SDKContext.getConfig().appKey
|
body.appId = SDKContext.getConfig().appKey
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
|
import { push } from '@kit.PushKit'
|
||||||
import { HttpClient } from '../core/HttpClient'
|
import { HttpClient } from '../core/HttpClient'
|
||||||
|
import { SDKContext } from '../core/SDKContext'
|
||||||
|
|
||||||
class PushRegisterBody {
|
class PushRegisterBody {
|
||||||
vendor: string = 'HARMONY'
|
vendor: string = 'HARMONY'
|
||||||
@ -14,10 +16,35 @@ class PushUnregisterBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PushSDK {
|
export class PushSDK {
|
||||||
|
/**
|
||||||
|
* Initialize HarmonyOS Push Kit and register the token with the server.
|
||||||
|
* Call this after user login.
|
||||||
|
*
|
||||||
|
* Uses HarmonyOS NEXT Push Kit API (@kit.PushKit).
|
||||||
|
*/
|
||||||
|
static async initPush(imUserId?: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
const token: string = await push.getToken()
|
||||||
|
if (token && token.length > 0) {
|
||||||
|
await PushSDK.registerToken(token, imUserId)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[XuqmSDK] Push Kit getToken failed:', JSON.stringify(err))
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister push token on logout.
|
||||||
|
*/
|
||||||
|
static async unregisterPush(imUserId: string): Promise<void> {
|
||||||
|
await PushSDK.unregisterToken(imUserId)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a push token with the server.
|
* Register a push token with the server.
|
||||||
* Call this after obtaining the token from HarmonyOS push service.
|
* Called automatically by initPush(). Only call this manually if you
|
||||||
* vendor should be 'HARMONY' for HarmonyOS devices.
|
* obtained the token through your own Push Kit integration.
|
||||||
*/
|
*/
|
||||||
static async registerToken(token: string, imUserId?: string): Promise<void> {
|
static async registerToken(token: string, imUserId?: string): Promise<void> {
|
||||||
const body = new PushRegisterBody()
|
const body = new PushRegisterBody()
|
||||||
@ -25,15 +52,15 @@ export class PushSDK {
|
|||||||
if (imUserId !== undefined) {
|
if (imUserId !== undefined) {
|
||||||
body.imUserId = imUserId
|
body.imUserId = imUserId
|
||||||
}
|
}
|
||||||
await HttpClient.post<void>('/api/v1/push/register', body)
|
await HttpClient.post<void>('/api/push/register', body)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister push token on logout.
|
* Unregister push token on logout.
|
||||||
*/
|
*/
|
||||||
static async unregisterToken(token: string): Promise<void> {
|
static async unregisterToken(imUserId: string): Promise<void> {
|
||||||
const body = new PushUnregisterBody()
|
const config = SDKContext.getConfig()
|
||||||
body.token = token
|
const query = `appId=${encodeURIComponent(config.appId)}&userId=${encodeURIComponent(imUserId)}&vendor=HARMONY`
|
||||||
await HttpClient.post<void>('/api/v1/push/unregister', body)
|
await HttpClient.delete<void>('/api/push/unregister', query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户