EXAMPLES.md
May 19, 2026 · View on GitHub
Example Usage
Get the Default Singleton Instance
CleverTapAPI clevertap = CleverTapAPI.getDefaultInstance(getApplicationContext());
Creating Default Instance by specifying custom CleverTap ID
- Add the following to
AndroidManifest.xmlfile
<meta-data
android:name="CLEVERTAP_USE_CUSTOM_ID"
android:value="1"/>
- Register the ActivityLifecycleCallback with a unique custom CleverTap ID per user
ActivityLifecycleCallback.register(this,"uniqueCustomClevertapIDForUser");
- Or, create a default instance with a unique custom CleverTap ID per users
CleverTapAPI cleverTapAPI = CleverTapAPI.getDefaultInstance(getApplicationContext(),"uniqueCustomClevertapIDForUser");
Record Events
clevertap.pushEvent(“Event Name”);
- Record an Event with properties
HashMap<String, Object> prodViewedAction = new HashMap<String, Object>();
prodViewedAction.put("Product Name", "Casio Chronograph Watch");
prodViewedAction.put("Category", "Mens Accessories");
prodViewedAction.put("Price", 59.99);
prodViewedAction.put("Date", new java.util.Date());
clevertap.pushEvent("Product viewed", prodViewedAction);
- Record a Charged (purchase made) Event
HashMap<String, Object> chargeDetails = new HashMap<String, Object>();
chargeDetails.put("Amount", 300);
chargeDetails.put("Payment Mode", "Credit card");
chargeDetails.put("Charged ID", 24052013);
HashMap<String, Object> item1 = new HashMap<String, Object>();
item1.put("Product category", "books");
item1.put("Book name", "The Millionaire next door");
item1.put("Quantity", 1);
HashMap<String, Object> item2 = new HashMap<String, Object>();
item2.put("Product category", "books");
item2.put("Book name", "Achieving inner zen");
item2.put("Quantity", 1);
HashMap<String, Object> item3 = new HashMap<String, Object>();
item3.put("Product category", "books");
item3.put("Book name", "Chuck it, let's do it");
item3.put("Quantity", 5);
ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>();
items.add(item1);
items.add(item2);
items.add(item3);
clevertap.pushChargedEvent(chargeDetails, items);
Record User Profile properties
// each of the below fields are optional
// if set, these populate demographic information in the Dashboard
HashMap<String, Object> profileUpdate = new HashMap<String, Object>();
profileUpdate.put("Name", "Jack Montana"); // String
profileUpdate.put("Identity", 61026032); // String or number
profileUpdate.put("Email", "jack@gmail.com"); // Email address of the user
profileUpdate.put("Phone", "+14155551234"); // Phone (with the country code, starting with +)
profileUpdate.put("Gender", "M"); // Can be either M or F
profileUpdate.put("Employed", "Y"); // Can be either Y or N
profileUpdate.put("Education", "Graduate"); // Can be either Graduate, College or School
profileUpdate.put("Married", "Y"); // Can be either Y or N
profileUpdate.put("DOB", new Date()); // Date of Birth. Set the Date object to the appropriate value first
profileUpdate.put("Age", 28); // Not required if DOB is set
profileUpdate.put("Tz", "Asia/Kolkata"); //an abbreviation such as "PST", a full name such as "America/Los_Angeles",
//or a custom ID such as "GMT-8:00"
profileUpdate.put("Photo", "www.foobar.com/image.jpeg"); // URL to the Image
// optional fields. controls whether the user will be sent email, push etc.
profileUpdate.put("MSG-email", false); // Disable email notifications
profileUpdate.put("MSG-push", true); // Enable push notifications
profileUpdate.put("MSG-sms", false); // Disable SMS notifications
ArrayList<String> stuff = new ArrayList<String>();
stuff.add("bag");
stuff.add("shoes");
profileUpdate.put("MyStuff", stuff); //ArrayList of Strings
String[] otherStuff = {"Jeans","Perfume"};
profileUpdate.put("MyStuff", otherStuff); //String Array
clevertap.pushProfile(profileUpdate);
Handling Multiple Device Users
Use onUserLogin to maintain multiple distinct user profiles on the same device
// each of the below fields are optional
// with the exception of one of Identity, Email, FBID or GPID
HashMap<String, Object> profileUpdate = new HashMap<String, Object>();
profileUpdate.put("Name", "Jack Montana"); // String
profileUpdate.put("Identity", 61026032); // String or number
profileUpdate.put("Email", "jack@gmail.com"); // Email address of the user
profileUpdate.put("Phone", "+14155551234"); // Phone (with the country code, starting with +)
profileUpdate.put("Gender", "M"); // Can be either M or F
profileUpdate.put("Employed", "Y"); // Can be either Y or N
profileUpdate.put("Education", "Graduate"); // Can be either Graduate, College or School
profileUpdate.put("Married", "Y"); // Can be either Y or N
profileUpdate.put("DOB", new Date()); // Date of Birth. Set the Date object to the appropriate value first
profileUpdate.put("Age", 28); // Not required if DOB is set
// optional fields. controls whether the user will be sent email, push etc.
profileUpdate.put("MSG-email", false); // Disable email notifications
profileUpdate.put("MSG-push", true); // Enable push notifications
profileUpdate.put("MSG-sms", false); // Disable SMS notifications
ArrayList<String> stuff = new ArrayList<String>();
stuff.add("bag");
stuff.add("shoes");
profileUpdate.put("MyStuff", stuff); //ArrayList of Strings
String[] otherStuff = {"Jeans","Perfume"};
profileUpdate.put("MyStuff", otherStuff); //String Array
cleverTapAPI.onUserLogin(profileUpdate);
Integrate Custom Proxy Domain
The custom proxy domain feature allows to proxy all events raised from the CleverTap SDK through your required domain, ideal for handling or relaying CleverTap events and Push Impression events with your application server. Following ways can be used to configure custom proxy domain(s):
Using Manifest file
- Add your CleverTap Account credentials in the Manifest file against the
CLEVERTAP_ACCOUNT_IDandCLEVERTAP_TOKENkeys. - Add the CLEVERTAP_PROXY_DOMAIN key with the proxy domain value for handling events through the custom proxy domain.
- Add the CLEVERTAP_SPIKY_PROXY_DOMAIN key with proxy domain value for handling push impression events.
<meta-data
android:name="CLEVERTAP_ACCOUNT_ID"
android:value="YOUR ACCOUNT ID" />
<meta-data
android:name="CLEVERTAP_TOKEN"
android:value="YOUR ACCOUNT TOKEN" />
<meta-data
android:name="CLEVERTAP_PROXY_DOMAIN"
android:value="YOUR PROXY DOMAIN"/>
<meta-data
android:name="CLEVERTAP_SPIKY_PROXY_DOMAIN"
android:value="YOUR SPIKY PROXY DOMAIN"/>
Using changeCredentials API
CleverTapAPI.changeCredentials(
"YOUR CLEVERTAP ACCOUNT ID",
"YOUR CLEVERTAP ACCOUNT TOKEN",
"YOUR PROXY DOMAIN",
"YOUR SPIKY PROXY DOMAIN"
);
Using CleverTap's Additional Instance
CleverTapInstanceConfig cleverTapInstanceConfig = CleverTapInstanceConfig.createInstance(
applicationContext,
"YOUR CLEVERTAP ACCOUNT ID",
"YOUR CLEVERTAP ACCOUNT TOKEN"
);
cleverTapInstanceConfig.setProxyDomain("YOUR PROXY DOMAIN");
cleverTapInstanceConfig.setSpikyProxyDomain("YOUR SPIKY PROXY DOMAIN");
CleverTapAPI.instanceWithConfig(applicationContext, cleverTapInstanceConfig);
Using App Inbox
Adding Inbox Dependencies
Add the following dependencies in your app's build.gradle
implementation "androidx.appcompat:appcompat:1.7.0"//MANDATORY for App Inbox
implementation "androidx.recyclerview:recyclerview:1.3.2"//MANDATORY for App Inbox
implementation "androidx.viewpager:viewpager:1.0.0"//MANDATORY for App Inbox
implementation "com.google.android.material:material:1.12.0"//MANDATORY for App Inbox
implementation "com.github.bumptech.glide:glide:4.12.0"//MANDATORY for App Inbox
//Optional ExoPlayer Libraries for Audio/Video Inbox Messages. Audio/Video messages will be dropped without these dependencies
implementation "com.google.android.exoplayer:exoplayer:2.19.1"
implementation "com.google.android.exoplayer:exoplayer-hls:2.19.1"
implementation "com.google.android.exoplayer:exoplayer-ui:2.19.1"
Migrating from Exoplayer to AndroidX Media3
Clevertap supports AndroidX Media3 from v7.0.0+ to replace the deprecated ExoPlayer libraries. For migration change the following dependencies.
| Old Dependency | New Dependency |
|---|---|
com.google.android.exoplayer:exoplayer:2.19.1 | androidx.media3:media3-exoplayer:1.4.0 |
com.google.android.exoplayer:exoplayer-hls:2.19.1 | androidx.media3:media3-exoplayer-hls:1.4.0 |
com.google.android.exoplayer:exoplayer-ui:2.19.1 | androidx.media3:media3-ui:1.4.0 |
Initializing the Inbox
Initializing the Inbox will provide a callback to two methods inboxDidInitialize() AND inboxMessagesDidUpdate()
import com.clevertap.android.sdk.inbox.CTInboxActivity;
import com.clevertap.android.sdk.CTInboxListener;
import com.clevertap.android.sdk.CTInboxStyleConfig;
import com.clevertap.android.sdk.CleverTapAPI;
import com.clevertap.android.sdk.CleverTapInstanceConfig;
public class MainActivity extends AppCompatActivity implements CTInboxListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
private CleverTapAPI cleverTapDefaultInstance = CleverTapAPI.getDefaultInstance(this);
if (cleverTapDefaultInstance != null) {
//Set the Notification Inbox Listener
cleverTapDefaultInstance.setCTNotificationInboxListener(this);
//Initialize the inbox and wait for callbacks on overridden methods
cleverTapDefaultInstance.initializeInbox();
}
}
}
Configure Styling and Showing the Inbox
Customize the config object and call the Inbox in the inboxDidInitialize() method
Call this method on the button click which opens the CleverTap Inbox for your App
@Override
public void inboxDidInitialize(){
ArrayList<String> tabs = new ArrayList<>();
tabs.add("Promotions");
tabs.add("Offers");
tabs.add("Others");//We support upto 2 tabs only. Additional tabs will be ignored
CTInboxStyleConfig styleConfig = new CTInboxStyleConfig();
styleConfig.setFirstTabTitle("First Tab");//By default, name of the first tab is "ALL"
styleConfig.setTabs(tabs);//Do not use this if you don't want to use tabs
styleConfig.setTabBackgroundColor("#FF0000");//provide Hex code in string ONLY
styleConfig.setSelectedTabIndicatorColor("#0000FF");
styleConfig.setSelectedTabColor("#000000");
styleConfig.setUnselectedTabColor("#FFFFFF");
styleConfig.setBackButtonColor("#FF0000");
styleConfig.setNavBarTitleColor("#FF0000");
styleConfig.setNavBarTitle("MY INBOX");
styleConfig.setNavBarColor("#FFFFFF");
styleConfig.setInboxBackgroundColor("#00FF00");
cleverTapDefaultInstance.showAppInbox(styleConfig); //Opens activity tith Tabs
//OR
cleverTapDefaultInstance.showAppInbox();//Opens Activity with default style config
}
Dismissing App Inbox
Use the following method to dismiss the App Inbox Activity as per your business use case -
cleverTapDefaultInstance.dismissAppInbox();
App Inbox Item and Button Click Callbacks
Let's understand the types of buttons first that App Inbox supports:
- URL button (fires the deeplink with the associated URL)
- Copy to button (Copies the associated text to the clipboard)
- KV button (contains the custom kev-value pair for custom handling)
The Android SDK v4.6.1 and above supports onInboxItemClicked callback on the click of an App Inbox item, such as text or media.
From the Android SDK v4.6.8 onwards and below v4.7.0, the onInboxItemClicked callback supports the button click besides the item click.
The callback returns CTInboxMessage object, itemIndex and buttonIndex parameters. To use this callback, check that your activity implements the InboxMessageListener and overrides the following method:
@Override
public void onInboxItemClicked(CTInboxMessage message, int contentPageIndex, int buttonIndex){
Log.i(TAG, "InboxItemClicked at" + contentPageIndex + " page-index with button-index:" + buttonIndex);
//The buttonIndex corresponds to the CTA button clicked (0, 1, or 2). A value of -1 indicates the app inbox body/message clicked.
List<CTInboxMessageContent> inboxMessageContentList = message.getInboxMessageContents();
//The contentPageIndex corresponds to the page index of the content, which ranges from 0 to the total number of pages for carousel templates. For non-carousel templates, the value is always 0, as they only have one page of content.
CTInboxMessageContent messageContentObject = inboxMessageContentList.get(contentPageIndex);
if (buttonIndex != -1) {
//button is clicked
try {
List<CTInboxMessageContent> inboxMessageContentList = message.getInboxMessageContents();
JSONObject buttonObject = (JSONObject) messageContentObject.getLinks().get(buttonIndex);
String buttonType = buttonObject.getString("type");
Log.i(TAG, "type of button clicked: " + buttonType);
} catch (Throwable t) {
t.printStackTrace();
}
} else {
//Item is clicked
Log.i(TAG, "type/template of App Inbox item:" + message.type);
}
}
Android SDK v3.6.1 and above supports an exclusive onInboxButtonClick callback on the click of KV type of buttons. It returns a Map of Key-Value pairs. To use this, make sure your activity implements the InboxMessageButtonListener and override the following method:
@Override
public void onInboxButtonClick(HashMap<String, String> hashMap) {
Log.i(TAG, "InboxButtonClick with payload:" + payload);
}
Creating your own App Inbox
You can choose to create your own App Inbox with the help of the following APIs -
//Initialize App Inbox
cleverTapDefaultInstance.initializeInbox();
// Available from v8.2.0 (App Inbox Sync). The SDK automatically fetches inbox messages
// on app launch and user login. Use fetchInbox() for on-demand refresh (e.g. pull-to-refresh).
// Throttled to once every 5 minutes between consecutive calls.
cleverTapDefaultInstance.fetchInbox(success -> {
// success is true if the fetch completed and new messages were received.
// Inbox listener callbacks (inboxMessagesDidUpdate) fire automatically.
// Note: this callback runs on the SDK's network thread — post to main if touching UI.
});
//Get Inbox Message Count
cleverTapDefaultInstance.getInboxMessageCount();
//Get Inbox Unread Count
cleverTapDefaultInstance.getInboxMessageUnreadCount();
//Get All messages
cleverTapDefaultInstance.getAllInboxMessages();
//Get only Unread messages
cleverTapDefaultInstance.getUnreadInboxMessages();
//Get message object belonging to the given message id only. Message id should be a String
cleverTapDefaultInstance.getInboxMessageForId(messageId);
//Delete message from the Inbox. Message id should be a String
cleverTapDefaultInstance.deleteInboxMessage(messageId);
//Delete message from the Inbox. Message should object of CTInboxMessage
cleverTapDefaultInstance.deleteInboxMessage(message);
//Mark Message as Read. Message id should be a String
cleverTapDefaultInstance.markReadInboxMessage(messageId);
//Mark message as Read. Message should object of CTInboxMessage
cleverTapDefaultInstance.markReadInboxMessage(message);
//Raise Notification Viewed event for Inbox Message. Message id should be a String
cleverTapDefaultInstance.pushInboxNotificationViewedEvent(messageId);
//Raise Notification Clicked event for Inbox Message. Message id should be a String
cleverTapDefaultInstance.pushInboxNotificationClickedEvent(messageId);
//Callback on Inbox Message update/delete/read (any activity)
@Override
public void inboxMessagesDidUpdate() { }
Additional AndroidManifest.xml Configuration to Support Notifications
Push Notifications
If using FCM, inside the <application></application> tags, register the following services
<service android:name="com.clevertap.android.sdk.pushnotification.fcm.FcmMessageListenerService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
To set a custom notification icon (only for small icon), add the following meta data entry in your AndroidManifest.xml
<meta-data
android:name="CLEVERTAP_NOTIFICATION_ICON"
android:value="ic_stat_red_star"/> <!-- name of your file in the drawable directory without the file extension. -->
To track the push notification events and deeplinks add the following receiver in your AndroidManifest.xml -
<receiver
android:name="com.clevertap.android.sdk.pushnotification.CTPushNotificationReceiver"
android:exported="false"
android:enabled="true">
</receiver>
CleverTap handles closing the notification with Action buttons. You will have to add an additional CleverTap IntentService to your AndroidManifest.xml and the SDK will do it for you automatically
<service
android:name="com.clevertap.android.sdk.pushnotification.CTNotificationIntentService"
android:exported="false">
<intent-filter>
<action android:name="com.clevertap.PUSH_EVENT"/>
</intent-filter>
</service>
Starting from core v5.1.0 we have introduced a new feature that allows developers to define a
default notification channel for their app. This feature provides flexibility in handling push
notifications. Please note that this is only supported for clevertap core notifications. Support for
push templates will be released soon.
To specify the default notification channel ID, you can add the following metadata in your app's
manifest file:
<meta-data
android:name="CLEVERTAP_DEFAULT_CHANNEL_ID"
android:value="your_default_channel_id" />
By including this metadata, you can define a specific notification channel that CleverTap will use if the channel provided in push payload is not registered by your app. This ensures that push notifications are displayed consistently even if the app's notification channels are not set up.
In case the SDK does not find the default channel ID specified in the manifest, it will automatically fallback to using a default channel called "Miscellaneous". This ensures that push notifications are still delivered, even if no specific default channel is specified in the manifest.
This enhancement provides developers with greater control over the default notification channel used by CleverTap for push notifications, ensuring a seamless and customizable user experience.
Starting from core v5.1.0 below APIs allows you to retrieve a notification bitmap from the
specified bitmapSrcUrl with a specified timeout and size. In case the bitmap retrieval fails, you
can choose to fallback to the app icon by setting the fallbackToAppIcon parameter. This API
provides more control over the bitmap retrieval process for custom rendering.
@Override
public void onMessageReceived(RemoteMessage message) {
Bundle messageBundle = mParser.toBundle(message);
// this method must be called on background thread
// context, messageBundle must be non null.
// timeout must be in range of 1 - 20000 millis.
CleverTapAPI.getNotificationBitmapWithTimeout(
context,messageBundle, "https://www.pushicons.com/icon",
true, 5000);
}
Below API extends the functionality of the previous one by additionally allowing you to specify the desired size in bytes for the retrieved bitmap.
@Override
public void onMessageReceived(RemoteMessage message) {
Bundle messageBundle = mParser.toBundle(message);
// this method must be called on background thread
// context, messageBundle must be non null.
// timeout must be in range of 1 - 20000 millis and size must be greater than 0.
CleverTapAPI.getNotificationBitmapWithTimeoutAndSize(
context,messageBundle, "https://www.pushicons.com/icon",
true, 5000,1024);
}
Pull Notifications
Starting with v3.4.0, the SDK supports Pull Notifications. Pull Notifications is a capability that
allows you to reach users on devices which suppress notifications via GCM/FCM. To allow your app to
use CleverTap's Pull Notifications via background ping service, add the following fields in your
app's AndroidManifest.xml
<meta-data
android:name="CLEVERTAP_BACKGROUND_SYNC"
android:value="1"/>
In-App Notifications
To support in-app notifications, register the following activity in your AndroidManifest.xml
<activity
android:name="com.clevertap.android.sdk.InAppNotificationActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="orientation|keyboardHidden"/>
<meta-data
android:name="CLEVERTAP_INAPP_EXCLUDE"
android:value="YourSplashActivity1, YourSplashActivity2" />
Push primer Android 13 notification runtime permission.
Using Half-Interstitial in-app
Java
JSONObject jsonObject = CTLocalInApp.builder()
.setInAppType(CTLocalInApp.InAppType.HALF_INTERSTITIAL)
.setTitleText("Get Notified")
.setMessageText("Please enable notifications on your device to use Push Notifications.")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.setBackgroundColor(Constants.WHITE)
.setBtnBorderColor(Constants.BLUE)
.setTitleTextColor(Constants.BLUE)
.setMessageTextColor(Constants.BLACK)
.setBtnTextColor(Constants.WHITE)
.setImageUrl("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png", "Alt Text")
.setBtnBackgroundColor(Constants.BLUE)
.build();
cleverTapAPI.promptPushPrimer(jsonObject);
Kotlin
val jsonObject = CTLocalInApp.builder()
.setInAppType(CTLocalInApp.InAppType.HALF_INTERSTITIAL)
.setTitleText("Get Notified")
.setMessageText("Please enable notifications on your device to use Push Notifications.")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.setBackgroundColor(Constants.WHITE)
.setBtnBorderColor(Constants.BLUE)
.setTitleTextColor(Constants.BLUE)
.setMessageTextColor(Constants.BLACK)
.setBtnTextColor(Constants.WHITE)
.setBtnBackgroundColor(Constants.BLUE)
.build()
cleverTapAPI.promptPushPrimer(jsonObject)
Using Alert in-app
Java
JSONObject jsonObject = CTLocalInApp.builder()
.setInAppType(CTLocalInApp.InAppType.ALERT)
.setTitleText("Get Notified")
.setMessageText("Enable Notification permission")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.build();
cleverTapAPI.promptPushPrimer(jsonObject);
Kotlin
val jsonObject = CTLocalInApp.builder()
.setInAppType(CTLocalInApp.InAppType.ALERT)
.setTitleText("Get Notified")
.setMessageText("Enable Notification permission")
.followDeviceOrientation(true)
.setPositiveBtnText("Allow")
.setNegativeBtnText("Cancel")
.build()
cleverTapAPI.promptPushPrimer(jsonObject)
Call Android OS runtime notification dialog without using push primer.
Takes boolean as a parameter. If true and the permission is denied then we fallback to app’s notification settings, if it’s false then we just throw a verbose log saying permission is denied.
Java
cleverTapAPI.promptForPushPermission(true);
Kotlin
cleverTapAPI.promptForPushPermission(true)
Check the status of notification permission whether it's granted or denied.
Returns true if permission is granted, else returns false if permission is denied.
Java
cleverTapAPI.isPushPermissionGranted();
Kotlin
cleverTapAPI.isPushPermissionGranted
Call Android OS runtime notification dialog for HTML in-app campaigns.
Two methods will be available to call hard permission dialog flow from HTML InApp’s as shown below:- promptPushPermission(boolean shouldShowFallbackSettings) - Use to trigger OS notification dialog. dismissInAppNotification() - Use to dismiss the current InApp.
Sample code usage
<script>
document.querySelector('#bt_gnp').addEventListener(
'click',e => {
if(window.CleverTap){
CleverTap.promptPushPermission(true); // true/false on whether to show app’s notification page if permission is denied.
}
})</script>
CTLocalInApp builder methods description
| Builder Methods | Parameters | Description | Required |
|---|---|---|---|
setInAppType(InAppType) | CTLocalInApp.InAppType.HALF_INTERSTITIAL OR CTLocalInApp.InAppType.ALERT | Accepts only HALF_INTERSTITIAL & ALERT type to display the type of InApp | Required |
setTitleText(String) | Text | Sets the title of the local in-app | Required |
setMessageText(String) | Text | Sets the subtitle of the local in-app | Required |
followDeviceOrientation(boolean) | true/false | If true then the local InApp is shown for both portrait and landscape. If it sets false then local InApp only displays for portrait mode | Required |
setPositiveBtnText(String) | Text | Sets the text of the positive button | Required |
setNegativeBtnText(String) | Text | Sets the text of the negative button | Required |
setFallbackToSettings(boolean) | true/false | If true and the permission is denied then we fallback to app’s notification settings, if it’s false then we just throw a verbose log saying permission is denied | Optional |
setBackgroundColor(String) | Accepts Hex color as String | Sets the background color of the local in-app | Optional |
setBtnBorderColor(String) | Accepts Hex color as String | Sets the border color of both positive/negative buttons | Optional |
setTitleTextColor(String) | Accepts Hex color as String | Sets the title color of the local in-app | Optional |
setMessageTextColor(String) | Accepts Hex color as String | Sets the sub-title color of the local in-app | Optional |
setBtnTextColor(String) | Accepts Hex color as String | Sets the color of text for both positive/negative buttons | Optional |
setBtnBackgroundColor(String) | Accepts Hex color as String | Sets the background color for both positive/negative buttons | Optional |
setBtnBorderRadius(String) | Text | Sets the radius for both positive/negative buttons. Default radius is “2” if not set | Optional |
Available Callbacks for Push Primer
Based on notification permission grant/deny, we’ll be providing a callback PushPermissionResponseListener .Below is a sample implementation to get the permission result
public class MainActivity extends AppCompatActivity implements PushPermissionResponseListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
private CleverTapAPI cleverTapDefaultInstance = CleverTapAPI.getDefaultInstance(this);
if (cleverTapDefaultInstance != null) {
cleverTapDefaultInstance.ct.setPushPermissionResponseListener(this);
}
}
@Override
public void onPushPermissionResponse(boolean accepted) {
Log.i(TAG, "onPushPermissionResponse : InApp---> response() called accepted="+accepted);
}
}
From CT-SDK 4.7.0+, new method onShow() is introduced for InAppNotificationListener . Below is the new method added for when the InApp is shown:-
@Override
public void onShow(CTInAppNotification ctInAppNotification) {
}
Please note from Android 13+ devices to render notification we'll have to call createNotificationChannel() after the permission is accepted.
Java
public class MainActivity extends AppCompatActivity implements PushPermissionResponseListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
private CleverTapAPI cleverTapDefaultInstance = CleverTapAPI.getDefaultInstance(this);
if (cleverTapDefaultInstance != null) {
cleverTapDefaultInstance.ct.setPushPermissionResponseListener(this);
}
}
@Override
public void onPushPermissionResponse(boolean accepted) {
if(accepted){
//For Android 13+ we need to create notification channel after notification permission is accepted
CleverTapAPI.createNotificationChannel(getApplicationContext(), "BRTesting", "Testing Channel",
"Testing Channel for BR", NotificationManager.IMPORTANCE_HIGH, true);
}
}
}
Kotlin
class HomeScreenActivity : AppCompatActivity(),PushPermissionResponseListener{
override fun onCreate(savedInstanceState: Bundle?) {
var cleverTapDefaultInstance = CleverTapAPI.getDefaultInstance(this)
cleverTapDefaultInstance?.apply {
pushPermissionNotificationResponseListener = this@HomeScreenActivity
}
}
override fun onPushPermissionResponse(accepted: Boolean) {
if(accepted){
//For Android 13+ we need to create notification channel after notification permission is accepted
CleverTapAPI.createNotificationChannel(
this, "BRTesting", "Core",
"Core notifications", NotificationManager.IMPORTANCE_MAX, true
)
}
}
}
Google Ad Id changes for Android 13
Please note if using Google Ad Id for apps targeting Android 13+, will have to declare the below permission
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
Remote Config Variables
From CleverTap SDK v5.0.0 onwards, you can use Remote Config Variables in your app. Please refer to the Remote Config Variables doc to read more on how to integrate this to your app.
A/B Experiment Variants
From CleverTap SDK v7.7.1 onwards, you can retrieve information about the active A/B experiment variants for the current user. This is useful when you need to access variant data for custom implementations or analytics.
The variants() method returns a list of active variants, where each variant contains an id key mapping to the numeric ID of the variant.
Java
CleverTapAPI clevertap = CleverTapAPI.getDefaultInstance(getApplicationContext());
if (clevertap != null) {
List<Map<String, Object>> activeVariants = clevertap.variants();
}
Kotlin
val clevertap = CleverTapAPI.getDefaultInstance(applicationContext)
clevertap?.let {
val activeVariants: List<Map<String, Any>> = it.variants()
}
Note: The returned list is unmodifiable. If no variants are active for the current user, an empty list is returned.
User Privacy & Opt-Out
setOptOut(boolean userOptOut)
Use this method to opt the user out of all event tracking, or opt them back in. When a user is opted out, no events (including user actions and system events) are sent to CleverTap.
Java
CleverTapAPI clevertap = CleverTapAPI.getDefaultInstance(this);
// Opt the user out of tracking
clevertap.setOptOut(true);
// Opt the user back in
clevertap.setOptOut(false);
Kotlin
val clevertap = CleverTapAPI.getDefaultInstance(this)
// Opt the user out of tracking
clevertap.setOptOut(true)
// Opt the user back in
clevertap.setOptOut(false)
setOptOut(boolean userOptOut, boolean allowSystemEvents)
This overload improves GDPR opt-out functionality by allowing you to control whether critical system events (such as app installs, uninstalls, and push notification registration) are still sent to CleverTap, even when a user has opted out of tracking. This helps you respect user privacy choices while still maintaining essential app functionality and compliance with regulations.
- If userOptOut is true and allowSystemEvents is true, the user is opted out of tracking, but critical system events will still be sent.
- If userOptOut is true and allowSystemEvents is false, the user is fully opted out, and even critical system events will not be sent.
- If userOptOut is false, the user is opted back in, and all events (including system events) will be sent.
Java
CleverTapAPI clevertap = CleverTapAPI.getDefaultInstance(this);
// Opt the user out, but allow critical system events (GDPR compliant)
clevertap.setOptOut(true, true);
// Opt the user out, do not allow any events (full opt-out)
clevertap.setOptOut(true, false);
// Opt the user back in, allow all events
clevertap.setOptOut(false, true);
Kotlin
val clevertap = CleverTapAPI.getDefaultInstance(this)
// Opt the user out, but allow critical system events (GDPR compliant)
clevertap.setOptOut(true, true)
// Opt the user out, do not allow any events (full opt-out)
clevertap.setOptOut(true, false)
// Opt the user back in, allow all events
clevertap.setOptOut(false, true)
Encryption of data stored in the SDK
The SDK might contain PII data which could be sensitive information. From CleverTap SDK v5.2.0 onwards, you can enable encryption for PII data wiz. Email, Identity, Name and Phone at the app storage level. From CleverTap SDK v7.7.0 onwards, a new Full_Data encryption level is introduced that encrypts all data including content and profile information.
Currently 3 levels of encryption are supported i.e None(0), Medium(1) and Full_Data(2). If not specified, the encryption level defaults to None(0).
None - All stored data is in plaintext
Medium - PII data is encrypted completely (PII keys mentioned above).
Full_Data (v7.7.0+) - All client data including content and profile information is encrypted. Metadata might still be visible.
The only way to set encryption level for default instance is from the AndroidManifest.xml
- Add the following to
AndroidManifest.xmlfile
<meta-data
android:name="CLEVERTAP_ENCRYPTION_LEVEL"
android:value="2" />
<!-- Use value="1" for Medium encryption level -->
<!-- If not specified, default is 0 (None) -->
- Different instances can have different encryption levels. To set an encryption level for an additional instance
Java
CleverTapInstanceConfig config = CleverTapInstanceConfig.createInstance(
applicationContext,
"CLEVERTAP_ACCOUNT_ID",
"CLEVERTAP_ACCOUNT_TOKEN",
"CLEVERTAP_ACCOUNT_REGION"
);
// For Medium encryption
config.setEncryptionLevel(EncryptionLevel.MEDIUM);
// For High encryption (v7.7.0+)
config.setEncryptionLevel(EncryptionLevel.FULL_DATA);
CleverTapAPI clevertap = CleverTapAPI.instanceWithConfig(applicationContext, config);
Kotlin
val clevertap = CleverTapInstanceConfig.createInstance(
applicationContext,
"CLEVERTAP_ACCOUNT_ID",
"CLEVERTAP_ACCOUNT_TOKEN",
"CLEVERTAP_ACCOUNT_REGION"
).apply {
// For Medium encryption
setEncryptionLevel(EncryptionLevel.MEDIUM)
// For High encryption (v7.7.0+)
setEncryptionLevel(EncryptionLevel.FULL_DATA)
}.let { config ->
CleverTapAPI.instanceWithConfig(applicationContext, config)
}
Encryption over Network
Clevertap can send data over the network in encrypted form instead of plain text. From CleverTap SDK v7.5.0 onwards, you can enable encryption in transit for all eventd data that is sent over the network.
To enable encryption in transit, add the following to your AndroidManifest.xml
- Add the following to
AndroidManifest.xmlfile
<meta-data
android:name="CLEVERTAP_ENCRYPTION_IN_TRANSIT"
android:value="1" />
- Different instances can have different encryption over network settings. To enable encryption for an additional instance
// 1. Create a configuration object for your additional instance
val clevertapAdditionalInstanceConfig = CleverTapInstanceConfig.createInstance(
applicationContext,
"YOUR_ADDITIONAL_ACCOUNT_ID", // Replace with your actual Account ID
"YOUR_ADDITIONAL_ACCOUNT_TOKEN", // Replace with your actual Account Token
"YOUR_ADDITIONAL_ACCOUNT_REGION"
)
// 2. Enable encryption in transit for this specific instance
clevertapAdditionalInstanceConfig.setEncryptionInTransit(true)
// 3. Get the CleverTapAPI instance using the configured settings
val clevertapAdditionalInstance = CleverTapAPI.instanceWithConfig(applicationContext, clevertapAdditionalInstanceConfig)
User event logging APIs
Get user event details
Java
UserEventLog eventLog = clevertap.getUserEventLog("Product Viewed");
if (eventLog != null) {
String eventName = eventLog.getEventName();
long firstTime = eventLog.getFirstTs();
long lastTime = eventLog.getLastTs();
int count = eventLog.getCountOfEvents();
String deviceId = eventLog.getDeviceID();
} else {
System.out.println("Event not performed");
}
Kotlin
clevertap.getUserEventLog("Product Viewed")?.let { eventLog ->
val eventName = eventLog.eventName
val firstTime = eventLog.firstTs
val lastTime = eventLog.lastTs
val count = eventLog.countOfEvents
val deviceId = eventLog.deviceID
} ?: println("Event not performed")
Get count of event occurrences
Java
int eventCount = clevertap.getUserEventLogCount("Product Viewed");
Kotlin
val eventCount = clevertap.getUserEventLogCount("Product Viewed")
Get user's last app visit timestamp
Java
long lastVisitTs = clevertap.getUserLastVisitTs();
Kotlin
val lastVisitTs = clevertap.userLastVisitTs
Get total number of app launches by user
Java
int appLaunchCount = clevertap.getUserAppLaunchCount();
Kotlin
val appLaunchCount = cleverTapAPI?.userAppLaunchCount
Get full event history for user
Java
Map<String, UserEventLog> eventHistory = clevertap.getUserEventLogHistory();
for (Map.Entry<String, UserEventLog> entry : eventHistory.entrySet()) {
String eventName = entry.getKey();
UserEventLog log = entry.getValue();
// Process event details
}
Kotlin
val eventHistory = clevertap.userEventLogHistory
eventHistory?.forEach { (eventName, log) ->
// Process event details
} ?: println("Events not performed")
Push registration tokens to Clevertap
Push FCM device token to CleverTap
override fun onNewToken(token: String) {
super.onNewToken(token)
cleverTapAPI.pushFcmRegistrationId(token, true)
}
Push Huawei registration token to CleverTap
override fun onNewToken(token: String?, bundle: Bundle?) {
super.onNewToken(token, bundle)
if (token != null) {
cleverTapAPI.pushRegistrationToken(token, HmsConstants.HPS, true)
}
}
Baidu Setup and send channelId to CleverTap
Enable baidu Push type in AndroidManifest.xml
<meta-data
android:name="CLEVERTAP_PROVIDER_2"
android:value="bps,bps_token,com.clevertap.android.bps.BaiduPushProvider,com.baidu.android.pushservice.PushMessageReceiver" />
Push Baidu registration token to CleverTap
companion object {
private val BAIDU_PUSH_TYPE = PushType(
"bps",
"bps_token",
"com.clevertap.android.bps.BaiduPushProvider",
"com.baidu.android.pushservice.PushMessageReceiver"
)
}
override fun onBind(context:Context, errorCode:Int, appid:String,
userId:String, channelId:String, requestId:String) {
//..
if (channelId != null) {
cleverTapAPI.pushRegistrationToken(channelId, BAIDU_PUSH_TYPE, true)
}
}
Also additionally add this to proguard/any similar tool
-dontwarn com.baidu.**