Skip to main content

Android push notification integration

Last updated 10/07/2026

Automatic collection solution​

In the automatic collection solution, the SDK internally reports the push tokens and push message click events (te_ops_push_click) of each platform (currently FCM and JPush) automatically.

Integration process:

  1. Integrate the data collection SDK, version 3.0.1 or later
implementation 'cn.thinkingdata.android:ThinkingAnalyticsSDK:3.0.1'
  1. Integrate the auto-tracking plugin, and choose the plugin version based on the data collection SDK version: use 2.1.0 for SDK 3.0.1 to 3.1.0, and 2.2.0 for SDK versions later than 3.1.0
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'cn.thinkingdata.android:android-gradle-plugin2:2.1.0'
}
}

Configure the plugin parameters in the project's build.gradle file

apply plugin: 'cn.thinkingdata.android'
android {

}
  1. Enable automatic push collection
val config = TDConfig.getInstance(
this,
TA_APP_ID,
TA_SERVER_URL
)
//Enable automatic push collection
config.enableAutoPush()
TDAnalytics.init(config)
  1. Switch accounts

After switching accounts, call the login API. The SDK automatically reports the push token to the new account through the user_set API.

TDAnalytics.login("new_account_id")

1. FCM push​

Customize a FirebaseMessagingService. This solution works by hooking the onNewToken method of FirebaseMessagingService at compile time, so you need to provide this class.

class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onNewToken(@NonNull String token) {

}
}

Register it in the manifest file

<service
android:name="Custom Service"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

2. JPush​

Customize a JPushMessageReceiver. This solution works by hooking the onRegister method of JPushMessageReceiver at compile time, so you need to provide this class.

public class PushMessageReceiver extends JPushMessageReceiver {
@Override
public void onRegister(Context context, String registrationId) {

}
}

Register it in the manifest file

<receiver
android:name="Custom Receiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
<category android:name="Your app package name" />
</intent-filter>
</receiver>

Manual collection solution​

1. FCM push​

1.1 Report the "push ID"​

  • Upload the FCM token after calling AE login or switching accounts.
// Initialize the 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);
}
});
  • When the FCM token changes, update the user property:
@Override
public void onNewToken(@NonNull String token) {
JSONObject properties = new JSONObject();
properties.put("fcm_token",token);
TDAnalytics.userSet(properties);
}

1.2. Track push click events​

Upload the push click event when the user clicks the notification. You can get the push parameters in onCreate or 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. Handle push messages​

Use one of the following two solutions

  • Regular parameters: Call the handleTEPushAction method.
  • Passthrough parameters: Call the handleTEPassThroughAction method.
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");
//To handle regular parameters, call the following method
TEPushUtil.handleTEPushAction(teExtras);
//To handle passthrough parameters, call the following method
TEPushUtil.handleTEPassThroughAction(teExtras);
} catch (Exception e) {
e.printStackTrace();
}
}
}

2. JPush​

2.1 Report the "push ID"​

  • Upload the JPush Registration ID after calling AE login or switching accounts.
//Call after logging in or switching accounts
TDAnalytics.login("user_id");

JSONObject properties = new JSONObject();
properties.put("jiguang_id",JPushInterface.getRegistrationID(context));
//instance is the AE instance
TDAnalytics.userSet(properties);
  • Upload the JPush Registration ID in the onRegister API provided by JPush.
public class PushMessageReceiver extends JPushMessageReceiver {
@Override
public void onRegister(Context context, String registrationId) {
JSONObject properties = new JSONObject();
properties.put("jiguang_id",registrationId);
//instance is the AE instance
TDAnalytics.userSet(properties);
}
}

2.2. Track push click events​

For non-vendor channels, you can send the push click event in the onNotifyMessageOpened API.

public class PushMessageReceiver extends JPushMessageReceiver {

@Override
public void onNotifyMessageOpened(Context context, NotificationMessage message) {
//Send the notification click event in the notification click callback
String te_extras = TEPushUtil.getPushExtras(message.notificationExtra);
TEPushUtil.trackAppOpenNotification(te_extras);
}

}

When you use vendor channels, get the intent in onCreate and onNewIntent of the vendor channel Activity, parse the corresponding parameters, and then send the push click event.

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 channel message data
if (getIntent().getData() != null) {
pushData = getIntent().getData().toString();
}
// Xiaomi, vivo, OPPO, and FCM channel message data (Meizu calls back onNotifyMessageOpened )
if (TextUtils.isEmpty(pushData) && getIntent().getExtras() != null) {
pushData = getIntent().getExtras().getString("JMessageExtra");
}
if (TextUtils.isEmpty(pushData)) {
return;
}
JSONObject jsonObject = new JSONObject(pushData);
// Additional fields of the push message
String extras = jsonObject.optString("n_extras");
String te_extras = TEPushUtil.getPushExtras(extras);
TEPushUtil.trackAppOpenNotification(te_extras);
} catch (Exception e) {
e.printStackTrace();
}
}

}

2.3. Handle push messages​

Use one of the following two solutions

  • Regular parameters: Call the handleTEPushAction method.
  • Passthrough parameters: Call the handleTEPassThroughAction method.

For non-vendor channels, you can handle push messages in the onNotifyMessageOpened API.

public class PushMessageReceiver extends JPushMessageReceiver {

@Override
public void onNotifyMessageOpened(Context context, NotificationMessage message) {
//Handle push parameters in the notification click callback
String teExtras = TEPushUtil.getPushExtras(message.notificationExtra);
//To handle regular parameters, call the following method
TEPushUtil.handleTEPushAction(teExtras);
//To handle passthrough parameters, call the following method
TEPushUtil.handleTEPassThroughAction(teExtras);
}

}

When you use vendor channels, get the intent in onCreate and onNewIntent of the vendor channel Activity, parse the corresponding parameters, and then handle the push message.

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 channel message data
if (getIntent().getData() != null) {
pushData = getIntent().getData().toString();
}
// Xiaomi, vivo, OPPO, and FCM channel message data (Meizu calls back onNotifyMessageOpened )
if (TextUtils.isEmpty(pushData) && getIntent().getExtras() != null) {
pushData = getIntent().getExtras().getString("JMessageExtra");
}
if (TextUtils.isEmpty(pushData)) {
return;
}
JSONObject jsonObject = new JSONObject(pushData);
// Additional fields of the push message
String extras = jsonObject.optString("n_extras");
String teExtras = TEPushUtil.getPushExtras(extras);
//To handle regular parameters, call the following method
TEPushUtil.handleTEPushAction(teExtras);
//To handle passthrough parameters, call the following method
TEPushUtil.handleTEPassThroughAction(teExtras);
} catch (Exception e) {
e.printStackTrace();
}
}

}

Appendix​

Example of push parameters received by the client​

The following shows only the extended field parameters received by the client

{
"te_extras": {
//Jump mode when the push is clicked
"ops_loading_type": "OPEN_APP",
//Passthrough parameters
"passthrough_params": {
"param1": "abc",
"param2": 101,
"param3": [{
"subText1": "xyz",
"subText2": 2
}]
},
//AE operation channel receipt properties
"#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"
}
}
}

How do I verify that the customer's push collection is integrated successfully?​

  1. After integrating push, check whether the following events are reported on first launch or when the push token changes.
{
"#type": "user_set",
"#time": "2023-11-13 15:50:55.729",
"#distinct_id": "distinct",
"properties": {
"jiguang_id": "190e35f7e15c8481caa"
},
"#uuid": "9f233c31-a664-46ff-94d6-f767a3098c3a"
}
  1. Tap the push notification to launch the app, and check whether the te_ops_push_click event is uploaded and whether its event properties include 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);
//Report immediately
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 Handle the open App message --> launch the App
} else if ("OPEN_URL".equals(type)) {
String url = jsonObject.optString("ops_url");
if (!TextUtils.isEmpty(url)) {
// TODO Handle the open URL message --> handle the URL
}
} else if ("CUSTOMIZED".equals(type)) {
String custom = jsonObject.optString("ops_customized");
if (!TextUtils.isEmpty(custom)) {
// TODO Handle the custom message --> handle the custom message
}
}
} 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 is the passthrough parameter. Implement the specific business logic next
} catch (Exception e) {
e.printStackTrace();
}
}

TEPushUtil class​

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);
//Report immediately
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 Handle the open App message --> launch the App
} else if ("OPEN_URL".equals(type)) {
String url = jsonObject.optString("ops_url");
if (!TextUtils.isEmpty(url)) {
// TODO Handle the open URL message --> handle the URL
}
} else if ("CUSTOMIZED".equals(type)) {
String custom = jsonObject.optString("ops_customized");
if (!TextUtils.isEmpty(custom)) {
// TODO Handle the custom message --> handle the custom message
}
}
} 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 is the passthrough parameter. Implement the specific business logic next
} 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;
}

}
Was this page helpful?