本文介绍如何快速将消息推送组件接入到 Android 客户端。消息推送支持 原生 AAR、mPaaS Inside 和 组件化(Portal & Bundle) 三种接入方式。
完整的接入过程分为以下五步:
- 添加 pushSDK:添加 SDK 依赖。
- 初始化 pushSDK:建立客户端和移动推送网关的长连接,获取设备标识。
- 监听消息:为接收消息、获取 Android 设备标识(Ad-token)编写 service,实现设备维度的消息推送。
- 上报用户 ID:将用户标识上传到服务端,进行用户和设备绑定,实现用户维度的消息推送。
- 上报推送数据:将消息到达、打开和忽略的数据上传至服务端进行统计分析,可在控制台页面上查看统计分析结果。
前置条件
- 已参考 通用步骤说明 完成基础配置。
- 若采用原生 AAR 方式接入,需要先 将 mPaaS 添加到项目。
- 若采用 mPaaS Inside 方式接入,需要先完成 mPaaS Inside 接入流程。
- 若采用组件化方式接入,需要先完成 组件化接入流程。
- 如果已经接入过 pushSDK,请检查一下工程是否引入了
pushservice
依赖。如果已经引入该依赖,则需要将其移除。 - 已通过 mPaaS 控制台获取
.config
配置文件。关于如何生成并下载配置文件,请参考 将配置文件添加到项目。
添加 pushSDK
添加 SDK 依赖。
原生 AAR 方式
参考 AAR 组件管理,通过 组件管理(AAR)在工程中安装 消息推送(PUSH)组件。
mPaaS Inside 方式
在工程中通过 组件管理 安装 消息推送(PUSH)组件。
更多信息,请参考 添加组件依赖。
组件化方式
在 Portal 和 Bundle 工程中通过 组件管理 安装 消息推送(PUSH)组件。
更多信息,请参考 添加组件依赖。
初始化 pushSDK
初始化 pushSDK,建立客户端和移动推送网关的长连接,获取设备标识。
客户端通过调用 mPaaS 中间层的 MPPush
类来实现对 pushSDK 的初始化:
MPPush.setup(Application application);
MPPush.init(Context context);
初始化过程中,pushSDK 会用设定好的地址和端口尝试建立连接。如果客户端建连信息中未携带设备标识,移动推送网关在建连成功后将下发设备标识(Ad-token)。
在 pushSDK 成功获取到设备标识后,您可以通过 App 中配置好的 service
来获取这个设备标识。具体方法,参考 监听消息 中的示例。
监听消息
在接收到推送消息,或者获取到 Ad-token 后,pushSDK 都会启动一个 service 来对该消息或该 Ad-token 进行处理。为接收消息、获取 Android 设备标识(Ad-token)编写 service,实现设备维度的消息推送。
关于此任务
通过编写和配置继承自 AliPushRcvService
的 service,用来接收移动推送网关下发的设备标识和消息。
操作步骤
-
编写 service。客户端可以分别为接收消息、获取 Ad-token 各编写一个 service,也可以共用同一个 service。下面是共用同一个 service 的示例代码:
public class PushMsgService extends AliPushRcvService {
private static final String TAG = "pushTag";
public static final String PUSH_SERVICE_ACTION = "tt-action";
//推送消息的类型,用户自定义即可
public static final int TYPE_MSG = -1;
public static final int TYPE_INNER_PUSH_INIT = -2;
public static final int TYPE_THIRD_PUSH_INIT = -3;
//自建渠道推送标识
public static String mAdToken = "";
//第三方渠道推送标识
public static String mThirdToken = "";
public static String mUserId = "mpaas_push_demo";
public static int platformType = 0;
public static boolean useDefault = false;
public PushMsgService() {
super();
}
/**
* 判断展示类消息是否使用内建通知。
* 返回true,则所有展示类(非静默)消息由mPaaS进行处理,handleActionReceived不再被调用。
* 返回false,表示透传所有消息。
*/
@Override
protected boolean useDefaultNotification(String msgKey, String msgValue) {
Intent intent = new Intent(PUSH_SERVICE_ACTION);
intent.putExtra("push_type", TYPE_MSG);
intent.putExtra("push_key", msgKey);
intent.putExtra("push_value", msgValue);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
LoggerFactory.getTraceLogger().debug(TAG, "onHandleIntent sendLocalBroadcast: " + intent.toString());
return useDefault;
}
/**
* 消息处理回调,自建消息需要接入方自行处理弹出通知等工作。
* @param msgKey 消息推送的 key
* @param msgValue 消息推送的 value
* @param clicked 是否已经点击了
* 对于三方渠道来说clicked = true,展示通知栏
* 对于自建渠道来说clicked = false,没有展示通知栏
*/
@Override
protected void handleActionReceived(String msgKey, String msgValue, boolean clicked) {
if (TextUtils.isEmpty(msgValue)) {
return;
}
BDataBean data = BDataBean.create(msgValue);
if (clicked) {
try {
Uri uri = Uri.parse(data.getUrl());
Intent actionIntent = new Intent(Intent.ACTION_VIEW);
actionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
actionIntent.setData(uri);
actionIntent.putExtra("data", data.getParams());
startActivity(actionIntent);
} catch (Exception e) {
Log.e(TAG, "Unable start activity due to wrong format uri", e);
}
} else {
// show your notification and handle action
NotificationHelper helper = new NotificationHelper(getApplicationContext());
helper.notify("(注意:非内建消息)" + data.getTitle(), data.getContent());
}
}
/**
* @param adToken 自建渠道的推送标识
*/
@Override
protected void handleActionId(String adToken) {
PushAppInfo pushAppInfo = new PushAppInfo(getApplicationContext());
pushAppInfo.setAppToken(adToken);
LoggerFactory.getTraceLogger().debug(TAG, "自建渠道的adToken: " + adToken);
Intent intent = new Intent(PUSH_SERVICE_ACTION);
intent.putExtra("push_type", TYPE_INNER_PUSH_INIT);
intent.putExtra("push_token", adToken);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
mAdToken = adToken;
}
/**
* @param thirdToken 三方渠道的推送标识
* @param platformType 三方渠道的类型 华为=5 小米=4 OPPO=7 VIVO=8
*/
@Override
protected void handleActionThirdId(String thirdToken, int platformType) {
LoggerFactory.getTraceLogger().debug(TAG, "第三方渠道的adToken: " + thirdToken + "platformType: " + platformType);
Intent intent = new Intent(PUSH_SERVICE_ACTION);
intent.putExtra("push_type", TYPE_THIRD_PUSH_INIT);
intent.putExtra("push_thirdToken", thirdToken);
intent.putExtra("push_channel", platformType);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
mThirdToken = thirdToken;
PushMsgService.platformType = platformType;
}
}
-
在
AndroidManifest.xml
配置此 service。基于 mPaaS 框架的工程,在 portal 或 bundle 的AndroidManifest.xml
中都可以配置。通配符说明:需要将代码中
${}
替换为真实的值。${applicationId}
:包名。
示例:将${applicationId}.push.action.CHECK
替换为com.mpaas.demo.push.action.CHECK
。${appId}
与${workspaceId}
:应用 ID 与工作空间 ID。在 mPaaS 控制台 > 总览 页面,点击 代码配置 > 下载配置文件,.config
文件包含了两者的值。<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- PushMsgService 是指前文代码中定义的 service -->
<service android:name="com.mpaas.demo.push.PushMsgService"
android:exported="false" >
<intent-filter>
<!-- MESSAGE_RECEIVED 表示处理接收到的消息-->
<action android:name="${applicationId}.push.action.MESSAGE_RECEIVED" />
<!--REGISTRATION_ID 表示处理获取到的设备标识-->
<action android:name="${applicationId}.push.action.REGISTRATION_ID" />
<category android:name="${applicationId}" />
</intent-filter>
</service>
<!-- 需要配置 alipush appId-->
<meta-data
android:name="ALIPUSH_APPID"
android:value="${appId}-${workspaceId}" />
<service
android:name="com.alipay.pushsdk.push.NotificationService"
android:enabled="true"
android:exported="false"
android:process=":push"
android:label="NotificationService">
<intent-filter>
<action android:name="${applicationId}.push.action.START_PUSHSERVICE" />
</intent-filter>
</service>
<service
android:name="com.alipay.pushsdk.push.AppInfoRecvIntentService"
android:exported="false"
android:process=":push">
</service>
<receiver
android:name="com.alipay.pushsdk.BroadcastActionReceiver"
android:enabled="true"
android:process=":push">
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
</intent-filter>
</receiver>
<receiver
android:name="com.alipay.mobile.logmonitor.ClientMonitorWakeupReceiver"
android:enabled="true"
android:process=":push">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="${applicationId}.push.action.CHECK" />
<action android:name="${applicationId}.monitor.command" />
</intent-filter>
</receiver>
-
可在控制台上创建极简推送类型的消息,测试基于设备维度的消息推送是否成功。
创建消息的操作方法,参见 创建消息 > 操作方法。
后续步骤
- 10.1.60 基线已支持内建通知消息,以满足展示类消息推送场景,具体方法参考 内建消息通知。
- 为了提升消息推送的到达率,您可以选择接入 Android 客户端三方推送渠道,具体方法参考 第三方推送渠道。
- pushSDK 支持基于用户标识的推送,可以选择将用户标识和设备标识进行绑定,具体方法参考 上报用户 ID。
上报用户 ID
如果需要用户维度的推送,当用户登录时,将该用户标识上传到服务端,由服务端向移动推送服务发出请求,将用户和设备进行绑定。当用户登出时,将该绑定关系解绑。
服务端的相关处理请参考 配置服务端。
操作步骤如下:
-
为了方便开发者进行用户绑定,提供接口进行绑定和解除绑定操作,示例代码如下:
// 具体代码可以参考 Demo
// 此处的用户 userId 不一定为开发者用户系统的真实标识,但是一定是可以与用户形成一一映射关系。
// 参数 userId,adtoken(会在 service handleActionId 中接收到)
ResultPbPB resultBean = MPPush.bind(getApplicationContext(), your userId, ad-token);
ResultPbPB resultBean = MPPush.unbind(getApplicationContext(), your userId, ad-token);
// 如果已经通过调用 MPLogger.reportUserLogin() 或 MPLogger.setUserId() 设置了 userId,也可以直接使用以下方法(版本须为 10.1.60.9 及以上,或 10.1.68.3 及以上)
ResultPbPB resultBean = MPPush.bind(getApplicationContext(), ad-token);
ResultPbPB resultBean = MPPush.unbind(getApplicationContext(), ad-token);
-
选择绑定时机,可选的关键时机如下:
- 用户登录(有登录态 App)和 push 收到 Ad-token 后,为了登录后首次接口收到 push。
- App 冷启动,为了防止出现未注册情形。
上报推送数据
PushSDK 定义消息到达、打开和忽略的接口,调用这些接口,上报相关数据至服务端。
到达
在接入 PushSDK 之后,无需执行任何操作,MPS 将自动完成消息到达相关数据的统计分析。
对于通过不同渠道推送的消息,MPS 采用不同的方式统计其到达量和到达率。
- 自建渠道
通过自建渠道推送的消息,在其到达客户端时,PushSDK 将自动上报消息到达事件,服务端自动统计消息的到达量以及到达率。 - 三方渠道
通过三方渠道推送的消息,由相应渠道的后端服务返回推送结果数据,MPS 对此数据进行统计分析,得到消息的到达量和到达率。
打开
调用 reportPushOpen
接口,上报消息打开事件,服务端将统计消息被打开的数量以及打开率。
public static void reportPushOpen(String pushMsgId, String pushMsgValue)
调用时机
对于三方渠道的通知栏消息以及需要自定义展示的消息,调用时机不同,具体如下:
- 三方渠道通知栏消息:消息被打开后,PushSDk 将自动调用
reportPushOpen
接口,上报相关数据。 - 自定义展示的消息:您需要添加消息打开操作的监听,监听到打开操作时,调用
reportPushOpen
接口,上报相关数据。
参数说明
pushMsgId
和 pushMsgValue
可从推送的消息体中获取,如下图所示。
- pushMsgId:对应于以上消息体中的
k
值,为消息 ID。 - pushMsgValue:对应于以上消息体中的
bData
值。
忽略
调用 reportPushIgnored
接口,上报消息的忽略事件,服务端将统计消息的忽略量以及忽略率。
public static void reportPushIgnored(String pushMsgId, String pushMsgValue)
调用时机
对于需要自定义展示的消息,您需要添加消息被忽略的监听,监听到消息被忽略时,调用 reportPushIgnored
接口,上报相关数据。
参数说明
参见上述 参数说明。
代码示例
点击此处 下载示例代码包。
后续操作
接入完成后,可以通过服务端调用 RESTful 接口,推送消息。具体内容请参考 服务端配置 > 推送消息。