The Amp Devcenter Test Developer Hub

Welcome to the Amp Devcenter Test developer hub. You'll find comprehensive guides and documentation to help you start working with Amp Devcenter Test as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    

Maven CentralMaven Central

SDK Installation

1. Add dependencies

  • We recommend using Android Studio as an IDE and Gradle to manage dependencies.
  • In build.gradle file, please add the following dependencies. OkHttp is needed for our SDK.
dependencies {
  implementation 'com.amplitude:android-sdk:2.31.0'
  implementation 'com.squareup.okhttp3:okhttp:4.2.2'
  • Sync project with gradle files.

2. Add permissions

To report events to Amplitude, add the INTERNET permission to your AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET" />

For Android 6.0 (Marshmallow) and above, explicitly add the READ_PHONE_STATE permission to fetch phone related information.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />


Import Amplitude into any file that uses it.

import com.amplitude.api.Amplitude;
import com.amplitude.api.AmplitudeClient;
Import any more files that are needed, use the SDK reference


Initialization is necessary before any instrumentation is done. The API key for your Amplitude project is required. In Android, we recommend putting this in onCreate(...) of your Activity class.

AmplitudeClient client = Amplitude.getInstance()
  .initialize(getApplicationContext(), "YOUR_API_KEY_HERE")
val client = Amplitude.getInstance()
  .initialize(getApplicationContext(), "YOUR_API_KEY_HERE")

Note that enableForegroundTracking(getApplication()) is necessary for accurate session tracking and off by default.

Amplitude.getInstance(String name) may optionally take a name which uniquely holds settings. This instance is now linked to the name and can be retrieved somewhere else.

AmplitudeClient client1 = Amplitude.getInstance("Andy_Client");
AmplitudeClient client2 = Amplitude.getInstance("Bob_Client");

//In the same file, or a different activity in the app
AmplitudeClient sameClient = Amplitude.getInstance("Andy_Client");
val client1 = Amplitude.getInstance("Andy_Client")
val client2 = Amplitude.getInstance("Bob_Client")

//In the same file, or a different activity in the app
val sameClient = Amplitude.getInstance("Andy_Client")

Sending Events

Basic Events

Events represent how users interact with your application. For example, “Button Clicked” may be an action you want to track.

client.logEvent("Button Clicked");

Events with Properties

Events can also contain properties. They provide context about the event taken. For example, “hover time” may be a relevant event property to “button click."

JSONObject eventProperties = new JSONObject();
try {
  eventProperties.put("Hover Time", 10).put("prop_2", "value_2");
} catch (JSONException e) {
  System.err.println("Invalid JSON");
client.logEvent("Button Clicked", eventProperties);
// Note: You will also need to add two JSONObject imports to the code.
// import org.json.JSONException;
// import org.json.JSONObject;
val eventProperties = JSONObject() 
try {
  eventProperties.put("Hover Time", 10).put("prop_2", "value_2")
} catch (e: JSONException) {
  System.err.println("Invalid JSON")
client.logEvent("Button Clicked", eventProperties)

Flush Events

Events are typically stored in a buffer and flushed periodically. This behavior is configurable. On Android, this is enabled by default.

client.setFlushEventsOnClose(false); //Don't flush events

Set User Properties


Privacy and Tracking

Please be sure to not track any user data that may be against your privacy terms. If you need any assistance with privacy concerns, then please reach out to our Platform team.


Identify is for setting the user properties of a particular user without sending any event. The SDK supports the operations set, setOnce, unset, add, append, prepend, preInsert, postInsert, and remove on individual user properties. The operations are declared via a provided Identify interface. Multiple operations can be chained together in a single Identify object. The Identify object is then passed to the Amplitude client to send to the server.


Important Note

If the Identify call is sent after the event, the results of operations will be visible immediately in the dashboard user’s profile area, but it will not appear in chart result until another event is sent after the Identify call. So the identify call only affects events going forward. More details here.

Managing User Identity

You can handle the identity of a user using the identify methods. Proper use of these methods can connect events to the correct user as they move across devices, browsers, and other platforms. Send an identify call containing those user property operations (please check the Identify section below) to Amplitude server to tie a user's events with specific user properties.

Identify identify = new Identify();
identify.set("color", "green");
val identify = Identify()
identify["color"] = "green"


set sets the value of a user property. You can also chain together multiple identify calls.

Identify identify = new Identify().set("color", "green");
val identify = Identify().set("color", "green")


setOnce sets the value of a user property only once. Subsequent calls using setOnce will be ignored.

Identify identify = new Identify().setOnce("color", "green");
val identify = Identify().setOnce("color", "green")


add increments a user property by some numerical value. If the user property does not have a value set yet, it will be initialized to 0 before being incremented.

Identify identify = new Identify().set("number_of_clients", 10);
identify.add("number_of_clients", 5); //15
identify.add("annual_revenue", 100);  //100
val identify = Identify().set("number_of_clients", 10)
identify.add("number_of_clients", 5) //15
identify.add("annual_revenue", 100) //100

Setting Multiple User Properties

logEvent() method allows you to set the user properties along with event logging. You can use setUserProperties as a shorthand to set multiple user properties at once. This method is simply a wrapper around Identify.set.

JSONObject userProperties = new JSONObject();
try {
  userProperties.put("team", "red").put("favorite_food", "cabbage");
} catch (JSONException e) {
  System.err.println("Invalid JSON");
client.logEvent("event name");
val userProperties = JSONObject()
try {
  userProperties.put("team", "red").put("favorite_food", "cabbage")
} catch (e: JSONException) {
  System.err.println("Invalid JSON")
client.logEvent("event name")

Arrays in User Properties

Arrays can be used as user properties. You can directly set arrays or use append (see section below this one) to generate an array.

JSONArray value1 = new JSONArray();

Identify identify = new Identify();
identify.set("array value", value1);
val value1 = JSONArray()

val identify = Identify()
identify["array value"] = value1


  • append will append a value or values to a user property array.
  • prepend will prepend a value or values to a user property.
    If the user property does not have a value set yet, it will be initialized to an empty list before the new values are added. If the user property has an existing value and it is not a list, it will be converted into a list with the new value added.


prepend and append do not check for duplicates. Please see preInsert and postInsert for that.

String property1 = "array value";
JSONArray value1 = new JSONArray();
Identify identify = new Identify();
identify.append(property1, value1);
identify.prepend("float value", 0.625f);
val property1 = "array value"
val value1 = JSONArray()
val identify = Identify()
identify.append(property1, value1)
identify.prepend("float value", 0.625f)


  • preInsert will insert a value or values to the front of a user property array if it does not exist in the array yet.
  • postInsert will insert a value or values to the end of a user property array if it does not exist in the array yet.

If the user property does not exist, it will be initialized to an empty list before the new values are pre-inserted. If the user property has an existing value, there will be no operation.

String property1 = "array value";
double[] values = {1, 2, 4, 8};
Identify identify = new Identify();
identify.postInsert(property1, values);

// identify should ignore this since duplicate key
identify.postInsert(property1, 3.0);
val property1 = "array value"
val values = doubleArrayOf(1.0, 2.0, 4.0, 8.0)
val identify = Identify()
identify.postInsert(property1, values)
identify.postInsert(property1, 3.0)

Clearing User Properties

clearUserProperties method is for clearing all user properties at once. This will wipe all of the current user's user properties.


The result is irreversible!

Amplitude will not be able to sync the user's user property values before the wipe to any future events that the user triggers as they will have been reset.



unset unsets and removes a user property.

Identify identify = new Identify().setOnce("favorite_food", "candy");
val identify = Identify().setOnce("favorite_food", "candy")

Setting User Groups


This feature is only available for Growth customers who have purchased the Accounts add-on.

Amplitude supports assigning users to groups and performing queries such as Count by Distinct on those groups. An example would be if you want to group your users based on what organization they are in by using an 'orgId'. You can designate Joe to be in 'orgId' '10' while Sue is in 'orgId' '15'. When performing a query in our Event Segmentation chart, you can then select "..performed by" 'orgId' to query the number of different organizations that have performed a specific event. As long as at least one member of that group has performed the specific event, that group will be included in the count.

When setting groups, you will need to define a groupType and groupName(s). In the above example, 'orgId' is the groupType and the values '10' and '15' are groupName(s). Another example of a groupType could be 'sport' with groupName(s) like 'tennis' and 'baseball'. You can use setGroup(groupType, groupName) to designate which groups a user belongs to. Note: This will also set the 'groupType:groupName' as a user property. This will overwrite any existing groupName value set for that user's groupType, as well as the corresponding user property value. groupType is a string and groupName can be either a string or an array of strings to indicate a user being in multiple groups (for example, if Joe is in 'orgId' '10' and '16', then the groupName would be '[10, 16]'). Here is what your code might look like:

Amplitude.getInstance().setGroup("orgId", "15");
Amplitude.getInstance().setGroup("sport", new JSONArray().put("tennis").put("soccer"));  // list values

You can also use logEventWithGroups to set event-level groups, meaning the group designation only applies for the specific event being logged and does not persist on the user unless you explicitly set it with setGroup:

JSONObject eventProperties = new JSONObject().put("key", "value");
JSONObject groups = new JSONObject().put("orgId", 10);

Amplitude.getInstance().logEvent("initialize_game", eventProperties, groups);

Track Revenue

Amplitude can track revenue generated by a user. Revenue is tracked through distinct revenue objects, which have special fields that are used in Amplitude's Event Segmentation and Revenue LTV charts. This allows Amplitude to automatically display data relevant to revenue in the platform. Revenue objects support the following special properties, as well as user-defined properties through the eventProperties field.

Revenue revenue = new Revenue().setProductId("").setPrice(3.99).setQuantity(3);
val revenue = Revenue().setProductId("").setPrice(3.99).setQuantity(3)
productId (optional)stringAn identifier for the product. We recommend something like the Google Play Store product ID.null
quantity (required)intThe quantity of products purchased. Note: revenue = quantity * price1
price (required)DoubleThe price of the products purchased, and this can be negative. Note: revenue = quantity * pricenull
revenueType (optional, required for revenue verification)StringThe type of revenue (e.g. tax, refund, income).null
receipt (optional)StringThe type of revenue (e.g. tax, refund, income).null
receiptSignature (optional, required for revenue verification)StringThe type of revenue (e.g. tax, refund, income).null
eventProperties (optional)JSONObjectAn object of event properties to include in the revenue event.null


Price can be negative, which may be useful for tracking revenue lost (such as refunds or costs)


Amplitude currently does not support currency conversion. All revenue data should be normalized to a currency of choice before being sent to Amplitude.

The logRevenue() API is deprecated, and the logRevenueV2() API should be used going forward.

Revenue Verification

The logRevenue method also supports revenue validation.

By default, revenue events recorded on the Android SDK will appear in Amplitude as [Amplitude] Revenue (Unverified) events. To enable revenue verification, copy your Google Play License Public Key into the Sources & Destinations section of your project in Amplitude. You must put in a key for every single project in Amplitude where you want revenue to be verified.

There are two main Android libraries for revenue verificaitons: AIDL and Google Play Billing. AIDL is the older and deprecated one. See this Google guide on how to migrate, as well as the class specification for the Purchase class. Please see the code examples below for the two different libraries, in Java or Kotlin.

After a successful purchase transaction, add the purchase data and receipt signature to the Revenue object:

// For AIDL (old deprecated library)

Intent data = ...;

String purchaseData = data.getStringExtra("PURCHASE_DATA");
String dataSignature = data.getStringExtra("DATA_SIGNATURE");

Revenue revenue = new Revenue().setProductId("").setQuantity(1);
revenue.setPrice(3.99).setReceipt(purchaseData, dataSignature);

//For Google Play Billing Library
public class MyBillingImpl implements PurchasesUpdatedListener {
    private BillingClient billingClient;

    public void initialize() {
        billingClient = BillingClient.newBuilder(activity).setListener(this).build();
        billingClient.startConnection(new BillingClientStateListener() {
            public void onBillingSetupFinished(BillingResult billingResult) {
                // Logic from ServiceConnection.onServiceConnected should be moved here.

            public void onBillingServiceDisconnected() {
                // Logic from ServiceConnection.onServiceDisconnected should be moved here.

    public void onPurchasesUpdated(
        @BillingResponse int responseCode, @Nullable List<Purchase> purchases) {
        //Here is the important part. 
        for (Purchase purchase: purchases) {
          Revenue revenue = new Revenue()
          revenue.setReceipt(purchase.getOriginalJson(), purchase.getSignature());
// For AIDL (old deprecated library)
Intent data = ...

val purchaseData: String = data.getStringExtra("PURCHASE_DATA")
val dataSignature: String = data.getStringExtra("DATA_SIGNATURE")

val revenue = Revenue().setProductId("").setQuantity(1)
revenue.setPrice(3.99).setReceipt(purchaseData, dataSignature)

class MyBillingImpl(private var billingClient: BillingClient) : PurchasesUpdatedListener {

    init {
        billingClient = BillingClient.newBuilder(activity).setListener(this).build()
        billingClient.startConnection(object : BillingClientStateListener {
            override fun onBillingSetupFinished(billingResult: BillingResult?) {
                // Logic from ServiceConnection.onServiceConnected should be moved here.

            override fun onBillingServiceDisconnected() {
                // Logic from ServiceConnection.onServiceDisconnected should be moved here.

    override fun onPurchasesUpdated(
        billingResult: BillingResult?,
        purchases: MutableList<Purchase>?
    ) {
        // Logic from onActivityResult should be moved here.
        for (Purchase purchase: purchases) {
          Revenue revenue = new Revenue()
          revenue.setReceipt(purchase.getOriginalJson(), purchase.getSignature());

Amazon Store Revenue Verification

For purchases on the Amazon store, you should copy your Amazon Developer Shared Secret into the Sources & Destinations section of your project in Amplitude. After a successful purchase transaction, you should send the purchase token as the 'receipt' and the User ID as the 'receiptSignature':

// for a purchase request onActivityResult
String purchaseToken = purchaseResponse.getReceipt();
String userId = getUserIdResponse.getUserId();

Revenue revenue = new Revenue().setProductId("").setQuantity(1);
revenue.setPrice(3.99).setReceipt(purchaseToken, userId);


User Sessions

A session on Android is a period of time that a user has the app in the foreground.

Amplitude groups events together by session. Events that are logged within the same session will have the same session_id. Sessions are handled automatically so you do not have to manually call an API like startSession() or endSession().

You can adjust the time window for which sessions are extended.

client.setMinTimeBetweenSessionsMillis(10000); //Must be a 'long'; 10 seconds

By default, '[Amplitude] Start Session' and '[Amplitude] End Session' events are not sent. Even though these events are not sent, sessions are still tracked by using session_id. To enable those session events, add this line before initializing the SDK.


You can also log events as out-of-session. Out-of-session events have a session_id of -1 and are not considered part of the current session, meaning they do not extend the current session. This might be useful if you are logging events triggered by push notifications, for example. You can log events as out-of-session by setting the input parameter outOfSession to true when calling logEvent().

JSONObject eventProperties = //...
//This event is now out of session
client.logEvent("event type", eventProperties, true);

You can also log identify events as out-of-session, which is useful if you are updating user properties in the background and do not want to start a new session. You can do this by setting the input parameter outOfSession to true when calling identify().

Identify identify = new Identify().set("key", "value");
Amplitude.getInstance().identify(identify, true);

You may also manually start a new session with its own ID.

long sessionId = ...;

You can use the helper method getSessionId to get the value of the current sessionId.

long sessionId = Amplitude.getInstance().getSessionId();


For Android API level 14 and above, a new session is created when the app comes back into the foreground after being in the background for five or more minutes or when the last event was logged (whichever occurred last). Otherwise, the background event logged will be part of the current session. Note that you can define your own session expiration time by calling setMinTimeBetweenSessionsMillis(timeout), where the timeout input is in milliseconds.

For Android API level 13 and below, foreground tracking is not available so a new session is automatically started when an event is logged 30 minutes or more after the last logged event. If another event is logged within 30 minutes, it will extend the current session. Note that you can define your own session expiration time here as well by calling setSessionTimeoutMillis(timeout), where the timeout input is in milliseconds. Also note that enableForegroundTracking(getApplication) is still safe to call for Android API level 13 and below even though it is not available.

Setting Custom User ID

If your app has its own login system that you want to track users with, you can call setUserId at any time.


You can also add the User ID as an argument to the init call.

client.initialize(this, "API_KEY", "USER_ID");

You should not assign users a User ID that could change as each unique User ID is interpreted as a unique user in Amplitude. Please see our article on how we identify and count unique users for further information.

Log Level

The log level allows you to set the level of logs printed to be printed in the developer console. The different levels are as follows:

  • 'INFO': This option will show error messages, warnings, and informative messages that may be useful for debugging.
  • 'WARN': This option will show error messages and warnings. This level will log issues that might be a problem and cause some oddities in the data. For example, this level would display a warning for properties with null values.
  • 'ERROR': This option will show error messages only.
  • 'DISABLE': This will suppress all log messages.

You can set the log level by calling the following on Android:


Log Out and Anonymous Users

A user's data will be merged on the backend so that any events up to that point from the same browser will be tracked under the same user. If a user logs out or you want to log the events under an anonymous user, you will need to:

  1. Set the userId to null.
  2. Regenerate a new deviceId.

After doing that, events coming from the current user/device will appear as a brand new user in Amplitude. Note: If you choose to do this, you will not be able to see that the two users were using the same device.


Advanced Topics

Disable Tracking

By default the Android SDK will track several user properties such as carrier, city, country, ip_address, language, platform, etc. You can use the provided TrackingOptions interface to customize and disable individual fields.

To use the TrackingOptions interface, you will first need to import the class.

import com.amplitude.api.TrackingOptions;

Before initializing the SDK with your apiKey, create a TrackingOptions instance with your configuration and set it on the SDK instance

TrackingOptions options = new TrackingOptions().disableCity().disableIpAddress().disableLatLng();

Each field can be individually disabled and has a corresponding disable method (for example, disableCountry, disableLanguage, etc.). This table describes the different methods:

disableAdid()Disable tracking of Google ADID
disableCarrier()Disable tracking of device's carrier
disableCity()Disable tracking of user's city
disableCountry()Disable tracking of user's country
disableDeviceBrand()Disable tracking of device brand
disableDeviceModel()Disable tracking of device model
disableDma()Disable tracking of user's dma
disableIpAddress()Disable tracking of user's ip address
disableLanguage()Disable tracking of device's language
disableLatLng()Disable tracking of user's current lattitude and longitude coordinates
disableOsName()Disable tracking of device's OS Name
disableOsVersion()Disable tracking of device's OS Version
disablePlatform()Disable tracking of device's platform
disableRegion()Disable tracking of user's couregiontry
disableVersionName()Disable tracking of your app's version name


Important Note

The TrackingOptions will only prevent default properties from being tracked on newly created projects, where data has not yet been sent. If you have a project with existing data that you would like to stop collecting the default properties for, please contact our Support team at Note that the existing data will not be deleted.

COPPA Control

COPPA (Children's Online Privacy Protection Act) restrictions on IDFA, IDFV, city, IP address and location tracking can be enabled or disabled all at once. Remember that apps asking for information from children under 13 years of age must comply with COPPA.

client.enableCoppaControl(); //Disables ADID, city, IP, and location tracking

Advertising ID

Advertiser ID (also referred to as IDFA) is a unique identifier provided by the iOS and Google Play stores. As it is unique to every person and not just their devices, it is useful for mobile attribution. Mobile attribution is the attribution of an installation of a mobile app to its original source (e.g. ad campaign, app store search). Mobile apps need permission to ask for IDFA, and apps targeted to children cannot track at all. Consider IDFV, device id, or an email login system as alternatives when IDFA is not available.

Follow the three steps below to use Android Ad ID.

1. Add play-services-ads as a dependency.

dependencies {
  implementation ''

2. AD_MANAGER_APP Permission

If you use Google Mobile Ads SDK version 17.0.0 above, you need to add AD_MANAGER_APP to AndroidManifest.xml.


3. Add Proguard exception

Amplitude Android SDK uses Java Reflection to use classes in Google Play Services. For Amplitude SDKs to work properly in your Android application, please add these exceptions to for the classes from play-services-ads.
-keep class** { *; }

Location Tracking

Amplitude converts the IP of a user event into a location (GeoIP lookup) by default. This information may be overridden by an app’s own tracking solution or user data.

Amplitude can access the Android location service (if possible) to add the specific coordinates (longitude and latitude) where an event is logged. This behavior is enabled by default but can be adjusted by calling the following methods after initializing:




If you use Proguard obfuscation, please also add the following exception to the file:
-keep class** { *; }

Opt Out of Tracking

Users may wish to opt out of tracking entirely, which means no events and no records of their browsing history. This API provides a way to fulfill certain users’ requests for privacy.

client.setOptOut(true); //Disables all tracking of events for this user

Push Notification Events

Push notification events should not be sent client-side via the Android SDK because a user must open the app to initialize the Amplitude SDK in order for the SDK to send the event. Therefore, if push notification events are tracked client-side then there can be data delays as the push notification event will not be sent to Amplitude's servers until the next time the user opens the app.

You can use our mobile marketing automation partners or our HTTP API V2 to send push notification events to Amplitude.

Event Explorer

To use Event Explorer, you will need to know either deviceId or userId to look up live events. Android SDKs provide functionalities to view them while using a debug build.

Add the following code in your root activity's onCreate life cycle.

public void onCreate(Bundle savedInstanceState) {

Dynamic Configuration

Android SDK allows users to configure their apps to use dynamic configuration. This feature will find the best server url automatically based on app users' geo location.

  • If you have your own proxy server and use setServerUrl API, please leave this OFF.
  • If you have users in China Mainland, we suggest you turn this on.
  • By default, this feature is OFF. So you need to explicitly set it to ON to use it.

SSL Pinning

SSL Pinning is a technique on the client side to avoid man-in-the-middle attacks by validating the server certificates again even after SSL handshaking. Please contact Amplitude Support before you ship any products with SSL pinning enabled so we are aware.

To use SSL Pinning in the Android SDK, use the class PinnedAmplitudeClient instead of AmplitudeClient to turn it on.

Need Help?

If you have any problems or issues over our SDK, feel free to create a github issue or submit a request on Amplitude Help.

Updated 10 days ago


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.