Title: Android SDK Locale: en URL: https://sensorswave.com/en/docs/data-integration/client-sdks/android/ Description: Android SDK integration guide and API reference The Sensors Wave Android SDK is a client-side data collection and AB testing tool designed for Android mobile applications. ## Core Features The Android SDK provides the following core capabilities: - **Event Tracking**: Manually track custom events and user behaviors - **AutoCapture**: Automatically collect app start, app end, page views, app install, and other events - **User Identification**: Support for Anonymous ID and Login ID identity association - **User Property Management**: Full User Property operations (set, append, increment, etc.) - **A/B Testing Integration**: Support for Feature Gate and experiment variable retrieval - **Batch Sending**: Optimized network request performance, sending up to 10 events in batches every 5 seconds - **Common Properties**: Support for static and dynamic common properties, automatically attached to all events ## System Requirements | Item | Requirement | |------|------| | **Minimum SDK Version** | API 21 (Android 5.0) | | **Target SDK Version** | API 34 (Android 14) | ## Installation ### Install via Maven Repository Add the dependency to your app module's `build.gradle` file: ```groovy dependencies { implementation 'com.sensorswave.android:SensorswaveSDK:0.1+' } ``` Or in the Kotlin DSL `build.gradle.kts` file: ```kotlin dependencies { implementation("com.sensorswave.android:SensorswaveSDK:0.1+") } ``` ## Quick Start ### 1. Add Required Permissions Add network permissions in your `AndroidManifest.xml`: ```xml ``` ### 2. Initialize the SDK Initialize the SDK in your Application class: ```kotlin class MyApplication : Application() { override fun onCreate() { super.onCreate() val config = SensorswaveConfig( apiHost = "https://your-api-host.com", autoCapture = true, enableAB = false ) Sensorswave.getInstance().setup( application = this, sourceToken = "your-source-token", config = config ) } } ``` Declare the Application class in `AndroidManifest.xml`: ```xml ... ``` ### 3. Set the User ID After initialization, set the user ID as soon as possible to ensure A/B testing and other features work correctly. ```kotlin // Set user ID (recommended approach) Sensorswave.getInstance().setLoginId("user_12345") // Or use identify (sends a binding event) Sensorswave.getInstance().identify("user_12345") ``` ### 4. Track Custom Events ```kotlin Sensorswave.getInstance().trackEvent("ButtonClick", mapOf( "button_name" to "submit", "page" to "home" )) ``` ## Configuration Options | Option | Type | Default | Description | |------|------|--------|------| | `apiHost` | `String` | `""` | API server address | | `autoCapture` | `Boolean` | `true` | Whether to auto-collect app events (page views, app start, app install, etc.) | | `enableClickTrack` | `Boolean` | `false` | Whether to enable automatic click tracking | | `enableAB` | `Boolean` | `false` | Whether to enable A/B testing | | `abRefreshInterval` | `Long` | `600000` | A/B testing configuration refresh interval (milliseconds), default 10 minutes | | `batchSend` | `Boolean` | `true` | Whether to use batch sending (every 5 seconds or every 10 events) | ### Complete Configuration Example ```kotlin val config = SensorswaveConfig( apiHost = "https://your-api-host.com", autoCapture = true, // Enable AutoCapture enableClickTrack = true, // Enable click tracking enableAB = true, // Enable A/B testing abRefreshInterval = 10 * 60 * 1000, // Refresh A/B test data every 10 minutes batchSend = true // Batch sending for performance ) Sensorswave.getInstance().setup( application = this, sourceToken = "your-source-token", config = config ) ``` > **Tip**: In production, selectively enable AutoCapture features based on actual needs to control data volume. ## API Methods ### Event Tracking #### trackEvent - Track Custom Events Manually track custom events and their properties. **Parameters**: - `eventName` (String, required): Event name - `properties` (Map, optional): Event properties **Example**: ```kotlin // Track a button click Sensorswave.getInstance().trackEvent("ButtonClick", mapOf( "button_name" to "submit", "page" to "home" )) ``` **Real-world examples**: ```kotlin // E-commerce: user views a product Sensorswave.getInstance().trackEvent("ProductView", mapOf( "product_id" to "12345", "product_name" to "Wireless Bluetooth Headphones", "category" to "Electronics", "price" to 299.00, "currency" to "CNY" )) // E-commerce: user adds to cart Sensorswave.getInstance().trackEvent("add_to_cart", mapOf( "product_id" to "12345", "quantity" to 1, "price" to 299.00 )) // Content platform: article read Sensorswave.getInstance().trackEvent("article_read", mapOf( "article_id" to "article_001", "title" to "Android Performance Optimization Tips", "category" to "Tech Blog", "read_duration" to 120 // Reading duration (seconds) )) ``` #### track - Advanced Event Tracking Send a fully-populated event object for more granular control. This method allows you to manually specify all event fields. **Parameters**: - `event` (AdvanceEvent, required): Full event object containing the following fields: - `event` (string, required): Event name - `properties` (mapOf, optional): Event properties - `time` (number, required): Timestamp (milliseconds) - `anon_id` (string, optional): Anonymous user ID - `login_id` (string, optional): Logged-in user ID. At least one of login_id or anon_id must be provided; when both are provided, login_id takes priority - `trace_id` (string, required): Request Trace ID - `user_properties` (mapOf, optional): User properties **Example**: ```kotlin Sensorswave.getInstance().track(mapOf( "event" to "purchase_completed", "properties" to mapOf( "product_id" to "12345", "amount" to 99.99, "currency" to "USD" ), "time" to System.currentTimeMillis(), "trace_id" to "unique-trace-id-12345", "login_id" to "user_12345" )) ``` > **Note**: The `track` method is an advanced feature. For most scenarios, `trackEvent` is sufficient. ### User Identification #### identify - Set Login User ID Set the Login user ID and send a binding event to associate anonymous behavior with the identified user. **Parameters**: - `loginId` (String, required): User's unique identifier (e.g., email, user ID, username) **Example**: ```kotlin // Set user ID after login Sensorswave.getInstance().identify("user_12345") ``` **Complete login flow example**: ```kotlin // User login flow fun handleUserLogin(email: String, password: String) { // Call login API apiService.login(email, password) { result -> when (result) { is Success -> { val userId = result.data.userId // Set user ID and associate anonymous behavior Sensorswave.getInstance().identify(userId) // Track login event Sensorswave.getInstance().trackEvent("user_login", mapOf( "login_method" to "email" )) } is Error -> { // Handle login failure } } } } ``` > **Important**: If the `loginId` contains sensitive information (such as phone numbers, email addresses, ID numbers, etc.), please encrypt it before transmission to avoid sending sensitive data in plain text. #### setLoginId - Set Login ID Only Set the Login user ID without sending a binding event. Use this if you only want to identify the user without associating their identity. **Parameters**: - `loginId` (String, required): User's unique identifier **Example**: ```kotlin Sensorswave.getInstance().setLoginId("user_12345") ``` > **Important**: If the `loginId` contains sensitive information (such as phone numbers, email addresses, ID numbers, etc.), please encrypt it before transmission to avoid sending sensitive data in plain text. > **Usage recommendations**: > - Use `identify` when the user logs in, as it records the user identity association event > - Use `setLoginId` when restoring a user session at app startup, to avoid unnecessary binding events ### User Properties User Properties describe user characteristics such as membership level, registration time, preferences, etc. Unlike Event Properties, User Properties are persistently stored and associated with the user. #### setProfile - Set User Properties Set User Properties, overwriting if they already exist. **Parameters**: - `properties` (Map, required): User properties to set **Example**: ```kotlin // Set User Properties after registration Sensorswave.getInstance().setProfile(mapOf( "name" to "John Doe", "age" to 30, "plan" to "premium" )) ``` #### setOnceProfile - Set Only Once Set User Properties only if they don't already exist; existing properties will not be overwritten. **Parameters**: - `properties` (Map, required): User properties to set **Example**: ```kotlin // Record first visit info (recorded once, never overwritten) Sensorswave.getInstance().setOnceProfile(mapOf( "signup_date" to "2024-01-15", "initial_referrer" to "google", "initial_campaign" to "spring_sale" )) ``` #### profileIncrement - Increment Numeric Properties Perform increment operations on numeric User Properties. Only supports numeric properties. **Parameters**: - `properties` (Map, required): Properties and their increment values **Example**: ```kotlin // Increment a single property Sensorswave.getInstance().profileIncrement(mapOf( "login_count" to 1 )) // Increment multiple properties Sensorswave.getInstance().profileIncrement(mapOf( "login_count" to 1, "points_earned" to 100, "purchases_count" to 1 )) ``` #### profileAppend - Append to Array Properties Append new values to array-type User Properties without deduplication. **Parameters**: - `properties` (Map, required): Properties and their array values to append **Example**: ```kotlin Sensorswave.getInstance().profileAppend(mapOf( "categories_viewed" to listOf("electronics", "mobile_phones"), "tags" to listOf("new_customer", "q1_2024") )) ``` #### profileUnion - Append to Set Properties (Deduplicated) Append new values to array-type User Properties with automatic deduplication. **Parameters**: - `properties` (Map, required): Properties and their array values to append **Example**: ```kotlin // First call Sensorswave.getInstance().profileUnion(mapOf( "interests" to listOf("technology", "gaming") )) // Second call, "technology" will not be added again Sensorswave.getInstance().profileUnion(mapOf( "interests" to listOf("technology", "music") // Only "music" will be added )) ``` #### profileUnset - Delete Specified Properties Set specified User Properties to null. **Parameters**: - `key` (String, required): Single property name to delete - or - `keys` (List, required): List of property names to delete **Example**: ```kotlin // Delete a single property Sensorswave.getInstance().profileUnset("temporary_campaign") // Delete multiple properties Sensorswave.getInstance().profileUnset(listOf("old_plan", "expired_flag", "temp_id")) ``` #### profileDelete - Delete All User Properties Delete all User Property data for the current user. This operation is irreversible. **Example**: ```kotlin // Delete all User Properties when the user deactivates their account Sensorswave.getInstance().profileDelete() ``` > **Warning**: `profileDelete` deletes all User Properties. Use with caution. #### User Property Usage Example **Membership upgrade scenario**: ```kotlin fun handleMembershipUpgrade(newPlan: String) { // Update membership level and upgrade time Sensorswave.getInstance().setProfile(mapOf( "plan" to newPlan, "upgrade_time" to System.currentTimeMillis().toString() )) // Increment upgrade count Sensorswave.getInstance().profileIncrement(mapOf( "upgrade_count" to 1 )) // Track upgrade event Sensorswave.getInstance().trackEvent("membership_upgrade", mapOf( "from_plan" to "basic", "to_plan" to newPlan )) } ``` ### Common Properties Common properties are automatically added to all events, suitable for universal information that should be included in every event. Supports static properties (fixed values) and dynamic properties (function return values). #### registerCommonProperties - Register Common Properties Register static or dynamic common properties that will be automatically included in all events. **Parameters**: - `properties` (Map, required): Properties to register - Static property: non-function type value - Dynamic property: function type value (returns `() -> Any`), evaluated for each event **Example**: ```kotlin Sensorswave.getInstance().registerCommonProperties(mapOf( // Static properties "app_version" to "1.0.0", "environment" to "production", // Dynamic properties (evaluated for each event) "current_time" to { System.currentTimeMillis() }, "user_session_id" to { getSessionId() } )) ``` #### clearCommonProperties - Clear Common Properties Remove specified registered common properties. **Parameters**: - `keys` (List, required): List of property names to remove **Example**: ```kotlin Sensorswave.getInstance().clearCommonProperties(listOf("app_version", "user_session_id")) ``` > **Note**: Common properties increase the data size of every event. Only add truly necessary universal properties. ### A/B Testing The Android SDK has built-in A/B testing support for retrieving Feature Gate states and experiment variables. #### Enable A/B Testing ```kotlin val config = SensorswaveConfig( apiHost = "https://your-api-host.com", enableAB = true, // Enable A/B testing abRefreshInterval = 10 * 60 * 1000 // Configuration refresh interval (default 10 minutes) ) ``` #### checkFeatureGate - Check Feature Gate Check whether a Feature Gate is enabled for the current user. **Parameters**: - `key` (String, required): Key of the Feature Gate - `callback` (Boolean -> Unit, required): Callback function returning the Feature Gate state **Example**: ```kotlin // Check if a feature is enabled Sensorswave.getInstance().checkFeatureGate("new_checkout_flow") { isEnabled -> if (isEnabled) { // Show new feature showNewCheckout() } else { // Show old feature showOldCheckout() } } ``` #### getExperiment - Get Experiment Variables Get the current user's experiment variable data. **Parameters**: - `key` (String, required): Key of the Experiment - `callback` (Map? -> Unit, required): Callback function returning the experiment configuration **Returns**: - `Map?`: Experiment configuration object containing the experiment's variable configuration values **Example**: ```kotlin // Get experiment configuration Sensorswave.getInstance().getExperiment("homepage_layout") { experiment -> if (experiment != null) { // Apply experiment configuration val layoutType = experiment["layout_type"] as? String applyLayout(layoutType) } } // Get specific fields from experiment configuration Sensorswave.getInstance().getExperiment("pricing_display") { experiment -> if (experiment != null) { val priceFormat = experiment["price_format"] as? String val discountType = experiment["discount_type"] as? String updatePricingDisplay(priceFormat, discountType) } } ``` **Complete A/B testing example**: ```kotlin // E-commerce homepage CTA button A/B test fun initHomepageCTA() { Sensorswave.getInstance().getExperiment("homepage_cta_test") { experiment -> if (experiment != null) { val buttonText = experiment["button_text"] as? String ?: "Buy Now" val buttonColor = experiment["button_color"] as? String ?: "#ff6600" val buttonSize = experiment["button_size"] as? String ?: "16px" // Apply experiment configuration val ctaButton: Button = findViewById(R.id.cta_button) ctaButton.text = buttonText ctaButton.setBackgroundColor(Color.parseColor(buttonColor)) ctaButton.textSize = buttonSize.toFloatOrNull() ?: 16f } } } // Call during Activity or Fragment initialization override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initHomepageCTA() } ``` > **Tip**: A/B testing features require configuring experiments and Feature Gates in the Sensors Wave dashboard before use. ### SDK Management #### isInitialized - Check SDK Initialization Check whether the SDK has been successfully initialized. **Returns**: Boolean **Example**: ```kotlin if (Sensorswave.getInstance().isInitialized()) { // SDK is initialized, safe to call Sensorswave.getInstance().trackEvent("custom_event", properties) } else { Log.w("MyApp", "SDK not initialized") } ``` #### destroy - Destroy SDK Instance Destroy the SDK instance and release all resources. After calling this method, you must call `setup()` again to use the SDK. **Functions**: 1. Clean up the batch sender 2. Deactivate and clean up all plugins 3. Clear common properties 4. Reset initialization state ## AutoCapture When AutoCapture is enabled, the SDK automatically collects the following event types: | Event Name | Description | Trigger Timing | |---------|------|---------| | `$AppInstall` | First app install | On first app installation | | `$AppStart` | App start | When the app starts | | `$AppEnd` | App end | When the app exits | | `$AppPageView` | Page view | When an Activity switches | | `$AppPageLeave` | Page leave | When an Activity switches | | `$AppClick` | Element click | When a user clicks an element (requires `enableClickTrack`) | ### Enable AutoCapture ```kotlin val config = SensorswaveConfig( apiHost = "https://your-api-host.com", autoCapture = true, // Enable AutoCapture enableClickTrack = true // Enable automatic click tracking ) ``` > **Tip**: AutoCapture can significantly reduce manual coding effort but increases data volume. Enable selectively based on actual needs. ## Best Practices ### Initialization Timing Initialize the SDK in the Application's `onCreate()` to ensure the SDK is available when the app starts. ```kotlin class MyApplication : Application() { override fun onCreate() { super.onCreate() val config = SensorswaveConfig( apiHost = "https://your-api-host.com", autoCapture = true ) Sensorswave.getInstance().setup(this, "your-source-token", config) // Set user ID as soon as possible val userId = getUserIdFromPrefs() if (userId.isNotEmpty()) { Sensorswave.getInstance().setLoginId(userId) } } } ``` ### User ID Setting Timing **Recommended**: Call `setLoginId()` or `identify()` immediately after user login. ```kotlin // After user login succeeds fun onLoginSuccess(userId: String) { // Save user ID saveUserId(userId) // Set SDK user ID Sensorswave.getInstance().setLoginId(userId) } ``` **Method comparison**: | Method | Sends Event | Use Case | |------|------------|---------| | `identify()` | Yes | When user logs in, need to record identity association event | | `setLoginId()` | No | When restoring user session at app startup | ### A/B Testing Integration Ensure user ID is set before calling A/B testing methods (if the allocation subject is Login ID): ```kotlin // 1. Initialize the SDK first Sensorswave.getInstance().setup(this, "your-source-token", config) // 2. Set user ID Sensorswave.getInstance().setLoginId(userId) // 3. Then use A/B testing features Sensorswave.getInstance().checkFeatureGate("new_feature") { isEnabled -> if (isEnabled) { enableNewFeature() } } ``` ### Using Common Properties Register app-level information as common properties to avoid repeating them in every event: ```kotlin Sensorswave.getInstance().registerCommonProperties(mapOf( "app_version" to BuildConfig.VERSION_NAME, "device_model" to android.os.Build.MODEL, "os_version" to android.os.Build.VERSION.RELEASE )) ``` ### Error Handling All SDK methods have built-in error handling, but adding extra checks is recommended: ```kotlin if (Sensorswave.getInstance().isInitialized()) { Sensorswave.getInstance().trackEvent("custom_event", properties) } else { Log.w("MyApp", "SDK not initialized") } ``` ## Important Notes ### Performance Optimization - Avoid calling `trackEvent` frequently in loops; consider merging events or using throttling - Batch sending is enabled by default, effectively reducing network requests - AutoCapture adds some performance overhead; enable only when needed ### Data Security - Do not pass sensitive information in event properties (e.g., passwords, credit card numbers, ID numbers) - Keep the Source Token secure; avoid exposing it in public code repositories - The SDK uses HTTPS to encrypt all transmitted data - User data is stored locally in SharedPreferences ### Data Loss Risk - Mobile tracking may be affected by network conditions, with approximately 5-10% data loss risk - For critical business data, server-side tracking is recommended. See [Tracking Strategy](../tracking-strategy.mdx) ## FAQ ### Why does A/B testing return an empty configuration? Check the following: 1. **Is A/B testing enabled**: Confirm `enableAB = true` 2. **Is the network connection working**: Confirm the device has a normal network connection 3. **Is the user ID set**: Confirm `setLoginId()` or `identify()` has been called 4. **Is the experiment configured on the server**: Confirm the corresponding experiment or Feature Gate is configured in the Sensors Wave dashboard ### What should I do when event sending fails? The SDK automatically retries failed events. Check the following: 1. **Network connection**: Confirm the device has a normal network connection 2. **Reporting endpoint**: Confirm the `apiHost` configuration is correct 3. **Network permissions**: Confirm `INTERNET` and `ACCESS_NETWORK_STATE` permissions have been added 4. **Debug mode**: Enable `debug` mode to view detailed logs ### How do I debug the SDK? Configure debug mode and check logs with the tag `SensorsWaveSDK` in Logcat to view detailed runtime information. ### What's the difference between batch sending and real-time sending? | Sending Mode | Description | Use Case | |---------|------|---------| | **Batch Sending** | Events are cached and sent in batches every 5 seconds or every 10 events | Most scenarios; reduces network requests | | **Real-time Sending** | Each event is sent immediately | Scenarios requiring real-time data | ## Related Documentation - [Tracking Strategy](../tracking-strategy.mdx): Understand the pros and cons of server-side and client-side tracking - [How to Properly Identify Users](../user-identification.mdx): Best practices for user identity recognition - [Data Model](../data-model.mdx): Understand the Sensors Wave data structure - [Events and Properties](../events-and-properties.mdx): Event design guidelines and best practices --- **Last updated**: January 19, 2026 **License**: Apache-2.0