消息与通知处理接口(4.x)

更新时间:
复制 MD 格式

本文介绍 Android SDK 4.x 接收消息、通知到达、点击和删除事件,以及按需拦截通知显示的方法。

说明

适用于移动推送 Android SDK 4.x,本文接口和示例以已发布的 4.0.0 版本为基线。使用 3.x 的应用请参见对应的 3.x API 文档。

选择一种回调方式

重要

Android SDK 4.x 中,MessageReceiver 和 AliyunMessageIntentService 的业务回调范围如下:

  • ACCS 自有通道和 FCM:支持消息接收(onMessage)、通知到达(onNotification)、通知点击(onNotificationOpened)、通知清除(onNotificationRemoved)等完整业务回调。

  • 除 FCM 外的其他 Android 厂商通道:仅支持 onNotificationOpened(通知点击),不触发消息接收、通知到达、通知清除等其他回调。

MessageReceiver 与 AliyunMessageIntentService 提供相同的业务回调,任选一种。默认使用 MessageReceiver;调用 setPushIntentService 后改由指定服务处理,不再通过 MessageReceiver 分发。

回调

适用范围

onMessage

ACCS 自有通道和 FCM 通道的透传消息到达。

onNotification

ACCS 自有通道和 FCM 通道的通知到达;应用拦截通知展示时仍使用此回调。

onNotificationOpened

SDK 展示的通知点击,以及正确接入辅助弹窗后的厂商系统通知点击。

onNotificationRemoved

ACCS 自有通道和 FCM 通道的通知被删除。其他安卓厂商通道仅提供 onNotificationOpened 点击回调。

请先完成 SDK 初始化和注册。FCM 适配器将 data 消息中的 payload 转交移动推送 SDK 处理。小米、华为、荣耀、OPPO、vivo、魅族等厂商系统通知点击仍需要正确配置中转 Activity 和服务端辅助弹窗参数;4.x 将业务点击处理统一交给 onNotificationOpened,不再由 onSysNoticeOpened 处理。

以下回调示例写在已继承 MessageReceiver 或 AliyunMessageIntentService 的类中;其余必需回调仍需实现。回调参数由 SDK 传入,参数表中的“是否必填”表示该值是否必须存在,标为“否”的值使用前应判空。

方式一:MessageReceiver

继承 MessageReceiver 并实现四个业务回调。将类名替换成应用实际类名,Kotlin 示例对可能为空的数据进行判空。

import android.content.Context;
import com.alibaba.sdk.android.push.MessageReceiver;
import com.alibaba.sdk.android.push.notification.CPushMessage;
import java.util.Map;

public class MyMessageReceiver extends MessageReceiver {
    @Override
    public void onMessage(Context context, CPushMessage message) {
        // SDK 处理的透传消息,不会自动显示为通知。
    }
    @Override
    public void onNotification(Context context, String title, String summary,
                               Map<String, String> extraMap) {
        // SDK 处理的通知到达,无论应用是否选择展示通知。
    }
    @Override
    public void onNotificationOpened(Context context, String title, String summary,
                                     Map<String, String> extraMap) {
        // 统一处理 SDK 通知及已正确接入的厂商系统通知点击。
        // 可从 extraMap 读取发送时设置的扩展参数,使用前需判空。
    }
    @Override
    public void onNotificationRemoved(Context context, String messageId) {
        // SDK 展示的通知被删除;messageId 是消息标识。
    }
}
import android.content.Context
import com.alibaba.sdk.android.push.MessageReceiver
import com.alibaba.sdk.android.push.notification.CPushMessage

class MyMessageReceiver : MessageReceiver() {
    override fun onMessage(context: Context, message: CPushMessage) {
        // SDK 处理的透传消息。
    }
    override fun onNotification(
        context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
    ) {
        // SDK 处理的通知到达。
    }
    override fun onNotificationOpened(
        context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
    ) {
        // 统一处理通知点击。
        // 可从 extraMap 读取发送时设置的扩展参数,使用前需判空。
    }
    override fun onNotificationRemoved(context: Context, messageId: String?) {}
}

在 AndroidManifest.xml 的 application 节点内注册。示例 .MyMessageReceiver 必须替换为应用实际的完整类名或可解析的相对类名。

<receiver
    android:name=".MyMessageReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="com.alibaba.sdk.android.push.RECEIVE" />
        <action android:name="com.alibaba.push2.action.NOTIFICATION_OPENED" />
        <action android:name="com.alibaba.push2.action.NOTIFICATION_REMOVED" />
    </intent-filter>
</receiver>

onReceive 回调中的网络请求和其他耗时操作,请交给应用的异步任务处理。

方式二:AliyunMessageIntentService

继承 SDK 的 AliyunMessageIntentService,以服务形式接收回调。回调中的耗时操作请交给异步任务处理,界面操作请切换到主线程执行。

import android.content.Context;
import com.alibaba.sdk.android.push.AliyunMessageIntentService;
import com.alibaba.sdk.android.push.notification.CPushMessage;
import java.util.Map;

public class MyMessageIntentService extends AliyunMessageIntentService {
    @Override
    public void onMessage(Context context, CPushMessage message) {
        // SDK 处理的透传消息,不会自动显示为通知。
    }
    @Override
    public void onNotification(Context context, String title, String summary,
                               Map<String, String> extraMap) {
        // SDK 处理的通知到达,无论应用是否选择展示通知。
    }
    @Override
    public void onNotificationOpened(Context context, String title, String summary,
                                     Map<String, String> extraMap) {
        // 统一处理 SDK 通知及已正确接入的厂商系统通知点击。
        // 可从 extraMap 读取发送时设置的扩展参数,使用前需判空。
    }
    @Override
    public void onNotificationRemoved(Context context, String messageId) {
        // SDK 展示的通知被删除;messageId 是消息标识。
    }
}
import android.content.Context
import com.alibaba.sdk.android.push.AliyunMessageIntentService
import com.alibaba.sdk.android.push.notification.CPushMessage

class MyMessageIntentService : AliyunMessageIntentService() {
    override fun onMessage(context: Context, message: CPushMessage) {
        // SDK 处理的透传消息。
    }
    override fun onNotification(
        context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
    ) {
        // SDK 处理的通知到达。
    }
    override fun onNotificationOpened(
        context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
    ) {
        // 统一处理通知点击。
        // 可从 extraMap 读取发送时设置的扩展参数,使用前需判空。
    }
    override fun onNotificationRemoved(context: Context, messageId: String?) {}
}

在 AndroidManifest.xml 的 application 节点内注册。

<service
    android:name=".MyMessageIntentService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.alibaba.sdk.android.push.RECEIVE" />
        <action android:name="com.alibaba.push2.action.NOTIFICATION_OPENED" />
        <action android:name="com.alibaba.push2.action.NOTIFICATION_REMOVED" />
    </intent-filter>
</service>

setPushIntentService:指定消息处理服务

指定继承 AliyunMessageIntentService 的服务类,使 SDK 通过该服务分发消息和通知事件。

接口定义

void setPushIntentService(Class intentService);

参数说明

参数

类型

是否必填

说明

intentService

Class

否

已在 AndroidManifest.xml 注册、继承 AliyunMessageIntentService 的服务类;传 null 恢复通过 MessageReceiver 分发。

返回值:无(void);该方法不执行推送注册,也不提供结果回调。

在 Application.onCreate() 中完成 init 后尽早设置,并在 register 前完成。每次应用启动均恢复此配置。

代码示例

PushServiceFactory.getCloudPushService()
        .setPushIntentService(MyMessageIntentService.class);
PushServiceFactory.getCloudPushService()
    .setPushIntentService(MyMessageIntentService::class.java)

透传消息回调

void onMessage(Context context, CPushMessage message);

SDK 将透传消息交给应用处理,不会自动显示通知。context 是组件上下文;message 包含消息数据。

参数说明

参数

类型

是否必填

说明

context

Context

是

SDK 分发事件使用的组件上下文。界面操作请使用有效的 Activity。

message

CPushMessage

是

本次到达的透传消息对象,读取示例中的 message 均来自此参数。

返回值:无(void)。应用处理消息内容;此回调不会自动创建通知。

代码示例

@Override
public void onMessage(Context context, CPushMessage message) {
    String content = message.getContent();
    if (content != null) {
        // 按应用约定解析消息正文;耗时操作交给应用任务调度。
    }
}
override fun onMessage(context: Context, message: CPushMessage) {
    val content = message.content
    if (content != null) {
        // 按应用约定解析消息正文。
    }
}

CPushMessage 方法

说明

getMessageId()

消息标识。

getAppId()

应用标识。

getTitle()

消息标题。

getContent()

消息正文。

getTraceInfo()

统计上报所需信息,应与原始消息一起保留,不自行改写。

若应用根据透传消息自行创建通知,请在实际点击或删除时使用自建通知统计上报接口,传入原始 CPushMessage。

CPushMessage.getMessageId:获取消息标识

读取 onMessage 回调参数 message 中的消息标识。

接口定义

public String getMessageId();

参数说明:无。

返回值:服务端消息标识,用于关联推送消息,不是 Android 整数通知 ID。 返回类型为 String。

示例中的 message 为 onMessage 回调参数,保留原始对象供后续自建通知统计使用。

代码示例

String messageId = message.getMessageId();
val messageId = message.getMessageId()

CPushMessage.getAppId:获取应用标识

读取 onMessage 回调参数 message 中的应用标识。

接口定义

public String getAppId();

参数说明:无。

返回值:消息携带的应用标识。 返回类型为 String。

示例中的 message 为 onMessage 回调参数,保留原始对象供后续自建通知统计使用。

代码示例

String appId = message.getAppId();
val appId = message.getAppId()

CPushMessage.getTitle:获取消息标题

读取 onMessage 回调参数 message 中的消息标题。

接口定义

public String getTitle();

参数说明:无。

返回值:透传消息标题;值可能为空。 返回类型为 String。

示例中的 message 为 onMessage 回调参数,保留原始对象供后续自建通知统计使用。

代码示例

String title = message.getTitle();
val title = message.getTitle()

CPushMessage.getContent:获取消息正文

读取 onMessage 回调参数 message 中的消息正文。

接口定义

public String getContent();

参数说明:无。

返回值:透传消息正文;内容格式由发送方与应用约定。 返回类型为 String。

示例中的 message 为 onMessage 回调参数,保留原始对象供后续自建通知统计使用。

代码示例

String content = message.getContent();
val content = message.getContent()

CPushMessage.getTraceInfo:获取统计信息

读取 onMessage 回调参数 message 中的统计信息。

接口定义

public String getTraceInfo();

参数说明:无。

返回值:SDK 统计上报使用的原始信息,请随原始消息保留和传递。返回类型为 String。

示例中的 message 为 onMessage 回调参数,保留原始对象供后续自建通知统计使用。

代码示例

String traceInfo = message.getTraceInfo();
val traceInfo = message.getTraceInfo()

通知到达回调

在 SDK 处理通知到达时调用。通知是否显示在系统通知栏,由展示判断及系统条件决定。

void onNotification(Context context, String title, String summary,
        Map<String, String> extraMap);

参数

类型

是否必填

说明

context

Context

是

SDK 分发事件使用的组件上下文。界面操作请使用有效的 Activity。

title

String

否

通知标题。

summary

String

否

通知正文。

extraMap

Map<String, String>

否

已解析的通知扩展参数;业务参数键由发送方约定,不存在固定的业务跳转键。

4.x 中,当 showNotificationNow 返回 false 或自定义样式设置前台不显示时,应用仍通过 onNotification 接收通知数据。通知栏展示还需满足系统通知权限和通知渠道设置。

返回值:无(void)。此回调表示通知数据到达。

代码示例

@Override
public void onNotification(Context context, String title, String summary,
                           Map<String, String> extraMap) {
    String businessId = extraMap == null ? null : extraMap.get("businessId");
    if (businessId != null) {
        // businessId 为发送方自定义的扩展参数,按业务需要更新应用数据。
    }
}
override fun onNotification(
    context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
) {
    val businessId = extraMap?.get("businessId")
    if (businessId != null) {
        // businessId 为发送方自定义的扩展参数。
    }
}

控制是否展示通知

boolean showNotificationNow(Context context, Map<String, String> map);

返回 true 交给 SDK 创建并展示通知;返回 false 不展示,由应用在 onNotification 中处理业务。map 包含 SDK 原始通知数据,业务扩展参数需从 ext 字段解析。默认实现会考虑自定义样式的前台展示设置。免打扰规则优先于此方法。

参数说明

参数

类型

是否必填

说明

context

Context

是

SDK 创建通知时使用的上下文。

map

Map<String, String>

是

SDK 原始通知数据的顶层 Map。业务扩展参数位于 ext 键对应的 JSON 字符串中,不会直接平铺为顶层键。

返回值:boolean。true 允许 SDK 继续构建和展示;false 拦截本次 SDK 通知展示。调用 super.showNotificationNow 可保留默认的前台展示规则。

以下示例仅在当前会话与通知业务扩展参数 conversationId 一致时拦截。conversationId 是应用自定义示例键;空值或 JSON 解析失败时回退到 SDK 默认判断。onNotification 和 onNotificationOpened 的 extraMap 已解析业务扩展字段,与这里的顶层 map 不同。

@Override
public boolean showNotificationNow(Context context, Map<String, String> map) {
    String ext = map.get("ext");
    if (ext != null) {
        try {
            String conversationId = new org.json.JSONObject(ext)
                    .optString("conversationId", "");
            if (!conversationId.isEmpty()
                    && conversationId.equals(getVisibleConversationId())) {
                return false;
            }
        } catch (org.json.JSONException ignored) {
            // 非法扩展参数不影响默认展示判断。
        }
    }
    return super.showNotificationNow(context, map);
}
private String getVisibleConversationId() {
    return ""; // 替换成应用当前正在查看的会话 ID;空字符串表示未查看会话。
}
override fun showNotificationNow(context: Context, map: Map<String, String>): Boolean {
    val ext = map["ext"]
    if (ext != null) {
        try {
            val conversationId = org.json.JSONObject(ext).optString("conversationId", "")
            if (conversationId.isNotEmpty() && conversationId == getVisibleConversationId()) {
                return false
            }
        } catch (ignored: org.json.JSONException) {
            // 非法扩展参数不影响默认展示判断。
        }
    }
    return super.showNotificationNow(context, map)
}
private fun getVisibleConversationId(): String = "" // 替换为应用当前会话 ID。

通知点击回调

void onNotificationOpened(Context context, String title, String summary,
        Map<String, String> extraMap);

4.x 的 extraMap 是 Map<String,String>,不再是 JSON 字符串;数据可能为空。自有通道的无跳转通知点击也进入本回调,不再实现 onNotificationClickedWithNoAction。厂商点击通过正确配置的中转 Activity 解析后进入同一回调。

需要页面跳转时,请结合应用路由和当前页面状态统一管理跳转入口,并使用有效的 Activity 处理界面操作。

参数说明

参数

类型

是否必填

说明

context

Context

是

SDK 分发事件使用的组件上下文。界面操作请使用有效的 Activity。

title

String

否

通知标题。

summary

String

否

通知正文。

extraMap

Map<String, String>

否

已解析的通知扩展参数;业务参数键由发送方约定,不存在固定的业务跳转键。

返回值:无(void)。在此处理业务点击;SDK 或服务端已配置页面跳转时,应避免重复跳转。

代码示例

@Override
public void onNotificationOpened(Context context, String title, String summary,
                                 Map<String, String> extraMap) {
    String businessId = extraMap == null ? null : extraMap.get("businessId");
    if (businessId != null) {
        // 按应用业务约定处理点击;businessId 不是 SDK 固定字段。
    }
}
override fun onNotificationOpened(
    context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
) {
    val businessId = extraMap?.get("businessId")
    if (businessId != null) {
        // 按应用业务约定处理点击。
    }
}

通知删除回调

void onNotificationRemoved(Context context, String messageId);

删除通知时返回服务端消息标识 messageId。它与 Android NotificationManager 使用的整数通知 ID 不是同一概念,不可直接互换。

参数说明

参数

类型

是否必填

说明

context

Context

是

SDK 分发删除事件使用的组件上下文。

messageId

String

否

被删除通知对应的服务端消息标识;使用前判空。

返回值:无(void)。表示 SDK 展示的通知被用户删除,不用于判断厂商系统通知的删除状态。

代码示例

@Override
public void onNotificationRemoved(Context context, String messageId) {
    if (messageId != null) {
        // 按消息标识清理应用保存的通知记录。
    }
}
override fun onNotificationRemoved(context: Context, messageId: String?) {
    if (messageId != null) {
        // 按消息标识清理应用保存的通知记录。
    }
}

迁移与验证

3.x 用法

4.x 用法

onNotificationOpened(..., String extraMap)

改为 Map<String,String>,使用前判空。

onNotificationClickedWithNoAction(...)

已删除,统一使用 onNotificationOpened。

onNotificationReceivedInApp(...)

已删除,统一使用 onNotification。

辅助弹窗 onSysNoticeOpened

业务逻辑移到 Receiver/Service 的 onNotificationOpened。

分别测试透传消息、自有通道通知前台/后台到达、展示拦截、自有与厂商通知点击、通知删除以及应用重新启动后的服务分发配置。排查 SDK 日志使用 TAG EMAS_PUSH,并结合正文模块筛选;应用示例自己的 Log TAG 与 SDK TAG 不必相同。

相关文档

接入流程请参见Android SDK接入(4.x)。

使用 3.x 的应用请参见消息与通知处理接口(3.x)。