整合融雲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<UIConversation> {
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檔案
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="#00000000">
<TextView
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" />
<TextView
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" />
<TextView
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" />
<TextView
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" />
<ImageView
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" />
</RelativeLayout>
接著上面寫
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<TempUser> 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<String> getUserIds(String text){
if(atUsers==null||atUsers.size()==0){
return null;
}
ArrayList<String> ids=new ArrayList();
for(int i=0;i<atUsers.size();i++){
if(text.contains(atUsers.get(i).name)){
ids.add(atUsers.get(i).uid);
}
}
return ids;
}
//接受 :誰@了我的列表
private Set<String> atGroupIds =new HashSet<>();
public Set<String> 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<Set<String>>(){}.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<String> 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<String> 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<size;i++){
if(content.endsWith("@")){
content = content.toString().substring(0,content.toString().length()-1);
}else{
break;
}
}
}
this.content = content;
}
為了解決這個問題,還重寫了融雲的TextInputProvider,只是修改了上面那一段。
相關文章
- iOS整合融雲SDK即時通訊整理iOS
- 如何在移動應用中整合美顏SDK實現人臉識別和美化功能
- 【小程式】使用UDP實現群聊功能UDP
- REST實戰討論組FAQREST
- 思否評論區 @ 人的功能實現
- REST實戰討論組的文件資料在什麼地方?REST
- 【討論】論 cursor 在測試中的使用
- 我們現在沒有討論的但有必要討論的模式模式
- 詳解在Android中整合高德定位功能Android
- 融雲 IM SDK 整合 — 重新整理會話介面和會話列表介面會話
- 適用更多會議場景,華為雲會議的分組討論功能來了!
- 請問struts中如何實現分頁功能,有請大家踴躍討論
- 對接融雲即時通訊元件SDK,輕鬆實現App聊天室元件APP
- 我自己封裝的 Laravel 融雲 sdk,簡單好用封裝Laravel
- 美顏SDK中磨皮功能的演算法實現演算法
- Operator-sdk 在 KaiwuDB 容器雲中的使用AI
- 如何基於 Agora Android SDK 在應用中實現視訊通話?GoAndroid
- 融雲 IM 在 Electron 平臺上的設計實踐
- 直播美顏SDK中的美白功能是怎麼實現的?
- 在Swift中實現撤銷功能Swift
- Android 仿釘釘、微信 群聊組合頭像Android
- 美顏sdk常用功能的實現原理
- 影片美顏sdk中的人臉磨皮功能實現流程
- 純技術貼:討論一個現實中的需求的架構架構
- oracle使用者討論組Oracle
- 資訊化技術討論組
- ORACLE索引組織表討論Oracle索引
- 主題討論,第六組
- [全程建模]績效管理模型在itsp組內的對話討論模型
- 5G在工業中應用的討論
- Fluwx:微信SDK在Flutter上的實現Flutter
- 和開發人員討論一個業務需求和簡單實現
- 【Android SDK】在命令列管理Android SDKAndroid命令列
- 極速指南:在 SpringBoot 中快速整合騰訊雲簡訊功能Spring Boot
- 在java中實現對FORM的列印功能 (轉)JavaORM
- 巢狀滾動效果實現討論巢狀
- 影片直播美顏sdk趣味功能的實現流程
- 關於雲流化系統-實時雲渲染延時性的討論