一、导入到工程(集成SDK)
开发环境要求:
JDK 1.6
Android 4.1及以上系统
官方提供了三种导入方式:
1、手动下载aar;2、手动下载jar+so库;3、通过gradle添加依赖。
我们采用了第三种导入方式
dependencies {
api 'com.tencent.imsdk:imsdk:版本号'
}
实际到我们的项目中,我们是写在一个library module的build.gradle文件中,代码如下:
dependencies {
api 'com.tencent.imsdk:imsdk:4.7.2'
}
这样子的好处是,在上层的不同application module中都可以引用这个sdk了。
二、初始化:
/**
* 初始化腾讯云IM
*
* @param applicationContext
* @param timSdkAppId
*/
public void initTIMSDK(Context applicationContext, int timSdkAppId) {
TIMSdkConfig config = new TIMSdkConfig(timSdkAppId);
if (!LogUtils.isPrintLog) {
config.setLogLevel(TIMLogLevel.OFF); //关闭腾讯云IM的日志(既不在控制台打印,也不进行文件日志输出)
}
//注:在开启日志的情况下,腾讯云IM的文件日志输出路径默认为:SD 卡下,/tencent/imsdklogs/(com.qftx.www.qifengcloud)/
TIMManager.getInstance().init(applicationContext, config);
}
我们在初始化后可以进行用户配置,代码如下:
TIMUserConfig userConfig = new TIMUserConfig()
//设置用户状态变更事件监听
.setUserStatusListener(new TIMUserStatusListener() {
@Override
public void onForceOffline() {
//被其他终端踢下线
LogUtils.i("腾讯云IM 被其他终端踢下线");
//这里可以写自己对业务代码,比如退出登录
}
@Override
public void onUserSigExpired() {
//用户签名过期了,需要刷新userSig,重新登录IM SDK
LogUtils.i("用户签名过期了,需要刷新userSig,重新登录IM SDK");
//这里可以写自己的业务代码,比如重新从后端获取用户签名,再重新登录IM SDK
}
})
//设置连接状态事件监听
.setConnectionListener(new TIMConnListener() {
@Override
public void onConnected() {
}
@Override
public void onDisconnected(int code, String desc) {
LogUtils.i("与腾讯云IM Server断开连接");
//这里可以写自己的业务代码,比如重新登录IM SDK
}
@Override
public void onWifiNeedAuth(String s) {
}
})
//设置消息撤回事件监听
.setMessageRevokedListener(new TIMMessageRevokedListener() {
@Override
public void onMessageRevoked(TIMMessageLocator timMessageLocator) {
LogUtils.i("对方撤回一条消息");
//这里可以写自己的业务代码,比如刷新聊天界面,如果是正在播放语音则还要停止语音
}
})
//设置会话刷新监听
.setRefreshListener(new TIMRefreshListener() {
@Override
public void onRefresh() {
}
@Override
public void onRefreshConversation(List<TIMConversation> list) {
for (int i = 0; i < list.size(); i++) {
LogUtils.i("会话刷新监听结果:", "会话ID:" + list.get(i).getPeer() + ",会话未读消息数量:" + list.get(i).getUnreadMessageNum());
}
}
});
/**
* 关闭存储来提升处理性能,并规避问题:
* 解散部门群,进行如下操作TIMManager.getInstance().deleteConversation(TIMConversationType.Group, peer);后,
* 调用腾讯云获取云端消息的接口得到的仍然有数据。
*/
userConfig.disableStorage();
TIMManager.getInstance().setUserConfig(userConfig);
三、获取会话列表
List<TIMConversation> timConversationList = TIMManager.getInstance().getConversationList();
四、发送消息
private TIMConversation timConversation;
/**
* 发送消息
*
* @param timMessage
* @param messageType
* @param file
*/
private void sendMessage(final TIMMessage timMessage, int messageType, String imagePath, int duration, final File file) {
/**
* 提高用户体验,在消息未成功发送到服务端之前,先往聊天界面尾部插入一条消息
*/
final IMMessage imMessage = new IMMessage();
imMessage.setUploading(true);
imMessage.setImAccount(myselfInformation.getImAccount());
imMessage.setSelf(true);
imMessage.setMessageTime(System.currentTimeMillis() / 1000);
final StringBuilder offlineContentStringBuilder = new StringBuilder();
offlineContentStringBuilder.append(myselfInformation.getUsername()).append(": ");
if (messageType == TIMElemType.Text.value()) {
imMessage.setMessageType(TIMElemType.Text.value());
imMessage.setText(chatView.getText());
offlineContentStringBuilder.append(chatView.getText());
chatView.clearEditText();
} else if (messageType == TIMElemType.Sound.value()) {
imMessage.setMessageType(TIMElemType.Sound.value());
offlineContentStringBuilder.append("[语音]");
} else if (messageType == TIMElemType.Image.value()) {
imMessage.setMessageType(TIMElemType.Image.value());
imMessage.setImagePath(imagePath);
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
float height = bitmap.getHeight();
imMessage.setLocalImageHeightDivideByWidth(height / bitmap.getWidth());
offlineContentStringBuilder.append("[图片]");
} else if (messageType == TIMElemType.Video.value()) {
imMessage.setMessageType(TIMElemType.Video.value());
imMessage.setVideoFirstFramePath(imagePath);
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
float height = bitmap.getHeight();
imMessage.setVideoFirstFrameHeightDividerByWidth(height / bitmap.getWidth());
imMessage.setDuration(duration);
offlineContentStringBuilder.append("[视频]");
} else if (messageType == TIMElemType.File.value()) {
imMessage.setMessageType(TIMElemType.File.value());
imMessage.setLocalFile(file);
offlineContentStringBuilder.append("[文件]");
}
chatView.getImMessageList().add(imMessage);
chatView.getExcludeFilteredIMMessageList().add(imMessage);
chatView.update();
/**
* 调用腾讯云IM api发送消息
*/
if (timConversation == null) {
if (chatView.getType().equals(ConversationBeanResponse.SINGLE_CHAT)) {
timConversation = TIMManager.getInstance().getConversation(TIMConversationType.C2C, chatView.getPeer());
} else if (chatView.getType().equals(ConversationBeanResponse.GROUP_CHAT)) {
timConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, chatView.getPeer());
}
}
if (timConversation != null) {
ownIMPresenter.getSessionNoDisturbing(myselfInformation.getSelectedCompanyBeanResponse().getCompanyId(), chatView.getSessionId(), chatView.getPeer(),
new AsyncTaskLibrary(context, ConfigInformationUtils.IM_SERVER_1, new ICallBack() {
@Override
public void complete(Map<String, Object> result) {
//针对单条消息设置离线推送配置
TIMMessageOfflinePushSettings settings = new TIMMessageOfflinePushSettings();
settings.setDescr(offlineContentStringBuilder.toString());
JSONObject extJSONObject = new JSONObject();
JSONObject entityJSONObject = new JSONObject();
if (chatView.getType().equals(ConversationBeanResponse.SINGLE_CHAT)) {
entityJSONObject.put("action", 1);
entityJSONObject.put("chatType", TIMConversationType.C2C.value());
entityJSONObject.put("sender", myselfInformation.getUsername());
entityJSONObject.put("senderId", myselfInformation.getImAccount());
entityJSONObject.put("version", 1);
} else if (chatView.getType().equals(ConversationBeanResponse.GROUP_CHAT)) {
entityJSONObject.put("action", 1);
entityJSONObject.put("chatType", TIMConversationType.Group.value());
entityJSONObject.put("groupId", chatView.getPeer());
entityJSONObject.put("groupName", chatView.getConversationName());
entityJSONObject.put("sender", myselfInformation.getUsername());
entityJSONObject.put("senderId", myselfInformation.getImAccount());
entityJSONObject.put("version", 1);
}
extJSONObject.put("entity", entityJSONObject);
settings.setExt(extJSONObject.toJSONString().getBytes());
JSONObject jsonObject = JSONObject.parseObject((String) result.get("responseBody"));
if (jsonObject.getBooleanValue("returnStatus")) {
JSONObject dataJsonObject = JSONObject.parseObject(new String(EncryptAndDecryptUtils.decryptBase64(jsonObject.getString("data").getBytes())));
if (dataJsonObject.getBooleanValue("nodisturbing")) {
settings.setEnabled(false);
} else {
settings.setEnabled(true);
}
} else {
settings.setEnabled(true); //如果调用接口失败,则默认设置进行离线推送
}
timMessage.setOfflinePushSettings(settings);
timConversation.sendMessage(timMessage, new TIMValueCallBack<TIMMessage>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("发送IM消息失败,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(TIMMessage timMessage) {
LogUtils.i("发送IM消息成功");
for (int i = 0; i < timMessage.getElementCount(); i++) {
TIMElem elem = timMessage.getElement(i);
imMessage.setMessageTime(timMessage.timestamp());
imMessage.setTimMessage(timMessage);
imMessage.setUploading(false);
if (elem.getType() == TIMElemType.Image) {
TIMImageElem imageElem = (TIMImageElem) elem;
for (int k = 0; k < imageElem.getImageList().size(); k++) {
TIMImage timImage = imageElem.getImageList().get(k);
float width = timImage.getWidth();
float value = timImage.getHeight() / width;
if (timImage.getType() == TIMImageType.Thumb) {
imMessage.setThumbImageUrl(timImage.getUrl());
imMessage.setThumbImageHeightDivideByWidth(value);
} else if (timImage.getType() == TIMImageType.Large) {
imMessage.setLargeImageUrl(timImage.getUrl());
imMessage.setLargeImageHeightDivideByWidth(value);
imMessage.setImageUuid(timImage.getUuid());
} else if (timImage.getType() == TIMImageType.Original) {
imMessage.setOriginalImageUrl(timImage.getUrl());
imMessage.setOriginalImageHeightDividerByWidth(value);
imMessage.setOriginalImageSize(timImage.getSize());
}
}
} else if (elem.getType() == TIMElemType.Sound) {
TIMSoundElem soundElem = (TIMSoundElem) elem;
LogUtils.i("语音时长:" + soundElem.getDuration());
imMessage.setDuration(soundElem.getDuration());
File dir = new File(new StringBuilder().append(FileManager.getInstance().getExternalApplicationFilePath(context)).append("/xxx/xxxxxx/voice").toString());
if (!dir.exists()) {
dir.mkdirs();
}
final String soundPath = new StringBuilder().append(dir.getPath()).append("/voice_").append(soundElem.getUuid()).append(".mp3").toString();
soundElem.getSoundToFile(soundPath, new TIMCallBack() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("下载语音文件到指定的保存路径,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess() {
LogUtils.i("下载语音文件到指定的保存路径:" + soundPath + ",成功");
imMessage.setSoundPath(soundPath);
}
});
} else if (elem.getType() == TIMElemType.Video) {
TIMVideoElem videoElem = (TIMVideoElem) elem;
LogUtils.i("VideoPath:" + videoElem.getVideoPath());
LogUtils.i("SnapshotPath:" + videoElem.getSnapshotPath());
TIMVideo timVideo = videoElem.getVideoInfo();
imMessage.setDuration(timVideo.getDuaration());
imMessage.setVideoUuid(timVideo.getUuid());
timVideo.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取视频url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取视频url成功,url:" + url);
imMessage.setVideoUrl(url);
}
});
TIMSnapshot timSnapshot = videoElem.getSnapshotInfo();
timSnapshot.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取视频截图url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取视频截图url成功,url:" + url);
imMessage.setVideoFirstFrameUrl(url);
}
});
float width = timSnapshot.getWidth();
float value = timSnapshot.getHeight() / width;
imMessage.setVideoFirstFrameHeightDividerByWidth(value);
} else if (elem.getType() == TIMElemType.File) {
TIMFileElem fileElem = (TIMFileElem) elem;
imMessage.setFileName(fileElem.getFileName());
imMessage.setFileSize(fileElem.getFileSize());
imMessage.setFileUuid(fileElem.getUuid());
fileElem.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取文件url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取文件url成功,url:" + url);
imMessage.setFileUrl(url);
}
});
}
if (MessageHomeFragment.currentConversation != null) {
LogUtils.i("MessageHomeFragment.currentConversation != null");
MessageHomeFragment.currentConversation.setLatestMsgTime(timMessage.timestamp() * 1000);
MessageHomeFragment.currentConversation.setLatestMsgRevoked(false);
MessageHomeFragment.currentConversation.setLatestMsgAccount(myselfInformation.getImAccount());
if (elem.getType() == TIMElemType.Text) {
MessageHomeFragment.currentConversation.setLatestMsgType(ConversationBeanResponse.TIM_TEXT_ELEM);
JSONObject jsonObject = new JSONObject();
jsonObject.put("text", ((TIMTextElem) elem).getText());
MessageHomeFragment.currentConversation.setLatestMsgContent(jsonObject.toJSONString());
} else if (elem.getType() == TIMElemType.Image) {
MessageHomeFragment.currentConversation.setLatestMsgType(ConversationBeanResponse.TIM_IMAGE_ELEM);
} else if (elem.getType() == TIMElemType.Sound) {
MessageHomeFragment.currentConversation.setLatestMsgType(ConversationBeanResponse.TIM_SOUND_ELEM);
} else if (elem.getType() == TIMElemType.Video) {
MessageHomeFragment.currentConversation.setLatestMsgType(ConversationBeanResponse.TIM_VIDEO_ELEM);
} else if (elem.getType() == TIMElemType.File) {
MessageHomeFragment.currentConversation.setLatestMsgType(ConversationBeanResponse.TIM_FILE_ELEM);
}
} else {
LogUtils.i("MessageHomeFragment.currentConversation == null");
App.refreshConversationList = true;
}
break;
}
if (firstTIMMessage == null) {
firstTIMMessage = timMessage;
}
chatView.update();
}
});
}
@Override
public void error() {
}
}, false));
}
}
public void sendTextMessage() {
TIMMessage msg = new TIMMessage();
TIMTextElem textElem = new TIMTextElem();
textElem.setText(chatView.getText());
msg.addElement(textElem);
sendMessage(msg, TIMElemType.Text.value(), null, 0, null);
}
public void sendVoiceMessage(int duration) {
TIMMessage msg = new TIMMessage();
TIMSoundElem elem = new TIMSoundElem();
elem.setPath(voicePath); //语音文件路径
elem.setDuration(duration); //语音时长
msg.addElement(elem);
sendMessage(msg, TIMElemType.Sound.value(), null, 0, null);
}
public void sendImageMessage(String imagePath) {
TIMMessage msg = new TIMMessage();
TIMImageElem elem = new TIMImageElem();
elem.setPath(imagePath);
elem.setLevel(1); //高压缩率图发送
msg.addElement(elem);
sendMessage(msg, TIMElemType.Image.value(), imagePath, 0, null);
}
public void sendVideoMessage(final String videoPath, final String firstFramePath) {
final TIMMessage msg = new TIMMessage();
final TIMVideoElem elem = new TIMVideoElem();
final TIMVideo video = new TIMVideo();
video.setType("mp4");
final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
new Thread() {
@Override
public void run() {
mediaMetadataRetriever.setDataSource(videoPath);
((IMPublicActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
String durationStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
int duration = 0;
try {
duration = Integer.parseInt(durationStr) / 1000;
LogUtils.i("视频时长:" + duration + "秒");
video.setDuaration(duration);
} catch (NumberFormatException e) {
e.printStackTrace();
}
elem.setVideo(video);
elem.setVideoPath(videoPath);
TIMSnapshot timSnapshot = new TIMSnapshot();
timSnapshot.setWidth((long) UiUtils.dpToPx(context, 80)); //暂时默认设置成80dp
timSnapshot.setHeight((long) UiUtils.dpToPx(context, 160)); //暂时默认设置成160dp
elem.setSnapshot(timSnapshot);
String finalFirstImagePath = null;
if (firstFramePath != null) {
elem.setSnapshotPath(firstFramePath);
finalFirstImagePath = firstFramePath;
} else {
Bitmap firstFrame = mediaMetadataRetriever.getFrameAtTime(0, OPTION_CLOSEST_SYNC);
File videoDir = new File(new StringBuilder().append(FileManager.getInstance().getExternalApplicationFilePath(context)).append("/xxx").append("/xxxxxx").append("/video").toString());
if (!videoDir.exists()) {
videoDir.mkdirs();
}
String firstFrameFileName = new StringBuilder().append(System.currentTimeMillis()).append("_firstFrame.png").toString();
String firstFrameFilePath = new StringBuilder().append(videoDir.getPath()).append("/").append(firstFrameFileName).toString();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(firstFrameFilePath);
firstFrame.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
elem.setSnapshotPath(firstFrameFilePath);
finalFirstImagePath = firstFrameFilePath;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
msg.addElement(elem);
sendMessage(msg, TIMElemType.Video.value(), finalFirstImagePath, duration, null);
}
});
}
}.start();
}
public void sendFileMessage(File file) {
TIMMessage msg = new TIMMessage();
TIMFileElem elem = new TIMFileElem();
elem.setPath(file.getPath());
elem.setFileName(file.getName());
msg.addElement(elem);
sendMessage(msg, TIMElemType.File.value(), null, 0, file);
}
五、接收消息
/**
* 调用获取消息的接口的前期工作
*
* @param action
* @return
*/
public TIMMessage prepareBeforeGetMessage(final String action) {
chatView.srl.setRefreshing(true);
if (timConversation == null) {
if (chatView.getType().equals(ConversationBeanResponse.SINGLE_CHAT)) {
timConversation = TIMManager.getInstance().getConversation(TIMConversationType.C2C, chatView.getPeer());
} else if (chatView.getType().equals(ConversationBeanResponse.GROUP_CHAT)) {
timConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, chatView.getPeer());
}
}
TIMMessage timMessage = null;
if (action.equals("loadMoreMessage")) {
timMessage = firstTIMMessage;
}
return timMessage;
}
/**
* 获取消息
*
* @param action
*/
public void getMessage(final String action) {
switch (messageLoadChannel) {
case FROM_LOCAL_MESSAGE:
getLocalMessage(action);
break;
case FROM_TIM_SERVER_MESSAGE:
getTIMServerMessage(action);
break;
}
}
/**
* 调用腾讯云IM SDK的api获取会话本地消息
*/
public void getLocalMessage(final String action) {
TIMMessage timMessage = prepareBeforeGetMessage(action);
timConversation.getLocalMessage(30, timMessage, new TIMValueCallBack<List<TIMMessage>>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取IM消息失败,错误码:" + code + ",错误描述:" + desc);
chatView.srl.setRefreshing(false);
ToastUtils.showCenterToast(TotalIMPresenter.this.context, "获取IM消息失败,错误码:" + code + ",错误描述:" + desc, Toast.LENGTH_SHORT);
}
@Override
public void onSuccess(List<TIMMessage> timMessages) {
LogUtils.i("获取IM消息成功");
if (timMessages != null && timMessages.size() != 0) {
doneAfterGetMessage(timMessages);
} else {
messageLoadChannel = FROM_TIM_SERVER_MESSAGE;
getMessage("loadMoreMessage");
}
}
});
}
/**
* 调用腾讯云IM SDK的api从腾讯云云端获取会话消息
*
* @param action
*/
public void getTIMServerMessage(final String action) {
TIMMessage timMessage = prepareBeforeGetMessage(action);
timConversation.getMessage(30, timMessage, new TIMValueCallBack<List<TIMMessage>>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取IM消息失败,错误码:" + code + ",错误描述:" + desc);
chatView.srl.setRefreshing(false);
ToastUtils.showCenterToast(TotalIMPresenter.this.context, "获取IM消息失败,错误码:" + code + ",错误描述:" + desc, Toast.LENGTH_SHORT);
}
@Override
public void onSuccess(List<TIMMessage> timMessages) {
LogUtils.i("获取IM消息成功");
if (timMessages != null && timMessages.size() != 0) {
doneAfterGetMessage(timMessages);
} else {
chatView.srl.setRefreshing(false);
}
}
});
}
/**
* 调用获取消息的接口获取完消息后的工作
*
* @param timMessages
*/
public void doneAfterGetMessage(List<TIMMessage> timMessages) {
chatView.srl.setRefreshing(false);
if (timMessages != null && timMessages.size() != 0) {
firstTIMMessage = timMessages.get(timMessages.size() - 1);
LogUtils.i("IM消息个数为:" + timMessages.size());
final List<IMMessage> imMessageList = new ArrayList<>();
for (int i = timMessages.size() - 1; i > -1; i--) {
TIMMessage timMessage = timMessages.get(i);
for (int j = 0; j < timMessage.getElementCount(); j++) {
TIMElem elem = timMessage.getElement(j);
final IMMessage imMessage = new IMMessage();
imMessage.setImAccount(timMessage.getSender());
imMessage.setSelf(timMessage.isSelf());
imMessage.setMessageTime(timMessage.timestamp());
imMessage.setTimMessage(timMessage);
imMessage.setRevoked(timMessage.status().getStatus() == TIMMessageStatus.HasRevoked.getStatus() ? true : false);
if (elem.getType() == TIMElemType.Text) {
TIMTextElem textElem = (TIMTextElem) elem;
imMessage.setMessageType(TIMElemType.Text.value());
imMessage.setText(textElem.getText());
imMessageList.add(imMessage);
} else if (elem.getType() == TIMElemType.Image) {
TIMImageElem imageElem = (TIMImageElem) elem;
imMessage.setMessageType(TIMElemType.Image.value());
for (int k = 0; k < imageElem.getImageList().size(); k++) {
TIMImage timImage = imageElem.getImageList().get(k);
float width = timImage.getWidth();
float value = timImage.getHeight() / width;
if (timImage.getType() == TIMImageType.Thumb) {
imMessage.setThumbImageUrl(timImage.getUrl());
imMessage.setThumbImageHeightDivideByWidth(value);
} else if (timImage.getType() == TIMImageType.Large) {
imMessage.setLargeImageUrl(timImage.getUrl());
imMessage.setLargeImageHeightDivideByWidth(value);
imMessage.setImageUuid(timImage.getUuid());
} else if (timImage.getType() == TIMImageType.Original) {
imMessage.setOriginalImageUrl(timImage.getUrl());
imMessage.setOriginalImageHeightDividerByWidth(value);
imMessage.setOriginalImageSize(timImage.getSize());
}
}
imMessageList.add(imMessage);
} else if (elem.getType() == TIMElemType.Sound) {
TIMSoundElem soundElem = (TIMSoundElem) elem;
imMessage.setMessageType(TIMElemType.Sound.value());
LogUtils.i("语音时长:" + soundElem.getDuration());
imMessage.setDuration(soundElem.getDuration());
imMessageList.add(imMessage);
File dir = new File(new StringBuilder().append(FileManager.getInstance().getExternalApplicationFilePath(context)).append("/qifeng/qifengyun/voice").toString());
if (!dir.exists()) {
dir.mkdirs();
}
final String soundPath = new StringBuilder().append(dir.getPath()).append("/voice_").append(soundElem.getUuid()).append(".mp3").toString();
soundElem.getSoundToFile(soundPath, new TIMCallBack() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("下载语音文件到指定的保存路径,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess() {
LogUtils.i("下载语音文件到指定的保存路径:" + soundPath + ",成功");
imMessage.setSoundPath(soundPath);
}
});
} else if (elem.getType() == TIMElemType.Video) {
TIMVideoElem videoElem = (TIMVideoElem) elem;
imMessage.setMessageType(TIMElemType.Video.value());
TIMVideo timVideo = videoElem.getVideoInfo();
imMessage.setVideoUuid(timVideo.getUuid());
imMessage.setDuration(timVideo.getDuaration());
timVideo.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取视频url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取视频url成功,url:" + url);
imMessage.setVideoUrl(url);
}
});
TIMSnapshot timSnapshot = videoElem.getSnapshotInfo();
timSnapshot.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取视频截图url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取视频截图url成功,url:" + url);
imMessage.setVideoFirstFrameUrl(url);
}
});
float width = timSnapshot.getWidth();
float value = timSnapshot.getHeight() / width;
imMessage.setVideoFirstFrameHeightDividerByWidth(value);
imMessageList.add(imMessage);
} else if (elem.getType() == TIMElemType.File) {
TIMFileElem fileElem = (TIMFileElem) elem;
imMessage.setMessageType(TIMElemType.File.value());
imMessage.setFileName(fileElem.getFileName());
imMessage.setFileSize(fileElem.getFileSize());
imMessage.setFileUuid(fileElem.getUuid());
fileElem.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取文件url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取文件url成功,url:" + url);
imMessage.setFileUrl(url);
}
});
imMessageList.add(imMessage);
} else if (elem.getType() == TIMElemType.Custom) {
TIMCustomElem customElem = (TIMCustomElem) elem;
imMessage.setMessageType(TIMElemType.Custom.value());
LogUtils.i("自定义数据Data:" + new String(customElem.getData()) + "\n自定义描述Desc:" + customElem.getDesc() + "\n自定义后台推送对应的Ext字段ext:" + new String(customElem.getExt()) + "\n自定义声音的数据Sound:" + new String(customElem.getSound()));
String jsonString = new String(customElem.getData());
JSONObject jsonObject = JSONObject.parseObject(jsonString);
if (jsonObject.containsKey("appSubMsgType")) {
imMessage.setAppSubMsgType(jsonObject.getString("appSubMsgType"));
}
if (jsonObject.containsKey("msgText")) {
imMessage.setText(jsonObject.getString("msgText"));
}
}
}
}
chatView.update(imMessageList, false, false);
}
}
六、新消息监听
/**
* 设置新消息监听
*/
TIMManager.getInstance().addMessageListener(new TIMMessageListener() {
@Override
public boolean onNewMessages(List<TIMMessage> list) {
LogUtils.i("接收到IM新消息");
for (int i = list.size() - 1; i > -1; i--) {
TIMMessage timMessage = list.get(i);
List<IMMessage> imMessageList = new ArrayList<>();
String peer = timMessage.getConversation().getPeer();
String type = "", contentTitle = "", sessionId = "";
if (timMessage.getConversation().getType() == TIMConversationType.C2C) {
type = ConversationBeanResponse.SINGLE_CHAT;
LogUtils.i("新消息对应的会话类型:SINGLE_CHAT");
} else if (timMessage.getConversation().getType() == TIMConversationType.Group) {
type = ConversationBeanResponse.GROUP_CHAT;
LogUtils.i("新消息对应的会话类型:GROUP_CHAT");
} else if (timMessage.getConversation().getType() == TIMConversationType.System) {
LogUtils.i("新消息对应的会话类型:System");
}
boolean isContainGroupNoticeMsg = false;
for (int j = 0; j < timMessage.getElementCount(); j++) {
TIMElem elem = timMessage.getElement(j);
StringBuilder contentText = new StringBuilder();
if (timMessage.getConversation().getType() == TIMConversationType.Group) {
for (int k = 0; k < myselfInformation.getSelectedCompanyBeanResponse().getAllGroupList().size(); k++) {
if (peer.equals(myselfInformation.getSelectedCompanyBeanResponse().getAllGroupList().get(k).getId())) {
contentTitle = myselfInformation.getSelectedCompanyBeanResponse().getAllGroupList().get(k).getName();
break;
}
}
for (int k = 0; k < myselfInformation.getSelectedCompanyBeanResponse().getAllContactsList().size(); k++) {
if (timMessage.getSender().equals(myselfInformation.getSelectedCompanyBeanResponse().getAllContactsList().get(k).getImAccount())) {
contentText.append(myselfInformation.getSelectedCompanyBeanResponse().getAllContactsList().get(k).getName()).append(": ");
break;
}
}
} else if (timMessage.getConversation().getType() == TIMConversationType.C2C) {
contentTitle = timMessage.getSenderNickname();
}
final IMMessage imMessage = new IMMessage();
imMessage.setImAccount(timMessage.getSender());
imMessage.setSelf(timMessage.isSelf());
imMessage.setMessageTime(timMessage.timestamp());
imMessage.setTimMessage(timMessage);
ConversationBeanResponse conversationBeanResponse = null;
for (int k = 0; k < conversationList.size(); k++) {
if (peer.equals(conversationList.get(k).getConversationId())) {
conversationBeanResponse = conversationList.get(k);
conversationBeanResponse.setLatestMsgTime(timMessage.timestamp() * 1000);
conversationBeanResponse.setLatestMsgAccount(timMessage.getSender());
conversationBeanResponse.setLatestAppSubMsgType(null);
conversationBeanResponse.setLatestMsgRevoked(false);
sessionId = conversationBeanResponse.getId();
break;
}
}
boolean isChatMsg = true, needSendNotification = true;
if (elem.getType() == TIMElemType.Text) { //文本消息
TIMTextElem textElem = (TIMTextElem) elem;
imMessage.setMessageType(TIMElemType.Text.value());
imMessage.setText(textElem.getText());
imMessageList.add(imMessage);
contentText.append(textElem.getText());
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationBeanResponse.TIM_TEXT_ELEM);
JSONObject jsonObject = new JSONObject();
jsonObject.put("text", textElem.getText());
conversationBeanResponse.setLatestMsgContent(jsonObject.toJSONString());
}
} else if (elem.getType() == TIMElemType.Image) { //图片消息
TIMImageElem imageElem = (TIMImageElem) elem;
imMessage.setMessageType(TIMElemType.Image.value());
for (int k = 0; k < imageElem.getImageList().size(); k++) {
TIMImage timImage = imageElem.getImageList().get(k);
float width = timImage.getWidth();
float value = timImage.getHeight() / width;
if (timImage.getType() == TIMImageType.Thumb) {
imMessage.setThumbImageUrl(timImage.getUrl());
imMessage.setThumbImageHeightDivideByWidth(value);
} else if (timImage.getType() == TIMImageType.Large) {
imMessage.setLargeImageUrl(timImage.getUrl());
imMessage.setLargeImageHeightDivideByWidth(value);
imMessage.setImageUuid(timImage.getUuid());
} else if (timImage.getType() == TIMImageType.Original) {
imMessage.setOriginalImageUrl(timImage.getUrl());
imMessage.setOriginalImageHeightDividerByWidth(value);
imMessage.setOriginalImageSize(timImage.getSize());
}
}
imMessageList.add(imMessage);
contentText.append("[图片]");
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationBeanResponse.TIM_IMAGE_ELEM);
}
} else if (elem.getType() == TIMElemType.Sound) {
TIMSoundElem soundElem = (TIMSoundElem) elem;
imMessage.setMessageType(TIMElemType.Sound.value());
imMessage.setDuration(soundElem.getDuration());
File dir = new File(new StringBuilder().append(FileManager.getInstance().getExternalApplicationFilePath(getApplicationContext())).append("/xxx/xxxxxx/voice").toString());
if (!dir.exists()) {
dir.mkdirs();
}
/*String uuid = "";
if (soundElem.getUuid().endsWith(".mp3")) {
uuid = soundElem.getUuid().substring(0, soundElem.getUuid().length() - ".mp3".length());
} else {
uuid = soundElem.getUuid();
}*/
final String soundPath = new StringBuilder().append(dir.getPath()).append("/voice_").append(soundElem.getUuid()).append(".mp3").toString();
soundElem.getSoundToFile(soundPath, new TIMCallBack() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("下载语音文件到指定的保存路径,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess() {
LogUtils.i("下载语音文件到指定的保存路径:" + soundPath + ",成功");
imMessage.setSoundPath(soundPath);
}
});
imMessageList.add(imMessage);
contentText.append("[语音]");
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationBeanResponse.TIM_SOUND_ELEM);
}
} else if (elem.getType() == TIMElemType.Video) { //视频消息
TIMVideoElem videoElem = (TIMVideoElem) elem;
imMessage.setMessageType(TIMElemType.Video.value());
TIMVideo timVideo = videoElem.getVideoInfo();
imMessage.setDuration(timVideo.getDuaration());
imMessage.setVideoUuid(timVideo.getUuid());
timVideo.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取视频url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取视频url成功,url:" + url);
imMessage.setVideoUrl(url);
}
});
TIMSnapshot timSnapshot = videoElem.getSnapshotInfo();
timSnapshot.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取视频截图url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取视频截图url成功,url:" + url);
imMessage.setVideoFirstFrameUrl(url);
}
});
float width = timSnapshot.getWidth();
float value = timSnapshot.getHeight() / width;
imMessage.setVideoFirstFrameHeightDividerByWidth(value);
imMessageList.add(imMessage);
contentText.append("[视频]");
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationBeanResponse.TIM_VIDEO_ELEM);
}
} else if (elem.getType() == TIMElemType.File) {
TIMFileElem fileElem = (TIMFileElem) elem;
imMessage.setMessageType(TIMElemType.File.value());
imMessage.setFileName(fileElem.getFileName());
imMessage.setFileSize(fileElem.getFileSize());
imMessage.setFileUuid(fileElem.getUuid());
fileElem.getUrl(new TIMValueCallBack<String>() {
@Override
public void one rror(int code, String desc) {
LogUtils.i("获取文件url错误,错误码:" + code + ",错误描述:" + desc);
}
@Override
public void onSuccess(String url) {
LogUtils.i("获取文件url成功,url:" + url);
imMessage.setFileUrl(url);
}
});
imMessageList.add(imMessage);
contentText.append("[文件]");
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationMessageBaseBean.TIM_FILE_ELEM);
}
} else if (elem.getType() == TIMElemType.Custom) { //自定义消息(目前走自定义消息有两类:业务通知、群通知)
TIMCustomElem customElem = (TIMCustomElem) elem;
imMessage.setMessageType(TIMElemType.Custom.value());
LogUtils.i("自定义数据Data:" + new String(customElem.getData()) + "\n自定义描述Desc:" + customElem.getDesc() + "\n自定义后台推送对应的Ext字段ext:" + new String(customElem.getExt()) + "\n自定义声音的数据Sound:" + new String(customElem.getSound()));
JSONObject jsonObject = JSON.parseObject(new String(customElem.getData()));
String appSubMsgType = jsonObject.getString("appSubMsgType");
if (!type.equals(ConversationMessageBaseBean.GROUP_CHAT)) {
imMessage.setText(jsonObject.getString("msgTitle"));
isChatMsg = false;
} else {
if (ConversationMessageBaseBean.CREATE_GROUP.equals(appSubMsgType)) {
setTIMMessageRead(timMessage, TIMConversationType.Group, peer);
//此时需要过滤而不发送该消息对应的通知
needSendNotification = false;
} else if (ConversationMessageBaseBean.ADD_GROUP_MEMBER.equals(appSubMsgType)) {
// setTIMMessageRead(timMessage, TIMConversationType.Group, peer);
needSendNotification = false;
imMessage.setText(jsonObject.getString("msgText"));
} else if (ConversationMessageBaseBean.DELETE_GROUP_MEMBER.equals(appSubMsgType)) {
// setTIMMessageRead(timMessage, TIMConversationType.Group, peer);
needSendNotification = false; //此时需要过滤而不发送该消息对应的通知
if (myselfInformation.getImAccount().equals(jsonObject.getString("toAccount"))) {
imMessage.setText(jsonObject.getString("msgText"));
}
} else if (ConversationMessageBaseBean.UPDATE_GROUP_NOTICE.equals(appSubMsgType)) {
if (timMessage.getSender().equals(myselfInformation.getImAccount())) {
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationBeanResponse.TIM_CUSTOM_ELEM);
conversationBeanResponse.setLatestAppSubMsgType(appSubMsgType);
}
continue;
} else {
imMessage.setText(jsonObject.getString("msgText"));
isContainGroupNoticeMsg = true;
SQLiteDatabase db = DbManager.getInstance(getApplicationContext()).getWritableDatabase();
DbManager.insertOrUpdateTheGroupShowNoticePanelValue(db, peer, true);
DbManager.closeDb(db);
}
} else if (ConversationMessageBaseBean.CHANGE_GROUP_POWNER.equals(appSubMsgType)) {
// setTIMMessageRead(timMessage, TIMConversationType.Group, peer);
if (myselfInformation.getImAccount().equals(jsonObject.getString("toAccount"))) {
imMessage.setText(jsonObject.getString("msgText"));
/**
* 下述代码是将该群对应的群主改成当前APP登录用户
*/
for (int k = 0; k < myselfInformation.getSelectedCompanyBeanResponse().getAllGroupList().size(); k++) {
if (peer.equals(myselfInformation.getSelectedCompanyBeanResponse().getAllGroupList().get(k).getId())) {
myselfInformation.getSelectedCompanyBeanResponse().getAllGroupList().get(k).setOwnerAccount(myselfInformation.getImAccount());
break;
}
}
} else { //此时需要过滤而不发送该消息对应的通知
needSendNotification = false;
}
}
}
imMessage.setAppSubMsgType(appSubMsgType);
imMessageList.add(imMessage);
contentText.append(imMessage.getText());
if (conversationBeanResponse != null) {
conversationBeanResponse.setLatestMsgType(ConversationBeanResponse.TIM_CUSTOM_ELEM);
conversationBeanResponse.setLatestAppSubMsgType(appSubMsgType);
if (!type.equals(ConversationMessageBaseBean.GROUP_CHAT)) {
conversationBeanResponse.setLatestMsgTitle(jsonObject.getString("msgTitle"));
} else {
JSONObject groupContentJsonObject = new JSONObject();
groupContentJsonObject.put("text", jsonObject.getString("msgText"));
conversationBeanResponse.setLatestMsgContent(groupContentJsonObject.toJSONString());
}
}
} else if (elem.getType() == TIMElemType.GroupSystem) {
TIMGroupSystemElem groupSystemElem = (TIMGroupSystemElem) elem;
if (groupSystemElem.getSubtype() == TIMGroupSystemElemType.TIM_GROUP_SYSTEM_DELETE_GROUP_TYPE) {
//此时通过String peer = timMessage.getConversation().getPeer();得到的peer为null,所以需要根据下面的代码取到peer
peer = groupSystemElem.getGroupId();
//删除会话(删除会话的同时 IM SDK 会删除该会话的本地和漫游消息,会话和消息删除后,无法再恢复)
boolean bl = TIMManager.getInstance().deleteConversation(TIMConversationType.Group, peer);
if (bl) {
LogUtils.i("删除会话成功");
} else {
LogUtils.i("删除会话失败");
}
//群被解散时,腾讯云发送的群系统消息(即群被解散,全员能够收到),此时需要过滤而不发送该消息对应的通知
needSendNotification = false;
if ("chat".equals(((BaseActivity) ActivityManager.currentActivity()).getKind()) && peer.equals(((ChatView) ((IMPublicActivity) ActivityManager.currentActivity()).imPublicView.getContentView("chat")).getPeer())) {
ActivityManager.finishAllActivityExcludeMainActivity();
NormalInteractionDialog normalInteractionDialog = new NormalInteractionDialog(ActivityManager.currentActivity(), R.style.DialogNoAnimationStyle);
normalInteractionDialog.init(true, true, null, "群已解散", getString(R.string.confirm), null);
normalInteractionDialog.show();
}
} else if (groupSystemElem.getSubtype() == TIMGroupSystemElemType.TIM_GROUP_SYSTEM_INVITED_TO_GROUP_TYPE) {
//成员被邀请入群时,腾讯云发送的群系统消息(即邀请入群通知,被邀请者能够收到),此时需要过滤而不发送该消息对应的通知,此时直接处理,因为不需要走下面的逻辑
continue;
} else if (groupSystemElem.getSubtype() == TIMGroupSystemElemType.TIM_GROUP_SYSTEM_KICK_OFF_FROM_GROUP_TYPE) {
//成员被踢出群时,腾讯云发送的群系统消息(即被管理员踢出群,只有被踢的人能够收到),此时需要过滤而不发送该消息对应的通知
needSendNotification = false;
}
} else if (elem.getType() == TIMElemType.GroupTips) {
TIMGroupTipsElem groupTipsElem = (TIMGroupTipsElem) elem;
if (groupTipsElem.getTipsType() == TIMGroupTipsType.ModifyGroupInfo) {
setTIMMessageRead(timMessage, TIMConversationType.Group, peer);
//群主被转让时,腾讯云发送的群事件消息,此时需要过滤而不发送该消息对应的通知,此时直接处理,因为不需要走下面的逻辑
continue;
}
} else if (elem.getType() == TIMElemType.ProfileTips) {
//用户资料变更系统通知,目前APP中我们不处理这种类型的通知,但是云端可能会发送,所以在APP端采取屏蔽不显示的处理
continue;
} else if (elem.getType() == TIMElemType.SNSTips) {
//关系链变更系统通知,目前APP中我们不处理这种类型的通知,但是云端可能会发送,所以在APP端采取屏蔽不显示的处理
continue;
}
if (needSendNotification) {
imNotificationSendDealLogic(peer, sessionId, contentTitle, contentText.toString(), type, isChatMsg, conversationBeanResponse);
}
if (conversationBeanResponse != null) {
if (((BaseActivity) ActivityManager.currentActivity()).getClass().equals(MainActivity.class)) {
((MessageHomeFragment) (((MainActivity) ((BaseActivity) ActivityManager.currentActivity())).getMessageHomeFragment())).messageHomeView.update(true);
}
} else {
if (((BaseActivity) ActivityManager.currentActivity()).getClass().equals(MainActivity.class)) {
((MessageHomeFragment) (((MainActivity) ((BaseActivity) ActivityManager.currentActivity())).getMessageHomeFragment())).autoRefresh();
} else {
refreshConversationList = true;
}
}
}
if ("chat".equals(((BaseActivity) ActivityManager.currentActivity()).getKind()) && peer.equals(((ChatView) ((IMPublicActivity) ActivityManager.currentActivity()).imPublicView.getContentView("chat")).getPeer())) {
setTIMMessageRead(timMessage, timMessage.getConversation().getType(), peer);
((ChatView) ((IMPublicActivity) ActivityManager.currentActivity()).imPublicView.getContentView("chat")).update(imMessageList, true, isContainGroupNoticeMsg);
} else if ("messageItem".equals(((BaseActivity) ActivityManager.currentActivity()).getKind()) && peer.equals(((MessageItemView) ((IMPublicActivity) ActivityManager.currentActivity()).imPublicView.getContentView("messageItem")).getConversationId())) {
setTIMMessageRead(timMessage, timMessage.getConversation().getType(), peer);
List<OwnIMMessage> tempMessageList = new ArrayList<>();
String[] msgIdElemArr = timMessage.getMsgId().split("-");
for (int j = 0; j < timMessage.getElementCount(); j++) {
TIMElem elem = timMessage.getElement(j);
if (elem.getType() == TIMElemType.Custom) {
TIMCustomElem customElem = (TIMCustomElem) elem;
OwnIMMessage ownIMMessage = new OwnIMMessage();
JSONObject jsonObject = JSON.parseObject(new String(customElem.getData()));
ownIMMessage.setSubBusinessType(jsonObject.getString("subBusinessType"));
ownIMMessage.setAppSubMsgType(jsonObject.getString("appSubMsgType"));
ownIMMessage.setMsgTime(timMessage.timestamp() * 1000);
JSONObject contentJsonObject = new JSONObject();
contentJsonObject.put("text", jsonObject.getString("msgText"));
ownIMMessage.setMsgContent(contentJsonObject.toJSONString());
ownIMMessage.setAppParameter(jsonObject.getString("appParameter"));
ownIMMessage.setMsgKey(new StringBuilder().append("00000").append("_").append(msgIdElemArr[2]).append("_").append(msgIdElemArr[1]).toString());
tempMessageList.add(ownIMMessage);
}
}
Collections.reverse(tempMessageList);
((MessageItemView) ((IMPublicActivity) ActivityManager.currentActivity()).imPublicView.getContentView("messageItem")).update(tempMessageList, true);
}
}
return false;
}
});