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;
}
网友评论