和尚之前因业务需求, 配合过推送平台的相关搭建, 其中涉及过 友盟 UmengPush, 极光 JPush, 个推, 公司自建 UPDPush, 华为 HMS, 小米 MiPush,OPPO Push 和 VIVO Push 等; 今天借 腾讯云 活动, 简单了解一下 腾讯移动通讯 TPNS;
和尚了解 腾讯移动通讯 TPNS 前身是腾讯信鸽, 前期经过长期等技术沉淀积累了良好的口碑; 现在由免费转为付费, 相信会提供更优质的服务; 而精准用户标签是 TPNS 的一个巨大优势;
1. TPNS 基本介绍
TPNS 为移动推送 Tencent Push Notification Service 首字母缩写, 为 App 提供稳定, 快速, 高抵达的推送服务; 具备多种推送形式和方式, 支持小米, 华为, 魅族, vivo,OPPO 等国内主流厂商通道集成, Google 境外支持 FCM 通道, 可以做到单推毫秒级抵达; 其具备精准用户标签能力, 有效助力 App 的精细化运营;
2. TPNS 集成
接下来和尚简单介绍一下 TPNS 的集成, 据和尚了解, 一般的 Push 接入方式主要是 Gradle 自动集成 和 jar 手动集成 两种; 特殊的还有华为 Push 通过 config 方式导入配置方式等; 而令和尚意外的是 TPNS 支持三种方式的接入;
和尚主要介绍 config 和 Gradle 自动集成两种方式; 两种集成方式都非常简单, 同时和尚不得不夸赞一下官网的接入文档, 真的非常人性化;
2.1 config 导入配置项
a. 在 TPNS[基本配置] 中下载对应 App 的配置文件, 并添加在 App 根目录下;
b. 在项目级 build.gradle 中添加配置信息;
- buildscript {
- ......
- dependencies {
- classpath 'com.android.tools.build:gradle:3.2.1'
- classpath "com.tencent.android.tpns:tpnsplugin:1.7.0"
- }
- }
- allprojects {
- repositories {
- ......
- maven { url 'https://dl.bintray.com/umsdk/release' }
- maven {url 'http://developer.huawei.com/repo/'}
- }
- }
c. 在应用级 App build.gradle 中添加依赖;
d. 配置混淆文件;
- -keep public class \* extends Android.App.Service
- -keep public class \* extends Android.content.BroadcastReceiver
- -keep class com.tencent.Android.tpush.\*\* {
- \*;
- }
- -keep class com.tencent.tpns.baseapi.\*\* {
- \*;
- }
- -keep class com.tencent.tpns.mqttchannel.\*\* {
- \*;
- }
- -keep class com.tencent.tpns.dataacquisition.\*\* {
- \*;
- }
2.2 Gradle 自动集成
a. 在 TPNS[基本配置] 中获取对应 App 的 ID 和 KEY;
b. 在 App build.gradle 文件下配置 ID 和 KEY 以及 SDK 版本;
- Android {
- ......
- defaultConfig {
- applicationId "com.ace.demo01"
- ......
- ndk {
- abiFilters "armeabi", "armeabi-v7a"
- }
- manifestPlaceholders =
- XG\_ACCESS\_ID : "1500018288",
- XG\_ACCESS\_KEY : "AYFMNKBGT92Z",
- multiDexEnabled true
- }
- ......
- }
- dependencies {
- ......
- // 添加以下依赖
- implementation 'com.tencent.jg:jg:1.1'
- implementation 'com.tencent.tpns:tpns:1.2.3.1-release'
- }
c. 配置混淆文件;
3. TPNS 应用
上述只是对 TPNS 的简单集成, 对于应用还需要初始化以及接收推送等一系列业务操作; 还可以进行一系列复杂操作, 比如根据标签自定义定量定向发送 Push 等; 和尚仅根据最基础需求进行学习测试;
3.1 初始化获取 Token
集成 TPNS 之后都需要初始化, 其中 Token 作为唯一标识可以通过 registerPush 初始化获取, 也可以通过继承 XGPushBaseReceiver 广播并在 onRegisterResult 回调中进行监听;
- XGPushManager.registerPush(this, new XGIOperateCallback() {
- @Override
- public void onSuccess(Object data, int flag) {
- //token 在设备卸载重装的时候有可能会变
- Log.d("TPush:", "注册成功, 设备 token 为:" + data);
- }
- @Override
- public void onFail(Object data, int errCode, String msg) {
- Log.d("TPush:", "注册失败, 错误码:" + errCode + ", 错误信息:" + msg);
- }
- });
- @Override
- public void onRegisterResult(Context context, int errorCode, XGPushRegisterResult message) {
- if (context == null || message == null) {
- return;
- }
- String text = "";
- if (errorCode == XGPushBaseReceiver.SUCCESS) {
- // 在这里拿 token
- String token = message.getToken();
- text = "注册成功 1. token:" + token;
- } else {
- text = message + "注册失败, 错误码:" + errorCode;
- }
- Log.d(LogTag, text);
- }
XGPushBaseReceiver 用于接收消息和结果反馈的 Receiver, 需要开发者在 AndroidManifest.xml 自主完成静态注册; 不管是通知类 Push 还是透传类 Push 均需通过 XGPushBaseReceiver 中的回调来处理;
3.2 通知类 Push
首先我们需要了解 通知类 Push 发布平台, 里面涉及很多内容, 其中有几点需要注意:
[通知标题] 和 [通知内容] 对应推送消息中展示内容;
[高级设置] 里面可以通过 [附加参数] 传递标题和内容之外的其他消息内容, 供用户自定义;
[推送时间] 可以设置立即或延迟推送;
[推送目标] 可以发布全量 Push 或根据地理围栏定向推送以及根据 Token 固定设备推送;
[角标数字] 在华为和小米手机开启角标通知权限之后, 会自动增加一, 而无需用户自己适配, 减轻了开发者工作量;
[点击打开] TPNS 提供了四种点击 Push 后续操作方式, 分别是仅打开应用 App; 客户端自定义, 此时需要在清单文件中设置 Intent 配置信息; URL 网络路径; 应用内 Activity, 但官方并不推荐使用, 需要设置 Activity 的完整路径;
通知类 Push 收到和点击事件通过 XGPushBaseReceiver 回调进行监听; onNotificationShowedResult 为通知类 Push 展示回调, 但和尚反复测试, 通知类 Push 中标题和内容只能是 XGPushShowedResult.getTitle() 和 XGPushShowedResult.getContent() 对应内容, 无法更改; onNotificationClickedResult 为通知类 Push 点击时回调, 业务处理主要是在该回调方法中完成;
- /**
- * 通知展示
- * @param notifiShowedRlt 包含通知的内容
- */
- @Override
- public void onNotificationShowedResult(Context context, XGPushShowedResult notifiShowedRlt) {
- if (context == null || notifiShowedRlt == null) {
- return;
- }
- Log.e("通知类 Push", "onNotificationShowedResult\n"
- + notifiShowedRlt.getCustomContent()
- + "\n"
- + notifiShowedRlt.getPushChannel()
- + "\n"
- + notifiShowedRlt.getNotifactionId()
- + "\n"
- + notifiShowedRlt.toString());
- Log.d(LogTag, "您有 1 条新消息, 通知被展示;" + notifiShowedRlt.toString() + ", PushChannel:" + notifiShowedRlt.getPushChannel());
- }
- /**
- * 通知点击回调
- * actionType=1 为该消息被清除, actionType=0 为该消息被点击
- * @param message 包含被点击通知的内容
- */
- @Override
- public void onNotificationClickedResult(Context context, XGPushClickedResult message) {
- if (context == null || message == null) {
- return;
- }
- String text = "";
- if (message.getActionType() == NotificationAction.clicked.getType()) {
- // 通知在通知栏被点击
- // App 自己处理点击的相关动作
- text = "通知被打开 :" + message;
- } else if (message.getActionType() == NotificationAction.delete.getType()) {
- // 通知被清除
- // App 自己处理通知被清除后的相关动作
- text = "通知被清除 :" + message;
- }
- Toast.makeText(context, "广播接收到通知被点击:" + message.toString(), Toast.LENGTH_SHORT).show();
- // 获取自定义 key-value
- String customContent = message.getCustomContent();
- if (customContent != null && customContent.length() != 0) {
- try {
- JSONObject obj = new JSONObject(customContent);
- if (!obj.isNull("extras")) {
- PushInfo pushInfo = new Gson().fromJson(obj.getString("extras"), PushInfo.class);
- if (pushInfo != null) {
- Log.e("PushInfo:", pushInfo.title + pushInfo.desc);
- }
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- Intent intent = new Intent(context, PageActivity.class);
- intent.putExtra("pushInfo", customContent);
- intent.putExtra("from", "通知类消息");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.getApplicationContext().startActivity(intent);
- }
对于通知类 Push 点击的操作, TPNS 提供了四种默认的方式, 但和尚为了适配其他的 Push 类型, 调整了点击后的操作, 默认为启动 App, 之后的业务逻辑通过解析 [附加参数] 来进行不同的业务处理; 例如根据某一个字段不同进行不同页面的跳转等;
3.3 透传类 Push
透传类消息后台相对于通知类型要简单, 主要区分在 [高级设置] 中, 透传类因厂商限制, 不能通过厂商通道下发, 仅通过 TPNS 通道下发; 且透传类消息下发之后不会出现 Notification, 需要自己根据业务来处理;
- /**
- * 消息透传处理
- * @param message 解析自定义的 JSON
- */
- @Override
- public void onTextMessage(Context context, XGPushTextMessage message) {
- String text = "收到消息:" + message.toString();
- // 获取自定义 key-value
- String customContent = message.getCustomContent();
- PushInfo pushInfo = Utils.getPushInfo(customContent);
- showNotification(context, getNotification(context, pushInfo, customContent));
- }
- public static Notification getNotification(Context context, PushInfo pushInfo, String msg) {
- Notification notification = null;
- try {
- Intent intent = new Intent(context, PageActivity.class);
- intent.putExtra("pushInfo", msg);
- intent.putExtra("from", "透传类消息");
- PendingIntent pendingIntent =
- PendingIntent.getActivity(context, new java.util.Random().nextInt(1000), intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "ace_push");
- notificationBuilder.setContentIntent(pendingIntent);
- notificationBuilder.setContentText(pushInfo.desc);
- notificationBuilder.setContentTitle(pushInfo.title);
- notificationBuilder.setSmallIcon(R.mipmap.icon_logo);
- notificationBuilder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.icon_logo));
- notificationBuilder.setAutoCancel(true);
- notificationBuilder.setOngoing(false);
- notificationBuilder.setWhen(System.currentTimeMillis());
- notificationBuilder.setDefaults(Notification.DEFAULT_ALL);
- notification = notificationBuilder.build();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return notification;
- }
- public void showNotification(Context context, Notification notification) {
- NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- if (manager != null) {
- manager.notify(new java.util.Random().nextInt(1000), notification);
- }
- }
和尚为了适配多种类型推送消息, 通过解析 [高级设置] 中的 [附加参数] 中的 JSON 来展示通知栏消息;
Notification 展示在 Android8.0 之后需要设置 NotificationChannel 通道;
App kill 状态下不会收到透传类消息, 需要启动应用之后才会收到消息, 包括历史消息;
4. TPNS 小对比
和尚尝试了多家推送模块, 简单分析如下:
优势:
TPNS 集成方式最为丰富和简单;
TPNS 中的定向标签丰富, 推送精准, 方便进行更精细化的运营;
TPNS 统计后台做的最为丰富全面; 可以实时统计推送的抵达, 展示, 点击效果等数据口径, 并将以上数据在管理台可视化地展现出来;
不足:
TPNS 付费模式可能会损失一些中小型 App 用户;
TPNS 通知类消息未提供消息送达的回调方法, 对于 App 自身维度的统计略有不便;
TPNS 未提及类似 [极光轻推送] 之类的辅助激活唤醒老用户的功能;
5. TPNS 小建议
TPNS 已经积累了足够的技术沉淀, 使用也非常简单, 官方文档介绍的非常详细; 和尚作为最底层的码农, 仅就集成使用过程中提出一点点小小的个人见解, 如有错误, 请多多指导!
1.XGPushBaseReceiver 中是否可以减少抽象方法, 对于用户不需要的业务模块, 每次实现所有的抽象方法是否略微有些冗余;
- public abstract void onRegisterResult(Context var1, int var2, XGPushRegisterResult var3);
- public abstract void onUnregisterResult(Context var1, int var2);
- public abstract void onSetTagResult(Context var1, int var2, String var3);
- public abstract void onDeleteTagResult(Context var1, int var2, String var3);
- public abstract void onSetAccountResult(Context var1, int var2, String var3);
- public abstract void onDeleteAccountResult(Context var1, int var2, String var3);
- public abstract void onSetAttributeResult(Context var1, int var2, String var3);
- public abstract void onDeleteAttributeResult(Context var1, int var2, String var3);
- public abstract void onTextMessage(Context var1, XGPushTextMessage var2);
- public abstract void onNotificationClickedResult(Context var1, XGPushClickedResult var2);
- public abstract void onNotificationShowedResult(Context var1, XGPushShowedResult var2);
2. 通知类消息在通知栏中的标题和内容无法通过 [高级设置] 中的 [附加参数] 来更改; 如果用户可以自由的定义设置就更方便了;
3. 服务后台中的 [推送任务] 在历史任务列表中, 如果有 [复用] 的功能的话, 会大大减轻开发测试和运营同学的工作量; 这个功能在友盟和极光等推送平台都有, 真的很方便;
- Umeng
- JPush
- TPNS
4. 希望 TPNS 可以提供类似 [极光轻推送] 辅助激活唤醒老用户的功能;
和尚仅尝试了 TPNS 最基础的推送功能, 对于高级的用户标签暂未涉及, 同时对 [实时推送效果分析] 后台观察不足; 同时涉及到其他厂商的推送模块, 和尚仅以基础程序员角度学习和了解, 并未涉及任何商业优劣区分; 如有错误, 请多多指导!
来源: https://www.qcloud.com/developer/article/1809526