android讨论功能,集成融云Android SDK实现在群聊/讨论组中@人的功能

集成融云Android SDK实现在群聊/讨论组中@人的功能

可以确定的是融云SDK本身不提供@的功能,需要自定义实现。

在实现这个功能时,基本模仿微信的做法:

在列表中显示有人@了你

通知显示有人@了你

群聊中输入框输入@时弹出群成员列表,选择要@的人

键盘回删的时候,不可以弹出成员列表

这消息未读时,有人@了你一直在列表中显示,包括程序杀死的情况

长按头像实现@人的功能

实现的逻辑

1.消息发送方:

发送@消息本身是个普通的文本消息,为了要明确@的人,在消息的extra中添加被@人的id数组(可以@多人)。

具体规则:

@弹出成员列表时,每点击一个成员,则用List进行保存(因为需要get某个id,所以没办法使用set)

在调用融云发送消息的时,判断这个列表是否有id,如果有,则为文本消息setExtra(ids);

2.接收方:

判定规则:

首先判断是否是群消息,是

判断是否是文本消息,是

判断是否包含@,是

判断文本消息中extra是否你的id,是

这个时候可以判定你收到了@消息,然后就是具体显示的问题了:

将这条消息的群id保存到一个set中,如果消息已读,则把id移除

写了这么多,感觉有点废话,直接上代码吧

具体实现

1.自定义群消息provider(列表中的),这个在融云的demo中有,是讨论组provider,拿过来稍微改一下

@ConversationProviderTag(conversationType = "group", portraitPosition = 1)

public class GroupConversationProvider implements IContainerItemProvider.ConversationProvider {

private static int i = 0;

private String TAG = GroupConversationProvider.class.getSimpleName();

class ViewHolder {

TextView title;

TextView time;

TextView content;

ImageView notificationBlockImage;

TextView atMe;

final GroupConversationProvider provider;

ViewHolder() {

provider = GroupConversationProvider.this;

}

}

public GroupConversationProvider() {

}

@Override

public void bindView(View view, int position, UIConversation data) {

ViewHolder holder = (ViewHolder) view.getTag();

ProviderTag tag = null;

if (data == null) {

holder.title.setText(null);

holder.time.setText(null);

holder.content.setText(null);

} else {

//设置会话标题

holder.title.setText(data.getUIConversationTitle());

//设置会话时间

String time = RongDateUtils.getConversationListFormatDate(new Date(data.getUIConversationTime()));

holder.time.setText(time);

//设置内容

if (!TextUtils.isEmpty(data.getDraft())) {

SpannableStringBuilder builder = new SpannableStringBuilder();

SpannableString string = new SpannableString("[草稿]");

string.setSpan(new ForegroundColorSpan(Color.parseColor("#cb120f")), 0, string.length(), 33);

if(data.getDraft().toString().substring(data.getDraft().toString().length() - 1, data.getDraft().toString().length()).equals("@")){

data.setDraft(data.getDraft().toString().substring(0,data.getDraft().toString().length()-1));

}

builder.append(string).append(data.getDraft());

AndroidEmoji.ensure(builder);

holder.content.setText(builder);

} else {

setDateView(holder, data);

holder.content.setText(data.getConversationContent());

}

if (RongContext.getInstance() != null && data.getMessageContent() != null)

tag = RongContext.getInstance().getMessageProviderTag(data.getMessageContent().getClass());

if (data.getSentStatus() != null && (data.getSentStatus() == io.rong.imlib.model.Message.SentStatus.FAILED || data.getSentStatus() == io.rong.imlib.model.Message.SentStatus.SENDING) && tag != null && tag.showWarning()) {

int width = ViewUtils.dp2px(17);

Drawable drawable = null;

if (data.getSentStatus() == io.rong.imlib.model.Message.SentStatus.FAILED)

drawable = view.getContext().getResources().getDrawable(R.drawable.de_conversation_list_msg_send_failure);

else if (data.getSentStatus() == io.rong.imlib.model.Message.SentStatus.SENDING)

drawable = view.getContext().getResources().getDrawable(R.drawable.de_conversation_list_msg_sending);

if (drawable != null) {

drawable.setBounds(0, 0, width, width);

holder.content.setCompoundDrawablePadding(10);

holder.content.setCompoundDrawables(drawable, null, null, null);

}

} else {

holder.content.setCompoundDrawables(null, null, null, null);

}

ConversationKey key = ConversationKey.obtain(data.getConversationTargetId(), data.getConversationType());

io.rong.imlib.model.Conversation.ConversationNotificationStatus status = RongContext.getInstance().getConversationNotifyStatusFromCache(key);

if (status != null && status.equals(io.rong.imlib.model.Conversation.ConversationNotificationStatus.DO_NOT_DISTURB))

holder.notificationBlockImage.setVisibility(View.VISIBLE);

else

holder.notificationBlockImage.setVisibility(View.GONE);

}

}

/**

* @param holder

* @param data

* @ 消息提示

*/

private void setDateView(ViewHolder holder, UIConversation data) {

if (AtUserService.getInstance().getAtGroupIds() != null && AtUserService.getInstance().getAtGroupIds().size() > 0

&&AtUserService.getInstance().getAtGroupIds().contains(data.getConversationTargetId())) {

if (data.getUnReadMessageCount() == 0) {

holder.atMe.setVisibility(View.GONE);

data.setExtraFlag(false);

} else if (data.getUnReadMessageCount() > 0) {

holder.atMe.setVisibility(View.VISIBLE);

data.setExtraFlag(true);

}

} else {

if (data.getExtraFlag()) {

holder.atMe.setVisibility(View.VISIBLE);

} else {

holder.atMe.setVisibility(View.GONE);

data.setExtraFlag(false);

}

if (data.getUnReadMessageCount() == 0) {

holder.atMe.setVisibility(View.GONE);

data.setExtraFlag(false);

}

}

}

@Override

public View newView(Context context, ViewGroup viewgroup) {

View result = LayoutInflater.from(context).inflate(R.layout.de_item_base_conversation, null);

ViewHolder holder = new ViewHolder();

holder.title = (TextView) result.findViewById(R.id.de_conversation_title);

holder.time = (TextView) result.findViewById(R.id.de_conversation_time);

holder.content = (TextView) result.findViewById(R.id.de_conversation_content);

holder.notificationBlockImage = (ImageView) result.findViewById(R.id.de_conversation_msg_block);

holder.atMe = (TextView) result.findViewById(R.id.de_at_me);

result.setTag(holder);

return result;

}

@Override

public String getTitle(String s) {

String name;

if (RongContext.getInstance().getGroupInfoFromCache(s) == null)

name = "群组";

else{

name = RongContext.getInstance().getGroupInfoFromCache(s).getName();

}

return name;

}

@Override

public Uri getPortraitUri(String s) {

Uri uri;

if (RongContext.getInstance().getGroupInfoFromCache(s) == null)

uri = null;

else{

uri = RongContext.getInstance().getGroupInfoFromCache(s).getPortraitUri();

}

return uri;

}

}

对应的xml文件

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_gravity="center_vertical"

android:background="#00000000">

android:id="@+id/de_conversation_title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_marginLeft="5dp"

android:layout_marginRight="85dp"

android:layout_marginTop="4dp"

android:background="#00000000"

android:ellipsize="end"

android:singleLine="true"

android:textColor="#353535"

android:textSize="16sp" />

android:id="@+id/de_conversation_time"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_marginRight="8dp"

android:layout_marginTop="5dp"

android:background="#00000000"

android:textColor="#d7d7d7"

android:textSize="14sp" />

android:id="@+id/de_at_me"

android:layout_width="wrap_content"

android:layout_height="24dp"

android:layout_below="@+id/de_conversation_title"

android:layout_marginBottom="2dp"

android:layout_marginLeft="5dp"

android:layout_marginTop="4dp"

android:background="#00000000"

android:ellipsize="end"

android:gravity="center_vertical"

android:singleLine="true"

android:text="[有人@我]"

android:textColor="#cb120f"

android:visibility="gone"

android:textSize="14sp" />

android:id="@+id/de_conversation_content"

android:layout_width="wrap_content"

android:layout_height="24dp"

android:layout_toRightOf="@+id/de_at_me"

android:layout_below="@+id/de_conversation_title"

android:layout_marginBottom="2dp"

android:layout_marginLeft="5dp"

android:layout_marginRight="70dp"

android:layout_marginTop="4dp"

android:background="#00000000"

android:ellipsize="end"

android:gravity="center_vertical"

android:singleLine="true"

android:textColor="#999999"

android:textSize="14sp" />

android:id="@+id/de_conversation_msg_block"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_below="@+id/de_conversation_time"

android:layout_marginRight="8dp"

android:layout_marginTop="10dp"

android:src="@drawable/de_ic_message_block"

android:visibility="gone" />

接着上面写

2.写了单独service来处理@相关数据

public class AtUserService {

private static AtUserService instance;

private static final String AT_GTOUP_IDS="at_group_ids";

public static AtUserService getInstance() {

if (instance == null) {

instance = new AtUserService();

}

return instance;

}

//发送时@人的列表

public List atUsers =new ArrayList<>();

public void addUser(User user){

TempUser tempUser=new TempUser();

tempUser.uid=user.id.toString();

tempUser.name=user.name;

atUsers.add(tempUser);

}

public List getUserIds(String text){

if(atUsers==null||atUsers.size()==0){

return null;

}

ArrayList ids=new ArrayList();

for(int i=0;i

if(text.contains(atUsers.get(i).name)){

ids.add(atUsers.get(i).uid);

}

}

return ids;

}

//接受 :谁@了我的列表

private Set atGroupIds =new HashSet<>();

public Set getAtGroupIds(){

if(atGroupIds==null||atGroupIds.size()==0){

String string=UserConfigUtil.getStringConfig(AT_GTOUP_IDS,"");

if(string!=null&&!string.equals("")){

atGroupIds=GSONUtil.getGsonInstence().fromJson(string,new TypeToken>(){}.getType());

}

}

return atGroupIds;

}

public void addAtGroupId(String id){

atGroupIds.add(id);

UserConfigUtil.setConfig(AT_GTOUP_IDS,GSONUtil.getGsonInstence().toJson(atGroupIds),true);

}

public void removeAtGroupId(String id){

atGroupIds.remove(id);

UserConfigUtil.setConfig(AT_GTOUP_IDS,GSONUtil.getGsonInstence().toJson(atGroupIds),true);

}

public Set curConversationId=new HashSet<>();

public void addCurConversationId(String id){

curConversationId.add(id);

}

public void removeCurConversationId(String id){

curConversationId.remove(id);

}

public class TempUser{

String uid;

String name;

}

}

3.RongService 里处理和融云相关的操作

发送消息

private void setSendMessageListener() {

if (RongIM.getInstance() != null) {

//设置自己发出的消息监听器。

RongIM.getInstance().setSendMessageListener(new RongIM.OnSendMessageListener() {

/**

* 消息发送前监听器处理接口(是否发送成功可以从SentStatus属性获取)。

*

* @param message 发送的消息实例。

* @return 处理后的消息实例。

*/

@Override

public Message onSend(Message message) {

MessageContent msgContent = message.getContent();

if(message.getConversationType().equals(Conversation.ConversationType.GROUP)&&msgContent.toString().contains("@")){

AtMsgBody msgBody=new AtMsgBody();

msgBody.groupId = message.getTargetId();

msgBody.senderName = AccountService.getInstance().me.name;

if(AtUserService.getInstance().getUserIds(((TextMessage) msgContent).getContent().toString())!=null){

List ids=AtUserService.getInstance().getUserIds(((TextMessage) msgContent).getContent().toString());

String uids="";

for(String str:ids){

uids+=str+",";

extraJson.addProperty("uids",uids.equals("")?"":uids.substring(0,uids.length()-1));

uids=uids.equals("")?"":uids.substring(0,uids.length()-1);

AtUserService.getInstance().atUsers.clear();

}

}

((TextMessage) msgContent).setExtra(extraJson.toString());

}

return message;

}

接收到消息

RongIM.setOnReceiveMessageListener(new RongIMClient.OnReceiveMessageListener() {

@Override

public boolean onReceived(Message message, int i) {

if(message.getConversationType().equals(Conversation.ConversationType.GROUP)&&message.getContent() instanceof TextMessage){

if(!AtUserService.getInstance().curConversationId.contains(message.getTargetId().toString())){

JsonObject jsonObject= GSONUtil.getGsonParser().parse(((TextMessage) message.getContent()).getExtra()).getAsJsonObject();

if(!jsonObject.isJsonNull()&& jsonObject.has("uids")&&!jsonObject.get("uids").isJsonNull()){

String strUids=jsonObject.get("uids").getAsString();

if(strUids.contains(AccountService.getInstance().me.id.toString())){

AtUserService.getInstance().addAtGroupId(message.getTargetId().toString());

}

}

}

}

}

消息点击后取消@显示

RongIM.setConversationListBehaviorListener(new RongIM.ConversationListBehaviorListener() {

@Override

public boolean onConversationClick(Context context, View view, final UIConversation uiConversation) {

if(uiConversation.getConversationType().equals(Conversation.ConversationType.GROUP)

&&AtUserService.getInstance().getAtGroupIds().contains(uiConversation.getConversationTargetId())){

AtUserService.getInstance().removeAtGroupId(uiConversation.getConversationTargetId());

}

}

}

最后一段,一些注意事项

写到这基本功能已经实现了,但是还是有些细节问题要处理

1.输入框调起成员列表,在聊天页面写入这个方法(我的聊天页面是ChatActivity)

InputProvider.MainInputProvider provider = RongContext.getInstance().getPrimaryInputProvider();

if (provider instanceof RongTextInputProvider) {

RongTextInputProvider textInputProvider = (RongTextInputProvider) provider;

textInputProvider.setEditTextContent("");

textInputProvider.setEditTextChangedListener(new TextWatcher() {

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

if(count==0){

//键盘回删操作,不调起列表

return;

}

if (mConversationType.equals(Conversation.ConversationType.GROUP)) {

if (s.length() > 0) {

String str = s.toString().substring(s.toString().length() - 1, s.toString().length());

if (str.equals("@")) {

Intent intent = new Intent(ChatActivity.this, ChatGroupUserListActivity.class);

intent.putExtra(ChatGroupUserListActivity.IS_AT, true);

intent.putExtra(ChatGroupUserListActivity.ARGUMENT_GID, mUserId);

startActivityForResult(intent, 29);

mEditText = s.toString();

}

}

}

}

@Override

public void afterTextChanged(Editable s) {;

}

});

}

2.如果当前app停留的页面就是这个会话页面,则不用在列表中显示有人@了我,具体实现我是在每次进入群聊就保存当前会话的id,关闭聊天页面时,remove掉。

3.如果聊天草稿最后一个字符是@,则进入聊天页面会默认调起成员列表,这样体验不好,想解决这个问题,最后”曲线救国“”了。

具体方法:如果草稿最后一个字符是@则将这个字符删,循环处理,直至最后一个字符不是@符号.

SaveDraftRunnable(Conversation conversation, String content) {

this.conversation = conversation;

if(content!=null&&content.toString().length()>0){

int size=content.length();

for(int i=0;i

if(content.endsWith("@")){

content = content.toString().substring(0,content.toString().length()-1);

}else{

break;

}

}

}

this.content = content;

}

为了解决这个问题,还重写了融云的TextInputProvider,只是修改了上面那一段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值