Androidメッセージプッシュ統合ドキュメント
自動回収方式
自動回収方式とは、SDK内部で各プラットフォーム(現段階ではFCMとJPush)のプッシュtokenと、プッシュメッセージのクリックイベント(te_ops_push_click)を自動的に送信する方式です。
接続の流れ:
- データ収集SDKを導入します。バージョン3.0.1以上が必要です
implementation 'cn.thinkingdata.android:ThinkingAnalyticsSDK:3.0.1'
- 自動収集プラグインを導入します。プラグインのバージョンはデータ収集SDKのバージョンに応じて選択します:SDK 3.0.1~3.1.0は2.1.0、3.1.0より高いバージョンは2.2.0を使用します
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'cn.thinkingdata.android:android-gradle-plugin2:2.1.0'
}
}
プロジェクトのbuild.gradleファイルで、プラグイン関連のパラメータを設定します
apply plugin: 'cn.thinkingdata.android'
android {
}
- プッシュ連携の自動回収を有効にします
val config = TDConfig.getInstance(
this,
TA_APP_ID,
TA_SERVER_URL
)
//プッシュの自動回収を有効化
config.enableAutoPush()
TDAnalytics.init(config)
- アカウントの切り替え
アカウントを切り替えた後は、loginインターフェースを呼び出す必要があります。SDK内部で、プッシュtokenがuser_setインターフェースを通じて新しいアカウントに自動的に送信されます。
TDAnalytics.login("new_account_id")
1. FCMプッシュ
FirebaseMessagingServiceをカスタマイズします。この方式は、コンパイル時にFirebaseMessagingServiceのonNewTokenメソッドをhookする仕組みのため、このクラスを用意する必要があります。
class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onNewToken(@NonNull String token) {
}
}
manifestファイルに登録します
<service
android:name="カスタムservice"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
2. JPushプッシュ
JPushMessageReceiverをカスタマイズします。この方式は、コンパイル時にJPushMessageReceiverのonRegisterメソッドをhookする仕組みのため、このクラスを用意する必要があります。
public class PushMessageReceiver extends JPushMessageReceiver {
@Override
public void onRegister(Context context, String registrationId) {
}
}
manifestファイルに登録します
<receiver
android:name="カスタム Receiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
<category android:name="アプリのパッケージ名" />
</intent-filter>
</receiver>
手動回収方式
1. FCMプッシュ
1.1 「プッシュID」の送信
- AEのloginを呼び出した後、またはアカウントを切り替えた後に、FCMのTokenを送信します。
// AE SDKの初期化
TDAnalytics.init(this, APPID, SERVER_URL);
TDAnalytics.login("user_id");
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
JSONObject properties = new JSONObject();
properties.put("fcm_token",token);
TDAnalytics.userSet(properties);
}
});
- FCM Tokenが変更されたときに、ユーザープロパティを更新します:
@Override
public void onNewToken(@NonNull String token) {
JSONObject properties = new JSONObject();
properties.put("fcm_token",token);
TDAnalytics.userSet(properties);
}
1.2. プッシュクリックイベントの収集
ユーザーが通知をクリックしたときに、プッシュクリックイベントを送信します。プッシュパラメータはonCreateまたはonNewIntentで取得できます。
public class PushOpenClickActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handlePushOpen();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handlePushOpen();
}
private void handlePushOpen() {
try {
Intent intent = getIntent();
if (intent == null) {
return;
}
Bundle bundle = intent.getExtras();
if (bundle == null) {
return;
}
String teExtras = bundle.getString("te_extras");
TEPushUtil.trackAppOpenNotification(teExtras);
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.3. プッシュメッセージの処理
次の2つの方式のいずれかを選択することをお勧めします
- 通常パラメータ:handleTEPushActionメソッドを呼び出します。
- パススルーパラメータ:handleTEPassThroughActionメソッドを呼び出します。
public class PushOpenClickActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handlePushOpen();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handlePushOpen();
}
private void handlePushOpen() {
try {
Intent intent = getIntent();
if (intent == null) {
return;
}
Bundle bundle = intent.getExtras();
if (bundle == null) {
return;
}
String teExtras = bundle.getString("te_extras");
//通常パラメータを処理する場合は、次のメソッドを呼び出します
TEPushUtil.handleTEPushAction(teExtras);
//パススルーパラメータを処理する場合は、次のメソッドを呼び出します
TEPushUtil.handleTEPassThroughAction(teExtras);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. JPushプッシュ
2.1 「プッシュID」の送信
- AEのloginを呼び出した後、またはアカウントを切り替えた後に、JPushのRegistration IDを送信します。
//ログインまたはアカウントの切り替え後に呼び出します
TDAnalytics.login("user_id");
JSONObject properties = new JSONObject();
properties.put("jiguang_id",JPushInterface.getRegistrationID(context));
//instance は AE インスタンスです
TDAnalytics.userSet(properties);
- JPushが提供するonRegisterインターフェースで、JPushのRegistration IDを送信します。
public class PushMessageReceiver extends JPushMessageReceiver {
@Override
public void onRegister(Context context, String registrationId) {
JSONObject properties = new JSONObject();
properties.put("jiguang_id",registrationId);
//instance は AE インスタンスです
TDAnalytics.userSet(properties);
}
}
2.2. プッシュクリックイベントの収集
メーカーチャネル以外では、onNotifyMessageOpenedインターフェースでプッシュクリックイベントを送信できます。
public class PushMessageReceiver extends JPushMessageReceiver {
@Override
public void onNotifyMessageOpened(Context context, NotificationMessage message) {
//通知クリックのコールバックで通知クリックイベントを送信します
String te_extras = TEPushUtil.getPushExtras(message.notificationExtra);
TEPushUtil.trackAppOpenNotification(te_extras);
}
}
メーカーチャネルを使用する場合は、メーカーチャネルのActivityのonCreate、onNewIntentでintentを取得し、対応するパラメータを解析してからプッシュクリックイベントを送信する必要があります。
public class PushOpenClickActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handlePushOpen();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handlePushOpen();
}
private void handlePushOpen() {
try {
Intent intent = getIntent();
if (intent == null) {
return;
}
String pushData = null;
// Huawei チャネルのメッセージデータ
if (getIntent().getData() != null) {
pushData = getIntent().getData().toString();
}
// Xiaomi、vivo、OPPO、FCM チャネルのメッセージデータ(Meizu は onNotifyMessageOpened がコールバックされます)
if (TextUtils.isEmpty(pushData) && getIntent().getExtras() != null) {
pushData = getIntent().getExtras().getString("JMessageExtra");
}
if (TextUtils.isEmpty(pushData)) {
return;
}
JSONObject jsonObject = new JSONObject(pushData);
// プッシュメッセージの追加フィールド
String extras = jsonObject.optString("n_extras");
String te_extras = TEPushUtil.getPushExtras(extras);
TEPushUtil.trackAppOpenNotification(te_extras);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.3. プッシュメッセージの処理
次の2つの方式のいずれかを選択することをお勧めします
- 通常パラメータ:handleTEPushActionメソッドを呼び出します。
- パススルーパラメータ:handleTEPassThroughActionメソッドを呼び出します。
メーカーチャネル以外では、onNotifyMessageOpenedインターフェースでプッシュメッセージを処理できます。
public class PushMessageReceiver extends JPushMessageReceiver {
@Override
public void onNotifyMessageOpened(Context context, NotificationMessage message) {
//通知クリックのコールバックでプッシュパラメータを処理します
String teExtras = TEPushUtil.getPushExtras(message.notificationExtra);
//通常パラメータを処理する場合は、次のメソッドを呼び出します
TEPushUtil.handleTEPushAction(teExtras);
//パススルーパラメータを処理する場合は、次のメソッドを呼び出します
TEPushUtil.handleTEPassThroughAction(teExtras);
}
}
メーカーチャネルを使用する場合は、メーカーチャネルのActivityのonCreate、onNewIntentでintentを取得し、対応するパラメータを解析してからプッシュメッセージを処理する必要があります。
public class PushOpenClickActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handlePushOpen();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handlePushOpen();
}
private void handlePushOpen() {
try {
Intent intent = getIntent();
if (intent == null) {
return;
}
String pushData = null;
// Huawei チャネルのメッセージデータ
if (getIntent().getData() != null) {
pushData = getIntent().getData().toString();
}
// Xiaomi、vivo、OPPO、FCM チャネルのメッセージデータ(Meizu は onNotifyMessageOpened がコールバックされます)
if (TextUtils.isEmpty(pushData) && getIntent().getExtras() != null) {
pushData = getIntent().getExtras().getString("JMessageExtra");
}
if (TextUtils.isEmpty(pushData)) {
return;
}
JSONObject jsonObject = new JSONObject(pushData);
// プッシュメッセージの追加フィールド
String extras = jsonObject.optString("n_extras");
String teExtras = TEPushUtil.getPushExtras(extras);
//通常パラメータを処理する場合は、次のメソッドを呼び出します
TEPushUtil.handleTEPushAction(teExtras);
//パススルーパラメータを処理する場合は、次のメソッドを呼び出します
TEPushUtil.handleTEPassThroughAction(teExtras);
} catch (Exception e) {
e.printStackTrace();
}
}
}
付録
クライアントが受信するプッシュパラメータの例
以下は、クライアントが受信する拡張フィールドのパラメータのみを示しています
{
"te_extras": {
//プッシュクリック時の遷移方式
"ops_loading_type": "OPEN_APP",
//パススルーパラメータ
"passthrough_params": {
"param1": "abc",
"param2": 101,
"param3": [{
"subText1": "xyz",
"subText2": 2
}]
},
//AE運用チャネルのレシートプロパティ
"#ops_receipt_properties": {
"ops_task_id": "0082",
"ops_project_id": 1,
"ops_task_instance_id": "0082_20230331",
"ops_push_language": "default",
"ops_task_exec_detail_id": "55"
}
}
}
プッシュ回収フローの接続が成功したことを確認するには?
- プッシュを接続した後、初回起動時またはプッシュtokenの変更時に、次のイベントが送信されるかどうかを確認します。
{
"#type": "user_set",
"#time": "2023-11-13 15:50:55.729",
"#distinct_id": "distinct",
"properties": {
"jiguang_id": "190e35f7e15c8481caa"
},
"#uuid": "9f233c31-a664-46ff-94d6-f767a3098c3a"
}
- プッシュ通知をクリックしてアプリを起動し、te_ops_push_clickイベントが送信されるか、イベントプロパティにops_receipt_propertiesが含まれているかを確認します。
{
"#type": "track",
"#time": "2023-03-16 16:08:32.191",
"#distinct_id": "90d80464-6832-43f1-80d9-bd93fc09c4fe",
"#event_name": "te_ops_push_click",
"properties": {
"#lib_version": "3.0.1-beta.1",
"#carrier": "中国移动",
"#os": "Android",
"#device_id": "6262ca7f71e6aca3",
"#screen_height": 2400,
"#bundle_id": "cn.thinkingdata.random",
"#device_model": "M2012K11AC",
"#screen_width": 1080,
"#system_language": "zh",
"#install_time": "2023-03-10 11:24:44.285",
"#simulator": false,
"#lib": "Android",
"#manufacturer": "Xiaomi",
"#os_version": "11",
"#app_version": "1.0",
"#fps": 60,
"#network_type": "WIFI",
"#ram": "2.7\/7.4",
"#disk": "4.6\/106.3",
"#device_type": "Phone",
"ops_receipt_properties": {
"ops_project_id": 1,
"ops_request_id": "3b21d2a8-8d3d-44fa-b460-3bb311ed3bcd"
},
"#zone_offset": 8
},
"#uuid": "7a977e23-b78a-4433-baae-ead17ad2fde9"
}
trackAppOpenNotification
public static void trackAppOpenNotification(String extras) {
try {
if (TextUtils.isEmpty(extras)) {
return;
}
JSONObject jsonObject = new JSONObject(extras);
JSONObject properties = new JSONObject();
Object obj = jsonObject.opt("#ops_receipt_properties");
JSONObject ops = null;
if (obj instanceof String) {
ops = new JSONObject(( String ) obj);
} else if (obj instanceof JSONObject) {
ops = ( JSONObject ) obj;
}
properties.put("#ops_receipt_properties", ops);
TDAnalytics.track("te_ops_push_click", properties);
//すぐに送信
TDAnalytics.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
handleTEPushAction
public static void handleTEPushAction(String extras) {
try {
if (TextUtils.isEmpty(extras)) {
return;
}
JSONObject jsonObject = new JSONObject(extras);
String type = jsonObject.optString("ops_loading_type");
if ("OPEN_APP".equals(type)) {
// TODO App を開くメッセージの処理、--> App を起動してください
} else if ("OPEN_URL".equals(type)) {
String url = jsonObject.optString("ops_url");
if (!TextUtils.isEmpty(url)) {
// TODO URL を開くメッセージの処理、--> URL を処理してください
}
} else if ("CUSTOMIZED".equals(type)) {
String custom = jsonObject.optString("ops_customized");
if (!TextUtils.isEmpty(custom)) {
// TODO カスタムメッセージの処理、--> カスタムメッセージを処理してください
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
handleTEPassThroughAction
public static void handleTEPassThroughAction(String extras) {
try {
if (TextUtils.isEmpty(extras)) {
return;
}
JSONObject jsonObject = new JSONObject(extras);
String params = jsonObject.optString("passthrough_params");
//params はパススルーパラメータです。以降で具体的な業務ロジックを実装します
} catch (Exception e) {
e.printStackTrace();
}
}
TEPushUtilクラス
public class TEPushUtil {
public static void trackAppOpenNotification(String extras) {
try {
if (TextUtils.isEmpty(extras)) {
return;
}
JSONObject jsonObject = new JSONObject(extras);
JSONObject properties = new JSONObject();
Object obj = jsonObject.opt("#ops_receipt_properties");
JSONObject ops = null;
if (obj instanceof String) {
ops = new JSONObject(( String ) obj);
} else if (obj instanceof JSONObject) {
ops = ( JSONObject ) obj;
}
properties.put("#ops_receipt_properties", ops);
TDAnalytics.track("te_ops_push_click", properties);
//すぐに送信
TDAnalytics.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void handleTEPushAction(String extras) {
try {
if (TextUtils.isEmpty(extras)) {
return;
}
JSONObject jsonObject = new JSONObject(extras);
String type = jsonObject.optString("ops_loading_type");
if ("OPEN_APP".equals(type)) {
// TODO App を開くメッセージの処理、--> App を起動してください
} else if ("OPEN_URL".equals(type)) {
String url = jsonObject.optString("ops_url");
if (!TextUtils.isEmpty(url)) {
// TODO URL を開くメッセージの処理、--> URL を処理してください
}
} else if ("CUSTOMIZED".equals(type)) {
String custom = jsonObject.optString("ops_customized");
if (!TextUtils.isEmpty(custom)) {
// TODO カスタムメッセージの処理、--> カスタムメッセージを処理してください
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void handleTEPassThroughAction(String extras) {
try {
if (TextUtils.isEmpty(extras)) {
return;
}
JSONObject jsonObject = new JSONObject(extras);
String params = jsonObject.optString("passthrough_params");
//params はパススルーパラメータです。以降で具体的な業務ロジックを実装します
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getPushExtras(Object notificationExtras) {
String teExtras = "";
try {
if (notificationExtras != null) {
if (notificationExtras instanceof String) {
teExtras = new JSONObject((String) notificationExtras).optString("te_extras");
} else if (notificationExtras instanceof Map) {
teExtras = new JSONObject((Map) notificationExtras).optString("te_extras");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return teExtras;
}
}

