feat(android-sdk): 添加完整的IM客户端SDK实现

- 实现了Android SDK的完整IM功能接口,包括消息、群组、好友、会话等核心功能
- 添加了消息收发、历史记录、撤回编辑等完整的消息操作能力
- 实现了群组管理功能,包括创建、成员管理、权限设置等操作
- 添加了好友关系链管理,支持添加、删除、分组等操作
- 实现了会话管理功能,包括置顶、免打扰、已读状态等
- 添加了黑名单、资料管理、搜索等辅助功能
- 补齐了批量操作接口,提升客户端操作效率
- 实现了WebSocket连接管理和事件监听机制
- 添加了离线消息同步和状态管理功能
这个提交包含在:
XuqmGroup 2026-05-02 22:57:55 +08:00
父节点 7e8fc55e41
当前提交 6e42862512
共有 2 个文件被更改,包括 210 次插入7 次删除

查看文件

@ -456,6 +456,182 @@ export class ImClient {
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 {
const body = new AppBody()
body.appId = SDKContext.getConfig().appKey

查看文件

@ -1,4 +1,6 @@
import { push } from '@kit.PushKit'
import { HttpClient } from '../core/HttpClient'
import { SDKContext } from '../core/SDKContext'
class PushRegisterBody {
vendor: string = 'HARMONY'
@ -14,10 +16,35 @@ class PushUnregisterBody {
}
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.
* Call this after obtaining the token from HarmonyOS push service.
* vendor should be 'HARMONY' for HarmonyOS devices.
* Called automatically by initPush(). Only call this manually if you
* obtained the token through your own Push Kit integration.
*/
static async registerToken(token: string, imUserId?: string): Promise<void> {
const body = new PushRegisterBody()
@ -25,15 +52,15 @@ export class PushSDK {
if (imUserId !== undefined) {
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.
*/
static async unregisterToken(token: string): Promise<void> {
const body = new PushUnregisterBody()
body.token = token
await HttpClient.post<void>('/api/v1/push/unregister', body)
static async unregisterToken(imUserId: string): Promise<void> {
const config = SDKContext.getConfig()
const query = `appId=${encodeURIComponent(config.appId)}&userId=${encodeURIComponent(imUserId)}&vendor=HARMONY`
await HttpClient.delete<void>('/api/push/unregister', query)
}
}