Android基于Bmob群聊功能的实现

Bmob算是国内做的比较好的做BaaS或MBaaS服务的公司了,官方写的IM的Demo目前可以实现登录注册、搜索添加好友、与好友进行文字图片音频位置对话功能,但感觉还有很多缺陷,比如说删除表中的数据时只能根据ID查找,没提供数据库事务操作的接口,IM没实现群聊的功能,有些API太少太局限,可能因为公司团队小吧,希望能越做越好。
回到正题,既然Bmob的IM没有实现群聊,那就自己实现,Bmob有一个“数据实时同步”的功能,用来让SDK对某些数据表进行监听,一旦数据表发生改变,就会通知到SDK。群聊时,用户发消息时就发到该群对应的消息表中,群中的所有成员都对这个消息表进行监听,因此一旦监听到表中数据变化就表明某个成员发了消息,就能取到这个消息对象。

数据库设计:

群组分类表TribeTypeBean(分类名、分类描述)

public class TribeTypeBean extends BmobObject {

    private String tribeTypeName;
    private String tribeTypeDescription;

群组表TribeBean(群组名、群组描述、群组头像、群组创建者、群组成员、群组所属分类),其中,群组创建者和群组分类是一对多关联,在SDK中直接用对象类型,在云端表现为Pointer< T >类型。群组成员是多对多关联,在SDK中要声明为BmobRelation类型,在云端表现为Relation< T >类型。

public class TribeBean extends BmobObject {

    private String tribeName;
    private String tribeDescription;
    private String tribeAvatar;
    private BmobUser tribeLeader;
    private BmobRelation tribeMember;
    private TribeTypeBean tribeTypeBean;

群组消息表GroupChatMsgBean(消息对应群组、消息发送者、消息内容、消息发送时间、是否已读、消息状态),在创建群组时,就要为这个群组创建一个消息表,消息表中要有一个字段表明该消息表对应的群组。这样就建立起了单向的一对一关联关系。但有个问题,我可以通过条件查询群组表知道自己加入了哪些群组,但并不知道这些群组对应的消息表是什么。所以我决定采用一种比较简单的方式来实现,让消息表的表名为“GroupChatMsg”+对应群组的id,这样就在语义上建立起了对应关系,也保证了表名的唯一性,监听表时就监听“GroupChatMsg”+对应群组的id这些表就行了。

public class GroupChatMsgBean extends BmobObject {

    private TribeBean tribe;
    private UserBean sender;
    private String msgContent;
    private Integer msgType;
    private String msgTime;
    private Integer isReaded;
    private Integer status;

虽然每个群组对应的表名不一样,但群消息实体还是一样的,因此发消息时不能直接调用BmobObject的save方法,需要用云端代码来完成:

function onRequest(request, response, modules) {
    var db = modules.oData;
    var tableName = request.body.tableName;
    var groupChatMsgObject = JSON.parse(request.body.groupChatMsg);
    db.insert({
        "table" : tableName,
        "data" : groupChatMsgObject
        },function(err,data){
            response.send(err+","+data);
        }
    );
}                                                                                                                         

调用参数是消息表名和消息实体。

因此,发消息时要组装好消息对象并调用云端代码:

                    UserBean currentUser = BmobUser.getCurrentUser(GroupChatActivity.this, UserBean.class);
                    try {
                        AsyncCustomEndpoints ace = new AsyncCustomEndpoints();
                        JSONObject cloudCodeParams = new JSONObject();
                        GroupChatMsgBean groupChatMsgBean = new GroupChatMsgBean();
                        groupChatMsgBean.setTribe(targetTribe);
                        groupChatMsgBean.setSender(currentUser);
                        groupChatMsgBean.setMsgContent(et_send.getText().toString());
                        groupChatMsgBean.setMsgType(BmobConfig.TYPE_TEXT);
                        groupChatMsgBean.setMsgTime(String.valueOf(BmobUtils.getTimeStamp()));
                        groupChatMsgBean.setIsReaded(0);
                        groupChatMsgBean.setStatus(BmobConfig.STATUS_SEND_SUCCESS);
                        sendMessageToUI(groupChatMsgBean);
                        Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
                            @Override
                            public boolean shouldSkipField(FieldAttributes f) {
                                return f.getName().contains("_c_")|f.getName().contains("increments")|f.getName().contains("tribe")|f.getName().contains("sender");
                            }

                            @Override
                            public boolean shouldSkipClass(Class<?> clazz) {
                                return false;
                            }
                        }).create();
                        JSONObject jsonObject = new JSONObject(gson.toJson(groupChatMsgBean));
                        jsonObject.put("tribe",new JSONObject(new Gson().toJson(new BmobPointer(targetTribe))));
                        jsonObject.put("sender", new JSONObject(new Gson().toJson(new BmobPointer(currentUser))));
                        cloudCodeParams.put("tableName", "GroupChatMsg" + targetTribe.getObjectId());
                        cloudCodeParams.put("groupChatMsg", jsonObject);
                        ace.callEndpoint(GroupChatActivity.this, "sendGroupChatMsg", cloudCodeParams,
                                new CloudCodeListener() {
                                    @Override
                                    public void onSuccess(Object object) {
                                        // TODO Auto-generated method stub
                                        LogUtils.LOGE("shang", "云端返回:" + object.toString());
                                    }

                                    @Override
                                    public void onFailure(int code, String msg) {
                                        // TODO Auto-generated method stub
                                        LogUtils.LOGE("shang", "访问云端失败:" + msg);
                                    }
                                });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

监听消息表的变化时用实时数据处理类BmobRealTimeData:

                bmobRealTimeData = new BmobRealTimeData();
                bmobRealTimeData.start(getActivity(), new ValueEventListener() {
                    @Override
                    public void onDataChange(JSONObject jsonObject) {
                        // TODO Auto-generated method stub
                        //{"data":{"content":"我就试试","objectId":"mynjZZZa","createdAt":"2016-01-15 18:02:47"},
                        // "action":"updateTable","objectId":"","tableName":"99aa3421bf","appKey":"44d4d237ac590c04a4cc0f3e030ab0a9"}
                        LogUtils.LOGE("shang", "onDataChange "+jsonObject.toString());
                        if (BmobRealTimeData.ACTION_UPDATETABLE.equals(jsonObject.optString("action"))) {
                            JSONObject data = jsonObject.optJSONObject("data");
                            Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
                                @Override
                                public boolean shouldSkipField(FieldAttributes f) {
                                    return f.getName().contains("sender") | f.getName().contains("tribe");
                                }

                                @Override
                                public boolean shouldSkipClass(Class<?> clazz) {
                                    return false;
                                }
                            }).create();
                            GroupChatMsgBean bean = gson.fromJson(data.toString(), GroupChatMsgBean.class);
                            //如果收到的是自己的消息更新或者是删除更新,直接return
                            if (currentUserId.equals(data.optString("sender")) || "".equals(data.optString("sender"))) {
                                return;
                            }
                            getTribeById(bean, data.optString("tribe"));
                            getUserById(bean, data.optString("sender"));
                        }
                    }

                    @Override
                    public void onConnectCompleted() {
                        // TODO Auto-generated method stub
                        if (bmobRealTimeData.isConnected()) {
                            LogUtils.LOGE("shang", "连接成功");
                            for (TribeBean tribeBean :
                                    myTribeBeanList) {
                                bmobRealTimeData.subTableUpdate("GroupChatMsg" + tribeBean.getObjectId());
                            }
                        }
                    }
                });                                                                                                        

在onDataChange回调中接收处理新增的消息,如发送广播:
    Intent intent = new Intent();
    intent.setAction(“cn.minitribe.group_chat_msg”);
    intent.putExtra(“GroupChatMsgBean”, bean);
    GroupChatFragment.this.getActivity().sendOrderedBroadcast(intent, null);
在onConnectCompleted回调中启动相关表的监听。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值