初識騰訊移動通訊 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 中添加配置信息

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 小對比

    小菜嘗試了多家推送模塊,簡單分析如下:

優勢:

  1. TPNS 集成方式最爲豐富和簡單;
  2. TPNS 中的定向標籤豐富,推送精準,方便進行更精細化的運營;
  3. TPNS 統計後臺做的最爲豐富全面;可以實時統計推送的抵達、展示、點擊效果等數據口徑,並將以上數據在管理臺可視化地展現出來;

不足:

  1. TPNS 付費模式可能會損失一些中小型 app 用戶;
  2. TPNS 通知類消息未提供消息送達的回調方法,對於 app 自身維度的統計略有不便;
  3. 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);
  1. 通知類消息在通知欄中的標題和內容無法通過【高級設置】中的【附加參數】來更改;如果用戶可以自由的定義設置就更方便了;
  2. 服務後臺中的【推送任務】在歷史任務列表中,如果有【複用】的功能的話,會大大減輕開發測試和運營同學的工作量;這個功能在友盟和極光等推送平臺都有,真的很方便;



  1. 希望 TPNS 可以提供類似【極光輕推送】輔助激活喚醒老用戶的功能;

    小菜僅嘗試了 TPNS 最基礎的推送功能,對於高級的用戶標籤暫未涉及,同時對【實時推送效果分析】後臺觀察不足;同時涉及到其他廠商的推送模塊,小菜僅以基礎程序員角度學習和了解,並未涉及任何商業優劣區分;如有錯誤,請多多指導!

來源: 阿策小和尚

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章