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.
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.
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.
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:
- GzipRequestInterceptor - OkHttp interceptor that compresses request bodies.
- CustomOkHttpClient -
HttpClientInterfaceimplementation using OkHttp.
To use the custom client:
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.
amplitude.track("Song Played")
You can also optionally include event properties.
amplitude.track(
"Song Played",
mutableMapOf<String, Any?>("title" to "Happy Birthday")
)
For more complex events you can create and track a BaseEvent object.
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.
val identify = Identify()
identify.set("color", "green")
amplitude.identify(identify)
Identify operations
The Identify object supports the following operations:
| Operation | Description |
|---|---|
set | Sets the value of a user property. Overwrites existing values. |
setOnce | Sets the value of a user property only once. Subsequent calls don't overwrite the initial value. |
add | Adds a numeric value to a numeric user property. |
append | Appends a value to a user property array. |
prepend | Prepends a value to a user property array. |
preInsert | Adds a value to the beginning of a user property array if it doesn't already exist in the array. |
postInsert | Adds a value to the end of a user property array if it doesn't already exist in the array. |
remove | Removes a value from a user property array. |
unset | Removes a user property. |
clearAll | Clears all user properties. |
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.
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.
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:
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.
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.
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.
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.
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.
Track deep links
Enable deep link event tracking by including AutocaptureOption.DEEP_LINKS in the autocapture configuration. Refer to the following code sample.
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.
Handle deep links in single-task activities
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.
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.
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.
// 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.
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.
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:
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:
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
rageClick | deadClick | Behavior |
|---|---|---|
true (default) | true (default) | Ignore all frustration analytics |
true | false | Ignore only rage click detection |
false | true | Ignore only dead click detection |
false | false | Track both (doesn't ignore anything) |
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.
// set group with a single group name
amplitude.setGroup("orgId", "15");
If Joe is in sport tennis and soccer, the groupName is ["tennis", "soccer"].
// 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.
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.
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.
val revenue = Revenue()
revenue.productId = "com.company.productId"
revenue.price = 3.99
revenue.quantity = 3
amplitude.revenue(revenue)
| Name | Description |
|---|---|
productId | Optional. String. An identifier for the product. Amplitude recommends something like the Google Play Store product ID. Defaults to null. |
quantity | Required. Integer. The quantity of products purchased. revenue = quantity * price. Defaults to 1 |
price | Required. Double. The price of the products purchased, and this can be negative. revenue = quantity * price. Defaults to null. |
revenueType | Optional, but required for revenue verification. String. The revenue type (for example, tax, refund, income). Defaults to null. |
receipt | Optional. String. The receipt identifier of the revenue. For example, 123456. Defaults to null. |
receiptSignature | Optional, but required for revenue verification. String. Defaults to null. |
Custom user identifier
If your app has its own login system that you want to track users with, call setUserId at any time.
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.
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
userIdtonull. - Setting
deviceIdto 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.
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.
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.
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:
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:
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:
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:
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.comwith status code 503: matches last rule's hosts → matches statusCodeRange → captured - A request to
example.comwith status code 401: matches last rule's hosts → doesn't match statusCodeRange → ignored - A request to
other.comwith status code 401: doesn't match last rule's hosts → matches first rule's hosts → matches statusCodeRange → captured - A request to
other.comwith 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:
| Property | Description |
|---|---|
[Amplitude] URL | The URL of the network request with sensitive information masked. |
[Amplitude] URL Query | The query parameters of the URL. |
[Amplitude] URL Fragment | The fragment identifier of the URL. |
[Amplitude] Request Method | The HTTP method used for the request (GET, POST, etc.). |
[Amplitude] Status Code | The HTTP status code of the response. |
[Amplitude] Error Message | The local error message if the request failed with out a status code. |
[Amplitude] Start Time | The timestamp when the request started, in milliseconds since Unix epoch. |
[Amplitude] Completion Time | The timestamp when the request completed, in milliseconds since Unix epoch. |
[Amplitude] Duration | The duration of the request in milliseconds. |
[Amplitude] Request Body Size | The size of the request body in bytes. |
[Amplitude] Response Body Size | The size of the response body in bytes. |
Privacy considerations
The Network Tracking Plugin masks the following sensitive information by default:
- Authentication credentials in URLs (username:password@domain.com).
- 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
loggerProviderclass fromLoggerProviderand 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']totrueon 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.
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.
val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) {
autocapture = setOf()
}
Use the helper method getSessionId to get the value of the current sessionId.
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:
- They aren't part of the current session.
- They don't extend the current session.
- They don't start a new session.
- They don't change the
sessionIdfor 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).
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.
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:
- Set the
userIdto null. - 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.
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.
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.
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).
| Method | Description |
|---|---|
disableAdid() | Disable tracking of Google ADID |
disableAppSetId() | Disable tracking of App Set Id |
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 |
disableTrackDeviceManufacturer() | Disable tracking of device manufacturer |
disableDma() | Disable tracking of user's designated market area (DMA). |
disableIpAddress() | Disable tracking of user's IP address |
disableLanguage() | Disable tracking of device's language |
disableLatLng() | Disable tracking of user's current latitude 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 region. |
disableVersionName() | Disable tracking of your app's version name |
disableApiLevel | Disable tracking of Android API level |
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.
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.
Add
play-services-ads-identifieras a dependency.bashdependencies { implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' }AD_MANAGER_APPPermission If you use Google Mobile Ads SDK version 17.0.0 or higher, you need to addAD_MANAGER_APPtoAndroidManifest.xml.xml <manifest> <application> <meta-data android:name="com.google.android.gms.ads.AD_MANAGER_APP" android:value="true"/> </application> </manifest>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.profor the classes fromplay-services-ads.-keep class com.google.android.gms.ads.** { *; }AD_IDPermissionWhen 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.
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.
Add
play-services-appsetas a dependency. For versions earlier than 2.35.3, use'com.google.android.gms:play-services-appset:16.0.0-alpha1'bashdependencies { implementation 'com.google.android.gms:play-services-appset:16.0.2' }Enable to use app set ID as Device ID.
kotlin val amplitude = Amplitude(AMPLITUDE_API_KEY, applicationContext) { useAppSetIdForDeviceId = true }
Was this helpful?