im::floo::floolib::BMXMessage
消息
Inherits from BMXBaseObject
Public Functions
Name | |
---|---|
synchronized void | delete() |
long | msgId() 消息唯一ID |
long | clientMsgId() 消息客户端ID,仅在消息发送端存在 |
long | fromId() 消息发送方ID |
long | toId() 消息接收方ID |
BMXMessage.MessageType | type() 消息类型 |
long | conversationId() 消息所属会话ID |
BMXMessage.DeliveryStatus | deliveryStatus() 消息投递状态 |
void | setDeliveryStatus(BMXMessage.DeliveryStatus arg0) 设置消息投递状态 |
long | serverTimestamp() 消息时间戳(服务端收到时的时间) |
void | setServerTimestamp(long arg0) 设置时间戳(服务端收到时的时间) |
long | clientTimestamp() 本地时间戳(消息创建或者收到时的本地时间) |
void | setClientTimestamp(long arg0) 设置消息本地时间戳 |
boolean | isPlayed() 语音或者视频消息是否播放过,仅对收到的音视频消息有效 |
void | setIsPlayed(boolean arg0) |
boolean | isPlayAcked() 语音或者视频消息是否收到播放回执,仅对收到的音视频消息有效 |
void | setIsPlayAcked(boolean arg0) |
boolean | isReceiveMsg() 是否接收的消息 |
void | setIsReceiveMsg(boolean arg0) |
boolean | isRead() 消息是否已读标志 |
void | setIsRead(boolean arg0) |
boolean | isReadAcked() 对于发送方表示是否收到了已读回执,对于接收方表示是否发送了已读回执 |
void | setIsReadAcked(boolean arg0) |
boolean | isDeliveryAcked() 对于发送方表示消息是否已投递到对方,对于接收方表示是否发送了消息已到达回执 |
void | setIsDeliveryAcked(boolean arg0) |
String | content() 消息文本内容 |
void | setContent(String content) 消息文本内容 |
BMXMessage.ContentType | contentType() 消息内容类型,如果带附件就表示附件类型,不带附件就是文本类型 |
BMXMessageAttachment | attachment() 消息附件,BMXMessage拥有附件的所有权,负责释放 |
BMXMessageConfig | config() 消息的配置信息 |
void | setConfig(BMXMessageConfig arg0) 设置消息配置信息 |
String | extension() 消息扩展信息 |
void | setExtension(String arg0) 设置消息扩展信息 |
BMXMessage.DeliveryQos | deliveryQos() 消息投递QOS |
void | setDeliveryQos(BMXMessage.DeliveryQos qos) 设置消息投递QOS |
String | senderName() 消息发送者的显示名称 |
void | setSenderName(String senderName) 设置消息的发送者显示名称 |
int | groupAckCount() 群消息已读AckCount数目 |
void | setGroupAckCount(int count) 设置消息已读groupAckCount数目(SDK 内部调用接口,上层不应该调用) |
int | groupAckUnreadCount() 群消息未读AckCount数目 |
void | setGroupAckUnreadCount(int count) 设置消息未读groupAckCount数目(SDK 内部调用接口,上层不应该调用) |
boolean | groupAckReadAll() 群消息是否全部已读 |
int | groupPlayAckCount() 获取群消息已播放计数 |
void | setGroupPlayAckCount(int count) |
int | groupPlayAckUnreadCount() 获取群消息已播放回执未读计数 |
void | setGroupPlayAckUnreadCount(int count) |
boolean | groupPlayAckReadAll() 设置所有群消息已播回执为已读 |
void | setPriority(int priority) 设置消息的扩散优先级,默认为0。0表示扩散,数字越小扩散的越多。 取值范围0-10。普通人在聊天室发送的消息级别默认为5,可以丢弃。管理员默认为0不会丢弃。其它值可以根据业务自行设置。 |
int | priority() 消息的扩散优先级 |
void | setPushMessageMode(boolean arg0) 设置是否推送消息 |
boolean | isPushMessage() 是否是推送消息 |
BMXMessage | createMessage(long from, long to, BMXMessage.MessageType type, long conversationId, String content) 创建发送文本消息 |
BMXMessage | createMessage(long from, long to, BMXMessage.MessageType type, long conversationId, BMXMessageAttachment attachment) 创建发送附件消息 |
BMXMessage | createCommandMessage(long from, long to, BMXMessage.MessageType type, long conversationId, String content) 创建发送命令消息(命令消息通过content字段或者extension字段存放命令信息) |
BMXMessage | createMessage(long msgId, long from, long to, BMXMessage.MessageType type, long conversationId, String content, long serverTimestamp) 创建收到的消息 |
BMXMessage | createMessage(long msgId, long from, long to, BMXMessage.MessageType type, long conversationId, BMXMessageAttachment attachment, long serverTimestamp) 创建收到的消息 |
BMXMessage | createCommandMessage(long msgId, long from, long to, BMXMessage.MessageType type, long conversationId, String content, long serverTimestamp) 创建收到的命令消息(命令消息通过content字段或者extension字段存放命令信息) |
BMXMessage | createForwardMessage(BMXMessage msg, long from, long to, BMXMessage.MessageType type, long conversationId) 创建转发消息 |
Protected Functions
Name | |
---|---|
BMXMessage(long cPtr, boolean cMemoryOwn) | |
void | finalize() |
long | getCPtr(BMXMessage obj) |
Public Functions Documentation
function delete
inline synchronized void delete()
Example:
function msgId
inline long msgId()
消息唯一ID
Return: int64_t
Example:
private long getFirstMessageId() {
if (mAdapter == null) {
return -1;
}
List<BMXMessage> list = mAdapter.getList();
BMXMessage bean = null;
if (list != null && list.size() > 0) {
bean = list.get(0);
}
return bean.msgId();
public final void onCallProgress(BMXMessage msg, int percent) {
if (msg == null) {
mainHandler.post(() -> onFail(-1));
return;
}
long msgId = msg.msgId();
if (percent >= 100) {
mainHandler.post(() -> onFinish(msgId));
} else {
mainHandler.post(() -> onProgress(msgId, percent <= 0 ? 0 : percent));
}
private void clearTypeWriterMsgId(BMXMessage message){
if (message.msgId() == ((MaxIMApplication) getApplication()).typeWriterMsgId){
((MaxIMApplication) getApplication()).typeWriterMsgId = 0;
}
if (TextUtils.isEmpty(picUrl)) {
// 正在下载
return;
}
List<PhotoViewBean> photoViewBeans = new ArrayList<>();
PhotoViewBean photoViewBean = new PhotoViewBean();
photoViewBean.setLocalPath(body.path());
photoViewBean.setThumbLocalPath(body.thumbnailPath());
photoViewBean.setThumbHttpUrl(body.thumbnailUrl());
photoViewBean.setHttpUrl(body.url());
photoViewBean.setMsgId(bean.msgId());
photoViewBeans.add(photoViewBean);
PhotoViewListBean listBean = new PhotoViewListBean();
listBean.setPhotoViewBeans(photoViewBeans);
PhotoDetailActivity.openPhotoDetail(mView.getContext(), listBean);
public void onProgressCallback(BMXMessage msg, int percent) {
if (msg == null) {
return;
}
long msgId = msg.msgId();
if (mListeners.get(msgId) != null) {
mListeners.get(msgId).onCallProgress(msg, percent);
}
public void onStartCallback(BMXMessage msg) {
if (msg == null) {
return;
}
long msgId = msg.msgId();
if (mListeners.get(msgId) != null) {
mListeners.get(msgId).onStart(msgId);
}
public void onFinishCallback(BMXMessage msg) {
if (msg == null) {
return;
}
long msgId = msg.msgId();
if (mListeners.get(msgId) != null) {
mListeners.get(msgId).onCallProgress(msg, 100);
}
public long getFirstMsgId() {
BMXMessage firstMessage = getFirstMessage();
return firstMessage != null ? firstMessage.msgId() : -1;
function clientMsgId
inline long clientMsgId()
消息客户端ID,仅在消息发送端存在
Return: int64_t
Example:
function fromId
inline long fromId()
消息发送方ID
Return: int64_t
Example:
boolean isOwner = GroupManager.getInstance().isGroupOwner(bmxGroup.ownerId());
boolean isAdmin = GroupManager.getInstance().isAdmin(bmxGroup, SharePreferenceUtils.getInstance().getUserId()) || isOwner;
boolean hideByGroupSettings = bmxGroup.hideMemberInfo();
if (!hideByGroupSettings || isAdmin){
hideMemberInfo = false;
}
}
}
if (mMaxMessage.isReceiveMsg()) {
BMXRosterItem item = RosterFetcher.getFetcher().getRoster(mMaxMessage.fromId());
if(group){
//如果是群 需要获取群成员名称
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (item != null && !TextUtils.isEmpty(item.alias())) {
userName = item.alias();
} else if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (item != null && !TextUtils.isEmpty(item.nickname())) {
userName = item.nickname();
if (!hideByGroupSettings || isAdmin){
hideMemberInfo = false;
}
}
}
if (mMaxMessage.isReceiveMsg()) {
BMXRosterItem item = RosterFetcher.getFetcher().getRoster(mMaxMessage.fromId());
if(group){
//如果是群 需要获取群成员名称
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (item != null && !TextUtils.isEmpty(item.alias())) {
userName = item.alias();
} else if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (item != null && !TextUtils.isEmpty(item.nickname())) {
userName = item.nickname();
} else if (item != null) {
userName = item.username();
if (hideMemberInfo){
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (item != null && !TextUtils.isEmpty(item.alias())) {
userName = item.alias();
} else if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (item != null && !TextUtils.isEmpty(item.nickname())) {
userName = item.nickname();
} else if (item != null) {
userName = item.username();
if (hideMemberInfo){
userName = CommonUtils.md5InBase64(item.username()+String.valueOf(mMaxMessage.fromId())).substring(0, 12);
}
}
} else{
if (item != null && !TextUtils.isEmpty(item.alias())) {
userName = item.alias();
} else if (item != null && !TextUtils.isEmpty(item.nickname())) {
userName = item.nickname();
} else if (item != null) {
userName = item.username();
userName = item.username();
}
}
if (mIconView != null) {
ChatUtils.getInstance().showRosterAvatar(item, mIconView, ICON_CONFIG);
}
} else {
BMXUserProfile profile = RosterFetcher.getFetcher().getProfile();
if (group) {
//如果是群 需要获取群成员名称
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (profile != null && !TextUtils.isEmpty(profile.nickname())) {
userName = profile.nickname();
} else if (profile != null) {
userName = profile.username();
}
} else {
if (profile != null && !TextUtils.isEmpty(profile.nickname())) {
RosterDetailActivity.openRosterDetail(mContext, mMaxMessage.fromId());
protected boolean filterMessage(BMXMessage message) {
if (message == null) {
return false;
}
if (message.contentType() == BMXMessage.ContentType.Text
&& !TextUtils.isEmpty(message.extension())) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(message.extension());
if (jsonObject.has(MessageConfig.INPUT_STATUS) && message.fromId() != mMyUserId) {
handelInputStatus(message.extension());
}
//TODO
// if (jsonObject.has("rtcKey") && jsonObject.has("rtcValue")) {
// if (TextUtils.equals(jsonObject.getString("rtcKey"), "join") && !TextUtils.isEmpty(jsonObject.getString("rtcValue"))) {
// String[] values = jsonObject.getString("rtcValue").split("_");
// String roomId = values[0];
// String[] chatIdArray = values[1].split(",");
// boolean hasVideo = TextUtils.equals(MessageConfig.CallMode.CALL_VIDEO+"", values[2]);
// List<Long> chatIds = new ArrayList<>();
@Override
protected boolean isCurrentSession(BMXMessage message) {
if (message == null || message.type() != BMXMessage.MessageType.Single) {
return false;
}
if (message.isReceiveMsg()) {
// 对方发过来的消息
return message.fromId() == mChatId;
}
return message.toId() == mChatId;
private void notifyMessage(List<BMXMessage> messages) {
if (messages == null || messages.isEmpty()) {
return;
}
ListOfLongLong rosterIds = new ListOfLongLong();
for (int i = 0; i < messages.size(); i++) {
BMXMessage message = messages.get(i);
if (message == null) {
continue;
}
rosterIds.add(message.fromId());
}
if (!rosterIds.isEmpty()) {
RosterManager.getInstance().getRosterList(rosterIds, true, (bmxErrorCode, itemList) -> {
RosterFetcher.getFetcher().putRosters(itemList);
if (BaseManager.bmxFinish(bmxErrorCode)) {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
function toId
inline long toId()
消息接收方ID
Return: int64_t
Example:
@Override
protected boolean isCurrentSession(BMXMessage message) {
return message != null && message.type() == BMXMessage.MessageType.Group
&& message.toId() == mChatId;
@Override
protected boolean isCurrentSession(BMXMessage message) {
if (message == null || message.type() != BMXMessage.MessageType.Single) {
return false;
}
if (message.isReceiveMsg()) {
// 对方发过来的消息
return message.fromId() == mChatId;
}
return message.toId() == mChatId;
private void notifyNotification(BMXMessage bean) {
if (bean == null || !bean.isReceiveMsg()) {
return;
}
Context context = AppContextUtils.getAppContext();
Intent intent = new Intent(String.format(context.getString(R.string.im_push_msg_action),
context.getPackageName()));
if (bean.type() == BMXMessage.MessageType.Group) {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.toId()));
} else {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.fromId()));
}
intent.setPackage(context.getPackageName());
context.sendBroadcast(intent);
function type
inline BMXMessage.MessageType type()
消息类型
Return: [MessageType]
Example:
private void showHead() {
if (mItemPos == ITEM_CENTER || mMaxMessage == null) {
return;
}
String userName = null;
boolean group = mMaxMessage.type() == BMXMessage.MessageType.Group;
boolean hideMemberInfo = true;
if (group){
BMXGroup bmxGroup = RosterFetcher.getFetcher().getGroup(mMaxMessage.conversationId());
if (bmxGroup != null) {
boolean isOwner = GroupManager.getInstance().isGroupOwner(bmxGroup.ownerId());
boolean isAdmin = GroupManager.getInstance().isAdmin(bmxGroup, SharePreferenceUtils.getInstance().getUserId()) || isOwner;
boolean hideByGroupSettings = bmxGroup.hideMemberInfo();
if (!hideByGroupSettings || isAdmin){
hideMemberInfo = false;
}
}
}
if (mMaxMessage.isReceiveMsg()) {
private void showReadStatus() {
if (mItemPos != ITEM_RIGHT || mTvReadStatus == null) {
return;
}
if (mMaxMessage == null) {
mTvReadStatus.setVisibility(View.GONE);
return;
}
if (mMaxMessage.type() == BMXMessage.MessageType.Single) {
// 单聊
mTvReadStatus.setVisibility(View.VISIBLE);
boolean isRead = mMaxMessage.isReadAcked();
mTvReadStatus.setText(isRead ? getResources().getString(R.string.read) : getResources().getString(R.string.unread));
} else if (mMaxMessage.type() == BMXMessage.MessageType.Group) {
// 群聊
mTvReadStatus.setVisibility(mShowReadAck ? View.VISIBLE : View.GONE);
int readCount = mMaxMessage.groupAckCount();
mTvReadStatus.setText(getResources().getString(R.string.read_persons) + (readCount > 0 ? readCount : 0));
} else {
mTvReadStatus.setVisibility(View.GONE);
}
if (mMaxMessage == null) {
mTvReadStatus.setVisibility(View.GONE);
return;
}
if (mMaxMessage.type() == BMXMessage.MessageType.Single) {
// 单聊
mTvReadStatus.setVisibility(View.VISIBLE);
boolean isRead = mMaxMessage.isReadAcked();
mTvReadStatus.setText(isRead ? getResources().getString(R.string.read) : getResources().getString(R.string.unread));
} else if (mMaxMessage.type() == BMXMessage.MessageType.Group) {
// 群聊
mTvReadStatus.setVisibility(mShowReadAck ? View.VISIBLE : View.GONE);
int readCount = mMaxMessage.groupAckCount();
mTvReadStatus.setText(getResources().getString(R.string.read_persons) + (readCount > 0 ? readCount : 0));
} else {
mTvReadStatus.setVisibility(View.GONE);
}
mTvReadStatus.setOnClickListener((v) -> {
if (!mShowReadAck || mActionListener == null) {
@Override
protected boolean isCurrentSession(BMXMessage message) {
return message != null && message.type() == BMXMessage.MessageType.Group
&& message.toId() == mChatId;
@Override
protected boolean isCurrentSession(BMXMessage message) {
if (message == null || message.type() != BMXMessage.MessageType.Single) {
return false;
}
if (message.isReceiveMsg()) {
// 对方发过来的消息
return message.fromId() == mChatId;
}
return message.toId() == mChatId;
private void notifyNotification(BMXMessage bean) {
if (bean == null || !bean.isReceiveMsg()) {
return;
}
Context context = AppContextUtils.getAppContext();
Intent intent = new Intent(String.format(context.getString(R.string.im_push_msg_action),
context.getPackageName()));
if (bean.type() == BMXMessage.MessageType.Group) {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.toId()));
} else {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.fromId()));
}
intent.setPackage(context.getPackageName());
context.sendBroadcast(intent);
private void notifyNotification(BMXMessage bean) {
if (bean == null || !bean.isReceiveMsg()) {
return;
}
Context context = AppContextUtils.getAppContext();
Intent intent = new Intent(String.format(context.getString(R.string.im_push_msg_action),
context.getPackageName()));
if (bean.type() == BMXMessage.MessageType.Group) {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.toId()));
} else {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.fromId()));
}
intent.setPackage(context.getPackageName());
context.sendBroadcast(intent);
private void notifyNotification(BMXMessage bean) {
if (bean == null || !bean.isReceiveMsg()) {
return;
}
Context context = AppContextUtils.getAppContext();
Intent intent = new Intent(String.format(context.getString(R.string.im_push_msg_action),
context.getPackageName()));
if (bean.type() == BMXMessage.MessageType.Group) {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.toId()));
} else {
intent.putExtra(MessageConfig.CHAT_MSG,
ChatUtils.getInstance().buildMessage(bean, bean.type(), bean.fromId()));
}
intent.setPackage(context.getPackageName());
context.sendBroadcast(intent);
function conversationId
inline long conversationId()
消息所属会话ID
Return: int64_t
Example:
private void showHead() {
if (mItemPos == ITEM_CENTER || mMaxMessage == null) {
return;
}
String userName = null;
boolean group = mMaxMessage.type() == BMXMessage.MessageType.Group;
boolean hideMemberInfo = true;
if (group){
BMXGroup bmxGroup = RosterFetcher.getFetcher().getGroup(mMaxMessage.conversationId());
if (bmxGroup != null) {
boolean isOwner = GroupManager.getInstance().isGroupOwner(bmxGroup.ownerId());
boolean isAdmin = GroupManager.getInstance().isAdmin(bmxGroup, SharePreferenceUtils.getInstance().getUserId()) || isOwner;
boolean hideByGroupSettings = bmxGroup.hideMemberInfo();
if (!hideByGroupSettings || isAdmin){
hideMemberInfo = false;
}
}
}
if (mMaxMessage.isReceiveMsg()) {
if (!hideByGroupSettings || isAdmin){
hideMemberInfo = false;
}
}
}
if (mMaxMessage.isReceiveMsg()) {
BMXRosterItem item = RosterFetcher.getFetcher().getRoster(mMaxMessage.fromId());
if(group){
//如果是群 需要获取群成员名称
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (item != null && !TextUtils.isEmpty(item.alias())) {
userName = item.alias();
} else if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (item != null && !TextUtils.isEmpty(item.nickname())) {
userName = item.nickname();
} else if (item != null) {
userName = item.username();
if (hideMemberInfo){
userName = item.username();
}
}
if (mIconView != null) {
ChatUtils.getInstance().showRosterAvatar(item, mIconView, ICON_CONFIG);
}
} else {
BMXUserProfile profile = RosterFetcher.getFetcher().getProfile();
if (group) {
//如果是群 需要获取群成员名称
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (profile != null && !TextUtils.isEmpty(profile.nickname())) {
userName = profile.nickname();
} else if (profile != null) {
userName = profile.username();
}
} else {
if (profile != null && !TextUtils.isEmpty(profile.nickname())) {
function deliveryStatus
inline BMXMessage.DeliveryStatus deliveryStatus()
消息投递状态
Return: [DeliveryStatus]
Example:
private void showSendStatus() {
if (mItemPos != ITEM_RIGHT || mSendFailImg == null || mSendingImg == null) {
return;
}
BMXMessage.DeliveryStatus sendStatus = mMaxMessage == null ? null
: mMaxMessage.deliveryStatus();
// 消息发送状态是否失败
if (sendStatus == null || sendStatus == BMXMessage.DeliveryStatus.Deliveried) {
// 空和成功都展示成功
mSendFailImg.setVisibility(View.GONE);
mSendingImg.setVisibility(View.GONE);
} else if (sendStatus == BMXMessage.DeliveryStatus.Failed) {
// 失败
mSendFailImg.setVisibility(View.VISIBLE);
mSendingImg.setVisibility(View.GONE);
} else {
mSendFailImg.setVisibility(View.GONE);
mSendingImg.setVisibility(View.VISIBLE);
}
dialog.dismiss();
ForwardMsgActivity.openForwardMsgRosterActivity((Activity)mView.getContext(),
ChatUtils.getInstance().buildMessage(message, mChatType, mChatId),
FORWARD_REQUEST);
});
ll.addView(relay, params);
// 自己发送的消息才有撤回
if (!message.isReceiveMsg()) {
// 撤回
BMXMessage.DeliveryStatus sendStatus = message.deliveryStatus();
// 发送成功才有撤回
if (sendStatus == null || sendStatus == BMXMessage.DeliveryStatus.Deliveried) {
TextView revoke = new TextView(mView.getContext());
revoke.setPadding(ScreenUtils.dp2px(15), ScreenUtils.dp2px(15),
ScreenUtils.dp2px(15), 0);
revoke.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
revoke.setTextColor(
mView.getContext().getResources().getColor(R.color.color_black));
revoke.setBackgroundColor(
function setDeliveryStatus
inline void setDeliveryStatus(
BMXMessage.DeliveryStatus arg0
)
设置消息投递状态
Example:
function serverTimestamp
inline long serverTimestamp()
消息时间戳(服务端收到时的时间)
Return: int64_t
Example:
long o1Time = m1 == null ? -1 : m1.serverTimestamp();
long o2Time = m2 == null ? -1 : m2.serverTimestamp();
private boolean isShowTime(int position) {
// 聊天消息时间戳为毫秒级 目前为10分钟间隔 也就是10 * 60 * 1000
long timeOut = 10 * 60 * 1000;
BMXMessage current = mBeans.get(position);
boolean showtime = true;
if (position > 0) {
BMXMessage pre = mBeans.get(position - 1);
if (current.serverTimestamp() == 0 || pre.serverTimestamp() == 0) {
showtime = false;
} else {
long time_cha = 0;
try {
time_cha = (current.serverTimestamp() - pre.serverTimestamp()) / timeOut;
} catch (Exception e) {
e.printStackTrace();
}
showtime = time_cha >= 1;
}
}
return showtime;
long timeOut = 10 * 60 * 1000;
BMXMessage current = mBeans.get(position);
boolean showtime = true;
if (position > 0) {
BMXMessage pre = mBeans.get(position - 1);
if (current.serverTimestamp() == 0 || pre.serverTimestamp() == 0) {
showtime = false;
} else {
long time_cha = 0;
try {
time_cha = (current.serverTimestamp() - pre.serverTimestamp()) / timeOut;
} catch (Exception e) {
e.printStackTrace();
}
showtime = time_cha >= 1;
}
}
return showtime;
} else {
ivDisturb.setVisibility(View.GONE);
if (unReadCount > 0) {
tvUnReadCount.setVisibility(View.VISIBLE);
tvUnReadCount.setText(String.valueOf(unReadCount));
} else {
tvUnReadCount.setVisibility(View.GONE);
}
}
tvTitle.setText(TextUtils.isEmpty(name) ? "" : name);
time.setText(lastMsg != null ? TimeUtils.millis2StringOnConversationList(mContext, lastMsg.serverTimestamp()) : "");
String draft = item == null ? "" : item.editMessage();
if (!TextUtils.isEmpty(draft)) {
// 有草稿
SpannableStringBuilder spannable = new SpannableStringBuilder();
String draftText = mContext.getString(R.string.draft);
SpannableString spannableString = new SpannableString(draftText);
spannableString.setSpan(new ForegroundColorSpan(Color.RED), 0, draftText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.append(spannableString).append(draft);
@Override
public void bindData(BMXMessage maXMessage) {
mMaxMessage = maXMessage;
mTxtMessageTime.setText(TimeUtils.millis2StringOnMessageList(mContext, maXMessage.serverTimestamp()));
showHead();
bindData();
showReadStatus();
showSendStatus();
function setServerTimestamp
inline void setServerTimestamp(
long arg0
)
设置时间戳(服务端收到时的时间)
Example:
function clientTimestamp
inline long clientTimestamp()
本地时间戳(消息创建或者收到时的本地时间)
Return: int64_t
Example:
function setClientTimestamp
inline void setClientTimestamp(
long arg0
)
设置消息本地时间戳
Example:
function isPlayed
inline boolean isPlayed()
语音或者视频消息是否播放过,仅对收到的音视频消息有效
Return: bool
Example:
function setIsPlayed
inline void setIsPlayed(
boolean arg0
)
Example:
function isPlayAcked
inline boolean isPlayAcked()
语音或者视频消息是否收到播放回执,仅对收到的音视频消息有效
Return: bool
Example:
function setIsPlayAcked
inline void setIsPlayAcked(
boolean arg0
)
Example:
function isReceiveMsg
inline boolean isReceiveMsg()
是否接收的消息
Return: bool
Example:
private int getChatItemType(BMXMessage bean) {
if (bean == null) {
return -1;
}
boolean isMySend = !bean.isReceiveMsg();
int viewType = MsgBodyHelper.getContentBodyClass(bean.contentType().swigValue()) != null
? bean.contentType().swigValue()
: -1;
return isMySend ? viewType : ~viewType;
// 有草稿
SpannableStringBuilder spannable = new SpannableStringBuilder();
String draftText = mContext.getString(R.string.draft);
SpannableString spannableString = new SpannableString(draftText);
spannableString.setSpan(new ForegroundColorSpan(Color.RED), 0, draftText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.append(spannableString).append(draft);
desc.setText(spannable);
} else {
String msgDesc = ChatUtils.getInstance().getMessageDesc(mContext, lastMsg);
if (lastMsg != null && lastMsg.isReceiveMsg() && lastMsg.config() != null) {
// 有@
try {
BMXMessageConfig config = lastMsg.config();
if (config.getMentionAll()) {
msgDesc = mContext.getString(R.string.someone_at_you) + msgDesc;
} else {
ListOfLongLong atList = config.getMentionList();
if (atList != null && !atList.isEmpty()) {
for (int i = 0; i < atList.size(); i++) {
if (bmxGroup != null) {
boolean isOwner = GroupManager.getInstance().isGroupOwner(bmxGroup.ownerId());
boolean isAdmin = GroupManager.getInstance().isAdmin(bmxGroup, SharePreferenceUtils.getInstance().getUserId()) || isOwner;
boolean hideByGroupSettings = bmxGroup.hideMemberInfo();
if (!hideByGroupSettings || isAdmin){
hideMemberInfo = false;
}
}
}
if (mMaxMessage.isReceiveMsg()) {
BMXRosterItem item = RosterFetcher.getFetcher().getRoster(mMaxMessage.fromId());
if(group){
//如果是群 需要获取群成员名称
BMXGroup.Member member = GroupManager.getInstance().getMemberByDB(mMaxMessage.conversationId(), mMaxMessage.fromId());
if (item != null && !TextUtils.isEmpty(item.alias())) {
userName = item.alias();
} else if (member != null && !TextUtils.isEmpty(member.getMGroupNickname())) {
userName = member.getMGroupNickname();
} else if (item != null && !TextUtils.isEmpty(item.nickname())) {
if (mMaxMessage.isReceiveMsg()) {
relay.setText(mView.getContext().getString(R.string.chat_msg_relay));
relay.setOnClickListener(v -> {
dialog.dismiss();
ForwardMsgActivity.openForwardMsgRosterActivity((Activity)mView.getContext(),
ChatUtils.getInstance().buildMessage(message, mChatType, mChatId),
FORWARD_REQUEST);
});
ll.addView(relay, params);
// 自己发送的消息才有撤回
if (!message.isReceiveMsg()) {
// 撤回
BMXMessage.DeliveryStatus sendStatus = message.deliveryStatus();
// 发送成功才有撤回
if (sendStatus == null || sendStatus == BMXMessage.DeliveryStatus.Deliveried) {
TextView revoke = new TextView(mView.getContext());
revoke.setPadding(ScreenUtils.dp2px(15), ScreenUtils.dp2px(15),
ScreenUtils.dp2px(15), 0);
revoke.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
revoke.setTextColor(
mView.getContext().getResources().getColor(R.color.color_white));
revoke.setText(mView.getContext().getString(R.string.chat_msg_revoke));
revoke.setOnClickListener(v -> {
dialog.dismiss();
revokeMessage(message);
});
ll.addView(revoke, params);
}
}
// 对方发送的消息才有标记已读
if (message.isReceiveMsg()) {
// 标记已读
TextView ackRead = new TextView(mView.getContext());
ackRead.setPadding(ScreenUtils.dp2px(15), ScreenUtils.dp2px(15), ScreenUtils.dp2px(15),
0);
ackRead.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
ackRead.setTextColor(mView.getContext().getResources().getColor(R.color.color_black));
ackRead.setBackgroundColor(
mView.getContext().getResources().getColor(R.color.color_white));
ackRead.setText(mView.getContext().getString(R.string.chat_msg_ack));
protected void ackMessage(final BMXMessage message) {
// 已读不在发送 自己发送的消息不设置已读
if (message == null || message.isReadAcked() || !message.isReceiveMsg()) {
return;
}
Observable.just(message).map(new Func1<BMXMessage, BMXMessage>() {
@Override
public BMXMessage call(BMXMessage message) {
ChatManager.getInstance().ackMessage(message);
return message;
}
}).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<BMXMessage>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
@Override
protected boolean isCurrentSession(BMXMessage message) {
if (message == null || message.type() != BMXMessage.MessageType.Single) {
return false;
}
if (message.isReceiveMsg()) {
// 对方发过来的消息
return message.fromId() == mChatId;
}
return message.toId() == mChatId;
function setIsReceiveMsg
inline void setIsReceiveMsg(
boolean arg0
)
Example:
function isRead
inline boolean isRead()
消息是否已读标志
Return: bool
Example:
function setIsRead
inline void setIsRead(
boolean arg0
)
Example:
function isReadAcked
inline boolean isReadAcked()
对于发送方表示是否收到了已读回执,对于接收方表示是否发送了已读回执
Return: bool
Example:
if (mItemPos != ITEM_RIGHT || mTvReadStatus == null) {
return;
}
if (mMaxMessage == null) {
mTvReadStatus.setVisibility(View.GONE);
return;
}
if (mMaxMessage.type() == BMXMessage.MessageType.Single) {
// 单聊
mTvReadStatus.setVisibility(View.VISIBLE);
boolean isRead = mMaxMessage.isReadAcked();
mTvReadStatus.setText(isRead ? getResources().getString(R.string.read) : getResources().getString(R.string.unread));
} else if (mMaxMessage.type() == BMXMessage.MessageType.Group) {
// 群聊
mTvReadStatus.setVisibility(mShowReadAck ? View.VISIBLE : View.GONE);
int readCount = mMaxMessage.groupAckCount();
mTvReadStatus.setText(getResources().getString(R.string.read_persons) + (readCount > 0 ? readCount : 0));
} else {
mTvReadStatus.setVisibility(View.GONE);
protected void ackMessage(final BMXMessage message) {
// 已读不在发送 自己发送的消息不设置已读
if (message == null || message.isReadAcked() || !message.isReceiveMsg()) {
return;
}
Observable.just(message).map(new Func1<BMXMessage, BMXMessage>() {
@Override
public BMXMessage call(BMXMessage message) {
ChatManager.getInstance().ackMessage(message);
return message;
}
}).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<BMXMessage>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
function setIsReadAcked
inline void setIsReadAcked(
boolean arg0
)
Example:
function isDeliveryAcked
inline boolean isDeliveryAcked()
对于发送方表示消息是否已投递到对方,对于接收方表示是否发送了消息已到达回执
Return: bool
Example:
function setIsDeliveryAcked
inline void setIsDeliveryAcked(
boolean arg0
)
Example:
function content
inline String content()
消息文本内容
Return: std::string
Example:
@Override
protected void onBindHolder(BaseViewHolder holder, int position) {
TextView tv = holder.findViewById(R.id.tv_push_msg);
BMXMessage message = getItem(position);
String content = message == null ? "" : message.content();
tv.setText(content);
private void copyMessage(BMXMessage message) {
if (message == null || message.contentType() != BMXMessage.ContentType.Text) {
return;
}
ClipboardManager clipboard = (ClipboardManager)mView.getContext()
.getSystemService(Context.CLIPBOARD_SERVICE);
if (clipboard == null) {
return;
}
String text = message.content();
if (TextUtils.isEmpty(text)) {
return;
}
ClipData clip = ClipData.newPlainText("chat_text", text);
clipboard.setPrimaryClip(clip);
ToastUtil.showTextViewPrompt(mView.getContext().getString(R.string.copy_successful));
public String getMessageDesc(Context context, BMXMessage message) {
if (message == null) {
return "";
}
BMXMessage.ContentType type = message.contentType();
String content = message.content();
return getMessageDesc(context, type, content, message.isReceiveMsg(), message);
if (mBmxMessage == null) {
return null;
}
MessageBean messageBean = new MessageBean();
BMXMessage.ContentType contentType = mBmxMessage.contentType();
messageBean.setContentType(contentType);
messageBean.setType(type);
messageBean.setChatId(chatId);
messageBean.setReceiveMsg(mBmxMessage.isReceiveMsg());
if (contentType == BMXMessage.ContentType.Text) {
String text = mBmxMessage.content();
if (!TextUtils.isEmpty(text)) {
messageBean.setContent(text);
return messageBean;
}
return null;
}
if (contentType == BMXMessage.ContentType.Image) {
// 图片
BMXImageAttachment body = BMXImageAttachment.dynamic_cast(mBmxMessage.attachment());
function setContent
inline void setContent(
String content
)
消息文本内容
Parameters:
- content 消息文本内容
Example:
function contentType
inline BMXMessage.ContentType contentType()
消息内容类型,如果带附件就表示附件类型,不带附件就是文本类型
Return: [ContentType]
Example:
private int getChatItemType(BMXMessage bean) {
if (bean == null) {
return -1;
}
boolean isMySend = !bean.isReceiveMsg();
int viewType = MsgBodyHelper.getContentBodyClass(bean.contentType().swigValue()) != null
? bean.contentType().swigValue()
: -1;
return isMySend ? viewType : ~viewType;
private int getChatItemType(BMXMessage bean) {
if (bean == null) {
return -1;
}
boolean isMySend = !bean.isReceiveMsg();
int viewType = MsgBodyHelper.getContentBodyClass(bean.contentType().swigValue()) != null
? bean.contentType().swigValue()
: -1;
return isMySend ? viewType : ~viewType;
@Override
public void onItemFunc(BMXMessage bean) {
if (bean == null) {
return;
}
BMXMessage.ContentType contentType = bean.contentType();
if (contentType == BMXMessage.ContentType.Text) {
// TODO
} else if (contentType == BMXMessage.ContentType.Image) {
// 图片
onImageItemClick(bean);
} else if (contentType == BMXMessage.ContentType.Voice) {
// 语音播放
onAudioItemClick(bean);
} else if (contentType == BMXMessage.ContentType.File) {
// 文件查看
onFileItemClick(bean);
} else if (contentType == BMXMessage.ContentType.Video) {
// 视频
openVideoItemClick(bean);
delete.setBackgroundColor(mView.getContext().getResources().getColor(R.color.color_white));
delete.setText(mView.getContext().getString(R.string.delete));
delete.setOnClickListener(v -> {
dialog.dismiss();
deleteMessage(message);
});
ll.addView(delete, params);
// 复制 文字才有
// 自己发送的消息才有撤回
if (message.contentType() == BMXMessage.ContentType.Text) {
// 撤回
TextView copy = new TextView(mView.getContext());
copy.setPadding(ScreenUtils.dp2px(15), ScreenUtils.dp2px(15), ScreenUtils.dp2px(15), 0);
copy.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
copy.setTextColor(mView.getContext().getResources().getColor(R.color.color_black));
copy.setBackgroundColor(
mView.getContext().getResources().getColor(R.color.color_white));
copy.setText(mView.getContext().getString(R.string.chat_msg_copy));
copy.setOnClickListener(v -> {
private void copyMessage(BMXMessage message) {
if (message == null || message.contentType() != BMXMessage.ContentType.Text) {
return;
}
ClipboardManager clipboard = (ClipboardManager)mView.getContext()
.getSystemService(Context.CLIPBOARD_SERVICE);
if (clipboard == null) {
return;
}
String text = message.content();
if (TextUtils.isEmpty(text)) {
return;
}
ClipData clip = ClipData.newPlainText("chat_text", text);
clipboard.setPrimaryClip(clip);
ToastUtil.showTextViewPrompt(mView.getContext().getString(R.string.copy_successful));
private void onAudioItemClick(final BMXMessage bean) {
if (mView == null || bean == null || bean.contentType() != BMXMessage.ContentType.Voice) {
return;
}
ackMessage(bean);
final BMXVoiceAttachment body = BMXVoiceAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
if (mVoicePlayHelper == null) {
mVoicePlayHelper = new VoicePlayHelper((Activity)mView.getContext());
registerSensor();
}
if (mVoicePlayHelper.isPlaying()) {
stopVoicePlay();
return;
}
if (TextUtils.isEmpty(body.path())) {
Log.i(TAG, "http voiceUrl is null");
private void playVoice(String voicePath, final BMXMessage bean) {
if (mView == null || TextUtils.isEmpty(voicePath) || bean == null
|| bean.contentType() != BMXMessage.ContentType.Voice || mVoicePlayHelper == null) {
return;
}
BMXVoiceAttachment body = BMXVoiceAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
mVoicePlayHelper.setOnVoiceFinishListener(new VoicePlayHelper.OnVoiceFinishListener() {
@Override
public void onFinish() {
if (mView == null) {
return;
}
VoicePlayManager.getInstance().onFinishCallback(bean);
// mView.getVoiceMessageMsgId(chatBean.getMsgId());
}
@Override
private void onFileItemClick(BMXMessage bean) {
if (mView == null || bean == null || bean.contentType() != BMXMessage.ContentType.File) {
return;
}
final BMXFileAttachment body = BMXFileAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
String filePath = null;
if (!TextUtils.isEmpty(body.path()) && new File(body.path()).exists()) {
filePath = body.path();
} else {
Log.i(TAG, "local path is null");
}
if (!TextUtils.isEmpty(filePath)) {
openFilePreView(filePath);
return;
}
ToastUtil.showTextViewPrompt(mView.getContext().getString(R.string.downloading));
BMXMessageAttachment.DownloadStatus status = body.downloadStatus();
function attachment
inline BMXMessageAttachment attachment()
消息附件,BMXMessage拥有附件的所有权,负责释放
Return: BMXMessageAttachmentPtr
Example:
private void onAudioItemClick(final BMXMessage bean) {
if (mView == null || bean == null || bean.contentType() != BMXMessage.ContentType.Voice) {
return;
}
ackMessage(bean);
final BMXVoiceAttachment body = BMXVoiceAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
if (mVoicePlayHelper == null) {
mVoicePlayHelper = new VoicePlayHelper((Activity)mView.getContext());
registerSensor();
}
if (mVoicePlayHelper.isPlaying()) {
stopVoicePlay();
return;
}
if (TextUtils.isEmpty(body.path())) {
Log.i(TAG, "http voiceUrl is null");
private void playVoice(String voicePath, final BMXMessage bean) {
if (mView == null || TextUtils.isEmpty(voicePath) || bean == null
|| bean.contentType() != BMXMessage.ContentType.Voice || mVoicePlayHelper == null) {
return;
}
BMXVoiceAttachment body = BMXVoiceAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
mVoicePlayHelper.setOnVoiceFinishListener(new VoicePlayHelper.OnVoiceFinishListener() {
@Override
public void onFinish() {
if (mView == null) {
return;
}
VoicePlayManager.getInstance().onFinishCallback(bean);
// mView.getVoiceMessageMsgId(chatBean.getMsgId());
}
@Override
private void onFileItemClick(BMXMessage bean) {
if (mView == null || bean == null || bean.contentType() != BMXMessage.ContentType.File) {
return;
}
final BMXFileAttachment body = BMXFileAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
String filePath = null;
if (!TextUtils.isEmpty(body.path()) && new File(body.path()).exists()) {
filePath = body.path();
} else {
Log.i(TAG, "local path is null");
}
if (!TextUtils.isEmpty(filePath)) {
openFilePreView(filePath);
return;
}
ToastUtil.showTextViewPrompt(mView.getContext().getString(R.string.downloading));
BMXMessageAttachment.DownloadStatus status = body.downloadStatus();
private void onImageItemClick(final BMXMessage bean) {
if (mView == null || bean == null || bean.contentType() != BMXMessage.ContentType.Image) {
return;
}
BMXImageAttachment body = BMXImageAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
String picUrl = null;
if (!TextUtils.isEmpty(body.thumbnailPath()) && new File(body.thumbnailPath()).exists()) {
picUrl = body.thumbnailPath();
} else if (!TextUtils.isEmpty(body.path()) && new File(body.path()).exists()) {
picUrl = body.path();
} else if (!TextUtils.isEmpty(body.thumbnailUrl())) {
picUrl = body.thumbnailUrl();
} else if (!TextUtils.isEmpty(body.url())) {
picUrl = body.url();
}
if (TextUtils.isEmpty(picUrl)) {
// 正在下载
private void openVideoItemClick(BMXMessage bean) {
if (mView == null || bean == null || bean.contentType() != BMXMessage.ContentType.Video) {
return;
}
BMXVideoAttachment body = BMXVideoAttachment.dynamic_cast(bean.attachment());
if (body == null) {
return;
}
String videoUrl = null;
if (!TextUtils.isEmpty(body.path()) && new File(body.path()).exists()) {
videoUrl = body.path();
}
if (TextUtils.isEmpty(videoUrl)) {
// 正在下载
ToastUtil.showTextViewPrompt(mView.getContext().getString(R.string.downloading));
return;
}
BMXMessageAttachment.DownloadStatus status = body.downloadStatus();
if (status == BMXMessageAttachment.DownloadStatus.Downloaing) {
ToastUtil.showTextViewPrompt(mView.getContext().getString(R.string.downloading));
if (contentType == BMXMessage.ContentType.Text) {
String text = mBmxMessage.content();
if (!TextUtils.isEmpty(text)) {
messageBean.setContent(text);
return messageBean;
}
return null;
}
if (contentType == BMXMessage.ContentType.Image) {
// 图片
BMXImageAttachment body = BMXImageAttachment.dynamic_cast(mBmxMessage.attachment());
if (body == null || body.size() == null || TextUtils.isEmpty(body.path())) {
return null;
}
int w = (int)body.size().getMWidth();
int h = (int)body.size().getMHeight();
messageBean.setPath(body.path());
messageBean.setW(w);
messageBean.setH(h);
return messageBean;
}
int w = (int)body.size().getMWidth();
int h = (int)body.size().getMHeight();
messageBean.setPath(body.path());
messageBean.setW(w);
messageBean.setH(h);
return messageBean;
}
if (contentType == BMXMessage.ContentType.Voice) {
// 语音
BMXVoiceAttachment body = BMXVoiceAttachment.dynamic_cast(mBmxMessage.attachment());
if (body == null || TextUtils.isEmpty(body.path())) {
return null;
}
messageBean.setPath(body.path());
messageBean.setDuration(body.duration());
return messageBean;
}
if (contentType == BMXMessage.ContentType.File) {
// 文件
BMXVoiceAttachment body = BMXVoiceAttachment.dynamic_cast(mBmxMessage.attachment());
if (body == null || TextUtils.isEmpty(body.path())) {
return null;
}
messageBean.setPath(body.path());
messageBean.setDuration(body.duration());
return messageBean;
}
if (contentType == BMXMessage.ContentType.File) {
// 文件
BMXFileAttachment body = BMXFileAttachment.dynamic_cast(mBmxMessage.attachment());
if (body == null || TextUtils.isEmpty(body.path())) {
return null;
}
messageBean.setPath(body.path());
messageBean.setDisplayName(body.displayName());
return messageBean;
}
if (contentType == BMXMessage.ContentType.Location) {
// 地图
function config
inline BMXMessageConfig config()
消息的配置信息
Return: JSON(std::string)
Example:
@Override
public void onBindViewHolder(BaseChatHolder holder, int position) {
if (holder == null) {
return;
}
holder.showChatExtra(isShowTime(position), showReadAck);
BMXMessage bean = mBeans.get(position);
BMXMessageConfig config = bean.config();
if (config != null){
String action = config.getRTCAction();
if (action != null && action.length() != 0 && !action.equals("record")){
RecyclerView.LayoutParams param = new RecyclerView.LayoutParams(1, 1);
holder.itemView.setLayoutParams(param);
}
}
holder.setData(bean);
// 有草稿
SpannableStringBuilder spannable = new SpannableStringBuilder();
String draftText = mContext.getString(R.string.draft);
SpannableString spannableString = new SpannableString(draftText);
spannableString.setSpan(new ForegroundColorSpan(Color.RED), 0, draftText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.append(spannableString).append(draft);
desc.setText(spannable);
} else {
String msgDesc = ChatUtils.getInstance().getMessageDesc(mContext, lastMsg);
if (lastMsg != null && lastMsg.isReceiveMsg() && lastMsg.config() != null) {
// 有@
try {
BMXMessageConfig config = lastMsg.config();
if (config.getMentionAll()) {
msgDesc = mContext.getString(R.string.someone_at_you) + msgDesc;
} else {
ListOfLongLong atList = config.getMentionList();
if (atList != null && !atList.isEmpty()) {
for (int i = 0; i < atList.size(); i++) {
SpannableString spannableString = new SpannableString(draftText);
spannableString.setSpan(new ForegroundColorSpan(Color.RED), 0, draftText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.append(spannableString).append(draft);
desc.setText(spannable);
} else {
String msgDesc = ChatUtils.getInstance().getMessageDesc(mContext, lastMsg);
if (lastMsg != null && lastMsg.isReceiveMsg() && lastMsg.config() != null) {
// 有@
try {
BMXMessageConfig config = lastMsg.config();
if (config.getMentionAll()) {
msgDesc = mContext.getString(R.string.someone_at_you) + msgDesc;
} else {
ListOfLongLong atList = config.getMentionList();
if (atList != null && !atList.isEmpty()) {
for (int i = 0; i < atList.size(); i++) {
if (atList.get(
i) == (SharePreferenceUtils.getInstance().getUserId())) {
msgDesc = mContext.getString(R.string.someone_at_you) + msgDesc;
} else if (type == BMXMessage.ContentType.File) {
desc = "[" + context.getString(R.string.file) + "]";
} else if (type == BMXMessage.ContentType.Voice) {
// 语音
desc = "[" + context.getString(R.string.voice) + "]";
} else if (type == BMXMessage.ContentType.RTC) {
if (message == null){
return "[" + context.getString(R.string.unknown_message) + "]";
}
boolean isRecordMsg = false;
BMXMessageConfig config = message.config();
if (config != null) {
String action = config.getRTCAction();
if (action != null) {
if (action.equals("record")) {
isRecordMsg = true;
}
}
}
if (!isRecordMsg){
function setConfig
inline void setConfig(
BMXMessageConfig arg0
)
设置消息配置信息
Example:
public String sendRTCCallMessage(BMXMessageConfig.RTCCallType type, long roomId, long from, long to,
String pin) {
BMXMessageConfig con = BMXMessageConfig.createMessageConfig(false);
con.setRTCCallInfo(type, roomId, from, BMXMessageConfig.RTCRoomType.Broadcast, pin);
con.setPushMessageLocKey("call_in");
BMXMessage msg = BMXMessage.createRTCMessage(from, to, BMXMessage.MessageType.Single, to, "");
msg.setConfig(con);
msg.setExtension("{\"rtc\":\"call\"}");
handlerMessage(msg);
return con.getRTCCallId();
public void sendRTCPickupMessage(long from, long to, String callId) {
BMXMessageConfig con = BMXMessageConfig.createMessageConfig(false);
con.setRTCPickupInfo(callId);
BMXMessage msg = BMXMessage.createRTCMessage(from, to, BMXMessage.MessageType.Single, to, "");
msg.setConfig(con);
handlerMessage(msg);
public void sendRTCHangupMessage(long from, long to, String callId, String content, String pushMessageLocKey, String pushMessageLocArgs, boolean peerDrop) {
BMXMessageConfig con = BMXMessageConfig.createMessageConfig(false);
con.setRTCHangupInfo(callId, peerDrop);
con.setPushMessageLocKey(pushMessageLocKey);
if (pushMessageLocArgs.length() > 0){
con.setPushMessageLocArgs(pushMessageLocArgs);
}
BMXMessage msg = BMXMessage.createRTCMessage(from, to, BMXMessage.MessageType.Single, to, content);
msg.setConfig(con);
handlerMessage(msg);
for (Map.Entry<String, String> entry : atMap.entrySet()) {
// 发送文字包含@对象的名称时再加入 防止输入框@对象名称被修改
if (entry.getValue() != null && !TextUtils.isEmpty(entry.getValue())
&& text.contains(entry.getValue())) {
// @部分成员 feed信息只需要feedId和userId 所以需要去除无用的信息
atIds.add(Long.valueOf(entry.getKey()));
}
}
config.setMentionList(atIds);
}
msg.setConfig(config);
}
return handlerMessage(msg);
function extension
inline String extension()
消息扩展信息
Return: JSON(std::string)
Example:
protected boolean filterMessage(BMXMessage message) {
if (message == null) {
return false;
}
if (message.contentType() == BMXMessage.ContentType.Text
&& !TextUtils.isEmpty(message.extension())) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(message.extension());
if (jsonObject.has(MessageConfig.INPUT_STATUS) && message.fromId() != mMyUserId) {
handelInputStatus(message.extension());
}
//TODO
// if (jsonObject.has("rtcKey") && jsonObject.has("rtcValue")) {
// if (TextUtils.equals(jsonObject.getString("rtcKey"), "join") && !TextUtils.isEmpty(jsonObject.getString("rtcValue"))) {
// String[] values = jsonObject.getString("rtcValue").split("_");
// String roomId = values[0];
// String[] chatIdArray = values[1].split(",");
// boolean hasVideo = TextUtils.equals(MessageConfig.CallMode.CALL_VIDEO+"", values[2]);
// List<Long> chatIds = new ArrayList<>();
protected boolean filterMessage(BMXMessage message) {
if (message == null) {
return false;
}
if (message.contentType() == BMXMessage.ContentType.Text
&& !TextUtils.isEmpty(message.extension())) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(message.extension());
if (jsonObject.has(MessageConfig.INPUT_STATUS) && message.fromId() != mMyUserId) {
handelInputStatus(message.extension());
}
//TODO
// if (jsonObject.has("rtcKey") && jsonObject.has("rtcValue")) {
// if (TextUtils.equals(jsonObject.getString("rtcKey"), "join") && !TextUtils.isEmpty(jsonObject.getString("rtcValue"))) {
// String[] values = jsonObject.getString("rtcValue").split("_");
// String roomId = values[0];
// String[] chatIdArray = values[1].split(",");
// boolean hasVideo = TextUtils.equals(MessageConfig.CallMode.CALL_VIDEO+"", values[2]);
// List<Long> chatIds = new ArrayList<>();
protected boolean filterMessage(BMXMessage message) {
if (message == null) {
return false;
}
if (message.contentType() == BMXMessage.ContentType.Text
&& !TextUtils.isEmpty(message.extension())) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(message.extension());
if (jsonObject.has(MessageConfig.INPUT_STATUS) && message.fromId() != mMyUserId) {
handelInputStatus(message.extension());
}
//TODO
// if (jsonObject.has("rtcKey") && jsonObject.has("rtcValue")) {
// if (TextUtils.equals(jsonObject.getString("rtcKey"), "join") && !TextUtils.isEmpty(jsonObject.getString("rtcValue"))) {
// String[] values = jsonObject.getString("rtcValue").split("_");
// String roomId = values[0];
// String[] chatIdArray = values[1].split(",");
// boolean hasVideo = TextUtils.equals(MessageConfig.CallMode.CALL_VIDEO+"", values[2]);
// List<Long> chatIds = new ArrayList<>();
private void handleRTCMessage(BMXMessage message){
if (message == null) {
return;
}
if (message.contentType() == BMXMessage.ContentType.RTC
&& !TextUtils.isEmpty(message.extension())) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(message.extension());
if(!jsonObject.has("rtc_cmd")){
return;
}
String cmd = jsonObject.getString("rtc_cmd");
switch (cmd){
case "switch_audio":
//切换为语音通话
switchAudio();
break;
default:
break;
private void handleRTCMessage(BMXMessage message){
if (message == null) {
return;
}
if (message.contentType() == BMXMessage.ContentType.RTC
&& !TextUtils.isEmpty(message.extension())) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(message.extension());
if(!jsonObject.has("rtc_cmd")){
return;
}
String cmd = jsonObject.getString("rtc_cmd");
switch (cmd){
case "switch_audio":
//切换为语音通话
switchAudio();
break;
default:
break;
function setExtension
inline void setExtension(
String arg0
)
设置消息扩展信息
Example:
public BMXMessage sendInputStatusMessage(BMXMessage.MessageType type, long from, long to,
String extension) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, "");
if (msg == null) {
return null;
}
msg.setDeliveryQos(BMXMessage.DeliveryQos.AtMostOnce);
msg.setExtension(extension);
return handlerMessage(msg);
public void sendRTCMessage(long from, long to,
String ext) {
BMXMessage msg = BMXMessage.createRTCMessage(from, to, BMXMessage.MessageType.Single, to, "");
msg.setExtension(ext);
handlerMessage(msg);
public String sendRTCCallMessage(BMXMessageConfig.RTCCallType type, long roomId, long from, long to,
String pin) {
BMXMessageConfig con = BMXMessageConfig.createMessageConfig(false);
con.setRTCCallInfo(type, roomId, from, BMXMessageConfig.RTCRoomType.Broadcast, pin);
con.setPushMessageLocKey("call_in");
BMXMessage msg = BMXMessage.createRTCMessage(from, to, BMXMessage.MessageType.Single, to, "");
msg.setConfig(con);
msg.setExtension("{\"rtc\":\"call\"}");
handlerMessage(msg);
return con.getRTCCallId();
function deliveryQos
inline BMXMessage.DeliveryQos deliveryQos()
消息投递QOS
Return: [DeliveryQos]
Example:
function setDeliveryQos
inline void setDeliveryQos(
BMXMessage.DeliveryQos qos
)
设置消息投递QOS
Parameters:
- qos 消息投递QOS
Example:
public BMXMessage sendInputStatusMessage(BMXMessage.MessageType type, long from, long to,
String extension) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, "");
if (msg == null) {
return null;
}
msg.setDeliveryQos(BMXMessage.DeliveryQos.AtMostOnce);
msg.setExtension(extension);
return handlerMessage(msg);
function senderName
inline String senderName()
消息发送者的显示名称
Return: std::string
Example:
function setSenderName
inline void setSenderName(
String senderName
)
设置消息的发送者显示名称
Parameters:
- senderName 消息文本内容
Example:
function groupAckCount
inline int groupAckCount()
群消息已读AckCount数目
Return: int
Example:
return;
}
if (mMaxMessage.type() == BMXMessage.MessageType.Single) {
// 单聊
mTvReadStatus.setVisibility(View.VISIBLE);
boolean isRead = mMaxMessage.isReadAcked();
mTvReadStatus.setText(isRead ? getResources().getString(R.string.read) : getResources().getString(R.string.unread));
} else if (mMaxMessage.type() == BMXMessage.MessageType.Group) {
// 群聊
mTvReadStatus.setVisibility(mShowReadAck ? View.VISIBLE : View.GONE);
int readCount = mMaxMessage.groupAckCount();
mTvReadStatus.setText(getResources().getString(R.string.read_persons) + (readCount > 0 ? readCount : 0));
} else {
mTvReadStatus.setVisibility(View.GONE);
}
mTvReadStatus.setOnClickListener((v) -> {
if (!mShowReadAck || mActionListener == null) {
return;
}
mActionListener.onGroupAck(mMaxMessage);
function setGroupAckCount
inline void setGroupAckCount(
int count
)
设置消息已读groupAckCount数目(SDK 内部调用接口,上层不应该调用)
Parameters:
- count 设置群消息已读数目
Example:
function groupAckUnreadCount
inline int groupAckUnreadCount()
群消息未读AckCount数目
Return: int
Example:
function setGroupAckUnreadCount
inline void setGroupAckUnreadCount(
int count
)
设置消息未读groupAckCount数目(SDK 内部调用接口,上层不应该调用)
Parameters:
- count 设置群消息未读数目
Example:
function groupAckReadAll
inline boolean groupAckReadAll()
群消息是否全部已读
Return: bool
Example:
function groupPlayAckCount
inline int groupPlayAckCount()
获取群消息已播放计数
Return: bool
Example:
function setGroupPlayAckCount
inline void setGroupPlayAckCount(
int count
)
Example:
function groupPlayAckUnreadCount
inline int groupPlayAckUnreadCount()
获取群消息已播放回执未读计数
Return: bool
Example:
function setGroupPlayAckUnreadCount
inline void setGroupPlayAckUnreadCount(
int count
)
Example:
function groupPlayAckReadAll
inline boolean groupPlayAckReadAll()
设置所有群消息已播回执为已读
Return: bool
Example:
function setPriority
inline void setPriority(
int priority
)
设置消息的扩散优先级,默认为0。0表示扩散,数字越小扩散的越多。 取值范围0-10。普通人在聊天室发送的消息级别默认为5,可以丢弃。管理员默认为0不会丢弃。其它值可以根据业务自行设置。
Parameters:
- priority 优先级
Example:
function priority
inline int priority()
消息的扩散优先级
Return: int
Example:
function setPushMessageMode
inline void setPushMessageMode(
boolean arg0
)
设置是否推送消息
Example:
function isPushMessage
inline boolean isPushMessage()
是否是推送消息
Return: boolean
Example:
function createMessage
static inline BMXMessage createMessage(
long from,
long to,
BMXMessage.MessageType type,
long conversationId,
String content
)
创建发送文本消息
Parameters:
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
- content 消息内容
Example:
public BMXMessage sendInputStatusMessage(BMXMessage.MessageType type, long from, long to,
String extension) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, "");
if (msg == null) {
return null;
}
msg.setDeliveryQos(BMXMessage.DeliveryQos.AtMostOnce);
msg.setExtension(extension);
return handlerMessage(msg);
public BMXMessage sendTextMessage(Context context, BMXMessage.MessageType type, long from, long to, String text,
Map<String, String> atMap, String senderName) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, text);
if (msg == null) {
return null;
}
// 文本功能添加@对象
if (atMap != null && !atMap.isEmpty()) {
BMXMessageConfig config = BMXMessageConfig.createMessageConfig(false);
config.setSenderNickname(senderName);
config.setPushMessage(ChatUtils.getInstance().getMessageDesc(context, msg));
// @对象的存储信息 包括全部成员或者部分成员
if (atMap.containsKey("-1")) {
// @全部
String atTitle = atMap.get("-1");
if (!TextUtils.isEmpty(atTitle) && text.contains(atTitle)) {
// 如果包含全部直接走全部 还需要判断文本消息是否包含完成的@名称 如果没有就不触发@
config.setMentionAll(true);
}
} else {
public BMXMessage sendImageMessage(BMXMessage.MessageType type, long from, long to, String path,
int w, int h) {
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(w, h);
BMXImageAttachment imageAttachment = new BMXImageAttachment(path, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, imageAttachment);
return handlerMessage(msg);
public BMXMessage sendAudioMessage(BMXMessage.MessageType type, long from, long to, String path,
int time) {
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(path, time);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, voiceAttachment);
return handlerMessage(msg);
public BMXMessage sendVideoMessage(BMXMessage.MessageType type, long from, long to, String path,
int time, int w, int h) {
BMXVideoAttachment.Size size = new BMXVideoAttachment.Size(w, h);
BMXVideoAttachment videoAttachment = new BMXVideoAttachment(path, time, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, videoAttachment);
return handlerMessage(msg);
public BMXMessage sendFileMessage(BMXMessage.MessageType type, long from, long to, String path,
String name) {
BMXFileAttachment fileAttachment = new BMXFileAttachment(path, name);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, fileAttachment);
return handlerMessage(msg);
public BMXMessage sendLocationMessage(BMXMessage.MessageType type, long from, long to,
double latitude, double longitude, String address) {
BMXLocationAttachment locationAttachment = new BMXLocationAttachment(latitude, longitude,
address);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, locationAttachment);
return handlerMessage(msg);
public BMXMessage forwardMessage(MessageBean messageBean, BMXMessage.MessageType type,
long from, long to) {
if (messageBean == null) {
return null;
}
BMXMessage.ContentType contentType = messageBean.getContentType();
BMXMessage message = null;
if (contentType == BMXMessage.ContentType.Text) {
message = BMXMessage.createMessage(from, to, type, to, messageBean.getContent());
} else if (contentType == BMXMessage.ContentType.Image) {
// 图片
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(messageBean.getW(),
messageBean.getH());
BMXImageAttachment imageAttachment = new BMXImageAttachment(messageBean.getPath(),
size);
message = BMXMessage.createMessage(from, to, type, to, imageAttachment);
} else if (contentType == BMXMessage.ContentType.Voice) {
// 语音
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(messageBean.getPath(),
messageBean.getDuration());
function createMessage
static inline BMXMessage createMessage(
long from,
long to,
BMXMessage.MessageType type,
long conversationId,
BMXMessageAttachment attachment
)
创建发送附件消息
Parameters:
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
- attachment 附件
Example:
public BMXMessage sendInputStatusMessage(BMXMessage.MessageType type, long from, long to,
String extension) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, "");
if (msg == null) {
return null;
}
msg.setDeliveryQos(BMXMessage.DeliveryQos.AtMostOnce);
msg.setExtension(extension);
return handlerMessage(msg);
public BMXMessage sendTextMessage(Context context, BMXMessage.MessageType type, long from, long to, String text,
Map<String, String> atMap, String senderName) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, text);
if (msg == null) {
return null;
}
// 文本功能添加@对象
if (atMap != null && !atMap.isEmpty()) {
BMXMessageConfig config = BMXMessageConfig.createMessageConfig(false);
config.setSenderNickname(senderName);
config.setPushMessage(ChatUtils.getInstance().getMessageDesc(context, msg));
// @对象的存储信息 包括全部成员或者部分成员
if (atMap.containsKey("-1")) {
// @全部
String atTitle = atMap.get("-1");
if (!TextUtils.isEmpty(atTitle) && text.contains(atTitle)) {
// 如果包含全部直接走全部 还需要判断文本消息是否包含完成的@名称 如果没有就不触发@
config.setMentionAll(true);
}
} else {
public BMXMessage sendImageMessage(BMXMessage.MessageType type, long from, long to, String path,
int w, int h) {
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(w, h);
BMXImageAttachment imageAttachment = new BMXImageAttachment(path, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, imageAttachment);
return handlerMessage(msg);
public BMXMessage sendAudioMessage(BMXMessage.MessageType type, long from, long to, String path,
int time) {
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(path, time);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, voiceAttachment);
return handlerMessage(msg);
public BMXMessage sendVideoMessage(BMXMessage.MessageType type, long from, long to, String path,
int time, int w, int h) {
BMXVideoAttachment.Size size = new BMXVideoAttachment.Size(w, h);
BMXVideoAttachment videoAttachment = new BMXVideoAttachment(path, time, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, videoAttachment);
return handlerMessage(msg);
public BMXMessage sendFileMessage(BMXMessage.MessageType type, long from, long to, String path,
String name) {
BMXFileAttachment fileAttachment = new BMXFileAttachment(path, name);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, fileAttachment);
return handlerMessage(msg);
public BMXMessage sendLocationMessage(BMXMessage.MessageType type, long from, long to,
double latitude, double longitude, String address) {
BMXLocationAttachment locationAttachment = new BMXLocationAttachment(latitude, longitude,
address);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, locationAttachment);
return handlerMessage(msg);
public BMXMessage forwardMessage(MessageBean messageBean, BMXMessage.MessageType type,
long from, long to) {
if (messageBean == null) {
return null;
}
BMXMessage.ContentType contentType = messageBean.getContentType();
BMXMessage message = null;
if (contentType == BMXMessage.ContentType.Text) {
message = BMXMessage.createMessage(from, to, type, to, messageBean.getContent());
} else if (contentType == BMXMessage.ContentType.Image) {
// 图片
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(messageBean.getW(),
messageBean.getH());
BMXImageAttachment imageAttachment = new BMXImageAttachment(messageBean.getPath(),
size);
message = BMXMessage.createMessage(from, to, type, to, imageAttachment);
} else if (contentType == BMXMessage.ContentType.Voice) {
// 语音
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(messageBean.getPath(),
messageBean.getDuration());
function createCommandMessage
static inline BMXMessage createCommandMessage(
long from,
long to,
BMXMessage.MessageType type,
long conversationId,
String content
)
创建发送命令消息(命令消息通过content字段或者extension字段存放命令信息)
Parameters:
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
- content 消息内容
Example:
public void sendCommandMessage(BMXMessage.MessageType type, long from, long to,
String content) {
handlerMessage(BMXMessage.createCommandMessage(from, to, type, to, content));
function createMessage
static inline BMXMessage createMessage(
long msgId,
long from,
long to,
BMXMessage.MessageType type,
long conversationId,
String content,
long serverTimestamp
)
创建收到的消息
Parameters:
- msgId 消息id
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
- content 消息内容
- serverTimestamp 服务器时间戳
Example:
public BMXMessage sendInputStatusMessage(BMXMessage.MessageType type, long from, long to,
String extension) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, "");
if (msg == null) {
return null;
}
msg.setDeliveryQos(BMXMessage.DeliveryQos.AtMostOnce);
msg.setExtension(extension);
return handlerMessage(msg);
public BMXMessage sendTextMessage(Context context, BMXMessage.MessageType type, long from, long to, String text,
Map<String, String> atMap, String senderName) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, text);
if (msg == null) {
return null;
}
// 文本功能添加@对象
if (atMap != null && !atMap.isEmpty()) {
BMXMessageConfig config = BMXMessageConfig.createMessageConfig(false);
config.setSenderNickname(senderName);
config.setPushMessage(ChatUtils.getInstance().getMessageDesc(context, msg));
// @对象的存储信息 包括全部成员或者部分成员
if (atMap.containsKey("-1")) {
// @全部
String atTitle = atMap.get("-1");
if (!TextUtils.isEmpty(atTitle) && text.contains(atTitle)) {
// 如果包含全部直接走全部 还需要判断文本消息是否包含完成的@名称 如果没有就不触发@
config.setMentionAll(true);
}
} else {
public BMXMessage sendImageMessage(BMXMessage.MessageType type, long from, long to, String path,
int w, int h) {
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(w, h);
BMXImageAttachment imageAttachment = new BMXImageAttachment(path, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, imageAttachment);
return handlerMessage(msg);
public BMXMessage sendAudioMessage(BMXMessage.MessageType type, long from, long to, String path,
int time) {
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(path, time);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, voiceAttachment);
return handlerMessage(msg);
public BMXMessage sendVideoMessage(BMXMessage.MessageType type, long from, long to, String path,
int time, int w, int h) {
BMXVideoAttachment.Size size = new BMXVideoAttachment.Size(w, h);
BMXVideoAttachment videoAttachment = new BMXVideoAttachment(path, time, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, videoAttachment);
return handlerMessage(msg);
public BMXMessage sendFileMessage(BMXMessage.MessageType type, long from, long to, String path,
String name) {
BMXFileAttachment fileAttachment = new BMXFileAttachment(path, name);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, fileAttachment);
return handlerMessage(msg);
public BMXMessage sendLocationMessage(BMXMessage.MessageType type, long from, long to,
double latitude, double longitude, String address) {
BMXLocationAttachment locationAttachment = new BMXLocationAttachment(latitude, longitude,
address);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, locationAttachment);
return handlerMessage(msg);
public BMXMessage forwardMessage(MessageBean messageBean, BMXMessage.MessageType type,
long from, long to) {
if (messageBean == null) {
return null;
}
BMXMessage.ContentType contentType = messageBean.getContentType();
BMXMessage message = null;
if (contentType == BMXMessage.ContentType.Text) {
message = BMXMessage.createMessage(from, to, type, to, messageBean.getContent());
} else if (contentType == BMXMessage.ContentType.Image) {
// 图片
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(messageBean.getW(),
messageBean.getH());
BMXImageAttachment imageAttachment = new BMXImageAttachment(messageBean.getPath(),
size);
message = BMXMessage.createMessage(from, to, type, to, imageAttachment);
} else if (contentType == BMXMessage.ContentType.Voice) {
// 语音
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(messageBean.getPath(),
messageBean.getDuration());
function createMessage
static inline BMXMessage createMessage(
long msgId,
long from,
long to,
BMXMessage.MessageType type,
long conversationId,
BMXMessageAttachment attachment,
long serverTimestamp
)
创建收到的消息
Parameters:
- msgId 消息id
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
- attachment 附件
- serverTimestamp 服务器时间戳
Example:
public BMXMessage sendInputStatusMessage(BMXMessage.MessageType type, long from, long to,
String extension) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, "");
if (msg == null) {
return null;
}
msg.setDeliveryQos(BMXMessage.DeliveryQos.AtMostOnce);
msg.setExtension(extension);
return handlerMessage(msg);
public BMXMessage sendTextMessage(Context context, BMXMessage.MessageType type, long from, long to, String text,
Map<String, String> atMap, String senderName) {
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, text);
if (msg == null) {
return null;
}
// 文本功能添加@对象
if (atMap != null && !atMap.isEmpty()) {
BMXMessageConfig config = BMXMessageConfig.createMessageConfig(false);
config.setSenderNickname(senderName);
config.setPushMessage(ChatUtils.getInstance().getMessageDesc(context, msg));
// @对象的存储信息 包括全部成员或者部分成员
if (atMap.containsKey("-1")) {
// @全部
String atTitle = atMap.get("-1");
if (!TextUtils.isEmpty(atTitle) && text.contains(atTitle)) {
// 如果包含全部直接走全部 还需要判断文本消息是否包含完成的@名称 如果没有就不触发@
config.setMentionAll(true);
}
} else {
public BMXMessage sendImageMessage(BMXMessage.MessageType type, long from, long to, String path,
int w, int h) {
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(w, h);
BMXImageAttachment imageAttachment = new BMXImageAttachment(path, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, imageAttachment);
return handlerMessage(msg);
public BMXMessage sendAudioMessage(BMXMessage.MessageType type, long from, long to, String path,
int time) {
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(path, time);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, voiceAttachment);
return handlerMessage(msg);
public BMXMessage sendVideoMessage(BMXMessage.MessageType type, long from, long to, String path,
int time, int w, int h) {
BMXVideoAttachment.Size size = new BMXVideoAttachment.Size(w, h);
BMXVideoAttachment videoAttachment = new BMXVideoAttachment(path, time, size);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, videoAttachment);
return handlerMessage(msg);
public BMXMessage sendFileMessage(BMXMessage.MessageType type, long from, long to, String path,
String name) {
BMXFileAttachment fileAttachment = new BMXFileAttachment(path, name);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, fileAttachment);
return handlerMessage(msg);
public BMXMessage sendLocationMessage(BMXMessage.MessageType type, long from, long to,
double latitude, double longitude, String address) {
BMXLocationAttachment locationAttachment = new BMXLocationAttachment(latitude, longitude,
address);
BMXMessage msg = BMXMessage.createMessage(from, to, type, to, locationAttachment);
return handlerMessage(msg);
public BMXMessage forwardMessage(MessageBean messageBean, BMXMessage.MessageType type,
long from, long to) {
if (messageBean == null) {
return null;
}
BMXMessage.ContentType contentType = messageBean.getContentType();
BMXMessage message = null;
if (contentType == BMXMessage.ContentType.Text) {
message = BMXMessage.createMessage(from, to, type, to, messageBean.getContent());
} else if (contentType == BMXMessage.ContentType.Image) {
// 图片
BMXImageAttachment.Size size = new BMXMessageAttachment.Size(messageBean.getW(),
messageBean.getH());
BMXImageAttachment imageAttachment = new BMXImageAttachment(messageBean.getPath(),
size);
message = BMXMessage.createMessage(from, to, type, to, imageAttachment);
} else if (contentType == BMXMessage.ContentType.Voice) {
// 语音
BMXVoiceAttachment voiceAttachment = new BMXVoiceAttachment(messageBean.getPath(),
messageBean.getDuration());
function createCommandMessage
static inline BMXMessage createCommandMessage(
long msgId,
long from,
long to,
BMXMessage.MessageType type,
long conversationId,
String content,
long serverTimestamp
)
创建收到的命令消息(命令消息通过content字段或者extension字段存放命令信息)
Parameters:
- msgId 消息id
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
- content 消息内容
- serverTimestamp 服务器时间戳
Example:
public void sendCommandMessage(BMXMessage.MessageType type, long from, long to,
String content) {
handlerMessage(BMXMessage.createCommandMessage(from, to, type, to, content));
function createForwardMessage
static inline BMXMessage createForwardMessage(
BMXMessage msg,
long from,
long to,
BMXMessage.MessageType type,
long conversationId
)
创建转发消息
Parameters:
- msg 要转发的消息
- from 消息发送者
- to 消息接收者
- type 消息类型
- conversationId 会话id
Protected Functions Documentation
Example:
function BMXMessage
inline BMXMessage(
long cPtr,
boolean cMemoryOwn
)
Example:
function finalize
inline void finalize()
Example:
function getCPtr
static inline long getCPtr(
BMXMessage obj
)
Example:
Updated on 2022-01-26 at 17:18:31 +0800