Android

Overview

IM terminal users need to obtain the latest messages at any time. However, considering the limited performance and battery SOC of mobile devices, IM recommends you use the system-grade push channels provided by vendors for message notifications when the app is running in the background to avoid excessive resource consumption caused by maintaining a persistent connection. Compared with third-party push channels, system-grade push channels provide more stable system-grade persistent connections, enabling users to receive push messages at any time and greatly reducing resource consumption.
Caution
If you want users to receive IM message notifications when, without proactive logout, the app is switched to the background, the mobile phone screen is locked, or the app process is killed by a user, you can enable the IM offline push.
If the logout API is called to log out proactively or you are forced to log out due to multi-device login, you cannot receive offline push messages even though IM offline push is enabled.

Running the demo for offline push

The TUIKit demo has integrated the offline push feature as described below. You may see the code links in the documentation.

Step 1. Register your app with vendor push platforms

The offline push feature depends on vendors' original channels. You need to register your app with each vendor's push platform to obtain parameters such as AppID and AppKey. Currently, mobile phone vendors supported are Google FCM, Mi, Huawei, OPPO, vivo, and Meizu.

Step 2. Create resources in the IM console

You need to log in to the IM console to add the push certificates of required vendors, and configure parameters obtained in Step 1 such as AppId, AppKey, and AppSecret to the push certificates in the console. Take Google as an example.
Vendor Push Platform
Configuring in the IM console








Step 3. Configure the redirected-to page for offline push

An offline push message received will be displayed in the notification bar as shown in the figure below. You can click the notification bar to open the app and go to the redirected-to page configured. Follow the steps below to configure the activities to be redirected to upon notification message clicking.
Configuring in the console The redirected-to page configuration varies by vendor as follows:
Vendor
Action after Click
Specified In-app Page
Mi
Open the specified in-app page
intent://your hostname/your path#Intent;scheme=your protocol, that is, the scheme you defined;launchFlags=0x4000000;component=complete class name of the page to which your app is to be redirected;endTUIKit demo configuration: intent://com.tencent.qcloud/detail#Intent;scheme=pushscheme;launchFlags=0x4000000;component=com.tencent.qcloud.tim.tuikit/com.tencent.qcloud.tim.demo.main.MainActivity;end
Huawei
Open the specified in-app page
intent://your hostname/your path#Intent;scheme=your protocol, that is, the scheme you defined;launchFlags=0x4000000;component=complete class name of the page to which your app is to be redirected;endTUIKit demo configuration: intent://com.tencent.qcloud/detail#Intent;scheme=pushscheme;launchFlags=0x4000000;component=com.tencent.qcloud.tim.tuikit/com.tencent.qcloud.tim.demo.main.MainActivity;end
Meizu
Open the specified in-app page
Complete class name of the page to which your app is to be redirectedTUIKit demo configuration: com.tencent.qcloud.tim.demo.main.MainActivity
OPPO
Open the specified in-app page
Complete class name of the page to which your app is to be redirectedTUIKit demo configuration: activity: com.tencent.qcloud.tim.demo.main.MainActivity
vivo
Open the specified in-app page
intent://your hostname/your path#Intent;scheme=your protocol, that is, the scheme you defined;launchFlags=0x4000000;component=complete class name of the page to which your app is to be redirected;endTUIKit demo configuration: intent://com.tencent.qcloud/detail#Intent;scheme=pushscheme;launchFlags=0x4000000;component=com.tencent.qcloud.tim.tuikit/com.tencent.qcloud.tim.demo.main.MainActivity;end
Google FCM
No need to configure
Redirect to the Launcher page of the app by default

Manifest file configuration In AndroidManifest.xml, configure the redirected-to page parameters. Please note that this configuration must be consistent with the Action after Click configured in the corresponding certificate in the IM console.
<!-- The redirected-to page configured in the TUIKit demo is `MainActivity`, so you need to fill in `com.tencent.qcloud.tim.demo.main.MainActivity` here. After integration with your app, you need to replace the class name with the complete class name of the page to which your app is to be redirected.-->
<activity
android:name="complete class name of the page to which your app is to be redirected"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize|stateHidden">

<!-- Open the in-app page for offline push -->
<intent-filter>
<action android:name="android.intent.a, and configuration for Google FCM: pushscheme://com.tencent.qcloud/detail -->
<data
android:host="your hostname"
android:path="your path"
android:scheme="your protocol, that is, the scheme you defined" />
</intent-filter>

</activity>

Step 4. Set vendor push rules

Applying the offline parameter configuration After you successfully add a push certificate as instructed in Step 2, the IM console will assign a certificate ID that needs to be filled in as a configuration parameter in PrivateConstants. This ID will be needed for registering the push service and reporting the token. Take Google as an example. Push certificate ID:

Parameters to be filled in:
public class PrivateConstants {
// Certificate ID generated after uploading a third-party push certificate in the IM console
public static final long GOOGLE_FCM_PUSH_BUZID = 15518;
}
Set vendor push rules in the manifest file You need to add vendor push rules in the manifest file. See configurations in the manifest file of TUIKit demo for details. Take Google as an example.
<!-- Note: The `applicationId` of the TUIKit demo is `com.tencent.qcloud.tim.tuikit`. You need to replace xxxx here with the `applicationId` of your app. -->

<!-- ********Google cloud messaging starts******** -->
<service
android:name="xxxx.GoogleFCMMsgService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- ********Google cloud messaging ends******** -->
Google FCM adaption For Huawei and Google FCM, you need to integrate the corresponding plugin and json configuration files by the vendor's methods.
1. Download the configuration file and place it under the root directory of the project.



2. Add the following configuration under "buildscript -> dependencies" of the project-level build.gradle file.
dependencies {
...
classpath 'com.google.gms:google-services:4.2.0'
}
3. Add the following configuration in the app-level build.gradle file.
apply plugin: 'com.google.gms.google-services'
4. Click Sync Now of the project.

Step 5. Integrate the vendor push SDK

Integrating SDK In the gradle file, add the vendor push SDK.
dependencies {
......
// Main package
implementation 'com.tencent.tpns:tpns:1.3.1.1-release'
// Google FCM
implementation "com.tencent.tpns:fcm:1.3.1.1-release"
// Google cloud messaging
implementation ('com.google.firebase:firebase-messaging:19.0.1')
// Mi
implementation "com.tencent.tpns:xiaomi:1.3.1.1-release"
// Meizu
implementation "com.tencent.tpns:meizu:1.3.1.1-release"
// OPPO
implementation "com.tencent.tpns:oppo:1.3.1.1-release"
// vivo
implementation "com.tencent.tpns:vivo:1.3.2.0-release"
// Huawei
implementation 'com.tencent.tpns:huawei:1.3.1.1-release'
implementation 'com.huawei.hms:push:5.0.2.300'
}
Adding push classes Include the vendor push classes. The methods are specific to vendors. See and copy the following files in TUIOfflinePush code links:


Registering push services To meet compliance requirements, you need to initialize and register the vendor push service after the user agrees to the privacy policy and logs in successfully, store the token (obtained after successful registration) in the registration result callback, and call the setOfflinePushConfig API to report the push token to the backend. For some vendors, the token can also be returned via API calls after registration. See the following code for details.
public void init() {
...

if (BrandUtil.isBrandXiaoMi()) {
// Mi offline push
MiPushClient.registerPush(this, PrivateConstants.XM_PUSH_APPID, PrivateConstants.XM_PUSH_APPKEY);
} else if (BrandUtil.isBrandHuawei()) {
// For Huawei offline push, set whether to receive the call example of the push notification bar message
HmsMessaging.getInstance(this).turnOnPush().addOnCompleteListener(new com.huawei.hmf.tasks.OnCompleteListener<Void>() {
@Override
public void onComplete(com.huawei.hmf.tasks.Task<Void> task) {
if (task.isSuccessful()) {
DemoLog.i(TAG, "huawei turnOnPush Complete");
} else {
DemoLog.e(TAG, "huawei turnOnPush failed: ret=" + task.getException().getMessage());
}
}
});

new Thread(){
@Override
public void run() {
try{
// read from agconnect-services.json
String appId = AGConnectServicesConfig.fromContext(MainActivity.this).getString("client/app_id");
String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM");
DemoLog.i(TAG, "huawei get token:" + token);
if(!TextUtils.isEmpty(token)) {
// Call the `setOfflinePushConfig` API of the IM SDK to report this token
String token = (String) o;
}
} catch (ApiException e) {
DemoLog.e(TAG, "huawei get token failed, " + e);
}
}
}.start();
} else if (MzSystemUtils.isBrandMeizu(this)) {
// Meizu offline push
PushManager.register(this, PrivateConstants.MZ_PUSH_APPID, PrivateConstants.MZ_PUSH_APPKEY);
} else if (BrandUtil.isBrandVivo()) {
// vivo offline push
PushClient.getInstance(getApplicationContext()).initialize();

DemoLog.i(TAG, "vivo support push: " + PushClient.getInstance(getApplicationContext()).isSupport());
PushClient.getInstance(getApplicationContext()).turnOnPush(new IPushActionListener() {
@Override
public void onStateChanged(int state) {
if (state == 0) {
String regId = PushClient.getInstance(getApplicationContext()).getRegId();
DemoLog.i(TAG, "vivopush open vivo push success regId = " + regId);

// // Call the `setOfflinePushConfig` API of the IM SDK to report this token
String token = (String) o;
} else {
// According to the vivo documentation, state = 101 means this particular vivo device or system version does not support vivo Push. See https://dev.vivo.com.cn/documentCenter/doc/156 for details.
DemoLog.i(TAG, "vivopush open vivo push fail state = " + state);
}
}
});
} else if (HeytapPushManager.isSupportPush()) {
// OPPO offline push
OPPOPushImpl oppo = new OPPOPushImpl();
oppo.createNotificationChannel(this);
// According to the OPPO documentation, the app must call the init(...) API before proceeding to subsequent operations.
HeytapPushManager.init(this, false);
HeytapPushManager.register(this, PrivateConstants.OPPO_PUSH_APPKEY, PrivateConstants.OPPO_PUSH_APPSECRET, oppo);
} else if (BrandUtil.isGoogleServiceSupport()) {
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new com.google.android.gms.tasks.OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
DemoLog.w(TAG, "getInstanceId failed exception = " + task.getException());
return;
}

// Get new Instance ID token
String token = task.getResult().getToken();
DemoLog.i(TAG, "google fcm getToken = " + token);

// Call the `setOfflinePushConfig` API of the IM SDK to report this token
String token = (String) o;
}
});
}
}
Take Google FCM as an example. Store the token (obtained after successful registration) in the registration result callback, and call the setOfflinePushConfig API to report the token to the backend.
public class GoogleFCMMsgService extends FirebaseMessagingService {

...

@Override
public void onNewToken(String token) {
DemoLog.i(TAG, "onNewToken token=" + token);

// Call the `setOfflinePushConfig` API of the IM SDK to report this token
String pushToken = token;
}

...
}
Reporting the push certificate and token to the backend Call the setOfflinePushConfig API to report the push token. Construct the V2TIMOfflinePushConfig class, where you need to set businessID as the certificate ID of the vendor and isTPNSToken as false and report the token obtained after successful registration of the vendor push service. Note: If you use the offline push service of TPNS, set isTPNSToken as true and report the token obtained after successful registration of the TPNS push service. Then, TPNS will provide the push service.
V2TIMOfflinePushConfig v2TIMOfflinePushConfig = null;
// Set `businessID` as the certificate ID of the vendor and `isTPNSToken` as `false`, and report the token obtained after registration of the vendor push service.
v2TIMOfflinePushConfig = new V2TIMOfflinePushConfig(0, token, true);
V2TIMManager.getOfflinePushManager().setOfflinePushConfig(v2TIMOfflinePushConfig, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
DemoLog.d(TAG, "setOfflinePushToken err code = " + code);
}

@Override
public void onSuccess() {
DemoLog.d(TAG, "setOfflinePushToken success");
}
});

Step 6. Sync foreground and background status

If a message newly received needs to be displayed in the phone's notification bar when your app is switched to the background, call the doBackground() API of the IM SDK to sync the app status to the IM backend. When your app is switched back to the foreground, call the doForeground() API of the IM SDK to sync the app status to the IM backend. For the scheme for listening for the app switching between foreground and background, see relevant logic in the initActivityLifecycle() class of TUIOfflinePushService.
// When the app is switched to the background
V2TIMManager.getOfflinePushManager().doBackground(totalCount, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
DemoLog.e(TAG, "doBackground err = " + code + ", desc = " + desc);
}

@Override
public void onSuccess() {
DemoLog.i(TAG, "doBackground success");
}
});
// When the app is switched back to the foreground
V2TIMManager.getOfflinePushManager().doForeground(new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
DemoLog.e(TAG, "doForeground err = " + code + ", desc = " + desc);
}

@Override
public void onSuccess() {
DemoLog.i(TAG, "doForeground success");
}
});

Step 7. Set offline push parameters when sending messages

When you call sendMessage to send messages, you can use V2TIMOfflinePushInfo to set offline push parameters. For more information, see the sendMessage() method in ChatProvider.
OfflineMessageContainerBean containerBean = new OfflineMessageContainerBean();
OfflineMessageBean entity = new OfflineMessageBean();
entity.content = message.getExtra().toString();
entity.sender = message.getFromUser();
entity.nickname = chatInfo.getChatName();
entity.faceUrl = TUIChatConfigs.getConfigs().getGeneralConfig().getUserFaceUrl();
containerBean.entity = entity;

V2TIMOfflinePushInfo v2TIMOfflinePushInfo = new V2TIMOfflinePushInfo();
v2TIMOfflinePushInfo.setExt(new Gson().toJson(containerBean).getBytes());
// For OPPO, you must set the `ChannelID` to receive push messages. The `ChannelID` must be identical with that in the console.
v2TIMOfflinePushInfo.setAndroidOPPOChannelID("tuikit");

final V2TIMMessage v2TIMMessage = message.getTimMessage();
String msgID = V2TIMManager.getMessageManager().sendMessage(v2TIMMessage, isGroup ? null : userID, isGroup ? groupID : null,
V2TIMMessage.V2TIM_PRIORITY_DEFAULT, false, v2TIMOfflinePushInfo, new V2TIMSendCallback<V2TIMMessage>() {
@Override
public void onProgress(int progress) {

}

@Override
public void onError(int code, String desc) {
TUIChatUtils.callbackOnError(callBack, TAG, code, desc);
}

@Override
public void onSuccess(V2TIMMessage v2TIMMessage) {
TUIChatLog.v(TAG, "sendMessage onSuccess:" + v2TIMMessage.getMsgID());
message.setMsgTime(v2TIMMessage.getTimestamp());
TUIChatUtils.callbackOnSuccess(callBack, message);
}
});

Step 8. Parse offline push messages

When a phone receives an offline push message, the message is displayed in the system notification bar. When you click the message in the notification bar, the system automatically redirects to the page configured in Step 4. On this page, you can call getIntent().getExtras() to get the offline push parameters configured in Step 6. For sample code, see the handleOfflinePush() method of the TUIKit demo.
private void handleOfflinePush() {
// Determine whether to log in to IM again based on the login status
// 1. If the login status is V2TIMManager.V2TIM_STATUS_LOGOUT, redirect to the login page and log in to IM again.
if (V2TIMManager.getInstance().getLoginStatus() == V2TIMManager.V2TIM_STATUS_LOGOUT) {
Intent intent = new Intent(MainActivity.this, SplashActivity.class);
if (getIntent() != null) {
intent.putExtras(getIntent());
}
startActivity(intent);
finish();
return;
}

// 2. If the login status is not V2TIMManager.V2TIM_STATUS_LOGOUT, the app runs in the background, and the offline push parameters can be parsed directly.
final OfflineMessageBean bean = OfflineMessageDispatcher.parseOfflineMessage(getIntent());
if (bean != null) {
setIntent(null);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();
}

if (bean.action == OfflineMessageBean.REDIRECT_ACTION_CHAT) {
if (TextUtils.isEmpty(bean.sender)) {
return;
}
TUIUtils.startChat(bean.sender, bean.nickname, bean.chatType);
}
}
}

Caution
For Google FCM, clicking the message in the notification bar will redirect to the Launcher page of the app by default. On this page, you can call getIntent().getExtras() to get the offline push parameters configured in Step 6, and then parse messages and customize the redirection.
Upon completion of the above configurations, when your app is switched to the background or the process is killed, the messages will be pushed offline and displayed in the notification bar. You can click the message in the notification bar to redirect to the specified app page.

IM - Groups

Join a Tencent Cloud IM group for:
Reliable technical support
Product details
Constant exchange of ideas
Telegram group: join
Disacord group: join

FAQs

How could I customize alert tones for offline push?

SDK v6.1.2155 or a later version supports customizing alert tones on devices of Huawei, Mi, FCM and APNS. See the setAndroidSound() and setIOSSound() APIs of V2TIMOfflinePushInfo for specific methods.

How could I troubleshoot if I cannot receive offline push messages?

1. OPPO devices

This generally occurs for the following reasons:
According to requirements on the official website of OPPO Push, ChannelID must be configured on OPPO mobile phones that run Android 8.0 or later versions. Otherwise, push messages cannot be displayed. For the configuration method, see OPPO Push configuration.
The custom content in the message for pass-through offline push is not in the JSON format. As a result, OPPO mobile phones do not receive push messages.
The notification bar display feature is disabled by default for applications installed on the OPPO device. If this is the case, check the feature button status.

2. Sending custom messages

The offline push for custom messages is different from that for ordinary messages. As we cannot parse the content of custom messages and determine the push content, custom messages are not pushed offline by default. If you need offline push for custom messages, set the desc field in offlinePushInfo when you call sendMessage, and the desc information will be displayed by default in the push message.

3. Effect of notification bar settings of the device

The offline push message can be intuitively expressed by the notification bar alert, so, just as other notifications, it is subject to the notification settings of the device. Take a Huawei device as an example.
"Settings - Notifications - Notifications (Lock Screen) - Hide or Do not Disturb" will affect the display of offline push notifications when the screen is locked.
"Settings - Notifications - Advanced Settings - Show Notification Icons (Status Bar)" will affect the showing of the offline push notification icon in the status bar.
"Settings - Notifications - Application Notifications - Allow Notifications" will directly affect the display of offline push notifications.
"Settings - Notifications - Application Notifications - Notification Sound" and "Settings - Notifications - Application Notifications - Notification Mute" will affect the effect of the offline push notification sound.

4. The failure still exists after integration as instructed

First, test whether messages can be properly pushed offline by using the offline test tool in the IM console. If offline push does not work properly, and the device status is exceptional, check the parameters in the IM console and then check the code initialization and registration logic, including the vendor push service registration and IM offline push configuration. If offline push does not work properly but the device status is normal, check whether the ChannelID is correct or whether the backend service is working properly.
The offline push feature relies on the vendor's capabilities. Some simple characters may be filtered by the vendor and cannot be passed through and pushed.
If offline push messages are not pushed timely or cannot be received, you need to check the vendor's push restrictions.

How could I troubleshoot redirection failure?

Page redirection is implemented as follows: The backend delivers the redirection modes and page parameters that you configure for various vendors in the console to vendor servers based on vendor API rules. When you click the notification bar for offline push messages, the system opens and redirects to the corresponding page. Opening of the corresponding page also depends on the manifest file. Only when the configuration in the manifest file is consistent with that in the console, the corresponding page can be opened and redirected properly.
1. First, you need to check whether the configuration in the console and that in the manifest file are correct and consistent with each other. For more information, see the configuration of the TUIKit demo. Note that the API modes may vary by vendor.
2. If the system redirects to the configuration page, you need to check whether the parsing of offline messages on the configuration page and the page redirection are proper.

Vendor's push restrictions

1. All vendors in China have adopted message classification mechanisms, and different push policies are assigned for different types of messages. To make the push timely and reliable, you need to set the push message type of your app as the system message or important message with a high priority based on the vendor's rules. In turn, offline push messages are affected by the vendor's push message classification and may vary from your expectations.
2. In addition, some vendors set limits on the daily volumes of app push messages. You can check such limits in the vendor's console. If offline push messages are not pushed timely or cannot be received, consider the following:
Huawei: Push messages are classified into service & communication messages and information & marketing messages with different push effects and policies. In addition, message classification is associated with the self-help message classification permission.
If there is no self-help message classification permission, the vendor will perform secondary intelligent message classification on push messages.
If you have applied for the self-help message classification permission, push messages will be classified based on the custom classification and then pushed. For more information, see Message Classification Criteria.
vivo: Push messages are classified into system messages and operational messages with different push effects and policies. The system messages are further subject to the vendor's intelligent classification for correction. A message that cannot be intelligently identified as a system message will be automatically corrected as an operational message. If the judgment is incorrect, you can give a feedback by email. In addition, the total number of push messages is subject to a daily limit determined based on the app subscription statistics by the vendor. See vendor description 1 or vendor description 2 for details.
OPPO: Push messages are classified into private messages and public messages with different push effects and policies. Private messages are those that the user pays certain attention to and wants to receive in time. The private message channel permission needs to be applied for via email. The public message channel is subject to a number limit. See vendor description 1 or vendor description 2 for details.
Mi: Push messages are classified into important messages and general messages with different push effects and policies. In particular, only instant messages, dynamics reminders of the user's interest events, agenda reminders, order status change, financial reminders, personal status change, resource changes, and device reminders fall into the important message category. The important message channel can be applied for in the vendor's console. General push messages are subject to a number limit. See vendor description 1 or vendor description 2 for details.
Meizu: Push messages are subject to a number limit. See vendor description for details.
FCM: Upstream message push is subject to a frequency limit. See vendor description for details.