【玩转腾讯云】初识腾讯移动通讯 TPNS~

    和尚之前因业务需求,配合过推送平台的相关搭建,其中涉及过 友盟 UmengPush极光 JPush个推公司自建 UPDPush华为 HMS小米 MiPushOPPO PushVIVO Push 等;今天借 腾讯云 活动,简单了解一下 腾讯移动通讯 TPNS

    和尚了解 腾讯移动通讯 TPNS 前身是腾讯信鸽,前期经过长期等技术沉淀积累了良好的口碑;现在由免费转为付费,相信会提供更优质的服务;而精准用户标签是 TPNS 的一个巨大优势;

1. TPNS 基本介绍

    TPNS 为移动推送 Tencent Push Notification Service 首字母缩写,为 app 提供稳定、快速、高抵达的推送服务;具备多种推送形式和方式,支持小米、华为、魅族、vivoOPPO 等国内主流厂商通道集成,Google 境外支持 FCM 通道,可以做到单推毫秒级抵达;其具备精准用户标签能力,有效助力 app 的精细化运营;

2. TPNS 集成

    接下来和尚简单介绍一下 TPNS 的集成,据和尚了解,一般的 Push 接入方式主要是 Gradle 自动集成jar 手动集成 两种;特殊的还有华为 Push 通过 config 方式导入配置方式等;而令和尚意外的是 TPNS 支持三种方式的接入;

    和尚主要介绍 configGradle 自动集成两种方式;两种集成方式都非常简单,同时和尚不得不夸赞一下官网的接入文档,真的非常人性化;

2.1 config 导入配置项
  • a. 在 TPNS【基本配置】中下载对应 app 的配置文件,并添加在 app 根目录下
  • b. 在项目级 build.gradle 中添加配置信息
代码语言:txt
复制
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. 配置混淆文件
代码语言:txt
复制
-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 版本
代码语言:txt
复制
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 回调中进行监听;

代码语言:txt
复制
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 点击时回调,业务处理主要是在该回调方法中完成;

代码语言:txt
复制
/**

  • 通知展示
  • @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,需要自己根据业务来处理;

代码语言:txt
复制
/**

  • 消息透传处理

  • @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 小对比

        和尚尝试了多家推送模块,简单分析如下:

    优势:
    1. TPNS 集成方式最为丰富和简单;
    2. TPNS 中的定向标签丰富,推送精准,方便进行更精细化的运营;
    3. TPNS 统计后台做的最为丰富全面;可以实时统计推送的抵达、展示、点击效果等数据口径,并将以上数据在管理台可视化地展现出来;
    不足:
    1. TPNS 付费模式可能会损失一些中小型 app 用户;
    2. TPNS 通知类消息未提供消息送达的回调方法,对于 app 自身维度的统计略有不便;
    3. TPNS 未提及类似【极光轻推送】之类的辅助激活唤醒老用户的功能;

    5. TPNS 小建议

        TPNS 已经积累了足够的技术沉淀,使用也非常简单,官方文档介绍的非常详细;和尚作为最底层的码农,仅就集成使用过程中提出一点点小小的个人见解,如有错误,请多多指导!

    1.XGPushBaseReceiver 中是否可以减少抽象方法,对于用户不需要的业务模块,每次实现所有的抽象方法是否略微有些冗余;

    代码语言:txt
    复制
    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 最基础的推送功能,对于高级的用户标签暂未涉及,同时对【实时推送效果分析】后台观察不足;同时涉及到其他厂商的推送模块,和尚仅以基础程序员角度学习和了解,并未涉及任何商业优劣区分;如有错误,请多多指导!

    来源: 阿策小和尚