統合クラウドAndroid SDKは、チャット/ディスカッショングループにおける@人の機能を実現

18692 ワード

統合クラウドAndroid SDKは、チャット/ディスカッショングループにおける@人の機能を実現
融雲SDK自体は@の機能を提供しておらず,カスタム実装が必要であることが確認できる.この機能を実現するには、基本的に微信のやり方を真似します.
  • リストに @
  • が表示する.
  • 通知表示 @
  • チャット中入力ボックス@入力時にグループメンバーリストをポップアップし、@する人
  • を選択する.
  • キーボードが削除された場合、メンバーリスト
  • をポップアップできません.
  • このメッセージが未読の場合、 @ は、プログラムが殺す場合を含むリストに表示され続けている
  • .
  • 長押しアイコン実現@人の機能
  • 実装ロジック
    1.メッセージ送信者:
    送信@メッセージ自体は通常のテキストメッセージであり、@の人を明確にするために、メッセージのextraに被@人のid配列を追加する(@複数人可能).具体的なルール:
  • @メンバーリストがポップアップされると、1つのメンバーをクリックするごとにリストで保存(idをgetする必要があるので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ファイル
    
    
    
        
    
        
    
        
    
        
    
        
    
    
    

    次に上に書きます
    2.@関連データを処理するために個別サービスを書いた
    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 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

    この問題を解決するために、融雲のTextInputProviderも書き換えましたが、上の段落を修正しただけです.