File Management
Listen for Attachment Upload
When sending custom attachment messages, the message sent to the recipient is a network address, not the actual file. In this case, we need to listen for attachment uploads.Copy
WKIM.getInstance().getMsgManager().addOnUploadAttachListener(new IUploadAttachmentListener() {
@Override
public void onUploadAttachmentListener(WKMsg wkMsg, IUploadAttacResultListener listener) {
// Upload unuploaded files to server and return to SDK
if(wkMsg.type == WKMsgContentType.WK_IMAGE){
WKMediaMessageContent mediaMessageContent = (WKMediaMessageContent) wkMsg.baseContentMsgModel;
if (TextUtils.isEmpty(mediaMessageContent.url)) {
// TODO: Upload file
// ...
mediaMessageContent.url = "xxxxxx"; // Set network address and return to SDK
listener.onUploadResult(true, mediaMessageContent);
}
}
}
});
Listen for Attachment Download
The SDK will not actively download message attachments. When receiving messages with attachments, the app needs to download them as needed. After the app completes the download, it can change the local file address to avoid repeated downloads.Copy
/**
* Update message content
*
* @param clientMsgNo Client message ID
* @param messageContent Message module - save local address in messageContent
* @param isRefreshUI Whether to notify UI to refresh corresponding message
*/
WKIM.getInstance().getMsgManager().updateContent(String clientMsgNo, WKMessageContent messageContent, boolean isRefreshUI);
Complete File Management Example
Copy
public class FileManager {
private static final String TAG = "FileManager";
public void initialize() {
// Set file upload listener
WKIM.getInstance().getMsgManager().addOnUploadAttachListener(this::handleFileUpload);
}
private void handleFileUpload(WKMsg wkMsg, IUploadAttacResultListener listener) {
switch (wkMsg.type) {
case WKMsgContentType.WK_IMAGE:
uploadImage(wkMsg, listener);
break;
case WKMsgContentType.WK_VIDEO:
uploadVideo(wkMsg, listener);
break;
case WKMsgContentType.WK_VOICE:
uploadVoice(wkMsg, listener);
break;
case WKMsgContentType.WK_FILE:
uploadFile(wkMsg, listener);
break;
default:
listener.onUploadResult(false, null);
break;
}
}
private void uploadImage(WKMsg wkMsg, IUploadAttacResultListener listener) {
WKImageContent imageContent = (WKImageContent) wkMsg.baseContentMsgModel;
if (!TextUtils.isEmpty(imageContent.url)) {
// Already has network address, return directly
listener.onUploadResult(true, imageContent);
return;
}
// Upload image to server
String localPath = imageContent.localPath;
if (TextUtils.isEmpty(localPath)) {
listener.onUploadResult(false, null);
return;
}
// Async upload
uploadFileToServer(localPath, "image", new UploadCallback() {
@Override
public void onSuccess(String url) {
imageContent.url = url;
listener.onUploadResult(true, imageContent);
}
@Override
public void onError(String error) {
Log.e(TAG, "Image upload failed: " + error);
listener.onUploadResult(false, null);
}
});
}
private void uploadVideo(WKMsg wkMsg, IUploadAttacResultListener listener) {
WKVideoContent videoContent = (WKVideoContent) wkMsg.baseContentMsgModel;
if (!TextUtils.isEmpty(videoContent.url)) {
listener.onUploadResult(true, videoContent);
return;
}
String localPath = videoContent.localPath;
if (TextUtils.isEmpty(localPath)) {
listener.onUploadResult(false, null);
return;
}
// Upload video and thumbnail
uploadFileToServer(localPath, "video", new UploadCallback() {
@Override
public void onSuccess(String url) {
videoContent.url = url;
// If there's a thumbnail, upload it too
if (!TextUtils.isEmpty(videoContent.coverLocalPath)) {
uploadFileToServer(videoContent.coverLocalPath, "image", new UploadCallback() {
@Override
public void onSuccess(String coverUrl) {
videoContent.cover = coverUrl;
listener.onUploadResult(true, videoContent);
}
@Override
public void onError(String error) {
// Thumbnail upload failed, but video upload succeeded
listener.onUploadResult(true, videoContent);
}
});
} else {
listener.onUploadResult(true, videoContent);
}
}
@Override
public void onError(String error) {
Log.e(TAG, "Video upload failed: " + error);
listener.onUploadResult(false, null);
}
});
}
// File upload to server implementation
private void uploadFileToServer(String localPath, String fileType, UploadCallback callback) {
// Implement specific file upload logic here
// Can use OkHttp, Retrofit or other network libraries
File file = new File(localPath);
if (!file.exists()) {
callback.onError("File does not exist");
return;
}
// Example: Using OkHttp to upload file
RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
ApiService.uploadFile(filePart)
.enqueue(new Callback<UploadResponse>() {
@Override
public void onResponse(Call<UploadResponse> call, Response<UploadResponse> response) {
if (response.isSuccessful() && response.body() != null) {
callback.onSuccess(response.body().getUrl());
} else {
callback.onError("Upload failed: " + response.message());
}
}
@Override
public void onFailure(Call<UploadResponse> call, Throwable t) {
callback.onError("Network error: " + t.getMessage());
}
});
}
// Download file and update message content
public void downloadAndUpdateMessage(WKMsg message) {
if (message.baseContentMsgModel instanceof WKMediaMessageContent) {
WKMediaMessageContent mediaContent = (WKMediaMessageContent) message.baseContentMsgModel;
if (!TextUtils.isEmpty(mediaContent.url) && TextUtils.isEmpty(mediaContent.localPath)) {
downloadFile(mediaContent.url, new DownloadCallback() {
@Override
public void onSuccess(String localPath) {
mediaContent.localPath = localPath;
// Update message content
WKIM.getInstance().getMsgManager().updateContent(
message.clientMsgNO,
mediaContent,
true // Refresh UI
);
}
@Override
public void onError(String error) {
Log.e(TAG, "File download failed: " + error);
}
});
}
}
}
// Callback interfaces
interface UploadCallback {
void onSuccess(String url);
void onError(String error);
}
interface DownloadCallback {
void onSuccess(String localPath);
void onError(String error);
}
}
Recent Conversation Data Source
Copy
WKIM.getInstance().getConversationManager().addOnSyncConversationListener(new ISyncConversationChat() {
@Override
public void syncConversationChat(String last_msg_seqs, int msg_count, long version, ISyncConversationChatBack iSyncConversationChatBack) {
/**
* Sync conversations
*
* @param last_msg_seqs Recent conversation list msg_seq collection
* @param msg_count Message sync count in conversations
* @param version Maximum version number
* @param iSyncConvChatBack Callback
*/
// Need to request business interface and return data to SDK
syncConversationsFromServer(last_msg_seqs, msg_count, version, iSyncConversationChatBack);
}
});
Channel Information Data Source
Copy
// Listen for getting channel information
WKIM.getInstance().getChannelManager().addOnGetChannelInfoListener(new IGetChannelInfo() {
@Override
public WKChannel onGetChannelInfo(String channelID, byte channelType, IChannelInfoListener iChannelInfoListener) {
// Whether to get personal or group info can be distinguished by channelType
// If app has local channel info, return data directly; otherwise get network data and return via iChannelInfoListener
return getChannelFromCache(channelID, channelType, iChannelInfoListener);
}
});
Built-in channel types in SDK can be viewed through
WKChannelTypeChannel Member Data Source
Copy
// Listen for getting channel member information
WKIM.getInstance().getChannelMembersManager().addOnGetChannelMembersListener((channelID, channelType, keyword, page, limit, iChannelMemberListResult) -> {
// Get channel members and return to SDK via iChannelMembersListener
fetchChannelMembers(channelID, channelType, keyword, page, limit, iChannelMemberListResult);
});
Channel Message Data Source
Copy
WKIM.getInstance().getMsgManager().addOnSyncChannelMsgListener(new ISyncChannelMsgListener() {
@Override
public void syncChannelMsgs(String channelID, byte channelType, long startMessageSeq, long endMessageSeq, int limit, int pullMode, ISyncChannelMsgBack iSyncChannelMsgBack) {
/**
* Sync messages for a channel
*
* @param channelID Channel ID
* @param channelType Channel type
* @param startMessageSeq Start message sequence (result includes start_message_seq message)
* @param endMessageSeq End message sequence (result excludes end_message_seq message)
* @param limit Message count limit
* @param pullMode Pull mode 0: pull down 1: pull up
* @param iSyncChannelMsgBack Request return
*/
syncMessagesFromServer(channelID, channelType, startMessageSeq, endMessageSeq, limit, pullMode, iSyncChannelMsgBack);
}
});

