美文网首页
网易云信 即时聊天

网易云信 即时聊天

作者: 苏坡坡要吃婆婆酥 | 来源:发表于2020-07-23 10:51 被阅读0次

1.状态栏消息通知展示

在使用demo测试的时候可能会发现配置完死活都不弹出消息通知。
不要慌,首先确认通知权限是否打开。
然后,将demo切换到后台,看是否能收到通知。因为demo的写法是处于后台时候才会通知。

(1) 先进行配置
StatusBarNotificationConfig config = new StatusBarNotificationConfig();
// 点击通知需要跳转到的界面
// 这里就只演示一下常规配置
config.notificationEntrance = NoViewActivity.class;
NIMClient.updateStatusBarNotificationConfig(config);
(2) 开启通知
// 开启通知栏消息提醒
NIMClient.toggleNotification(true);
(3) 在页面内设置*
// 进入聊天界面,建议放在onResume中。表示来自account的消息无需进行消息提醒。
NIMClient.getService(MsgService.class).setChattingAccount(account, sessionType);

// 进入最近联系人列表界面,建议放在onResume中。表示所有消息无需进行消息提醒。
NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_ALL, SessionTypeEnum.None);

// 退出聊天界面或离开最近联系人列表界面,建议放在onPause中。表示所有消息都可以进行消息提醒。
NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, SessionTypeEnum.None);

就这样操作三步就可以收到消息通知了。
一般我们集成的是UiKit的库,在项目中直接加载库中最近会话列表和聊天页面等,聊天页面的通知已经默认做好,我们无需操作。
如果要全程收到通知,我们在主页设置一下代码就好了。

NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, SessionTypeEnum.None);

2.状态栏消息通知的点击事件

demo里面的写法是跳到启动页然后根据intent获取的参数继续跳聊天页。
正常情况下我们启动页已经写好了,再改起来有点麻烦。
所以我们直接可以写一个没有视图的空页面只做跳转。
有同学可能会疑惑为什么不能直接跳到主页面然后再操作呢。因为我们一般主页面都会设置为signTask,当前页面存在情况下再次跳转拿不到new Intent。

NoViewActivity局步代码

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        onParseIntent();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        onParseIntent();
    }

    private void onParseIntent() {
        Intent intent = getIntent();
        if (intent.hasExtra(NimIntent.EXTRA_NOTIFY_CONTENT)) {
            ArrayList<IMMessage> messages = (ArrayList<IMMessage>)
                    getIntent().getSerializableExtra(NimIntent.EXTRA_NOTIFY_CONTENT); // 可以获取消息的发送者,跳转到指定的单聊、群聊界面。
            if (messages == null || messages.size() == 0) {
                finish();
                return;
            }
            intent.removeExtra(NimIntent.EXTRA_NOTIFY_CONTENT);
            switch (messages.get(0).getSessionType()) {
                case P2P:
                    NimUIKit.startP2PSession(this, messages.get(0).getSessionId());
                    break;
            }
        }
        finish();
    }

3. 自定义消息(分享名片,分享文章等等)

根据UiKit中的文档可以看到分为九个步骤。
下面我们演示一下分享名片。

首先,先定义一个自定义消息的类型

public interface CustomAttachmentType {
    int ShareUserType = 1;
}

第二步,定义一个自定义消息附件的基类,负责解析你的自定义消息的公用字段,比如类型等 。

注意: 实现 MsgAttachment 接口的成员都要实现 Serializable。

public abstract class CustomAttachment implements MsgAttachment {
    protected int type;
    CustomAttachment(int type) {
        this.type = type;
    }
    public void fromJson(JSONObject data) {
        if (data != null) {
            parseData(data);
        }
    }
    @Override
    public String toJson(boolean send) {
        return CustomAttachParser.packData(type, packData());
    }
    public int getType() {
        return type;
    }
    protected abstract void parseData(JSONObject data);
    protected abstract JSONObject packData();
}

第三步,继承这个基类,实现“名片”的附件类型。

注意,成员变量都要实现 Serializable。

public class ShareUserAttachment extends CustomAttachment {

    private String userIcon;
    private String userName;
    private String userId;


    public ShareUserAttachment() {
        super(CustomAttachmentType.ShareUserMsg);
    }

    public ShareUserAttachment(String str) {
        this();
    }

    @Override
    protected void parseData(JSONObject data) {
      //括号里的这三个字段跟IOS端或者其他端商议好
        userName = data.getString("shareTitle");
        userIcon= data.getString("shareIcon");
        userId = data.getString("shareId");
    }

    @Override
    public JSONObject packData() {
        //括号里的这三个字段跟IOS端或者其他端商议好
        JSONObject data = new JSONObject();
        data.put("shareTitle", userName);
        data.put("shareIcon", userIcon);
        data.put("shareId", userId);
        return data;
    }

    public String getUserIcon() {
        return userIcon;
    }

    public void setUserIcon(String userIcon) {
        this.userIcon= userIcon;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }


    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }
}

第四步,实现自定义消息的附件解析器。

public class CustomAttachParser implements MsgAttachmentParser {
    private static final String KEY_TYPE = "type";
    private static final String KEY_DATA = "data";
    @Override
    public MsgAttachment parse(String json) {
        CustomAttachment attachment = null;
        try {
            JSONObject object = JSON.parseObject(json);
            int type = object.getInteger(KEY_TYPE);
            JSONObject data = object.getJSONObject(KEY_DATA);
            switch (type) {
                    case CustomAttachmentType.ShareUserType :
                    attachment = new ShareUserAttachment();
                    break;
            }
            if (attachment != null) {
                //注意了,按照Android UiKit文档里的写法自定义消息的参数是包在data字段里面的。IOS文档里面的写法没有包。
                //如果不需要data字段,此处直接解析object 
                //attachment.fromJson(object);
                attachment.fromJson(data);
            }
        } catch (Exception e) {

        }
        return attachment;
    }
    public static String packData(int type, JSONObject data) {
        JSONObject object = new JSONObject();
        object.put(KEY_TYPE, type);
        if (data != null) {
             //包装在data里面的写法
            object.put(KEY_DATA, data);
            //不放在data 直接放在外层
//            for (Map.Entry<String, Object> objectEntry : data.entrySet()) {
//                object.put(objectEntry.getKey(), objectEntry.getValue());
//            }
        }
        return object.toJSONString();
    }
}

第五步,将自定义消息UI

public class ShareUserViewHolder extends MsgViewHolderBase {

    private ImageView ivUser;
    private TextView tvName;
    private ShareUserAttachment attachment;
    private RelativeLayout rlItem;

    public ShareUserViewHolder(BaseMultiItemFetchLoadAdapter adapter) {
        super(adapter);
    }

    @Override
    public int getContentResId() {
        return R.layout.item_msg_share_user;
    }

    @Override
    public void inflateContentView() {
        rlItem = (RelativeLayout) findViewById(R.id.rl_item);
        ivUser = (ImageView) findViewById(R.id.iv_user);
        tvName = (TextView) findViewById(R.id.tv_name);
    }

    @Override
    public void bindContentView() {
        attachment = (ShareUserAttachment) message.getAttachment();

        Glide.with(context).load(attachment.getUrl()).into(ivUser);
        tvName.setText(attachment.getUserName());
        rlItem.setOnClickListener(lis -> {

        //这是一个隐藏键盘的方法,不需要自行去掉
        InputMethodManager imm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE);
        View v = ((AppCompatActivity) context).getWindow().peekDecorView();
        if (null != v) {
            imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
        }

      //点击事件
       context.startActivity(new Intent(context, OtherUserActivity.class)
                    .putExtra("userId", attachment.getUserId()));
        });
    }

    // 若是要自己修改气泡背景自行替换,当前为0表示没有
    // 当是发送出去的消息时,内容区域背景的drawable id
    @Override
    protected int rightBackground() {
        return 0;
    }

    @Override
    protected int leftBackground() {
        return 0;
    }

}

第六步,发送自定义消息。
文档里的写法是从聊天页面底部菜单的更多菜单位置发送的。可自行琢磨。当前写法直接用非聊天页面分享。

    ShareUserAttachment userAttachment = new ShareUserAttachment();
    userAttachment.setUserId(shareUserId);
    userAttachment.setUserName(shareUserName);
    userAttachment.setUserIcon(shareIcon);

    IMMessage message = MessageBuilder.createCustomMessage(account, SessionTypeEnum.P2P, userAttachment);

     //发送自定义消息
     NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
            @Override
            public void onSuccess(Void param) {

            }

            @Override
            public void onFailed(int code) {
               
            }

            @Override
            public void onException(Throwable exception) {

            }
        });

第七步,将该附件解析器注册到 SDK 中。为了保证生成历史消息时能够正确解析自定义附件,注册一般应放在 Application 的 onCreate 中完成

NIMClient.getService(MsgService.class).registerCustomAttachmentParser(new CustomAttachParser());

第八步,注册扩展消息类型的显示ViewHolder,由于这里使用我们UIKIT,所以也需要注册到Application的onCreate中

 NimUIKit.registerMsgItemViewHolder(ShareUserAttachment.class, ShareUserViewHolder .class);

第九步,我们暂时不需要从聊天底部菜单中发送所以省略。

4. 自定义聊天气泡,聊天界面时间显示,已读显示等

一下操作都是在MyApplication中进行

        // ... your codes
        if (NIMUtil.isMainProcess(this)) {
            // 注意:以下操作必须在主进程中进行
            // 1、UI相关初始化操作
            // 初始化
            NimUIKit.init(this, buildUIKitOptions());
        }


    private UIKitOptions buildUIKitOptions() {
        UIKitOptions options = new UIKitOptions();
        //自定义聊天界面消息气泡
        options.messageLeftBackground = R.drawable.shape_msg_text_bg_receive;
        options.messageRightBackground = R.drawable.shape_msg_text_bg_send;

        //消息列表每隔多久显示一条消息  默认五分钟,当前设置一小时
        options.displayMsgTimeWithInterval = 60 * 60 * 1000;
        //全局是否使用消息已读 
        options.shouldHandleReceipt = false;
        return options;
    }

相关文章

网友评论

      本文标题:网易云信 即时聊天

      本文链接:https://www.haomeiwen.com/subject/tvyclktx.html