On this page

Android-Kotlin SDK

The Kotlin Android SDK lets you send events to Amplitude.

System requirements

The Android Kotlin SDK supports Android API level 21 (Android 5.0 Lollipop) and higher.

Install the SDK

Amplitude recommends using Android Studio as an IDE and Gradle to manage dependencies.

If you use Gradle in your project, add the following dependency to build.gradle, and sync your project with the updated file.

groovy
dependencies {
    implementation 'com.amplitude:analytics-android:1.+'
}

Configure the SDK

Configure batching behavior

To support high-performance environments, the SDK sends events in batches. The SDK queues every event logged by the track method in memory and flushes them in batches in the background. Customize batch behavior with flushQueueSize and flushIntervalMillis. By default, serverUrl is https://api2.amplitude.com/2/httpapi. To send large batches of data at a time, set useBatch to true to set setServerUrl to the batch event upload API https://api2.amplitude.com/batch. Both regular mode and batch mode use the same event upload threshold and flush time intervals.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    flushIntervalMillis = 50000
    flushQueueSize = 20
}

EU data residency

Configure the server zone when initializing the client to send data to Amplitude's EU servers. The SDK sends data based on the server zone if you set it.

For EU data residency, set up the project inside Amplitude EU. Initialize the SDK with the API key from Amplitude EU.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    serverZone = ServerZone.EU
}

Custom HTTP client

The SDK uses HttpURLConnection by default for network requests. To use a custom HTTP client, implement HttpClientInterface and pass it to the httpClient configuration option.

OkHttp with gzip compression

The sample app demonstrates how to create a custom OkHttp client with gzip compression for event uploads:

To use the custom client:

kotlin
val httpClient = CustomOkHttpClient()

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    this.httpClient = httpClient
}

httpClient.initialize(amplitude.configuration)

The SDK's default HTTP client already compresses request bodies using gzip. Use a custom OkHttp client when you need additional features like custom timeouts, certificate pinning, or logging interceptors.

Track

Events represent how users interact with your application. For example, "Song Played" may be an action you want to note.

kotlin
amplitude.track("Song Played")

You can also optionally include event properties.

kotlin
amplitude.track(
  "Song Played",
  mutableMapOf<String, Any?>("title" to "Happy Birthday")
)

For more complex events you can create and track a BaseEvent object.

kotlin
var event = BaseEvent()
event.eventType = "Song Played"
event.eventProperties = mutableMapOf<String, Any?>("title" to "Happy Birthday")
event.groups = mutableMapOf<String, Any?>("test-group-type" to "test-group-value")
event.insertId = 1234
amplitude.track(event)

Identify

Starting in release v1.7.0, the SDK batches identify events that contain only set operations. This batching reduces the number of sent events and doesn't affect how set operations run. Use the identifyBatchIntervalMillis configuration setting to manage the interval at which the SDK flushes batched identify intercepts.

Identify sets the user properties of a particular user without sending any event. The SDK supports the operations set, setOnce, unset, add, append, prepend, preInsert, postInsert, remove, and clearAll on individual user properties. Use the Identify interface to declare the operations. You can chain multiple operations in a single Identify object, then pass the Identify object to the Amplitude client to send to the server.

If you send the Identify call after the event, the results of operations appear immediately in the dashboard user's profile area, but they don't appear in chart results until the SDK sends another event after the Identify call. The identify call only affects events going forward.

Use the identify methods to handle a user's identity. Proper use of these methods connects events to the correct user as they move across devices, browsers, and other platforms. Send an identify call containing those user property operations to the Amplitude server to tie a user's events to specific user properties.

kotlin
val identify = Identify()
identify.set("color", "green")
amplitude.identify(identify)

Identify operations

The Identify object supports the following operations:

kotlin
val identify = Identify()
identify
    .set("color", "green")
    .setOnce("initial_source", "organic")
    .add("login_count", 1)
    .append("visited_pages", "home")
    .prepend("notifications", "new_feature")
    .unset("temporary_property")

amplitude.identify(identify)

Clear all user properties

Use clearAll() to clear all user properties for the current user. This operation is irreversible.

Use with caution

The clearAll() operation removes all user properties. This action is permanent. You can't undo it.

kotlin
val identify = Identify()
identify.clearAll()
amplitude.identify(identify)

Autocapture

Starting from release v1.18.0, the SDK can track more events without manual instrumentation. Configure the SDK to track the following events automatically:

  • Sessions.
  • App lifecycles.
  • Screen views.
  • Deep links.
  • Element interactions.
  • Frustration interactions:
    • Rage clicks.
    • Dead clicks.

Configure Amplitude to start tracking Autocapture events. Otherwise, omit the configuration to keep only session tracking enabled.

The autocapture configuration accepts a Set of AutocaptureOption values. To create the Autocapture options, use the autocaptureOptions helper function and add the options to the set with a unary plus sign (+) before each option.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +sessions               // or `+AutocaptureOption.SESSIONS`
        +appLifecycles          // or `+AutocaptureOption.APP_LIFECYCLES`
        +deepLinks              // or `+AutocaptureOption.DEEP_LINKS`
        +screenViews            // or `+AutocaptureOption.SCREEN_VIEWS`
        +elementInteractions    // or `+AutocaptureOption.ELEMENT_INTERACTIONS`
        +frustrationInteractions // or `+AutocaptureOption.FRUSTRATION_INTERACTIONS`
    }
}

To enable all autocapture options, use AutocaptureOption.ALL or the addAll() method:

kotlin
import com.amplitude.android.Amplitude
import com.amplitude.android.AutocaptureOption

// Using AutocaptureOption.ALL constant
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = AutocaptureOption.ALL
}

// Or using addAll() method with builder
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        addAll()
    }
}

By default, if you don't explicitly set the autocapture configuration during initialization, configuration.autocapture automatically includes AutocaptureOption.SESSIONS.

To prevent automatic session event capture, set autocapture without the AutocaptureOption.SESSIONS option.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = setOf(AutocaptureOption.APP_LIFECYCLES)  // or use `setOf()` to disable autocapture.
}

Track sessions

Amplitude enables session tracking by default. Include AutocaptureOption.SESSIONS in the autocapture configuration to explicitly configure the SDK to track session events, or to enable session event tracking along with other Autocapture configurations.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +sessions    // or `+AutocaptureOption.SESSIONS`
    }
}

For more information about session tracking, refer to User sessions.

Track application lifecycles

Enable application lifecycle event tracking by including AutocaptureOption.APP_LIFECYCLES in the autocapture configuration. Refer to the following code sample.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +appLifecycles    // or `+AutocaptureOption.APP_LIFECYCLES`
    }
}

After you enable this setting, Amplitude tracks the following events:

  • [Amplitude] Application Installed: fires when a user opens the application for the first time right after installation.
  • [Amplitude] Application Updated: fires when a user opens the application after updating the application.
  • [Amplitude] Application Opened: fires when a user launches or foregrounds the application after the first open.
  • [Amplitude] Application Backgrounded: fires when a user backgrounds the application.

Track screen views

Enable screen and fragment view event tracking by including AutocaptureOption.SCREEN_VIEWS in the autocapture configuration. Refer to the following code sample.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +screenViews    // or `+AutocaptureOption.SCREEN_VIEWS`
    }
}

After you enable this setting, Amplitude tracks both [Amplitude] Screen Viewed and [Amplitude] Fragment Viewed events. Both events include a screen name property. For [Amplitude] Fragment Viewed events, Amplitude captures additional fragment-specific properties.

Enable deep link event tracking by including AutocaptureOption.DEEP_LINKS in the autocapture configuration. Refer to the following code sample.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +deepLinks    // or `+AutocaptureOption.DEEP_LINKS`
    }
}

After you enable this setting, Amplitude tracks the [Amplitude] Deep Link Opened event with the URL and referrer information.

If your activity uses singleTop, singleTask, or singleInstance launch mode, Android delivers deep links that arrive while the activity is already running to onNewIntent() instead of creating a new activity. In this case, call setIntent() to update the activity's intent so Amplitude can track the deep link.

kotlin
override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent) // Required for Amplitude to track the deep link
}

Without calling setIntent(), getIntent() continues to return the original intent that started the activity, and Amplitude doesn't detect the new deep link.

Track element interactions

Amplitude can track user interactions with clickable elements, with support for both classic Android Views and Jetpack Compose. To enable this option, include AutocaptureOption.ELEMENT_INTERACTIONS in the autocapture configuration.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +elementInteractions    // or `+AutocaptureOption.ELEMENT_INTERACTIONS`
    }
}

When you enable this setting, Amplitude tracks the [Amplitude] Element Interacted event whenever a user interacts with an element in the application.

Support for Jetpack Compose

Amplitude tracks user interactions with all clickable UI elements implemented in Jetpack Compose. Modifier.testTag is optional. Add it to @Composable functions to provide additional identification in the [Amplitude] Target Tag property. If no testTag is provided, Amplitude tracks the element with other available properties.

Use testTag for better element identification

While testTag is optional, Amplitude recommends that you identify specific Compose views that users clicked. The testTag property provides several benefits:

  • Precise element identification: helps distinguish between similar UI elements (like multiple buttons or cards) in your analytics data.
  • Stable tracking: provides a consistent identifier that doesn't change when you update or modify the UI structure or styling.
  • Easier analysis: enables easier filtering and analysis of interactions with specific elements in Amplitude charts.
  • Cross-platform consistency: helps you maintain consistent element naming across different platforms.
kotlin
// Example: Adding testTag for better identification
Button(
    onClick = { /* handle click */ },
    modifier = Modifier.testTag("login_button")
) {
    Text("Log In")
}

Card(
    onClick = { /* handle click */ },
    modifier = Modifier.testTag("product_card_${product.id}")
) {
    // Card content
}

When a user clicks these elements, the [Amplitude] Target Tag property contains the testTag value, making it easy to identify which specific element the user interacted with in your analytics data.

Track frustration interactions

Amplitude can track frustration interactions (Rage Clicks and Dead Clicks) with clickable UI elements in both Android Views and Jetpack Compose. To enable this option, include AutocaptureOption.FRUSTRATION_INTERACTIONS in the autocapture configuration.

kotlin
import com.amplitude.android.Amplitude

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +frustrationInteractions    // or `+AutocaptureOption.FRUSTRATION_INTERACTIONS`
    }
}

A rage click occurs when a user clicks the same element 4 or more times within 1 second, with each click no more than 50 device-independent pixels apart.

When a Rage Click occurs, Amplitude tracks the [Amplitude] Rage Click event.

A dead click is a user interaction on an interactive element that produces no visible change in the following 3 seconds.

When a Dead Click occurs, Amplitude tracks the [Amplitude] Dead Click event.

Configure frustration interaction types

Enabling FRUSTRATION_INTERACTIONS tracks both rage clicks and dead clicks. Use the interactionsOptions parameter to enable or disable each type individually.

kotlin
import com.amplitude.android.Amplitude
import com.amplitude.android.InteractionsOptions
import com.amplitude.android.RageClickOptions
import com.amplitude.android.DeadClickOptions

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = autocaptureOptions {
        +frustrationInteractions
    }
    interactionsOptions = InteractionsOptions(
        rageClick = RageClickOptions(enabled = true),
        deadClick = DeadClickOptions(enabled = false)
    )
}

Dead clicks require Session Replay

To track dead clicks, enable both Session Replay and frustration interactions.

Ignore specific elements from frustration analytics

Some UI elements generate expected rapid clicks or don't provide meaningful frustration signals. Use the ignore APIs to exclude these elements from frustration analytics while still tracking regular interaction events.

Common use cases:

  • Navigation elements: back buttons, close buttons, and drawer toggles.
  • Multi-click elements: increment/decrement buttons and like/favorite buttons.
  • Loading indicators: progress bars, spinners, and loading buttons.
  • Decorative elements: non-functional UI components.

Android Views

Use FrustrationAnalyticsUtils to ignore frustration analytics for Android Views:

kotlin
import com.amplitude.android.FrustrationAnalyticsUtils

// Ignore all frustration analytics for this view
val backButton = findViewById<Button>(R.id.back_button)
FrustrationAnalyticsUtils.ignoreFrustrationAnalytics(backButton)

// Ignore only rage clicks (allow dead click detection)
val incrementButton = findViewById<Button>(R.id.increment_button)
FrustrationAnalyticsUtils.ignoreFrustrationAnalytics(
    incrementButton,
    rageClick = true,
    deadClick = false
)

// Remove ignore marker from a view
FrustrationAnalyticsUtils.unignoreView(backButton)

Jetpack Compose

Use the Modifier.ignoreFrustrationAnalytics() extension to ignore frustration analytics for Compose elements:

kotlin
import com.amplitude.android.ignoreFrustrationAnalytics

// Ignore all frustration analytics
Button(
    onClick = { finish() },
    modifier = Modifier.ignoreFrustrationAnalytics()
) { Text("Back") }

// Ignore only dead clicks (allow rage click detection)
Button(
    onClick = { submitForm() },
    modifier = Modifier.ignoreFrustrationAnalytics(
        rageClick = false,
        deadClick = true
    )
) { Text("Submit") }

Parameter combinations

The SDK still tracks regular element interaction events ([Amplitude] Element Interaction) when you ignore frustration analytics. This affects only rage click and dead click events.

User groups

Amplitude supports assigning users to groups and running queries, such as Count by Distinct, on those groups. If at least one member of the group performs the specific event, the count includes the group.

For example, you want to group your users by organization using an orgId. Joe is in orgId 10, and Sue is in orgId 15. Both Sue and Joe perform a certain event. You can query their organizations in the Event Segmentation Chart.

When setting groups, define a groupType and groupName. In the previous example, orgId is the groupType and 10 and 15 are the values for groupName. Another example of a groupType is sport, with groupName values like tennis and baseball.

Setting a group also sets groupType:groupName as a user property and overwrites any existing groupName value for that user's groupType, along with the corresponding user property value. groupType is a string, and groupName is either a string or an array of strings to indicate that a user belongs to multiple groups.

If Joe is in orgId 15, the groupName is 15.

kotlin
// set group with a single group name
amplitude.setGroup("orgId", "15");

If Joe is in sport tennis and soccer, the groupName is ["tennis", "soccer"].

kotlin
// set group with multiple group names
amplitude.setGroup("sport", arrayOf("tennis", "soccer"))

You can also set event-level groups by passing an Event object with groups to track. With event-level groups, the group designation applies only to the specific event you log, and the designation doesn't persist on the user unless you explicitly set it with setGroup.

kotlin
val event = BaseEvent()
event.eventType = "event type"
event.eventProperties = mutableMapOf("event property" to "event property value")
event.groups = mutableMapOf("orgId" to "15")
amplitude.track(event)

Group identify

Use the Group Identify API to set or update the properties of particular groups. Note these considerations:

  • Updates affect only future events, and don't update historical events.
  • You can track up to 5 unique group types and 10 total groups.

The groupIdentify method accepts a group type string parameter, a group name object parameter, and an Identify object that Amplitude applies to the group.

kotlin
val groupType = "plan"
val groupName = "enterprise"

val identify = Identify().set("key", "value")
amplitude.groupIdentify(groupType, groupName, identify)

Track revenue

Amplitude can track revenue generated by a user. Amplitude tracks revenue through distinct revenue objects, which have special fields that Amplitude's Event Segmentation and Revenue LTV charts use. Revenue objects 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.

kotlin
val revenue = Revenue()
revenue.productId = "com.company.productId"
revenue.price = 3.99
revenue.quantity = 3
amplitude.revenue(revenue)

Custom user identifier

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

kotlin
amplitude.setUserId("user@amplitude.com")

Custom device identifier

Assign a new device ID using deviceId. When you set a custom device ID, make sure the value is sufficiently unique. Amplitude recommends using a UUID.

kotlin
import java.util.UUID

amplitude.setDeviceId(UUID.randomUUID().toString())

Reset when a user logs out

reset is a shortcut to anonymize users after they log out, by:

  • Setting userId to null.
  • Setting deviceId to a new value based on current configuration.

With an empty userId and a completely new deviceId, the current user appears as a brand new user in the dashboard.

kotlin
amplitude.reset()

SDK plugins

Plugins let you extend the Amplitude SDK's behavior, for example by modifying event properties (enrichment type) or sending to third-party APIs (destination type). A plugin is an object with methods setup() and execute().

Plugin.setup

This method contains logic for preparing the plugin for use and takes the amplitude instance as a parameter. The expected return value is null. A typical use for this method is to instantiate plugin dependencies. The SDK calls this method when the plugin is registered to the client through amplitude.add().

Plugin.execute

This method contains the logic for processing events and takes the event instance as a parameter. When used as an enrichment type plugin, the expected return value is the modified or enriched event. When used as a destination type plugin, the expected return value is a map with keys: event (BaseEvent), code (number), and message (string). The SDK calls this method for each event, including Identify, GroupIdentify, and Revenue events, that you instrument using the client interface.

Enrichment type plugin example

The following plugin modifies each instrumented event by adding an extra event property.

java
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.amplitude.core.Amplitude;
import com.amplitude.core.events.BaseEvent;
import com.amplitude.core.platform.Plugin;

import java.util.HashMap;

public class EnrichmentPlugin implements Plugin {
  public Amplitude amplitude;
  @NonNull
  @Override
  public Amplitude getAmplitude() {
    return this.amplitude;
  }

  @Override
  public void setAmplitude(@NonNull Amplitude amplitude) {
    this.amplitude = amplitude;
  }

  @NonNull
  @Override
  public Type getType() {
    return Type.Enrichment;
  }

  @Nullable
  @Override
  public BaseEvent execute(@NonNull BaseEvent baseEvent) {
    if (baseEvent.getEventProperties() == null) {
      baseEvent.setEventProperties(new HashMap<String, Object>());
    }
    baseEvent.getEventProperties().put("custom android event property", "test");
    return baseEvent;
  }

  @Override
  public void setup(@NonNull Amplitude amplitude) {
    this.amplitude = amplitude;
  }
}

amplitude.add(new EnrichmentPlugin());

Destination type plugin example

In a destination plugin, you can overwrite the track(), identify(), groupIdentify(), revenue(), and flush() functions.

java
import com.amplitude.core.Amplitude;
import com.amplitude.core.events.BaseEvent;
import com.amplitude.core.platform.DestinationPlugin;
import com.segment.analytics.Analytics;
import com.segment.analytics.Properties;

public class SegmentDestinationPlugin extends DestinationPlugin {
  android.content.Context context;
  Analytics analytics;
  String writeKey;
  public SegmentDestinationPlugin(android.content.Context appContext, String writeKey) {
    this.context = appContext;
    this.writeKey = writeKey;
  }
  @Override
  public void setup(Amplitude amplitude) {
    super.setup(amplitude);
    analytics = new Analytics.Builder(this.context, this.writeKey)
    .build();

    Analytics.setSingletonInstance(analytics);
    }

  @Override
  public BaseEvent track(BaseEvent event) {
    Properties properties = new Properties();
    for (Map.Entry<String,Object> entry : event.getEventProperties().entrySet()) {
      properties.putValue(entry.getKey(),entry.getValue());
    }
    analytics.track(event.eventType, properties);
    return event;
    }
}

amplitude.add(
new SegmentDestinationPlugin(this, SEGMENT_WRITE_KEY)
)

Network tracking plugin

The Network Tracking Plugin automatically tracks network requests and responses in your application. This plugin works with OkHttp and captures details about network calls including URLs, status codes, and timing information.

Installation

The Network Tracking Plugin requires the OkHttp dependency. To add it to your project:

groovy
dependencies {
    // OkHttp is required for the NetworkTrackingPlugin
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}

Configuration

Use the default configuration and add the plugin as an interceptor to integrate with OkHttp:

kotlin
import com.amplitude.core.network.NetworkTrackingPlugin

// Create the plugin with default configuration
val networkPlugin = NetworkTrackingPlugin()

// Add the plugin as an interceptor to your OkHttp client
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(networkPlugin)
    .build()

// Add the plugin to your Amplitude instance
amplitude.add(networkPlugin)

The default configuration tracks all hosts except *.amplitude.com with status codes 500 to 599.

Set NetworkTrackingOptions to customize tracking behavior and control which requests you track:

kotlin
import com.amplitude.android.Amplitude
import com.amplitude.core.network.NetworkTrackingOptions
import com.amplitude.core.network.NetworkTrackingPlugin
import com.amplitude.core.network.NetworkTrackingOptions.CaptureRule

// Create custom capture rules
val options = NetworkTrackingOptions(
    captureRules = listOf(
        // Track all responses from your API domain with status code from 400 to 599
        CaptureRule(
            hosts = listOf("*.example.com", "example.com"),
            statusCodeRange = (400..599).toList()
        )
    ),
    // Ignore specific domains
    ignoreHosts = listOf("analytics.example.com", "*.internal.com"),
    // Whether to ignore Amplitude API requests
    ignoreAmplitudeRequests = true
)

// Create the plugin with options
val networkPlugin = NetworkTrackingPlugin(options)

// Add the plugin to your Amplitude instance
amplitude.add(networkPlugin)

The captureRules and ignoreHosts properties are mutually exclusive. If both are set, ignoreHosts takes precedence. Amplitude matches incoming requests against the captureRules from bottom to top. For example, with this configuration:

kotlin
captureRules = listOf(
    CaptureRule(
        hosts = listOf("\*"),
        statusCodeRange = (400..599).toList()
    ),
    CaptureRule(
        hosts = listOf("\*.example.com", "example.com"),
        statusCodeRange = (500..599).toList()
    )
)

The SDK processes requests as follows:

  • A request to example.com with status code 503: matches last rule's hosts → matches statusCodeRange → captured
  • A request to example.com with status code 401: matches last rule's hosts → doesn't match statusCodeRange → ignored
  • A request to other.com with status code 401: doesn't match last rule's hosts → matches first rule's hosts → matches statusCodeRange → captured
  • A request to other.com with status code 200: doesn't match last rule's hosts → matches first rule's hosts → doesn't match statusCodeRange → ignored

Tracked event properties

When the plugin tracks a network request, it sends an event with the type [Amplitude] Network Request with the following properties:

Privacy considerations

The Network Tracking Plugin masks the following sensitive information by default:

  1. Authentication credentials in URLs (username:password@domain.com).
  2. Common sensitive query parameters (for example, username, password, email, phone).

Debugging

Confirm that the configuration and payload are accurate, and check for any unusual messages during debugging. If everything appears to be right, check the value of flushQueueSize or flushIntervalMillis. By default, the SDK queues and sends events in batches, so individual events don't dispatch to the server immediately. Wait for the SDK to send events to the server before checking for them in the charts.

Log

  • Set the log level to debug to collect useful information during debugging.
  • Customize the loggerProvider class from LoggerProvider and implement your own logic, such as logging error messages on a server in a production environment.

Plugins

Use a destination plugin to print the configuration value and event payload before sending them to the server. Set logLevel to debug, copy the following TroubleShootingPlugin into your project, then add the plugin to the Amplitude instance.

Event callback

The event callback runs after the SDK sends the event, for both successful and failed events. Use this method to monitor the event status and message. For more information, refer to the Callback configuration setting.

Advanced topics

User sessions

Amplitude starts a session when the app moves into the foreground or when the SDK tracks an event in the background. A session ends when the app remains in the background for more than the time set by setMinTimeBetweenSessionsMillis() without any tracked event. A session continues for the entire time the app is in the foreground, regardless of whether you enable session tracking through configuration.trackingSessionEvents, configuration.defaultTracking, or configuration.autocapture.

When the app enters the foreground, Amplitude tracks a session start, and starts a countdown based on setMinTimeBetweenSessionsMillis(). Amplitude extends the session and restarts the countdown any time it tracks a new event. If the countdown expires, Amplitude waits until the next event to track a session end event.

Amplitude doesn't set user properties on session events by default. To add these properties, use identify() and setUserId(). Amplitude aggregates the user property state and associates the user with events based on device_id or user_id.

Because of how Amplitude manages sessions, the SDK can work as expected even when events appear to be missing or session tracking appears inaccurate:

  • If a user doesn't return to the app, Amplitude doesn't track a session end event to correspond with a session start event.
  • If you track an event in the background, it's possible that Amplitude perceives the session length to be longer than the user spends on the app in the foreground.
  • If you modify user properties between the last event and the session end event, the session end event reflects the updated user properties, which may differ from other properties associated with events in the same session. To address this, use an enrichment plugin to set event['$skip_user_properties_sync'] to true on the session end event, which prevents Amplitude from synchronizing properties for that specific event. Refer to $skip_user_properties_sync in the Converter Configuration Reference article to learn more.

Amplitude groups events together by session. Events logged within the same session share the same session_id. Amplitude handles sessions automatically, so you don't have to manually call startSession() or endSession().

Adjust the time window for session extension. The default session expiration time is 30 minutes.

kotlin
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    minTimeBetweenSessionsMillis = 10000
}

By default, Amplitude automatically sends the [Amplitude] Start Session and [Amplitude] End Session events. Even when the SDK doesn't send these events, Amplitude still tracks sessions using session_id. You can also disable those session events.

kotlin
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    autocapture = setOf()
}

Use the helper method getSessionId to get the value of the current sessionId.

kotlin
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    minTimeBetweenSessionsMillis = 10000
}

You can also track events as out-of-session. Out-of-session events have a sessionId of -1 and behave as follows:

  1. They aren't part of the current session.
  2. They don't extend the current session.
  3. They don't start a new session.
  4. They don't change the sessionId for subsequent events.

A potential use case is events tracked from push notifications, which are usually external to the customer's app usage.

Set sessionId to -1 in EventOptions to mark an event as out-of-session when you call track(event, options) or identify(identify, options).

kotlin
val outOfSessionOptions = EventOptions().apply {
 sessionId = -1
}
amplitude.identify(
 Identify().set("user-prop", true),
 outOfSessionOptions
)
amplitude.track(
 BaseEvent().apply { eventType = "test event" },
 outOfSessionOptions
)

Log level

Control the level of logs that print to the developer console.

  • INFO: shows informative messages about events.
  • WARN: shows error messages and warnings. This level logs issues that might cause problems or oddities in the data. For example, this level displays a warning for properties with null values.
  • ERROR: shows error messages only.
  • DISABLE: suppresses all log messages.
  • DEBUG: shows error messages, warnings, and informative messages that may be useful for debugging.

Set the log level by calling setLogLevel with the level you want.

kotlin
amplitude.logger.logMode = Logger.LogMode.DEBUG

Logged out and anonymous users

Amplitude merges user data, so Amplitude links any events associated with a known userId or deviceId to the existing user. If a user logs out, Amplitude can merge that user's logged-out events to the user's record. You can change this behavior and log those events to an anonymous user instead.

To log events to an anonymous user:

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

Events coming from the current user or device appear as a new user in Amplitude. Note: if you do this, you can't see that the two users used the same device.

java
amplitude.reset()

Disable tracking

By default, the Android SDK tracks several user properties such as carrier, city, country, ip_address, language, and platform. Use the provided TrackingOptions interface to customize and toggle individual fields.

To use the TrackingOptions interface, import the class.

java
import com.amplitude.android.TrackingOptions

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

kotlin
val trackingOptions = TrackingOptions()
trackingOptions.disableCity().disableIpAddress().disableLatLng()

val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    this.trackingOptions = trackingOptions
}

You can individually control tracking for each field. Each field has a corresponding method (for example, disableCountry, disableLanguage).

Using TrackingOptions only prevents the SDK from tracking default properties on newly created projects, where you haven't sent data yet. If you have a project with existing data and you want to stop collecting the default properties, get help in the Amplitude Community. Disabling tracking doesn't delete any existing data in your project.

Carrier

Amplitude determines the user's mobile carrier using Android's TelephonyManager networkOperatorName, which returns the current registered operator of the tower.

COPPA control

You can enable or disable COPPA (Children's Online Privacy Protection Act) restrictions on IDFA, IDFV, city, IP address, and location tracking together. Apps that ask for information from children under 13 years of age must comply with COPPA.

kotlin
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    enableCoppaControl = true // Disables ADID, city, IP, and location tracking
}

Advertiser ID

The Android Advertising ID is a unique identifier provided by the Google Play store. Because it's unique to every person and not only to their devices, it's useful for mobile attribution. The Android Advertising ID is similar to the IDFA on iOS. Mobile attribution attributes an installation of a mobile app to its original source (such as an ad campaign or app store search). Users can choose to disable the Advertising ID, and apps targeted to children can't track at all.

Follow these steps to use Android Ad ID.

As of April 1, 2022, Google lets users opt out of Ad ID tracking. Ad ID may return null or error. You can use an alternative ID called App Set ID, which is unique to every app install on a device. For more information, refer to Google's Advertising ID documentation.

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

    bash
    dependencies {
      implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
    }
    
  2. AD_MANAGER_APP Permission If you use Google Mobile Ads SDK version 17.0.0 or higher, you need to add AD_MANAGER_APP to AndroidManifest.xml.

    xml <manifest> <application> <meta-data android:name="com.google.android.gms.ads.AD_MANAGER_APP" android:value="true"/> </application> </manifest>

  3. Add ProGuard exception

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

  4. AD_ID Permission

    When you update apps to target Android 13 or above, you must declare a Google Play services normal permission in the manifest file, as follows, to use the ADID as a deviceId:

    xml
    <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
    

    For more information, refer to Google's Advertising ID documentation.

Use the advertising ID as the device ID

After you set up the logic to fetch the advertising ID, enable useAdvertisingIdForDeviceId to use the advertising ID as the device ID.

kotlin
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
    useAdvertisingIdForDeviceId = true
}

App set ID

App set ID is a unique identifier for each app install on a device. The user resets app set ID manually when they uninstall the app, or it resets automatically after 13 months of not opening the app. Google designed app set ID as a privacy-friendly alternative to Ad ID for users who want to opt out of stronger analytics.

To use app set ID, follow these steps.

  1. Add play-services-appset as a dependency. For versions earlier than 2.35.3, use 'com.google.android.gms:play-services-appset:16.0.0-alpha1'

    bash
    dependencies {
    implementation 'com.google.android.gms:play-services-appset:16.0.2'
    }
    
    
  2. Enable to use app set ID as Device ID.

kotlin val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) { useAppSetIdForDeviceId = true }

Was this helpful?