本地通知
IMKit 已实现本地通知的创建、弹出与跳转行为,方便开发者快速构建应用。
什么是本地通知
本地通知指应用在前台或后台运行时,由 IMKit 或应用客户端直接调用系统接口创建并发送的通知(Notification)。IMKit SDK 内部已经实现了本地通知功能 (Notification),当应用处于后台接收到新消息时,IMKit 默认会在通知面板弹出通知提醒,即本地通知。
IMKit 的本地通知已支持以下场景:
-
当 App 刚进入后台时(仍处于后台活跃状态),IMKit 仍可通过长连接通道接收到新消息(撤回消息也会产生撤回信令消息)。接到新消息后,IMKit 默认会创建并弹出通知,即本地通知。点击此通知会跳转到会话页面。
提示App 在后台进入非活跃状态后(例如,被系统杀死),IMKit 与服务端断开连接。如果应用已集成第三方厂商推送服务(或融云自建推送服务),此时可通过接收推送通知。来自第三方厂商的离线推送通知一般由推送厂商直接创建并弹出,不属于本文所述的本地通知。
-
当 App 处于前台,且未打开任何会话页面时(未与任何人聊天),接收新消息后默认会响铃并震动,但不弹通知。可通过
setForegroundOtherPageAction
修改为静默或仅弹出通知,参考 NotificationConfig.java。
设置本地通知分类
华为从 2023 年 9 从2023年9月15日开始,华为推送服务将基于《华为消息分类标准》对本地通知进行灰度管控,主要包括对应用发送的本地通知进行分类管理,以及对资讯营销消息统一进行频次管控。应用在未申请华为自分类权益的情况下,发送的本地通知将全部按照资讯营销消息处理(限频2条或5条/天)。
为避免 IMKit 直接调用华为设备系统接口发送的本地通知无法弹出,应用应确保自身已向华为申请所需自分类权益。IMKit 从 5.6.4 版本开始,内部弹出本地通知的 category
默认设置为 CATEGORY_MESSAGE
,应用程序不需要额外调用 API 进行设置。
您可以在初始化之后,使用 IMKit 全局配置修改默认的本地通知分类:
RongConfigCenter.notificationConfig().setCategoryNotification(Notification.CATEGORY_MESSAGE);
如果您集成的 IMKit < 5.6.4,需要应用程序自定义本地通知,建议参考知识库文档关于华为限制本地通知频次及分类的适配流程。
设置前台本地通知铃声与震动
SDK 从 5.2.3 版本开始支持该功能。
从 5.2.3 开始,IMKit 增加了控制应用在前台非会话页面时,接收到新消息是否响铃提醒、是否震动提醒的独立控制开关。
如果修改 App 默认行为,您可以在应用 res/values
目录下创建 rc_config.xml
文件,修改以下配置项的值,默认开启。
//在前台非会话页面时,接收到新消息是否响铃
<bool name="rc_sound_in_foreground">true</bool>
//在前台非会 话页面时,接收到新消息是否震动
<bool name="rc_vibrate_in_foreground">true</bool>
针对本地通知响铃、震动行为控制,可通过 IMKit 全局配置动态修改。
/** 是否震动 */
RongConfigCenter.featureConfig().setVibrateInForeground(true)
/** 是否有铃声 */
RongConfigCenter.featureConfig().setSoundInForeground(false)
拦截本地通知
应用在本地通知显示前对通知进行拦截。IMKit 支持在拦截修改 Message
后继续弹出本地通知。您可以参考 IMKit 源码中的以下文件:
如果需要更多自定义效果,建议完全拦截,由应用程序自行接管并弹出本地通知。
拦截本地通知
从 SDK 版本 5.1.4 开始,请使用以下方法设置拦截器。
您可以拦截 SDK 的本地通知。设置拦截器后,可阻止 SDK 弹出本地通知,并按需自定义处理。请在初始化之后,建立 IM 连接之前设置监听器。
public class MyNotificationInterceptor extends DefaultInterceptor {
/**
* 是否拦截此本地通知,一般用于自定义本地通知的显示。
*
* @param message 本地通知对应的消息
* @return 是否拦截。true 拦截本地通知,SDK 不弹出通知,需要用户自己处理。false 不拦截,由 SDK 展示本地通知。
*/
@Override
public boolean isNotificationIntercepted(Message message) {
...
return true; //true, 拦截本地通知,SDK 不再处理本地通知的逻辑。
}
/**
* 是否为高优先级消息。高优先级消息不受全局静默时间和会话免打扰控制,比如 @ 消息。
*
* @param message 接收到的消息
* @return 是否为高优先级消息
*/
@Override
public boolean isHighPriorityMessage(Message message) {
return false;
}
/**
* 注册默认 channel 之前的回调。可以通过此方法拦截并修改默认 channel 里的配置,将修改后的 channel 返回。
*
* @param defaultChannel 默认通知频道
* @return 修改后的通知频道。
*/
@Override
public NotificationChannel onRegisterChannel(NotificationChannel defaultChannel) {
return defaultChannel;
}
/**
* 设置本地通知 PendingIntent 时的回调。
* 应用层可通过此方法更改 PendingIntent 里的设置,以便自定义本地通知的点击行为。
* 点击本地通知时,SDK 默认跳转到对应会话页面。
* @param pendingIntent SDK 默认 PendingIntent
* @param intent pendingIntent 里携带的 intent。
* 可通过 intent 获取以下信息:
* intent.getStringExtra(RouteUtils.CONVERSATION_TYPE);
* intent.getStringExtra(RouteUtils.TARGET_ID);
* intent.getIntExtra(RouteUtils.MESSAGE_ID, -1);;
* @return 本地通知里需配置的 PendingIntent.
*/
@Override
public PendingIntent onPendingIntent(PendingIntent pendingIntent, Intent intent) {
Intent intentNew = new Intent(getApplicationContext(), MainActivity.class); //自定义跳转到会话列表
PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(), 1, intentNew, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent1;
}
}
RongConfigCenter.notificationConfig().setInterceptor(new MyNotificationInterceptor());
拦截本地通知(< 5.1.4)
从 SDK 版本 5.1.4 开始,废弃以下方法。
您可以拦截 SDK 的本地通知。设置拦截器后,可阻止 SDK 弹出本地通知,并按需自定义处理。请在初始化之后,建立 IM 连接之前设置监听器。
RongConfigCenter.notificationConfig().setInterceptor(new NotificationConfig.Interceptor() {
/**
* 是否拦截此本地通知,一般用于自定义本地通知的显示。
*
* @param message 本地通知对应的消息
* @return 是否拦截。true 拦截本地通知,SDK 不弹出通知,需要用户自己处理。false 不拦截,由 SDK 展示本地通知。
*/
@Override
public boolean isNotificationIntercepted(Message message) {
...
return true; //true, 拦截本地通知,SDK 不再处理本地通知的逻辑。
}
/**
* 是否为高优先级消息。高优先级消息不受全局静默时间和会话免打扰控制,比如 @ 消息。
*
* @param message 接收到的消息
* @return 是否为高优先级消息
*/
@Override
public boolean isHighPriorityMessage(Message message) {
return false;
}
/**
* 注册默认 channel 之前的回调。可以通过此方法拦截并修改默认 channel 里的配置,将修改后的 channel 返回。
*
* @param defaultChannel 默认通知频道
* @return 修改后的通知频道。
*/
@Override
public NotificationChannel onRegisterChannel(NotificationChannel defaultChannel) {
return defaultChannel;
}
/**
* 设置本地通知 PendingIntent 时的回调。
* 应用层可通过此方法更改 PendingIntent 里的设置,以便自定义本地通知的点击行为。
* 点击本地通知时,SDK 默认跳转到对应会话页面。
* @param pendingIntent SDK 默认 PendingIntent
* @param intent pendingIntent 里携带的 intent。
* 可通过 intent 获取以下信息:
* intent.getStringExtra(RouteUtils.CONVERSATION_TYPE);
* intent.getStringExtra(RouteUtils.TARGET_ID);
* intent.getIntExtra(RouteUtils.MESSAGE_ID, -1);;
* @return 本地通知里需配置的 PendingIntent.
*/
@Override
public PendingIntent onPendingIntent(PendingIntent pendingIntent, Intent intent) {
Intent intentNew = new Intent(getApplicationContext(), MainActivity.class); //自定义跳转到会话列表
PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(), 1, intentNew, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent1;
}
});
自定义通知点击
点击本地通知时,SDK 默认跳转到通知对应的会话页面。您可以自定义点击时的跳转事件。在上文拦截通知的 onPendingIntent
回调中使用。
@Override
public PendingIntent onPendingIntent(PendingIntent pendingIntent, Intent intent) {
Intent intentNew = new Intent(getApplicationContext(), MainActivity.class); //自定义跳转到会话列表
PendingIntent pendingIntent1 = PendingIntent.getActivity(getApplicationContext(), 1, intentNew, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent1;
}