本文介绍移动推送 Android SDK 4.x 的接入方法,包括添加 SDK、初始化与注册、配置消息接收、接入厂商通道及验证接入结果。
前言
-
推荐使用 Gradle 管理依赖的 Android Studio 项目。
-
最低支持 Android 6.0(API 23)。
-
本文适用于移动推送 Android SDK 4.x。
移动推送 SDK 包含自有长连接通道和厂商通道。本文以 4.0.0 为例介绍接入步骤;接入厂商通道可提高应用离线时的通知到达率。
已有 3.x 项目升级请参见Android SDK 4.x升级指南;仍使用 3.x 的项目请参见Android SDK接入(3.x)。
准备工作
在 EMAS 控制台创建或选择 Android 应用,开通移动推送,并记录该应用的 AppKey、AppSecret。实际 APK 的 applicationId(包名)应与控制台登记的信息一致。具体操作请参见创建应用。
|
环境项 |
最低支持版本 |
|
Android 版本 |
Android 6.0(API 23)及以上。 |
|
compileSdk |
34 及以上。 |
|
Android Gradle Plugin(AGP) |
8.1.1 及以上。 |
|
Gradle |
8.0 及以上。 |
|
构建 JDK |
17 及以上。 |
|
Kotlin(仅 Kotlin 项目) |
1.8.0 及以上。 |
构建工具按 compileSdk 34 的官方最低支持组合列出;使用更高版本 AGP 时,需匹配其要求的 Gradle 和构建 JDK 版本。
第一步:将 SDK 添加到您的应用
推荐使用 Maven 依赖方式集成 SDK。以下为 Groovy 示例,在项目已有的仓库配置和 dependencies 中添加相应内容即可。
1 Maven 依赖方式
1.1 配置 Maven 仓库
如果项目使用 dependencyResolutionManagement 管理依赖,在项目级 settings.gradle 的 repositories 中添加仓库。
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
}
}
如果项目使用 allprojects 管理依赖,在项目级 build.gradle 的 repositories 中添加仓库。
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
}
}
两种仓库配置方式按项目现有结构选择一种。接入华为、荣耀等厂商通道时,按对应文档补充厂商 Maven 仓库。
1.2 添加 SDK 依赖
在应用模块的 build.gradle 文件中,在 dependencies 中添加 SDK 依赖。
dependencies {
implementation 'com.aliyun.ams:alicloud-android-push:4.0.0'
}
请使用固定版本号集成,保留 Maven 传递依赖,并统一通过 Maven 管理 SDK。4.+ 等动态版本号、@aar 和 transitive = false 会改变版本或依赖解析结果;已通过 Maven 引入的 SDK 无需再放入 libs。
4.x 的完整依赖由 Maven 自动引入,单独复制主 SDK 的 AAR 文件不能替代完整接入。已有项目升级时,请按升级指南处理旧版依赖。
第二步:配置使用 SDK
1 配置 AppKey 和 AppSecret
支持代码配置和 AndroidManifest 文件配置两种方式,选择其中一种即可。AppKey 和 AppSecret 必须来自 EMAS 控制台的同一个 Android 应用。
1.1 代码配置方式
在 Application 中构建 PushInitConfig,并在下一节初始化时传入该配置。
PushInitConfig pushInitConfig = new PushInitConfig.Builder()
.application(this) // 当前 Application 实例
.appKey("YOUR_APP_KEY")
.appSecret("YOUR_APP_SECRET")
.build();val pushInitConfig = PushInitConfig.Builder()
.application(this) // 当前 Application 实例
.appKey("YOUR_APP_KEY")
.appSecret("YOUR_APP_SECRET")
.build()1.2 AndroidManifest 文件配置方式
在 AndroidManifest.xml 的 application 节点内配置应用参数。
<application ...>
<meta-data android:name="com.alibaba.app.appkey" android:value="YOUR_APP_KEY" />
<meta-data android:name="com.alibaba.app.appsecret" android:value="YOUR_APP_SECRET" />
</application>
2 SDK 初始化与设备注册
2.1 初始化 SDK
在自定义 Application 的 onCreate() 主线程中调用 PushServiceFactory.init。应用已有 Application 时,将初始化逻辑加入现有类,并在所有需要接收推送的进程中执行。
使用代码配置时,将上一步创建的 PushInitConfig 传入 init。
PushServiceFactory.init(pushInitConfig);PushServiceFactory.init(pushInitConfig)使用 AndroidManifest 配置时,通过 Context 初始化。
PushServiceFactory.init(getApplicationContext());PushServiceFactory.init(applicationContext)在 AndroidManifest.xml 中声明自定义 Application;下面的 PushApplication 请替换为实际类名。
<application
android:name=".PushApplication"
...>
<!-- 保留应用原有配置。 -->
</application>
2.2 注册设备
设备注册会启动推送连接,可根据业务需要在满足应用隐私告知和授权要求后执行。调用 register 前须完成上一步初始化。未自定义推送服务进程时,在应用主进程中执行以下注册逻辑;已自定义推送服务进程时,在对应进程中执行。
final CloudPushService pushService = PushServiceFactory.getCloudPushService();
// 接入调试时开启日志和配置检查。
pushService.setLogLevel(CloudPushService.LOG_DEBUG);
pushService.setDebug(true);
pushService.register(this, new CommonCallback() {
@Override
public void onSuccess(String response) {
String deviceId = pushService.getDeviceId();
Log.d("PushDemo", "register success, deviceId=" + deviceId);
// 保存 deviceId,用于控制台或服务端定向推送。
}
@Override
public void onFailed(String errorCode, String errorMessage) {
Log.e("PushDemo", "register failed: " + errorCode + ", " + errorMessage);
}
});val pushService = PushServiceFactory.getCloudPushService()
// 接入调试时开启日志和配置检查。
pushService.setLogLevel(CloudPushService.LOG_DEBUG)
pushService.setDebug(true)
pushService.register(this, object : CommonCallback {
override fun onSuccess(response: String?) {
val deviceId = pushService.deviceId
Log.d("PushDemo", "register success, deviceId=$deviceId")
// 保存 deviceId,用于控制台或服务端定向推送。
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
Log.e("PushDemo", "register failed: $errorCode, $errorMessage")
}
})使用 register(Context, CommonCallback) 注册设备,并提供非空回调。收到 onSuccess 后,通过 getDeviceId() 获取设备标识,用于定向推送。
日志等级应在 init 之后、register 和厂商通道初始化之前设置。setDebug(true) 用于接入配置检查,不等同于开启 DEBUG 日志。上线前将日志等级调整为 LOG_ERROR,并关闭 setDebug。
更多初始化、设备标识、日志、接收方式设置请参见基础配置接口(4.x)。
3 配置通知通道和通知权限
3.1 创建通知通道
Android 8.0 及以上需要创建 NotificationChannel。以下示例在 Application 中创建通知通道;服务端推送时,AndroidNotificationChannel 参数须与客户端的 channelId 一致。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = getSystemService(NotificationManager.class);
String channelId = "push_default";
NotificationChannel channel = new NotificationChannel(
channelId, "消息通知", NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val manager = getSystemService(NotificationManager::class.java)
val channelId = "push_default"
val channel = NotificationChannel(
channelId, "消息通知", NotificationManager.IMPORTANCE_DEFAULT
)
manager.createNotificationChannel(channel)
}3.2 申请通知权限
Android 13 及以上需要申请 POST_NOTIFICATIONS 运行时权限。先在 AndroidManifest.xml 中声明权限,再在 Activity 的合适时机请求并处理授权结果。以下示例适用于 targetSdk 33 及以上的应用。
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
package com.example.pushdemo;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
public class MainActivity extends Activity {
private static final int REQUEST_NOTIFICATIONS = 1001;
// 在 Activity 中于用户主动开启推送等合适时机请求通知权限。
public void requestPushNotificationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(
new String[]{Manifest.permission.POST_NOTIFICATIONS},
REQUEST_NOTIFICATIONS);
}
}
@Override
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_NOTIFICATIONS) {
boolean granted = grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED;
Log.d("PushDemo", "notification permission granted=" + granted);
// 被拒绝时,按应用的交互设计说明通知能力受到限制。
}
}
}package com.example.pushdemo
import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
class MainActivity : Activity() {
private val requestNotifications = 1001
fun requestPushNotificationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) !=
PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(Manifest.permission.POST_NOTIFICATIONS), requestNotifications
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == requestNotifications) {
val granted = grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
Log.d("PushDemo", "notification permission granted=$granted")
}
}
}通知栏展示需要应用已获得通知权限,且应用通知开关和对应通知渠道均已开启。请分别验证权限状态、通知展示和透传消息回调。
4 消息接收配置
Android SDK 4.x 中,MessageReceiver 和 AliyunMessageIntentService 的业务回调范围如下:
ACCS 自有通道和 FCM:支持消息接收(onMessage)、通知到达(onNotification)、通知点击(onNotificationOpened)、通知清除(onNotificationRemoved)等完整业务回调。
除 FCM 外的其他 Android 厂商通道:仅支持 onNotificationOpened(通知点击),不触发消息接收、通知到达、通知清除等其他回调。
创建 MyMessageReceiver,继承 MessageReceiver 并覆盖所需回调。示例中的 PushDemo 是应用自定义日志 TAG,用于观察回调;SDK 日志使用 EMAS_PUSH TAG。
package com.example.pushdemo;
import android.content.Context;
import android.util.Log;
import com.alibaba.sdk.android.push.MessageReceiver;
import com.alibaba.sdk.android.push.notification.CPushMessage;
import java.util.Map;
public class MyMessageReceiver extends MessageReceiver {
private static final String TAG = "PushDemo";
@Override
public void onMessage(Context context, CPushMessage message) {
Log.d(TAG, "message received");
// 透传消息由应用处理,SDK 不会自动显示为通知。
}
@Override
public void onNotification(Context context, String title, String summary,
Map<String, String> extraMap) {
Log.d(TAG, "notification received");
}
@Override
public void onNotificationOpened(Context context, String title, String summary,
Map<String, String> extraMap) {
Log.d(TAG, "notification opened");
// 按业务需要处理通知点击,可从 extraMap 读取发送时设置的扩展参数。
}
@Override
public void onNotificationRemoved(Context context, String messageId) {
Log.d(TAG, "notification removed");
}
}package com.example.pushdemo
import android.content.Context
import android.util.Log
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) {
Log.d("PushDemo", "message received")
// 透传消息由应用处理。
}
override fun onNotification(
context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
) {
Log.d("PushDemo", "notification received")
}
override fun onNotificationOpened(
context: Context, title: String?, summary: String?, extraMap: Map<String, String>?
) {
Log.d("PushDemo", "notification opened")
// 按业务需要处理通知点击,可从 extraMap 读取发送时设置的扩展参数。
}
override fun onNotificationRemoved(context: Context, messageId: String?) {
Log.d("PushDemo", "notification removed")
}
}在 AndroidManifest.xml 的 application 节点中声明 Receiver。SDK 自身组件和基础权限由 AAR 的 Manifest 自动合并。
<application ...>
<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>
</application>
回调的线程和时机、通知显示控制,以及 AliyunMessageIntentService 接收方式请参见消息与通知处理接口(4.x)。接收回调中应避免耗时操作。
5 NDK 与混淆配置
5.1 NDK 配置
SDK 的传递依赖包含 libels.so 和 libjnidispatch.so,支持 arm64-v8a、armeabi-v7a、x86 和 x86_64。设置 abiFilters 或拆分 APK/AAB 时,须保留目标 ABI 下的上述库文件。
5.2 混淆与打包验证
4.0.0 主 SDK 及相关传递依赖已携带 consumer ProGuard 规则,通过 Maven 集成时自动合并。应用自身及厂商 SDK 如有额外混淆要求,请按对应文档配置。
使用开启混淆的 release 包验证初始化与收消息。遇到类或 native 库冲突时,可先通过依赖树定位重复依赖;同时检查最终 APK 是否包含目标 ABI 的库文件。
./gradlew :app:dependencies --configuration releaseRuntimeClasspath
./gradlew :app:assembleRelease
第三步:接入厂商通道
建议接入厂商通道,提高应用离线时的通知到达率。按所选通道完成厂商平台应用注册、EMAS 控制台参数配置、厂商 SDK 初始化及通知点击配置。
dependencies {
// 需要厂商通道时添加公共组件,并选择实际接入的适配组件。
implementation 'com.aliyun.ams:alicloud-android-third-push:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-xiaomi:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-huawei:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-honor:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-oppo:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-vivo:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-meizu:4.0.0'
// implementation 'com.aliyun.ams:alicloud-android-third-push-fcm:4.0.0'
}
主 SDK、辅助通道 SDK 及所选厂商扩展包统一使用 4.0.0。厂商原生 SDK 的版本由对应扩展包的 Maven 依赖管理。
按设备厂商选择厂商通道集成中的对应说明。小米、华为、荣耀、OPPO、vivo、魅族等厂商系统通知的点击需要完成辅助弹窗接入(4.x),并在 onNotificationOpened 中处理点击业务。FCM 的 data 消息由适配器转交移动推送 SDK 处理,不要求经过辅助弹窗 Activity。
第四步:接入验证
1 打开 SDK 日志
4.x SDK 日志统一使用 EMAS_PUSH TAG,模块信息写在日志正文。Android Studio Logcat 可使用 tag:EMAS_PUSH;命令行可执行以下命令。第三方 SDK 直接输出的日志和 Android 系统日志仍按各自 TAG 查询。
adb logcat -s EMAS_PUSH
调试时在 init 后、register 及厂商初始化前显式设置 LOG_DEBUG。setDebug(true) 用于接入检查,不等同于开启 DEBUG 日志。示例应用回调日志使用 PushDemo,可以同时过滤观察:
adb logcat -s EMAS_PUSH PushDemo
2 验证接入结果
|
验证项 |
操作与通过标准 |
|
依赖及组件 |
构建成功,最终包包含所需 AAR 组件、资源和 native 库;设备安装后无初始化崩溃。 |
|
设备注册 |
观察 register 成功回调并取得非空 deviceId;失败时记录 errorCode、errorMessage 并定位处理。 |
|
透传消息 |
在控制台向该 deviceId 发送一条消息,观察 onMessage;记录测试时间和消息标识核对本次请求。 |
|
通知展示 |
先经自有通道向同一 deviceId 发送通知,指定已创建的通知渠道;验证 onNotification、通知栏展示、系统权限和渠道开关。厂商通道按下方离线场景单独验证。 |
|
点击及删除 |
分别点击 ACCS 自有通道和厂商通道通知,检查 onNotificationOpened 和业务页面;仅针对 ACCS 自有通道和 FCM 通知验证 onNotificationRemoved。 |
|
厂商离线场景 |
每个已接入厂商分别验证通道注册、离线通知展示及点击跳转,确认服务端对应参数。 |
|
发布包 |
使用开启混淆的 release 包重复验证;验证前台、后台以及实际业务关心的进程状态。 |
接入验证包括设备注册、发送请求、通知接收、展示和点击。register 成功回调表示设备注册成功,发送接口成功表示请求已受理;请继续结合设备回调、通知栏和点击行为验证完整推送流程。
失败时参见错误处理(4.x);接口扩展见Android SDK 4.x API。