# Android Developer Guide Beta Feature Mobile Push is currently in beta. Features, APIs, and implementation details may change before general availability. ## Overview This guide provides implementation requirements for integrating Engage Studio Mobile Push notifications in your Android app using the Treasure Data Android SDK. Your development team must implement the following functionality: 1. **FCM Integration**: Receive push notifications via Firebase Cloud Messaging 2. **Token Management**: Register and update device tokens with Treasure Data 3. **Notification Display**: Show notifications with images, action buttons, and deep links 4. **Event Tracking**: Track user interactions (delivery, open, dismiss, links) using Treasure Data SDK 5. **Automated Data Upload**: Treasure Data SDK automatically handles event upload to Treasure Data Sample Implementation Available A complete, production-ready sample application is available on GitHub: **[Treasure Data Mobile Push - Android Sample](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android)** The sample includes: - Complete Firebase Messaging Service implementation - Event tracking with Treasure Data SDK - Deep link and web link handling - Notification UI with action buttons and images Clone the repository and use it as a reference for your implementation. ## Requirements | Component | Requirement | | --- | --- | | **Minimum Android Version** | Android 8.0 (API 26) or later | | **Language** | Kotlin (recommended) or Java | | **Required Dependencies** | - Firebase Messaging SDK (via Firebase BoM 34.7.0+) - Treasure Data Android SDK 1.1.0+ - WorkManager 2.9.1+ (for background tasks) - Chrome Custom Tabs 1.8.0+ (for web link handling) | | **Tracked Events** | `delivery`, `open`, `dismiss`, `deeplink_open`, `link_open`, `token_register` | ## Architecture Overview ``` ┌─────────────────────┐ │ Engage Studio │ │ Campaign │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ Firebase Cloud │ │ Messaging (FCM) │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ Your Android App │ ├─────────────────────┤ │ MyFirebaseMessaging │ ← Receives notifications │ Service │ ├─────────────────────┤ │ PushEventReceiver │ ← Handles user actions ├─────────────────────┤ │ Treasure Data SDK │ ← Tracks and uploads events └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ Treasure Data │ │ Ingest API │ └─────────────────────┘ ``` ## Implementation Components Your Android app must implement the following components: ### 1. Application Class **Purpose:** Initialize Treasure Data SDK and configure app-wide settings **Key Responsibilities:** - Initialize Treasure Data SDK with API endpoint and database configuration - Configure automatic data collection settings - Enable debug logging (optional) **Reference:** See `MyApplication.kt` in the [sample repository](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android) ### 2. Firebase Messaging Service **Purpose:** Receive and display push notifications from FCM **Key Responsibilities:** - Listen for incoming FCM messages - Extract notification payload (title, body, image, links) - Display notification with action buttons - Track `delivery` events using Treasure Data SDK when notification is received - Handle FCM token updates **Reference:** See `MyFirebaseMessagingService.kt` in the [sample repository](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android) ### 3. Push Event Receiver **Purpose:** Handle user interactions with notifications **Key Responsibilities:** - Handle notification tap (main content) - Handle action button taps (web link, deep link) - Handle notification dismiss - Track corresponding events (`open`, `dismiss`, `link_open`, `deeplink_open`) using Treasure Data SDK - Open web URLs using Chrome Custom Tabs - Open deep links within the app **Reference:** See `PushEventReceiver.kt` in the [sample repository](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android) ### 4. FCM Token Service **Purpose:** Manage device token registration with Treasure Data **Key Responsibilities:** - Obtain current FCM token - Register token with Treasure Data when app launches using SDK - Re-register token when it's refreshed by FCM - Associate token with user ID when user logs in - Track `token_register` events **Reference:** See `FcmTokenService.kt` in the [sample repository](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android) ### 5. MainActivity Integration **Purpose:** Handle notification taps and deep links **Key Responsibilities:** - Receive notification tap intents - Track `open` events using Treasure Data SDK - Navigate to appropriate screen based on deep link - Open web URLs when specified **Reference:** See `MainActivity.kt` in the [sample repository](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android) ## Data Payload Schema Your app will receive the following JSON structure in the FCM `data` payload: ```json { "td_campaign_id": "cmp_20251214_promo", "title": "Special Offer!", "body": "Get 20% off your next purchase", "image_url": "https://cdn.example.com/banner.png", "link": "https://example.com/promo" } ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `td_campaign_id` | String | Yes | Unique campaign identifier from Engage Studio | | `title` | String | Yes | Notification title | | `body` | String | Yes | Notification body text | | `image_url` | String | No | URL for rich notification image | | `link` | String | No | Web URL to open in browser | ## Event Tracking Your app must track the following events and send them to Treasure Data: | Event Type | When to Track | Required Fields | | --- | --- | --- | | `delivery` | When notification is received and displayed | `campaign_id`, `platform`, `time` | | `open` | When user taps the notification | `campaign_id`, `platform`, `time`, `user_id` | | `dismiss` | When user dismisses the notification | `campaign_id`, `platform`, `time`, `user_id` | | `link_open` | When user taps a web link | `campaign_id`, `platform`, `time`, `user_id`, `value` (URL) | | `deeplink_open` | When user taps a deep link | `campaign_id`, `platform`, `time`, `user_id`, `value` (URI) | | `token_register` | When FCM token is obtained or refreshed | `fcm_token`, `platform`, `time`, `user_id` (if logged in) | All events are automatically sent by the Treasure Data SDK to the configured Treasure Data endpoint. The SDK handles batching, queuing, and retry logic automatically. See the [Push Events Table](/products/marketing-cloud/engage-studio/channels/mobile-push/push-events-table) documentation for complete schema details. ## Configuration Requirements ### AndroidManifest.xml Your app must declare: - `INTERNET` permission - `POST_NOTIFICATIONS` permission (Android 13+) - Firebase Messaging Service - Broadcast Receiver for notification actions - Deep link intent filters ### build.gradle.kts Required dependencies: - Firebase BoM: `34.7.0` or later - Firebase Messaging (version managed by BoM) - Treasure Data Android SDK: `1.1.0` or later - WorkManager: `2.9.1` or later - Chrome Custom Tabs: `1.8.0` or later Example dependency configuration: ```kotlin dependencies { // Firebase implementation(platform("com.google.firebase:firebase-bom:34.7.0")) implementation("com.google.firebase:firebase-messaging") implementation("com.google.firebase:firebase-analytics") // Treasure Data SDK implementation("com.treasuredata:td-android-sdk:1.1.0") // Background tasks implementation("androidx.work:work-runtime-ktx:2.9.1") // Web links implementation("androidx.browser:browser:1.8.0") } ``` ### local.properties Configure Treasure Data settings in `local.properties` (this file should be excluded from version control): ```properties TD_WRITE_KEY=your_write_api_key_here TD_DATABASE=mobile TD_TABLE=push_events TD_ENDPOINT=https://in.treasuredata.com ``` Access these properties in your `build.gradle.kts`: ```kotlin val localProperties = Properties() localProperties.load(FileInputStream(rootProject.file("local.properties"))) android { defaultConfig { buildConfigField("String", "TD_WRITE_KEY", "\"${localProperties["TD_WRITE_KEY"]}\"") buildConfigField("String", "TD_DATABASE", "\"${localProperties["TD_DATABASE"]}\"") buildConfigField("String", "TD_TABLE", "\"${localProperties["TD_TABLE"]}\"") buildConfigField("String", "TD_ENDPOINT", "\"${localProperties["TD_ENDPOINT"]}\"") } } ``` ### Notification Permissions For Android 13+ (API 33), request `POST_NOTIFICATIONS` permission at runtime. ## User ID Association To link push notification events with specific users: 1. **Logged-in users**: Include `user_id` (e.g., customer ID, email hash) in all events 2. **Anonymous users**: Pass `null` for `user_id` in events 3. **On login**: Send new `token_register` event with `user_id` to associate the device Treasure Data will link all previous events from the same `fcm_token` to the user. ## Testing ### Test Notification Delivery 1. Run your app on a device with Google Play Services 2. Check logcat for FCM token 3. Send test notification from Firebase Console 4. Verify notification appears on device ### Verify Event Tracking Query Treasure Data to confirm events are being logged: ```sql SELECT time, type, campaign_id, platform FROM mobile.push_events WHERE platform = 'android' ORDER BY time DESC LIMIT 100 ``` ## Security Best Practices 1. **API Keys**: - Never commit `local.properties` to source control - Add `local.properties` to `.gitignore` - Use write-only keys (not master keys) - Store sensitive configuration in `local.properties`, not in code 2. **Deep Links**: - Always validate deep link destinations - Implement URL allowlists for sensitive actions - Sanitize parameters before navigation 3. **Event Data**: - Do not include PII in event payloads - Use hashed or anonymized user IDs when possible 4. **Network Security**: - Always use HTTPS for API endpoints - Consider certificate pinning for production ## Troubleshooting ### Notifications Not Received - Verify FCM token is generated and uploaded - Check Google Play Services is installed and updated - Verify notification permissions (Android 13+) - Check `google-services.json` is in `app/` directory ### Events Not Appearing in Treasure Data - Verify `TD_WRITE_KEY` in `local.properties` is correct - Check `TD_ENDPOINT` matches your region - Verify database and table exist in Treasure Data - Check Treasure Data SDK is properly initialized in `MyApplication` - Enable debug logging to see SDK activity: `TreasureData.enableLogging()` ### Deep Links Not Working - Verify intent filter in AndroidManifest.xml - Test with: `adb shell am start -W -a android.intent.action.VIEW -d "myapp://test"` - Check URI format matches registered scheme ## Sample Repository Complete, production-ready implementation: **[https://github.com/treasure-data/engage-push-notification-sample/tree/main/android](https://github.com/treasure-data/engage-push-notification-sample/tree/main/android)** The repository includes: - Full source code with inline documentation - Gradle configuration with Treasure Data SDK integration - AndroidManifest.xml setup - Testing instructions - Security best practices - Example configuration files ## Implementation Guide This section provides detailed instructions for building and testing the sample application. ### Project Structure The sample repository follows this directory structure: ``` android/ ├── app/ │ ├── src/main/ │ │ ├── java/com/treasuredata/pushsample/ │ │ │ ├── MainActivity.kt # Deep link and notification handling │ │ │ ├── MyApplication.kt # App initialization & TD SDK setup │ │ │ ├── CategoryActivity.kt # Category view example │ │ │ ├── ProductDetailActivity.kt # Product detail example │ │ │ ├── fcm/ │ │ │ │ ├── MyFirebaseMessagingService.kt # FCM message receiver │ │ │ │ ├── PushEventReceiver.kt # Notification action handler │ │ │ │ ├── PushAction.kt # Action constants │ │ │ │ └── FcmTokenService.kt # Token management │ │ │ └── utils/ # Utility classes │ │ ├── res/ │ │ │ ├── layout/ │ │ │ ├── drawable/ │ │ │ └── values/ │ │ └── AndroidManifest.xml │ ├── build.gradle.kts │ └── google-services.json.example # Firebase config template ├── gradle/ ├── build.gradle.kts ├── local.properties.example # TD configuration template └── settings.gradle.kts ``` ### Build and Run Instructions #### Prerequisites - Android Studio Hedgehog (2023.1.1) or later - JDK 17 or later - Android SDK 26 (Android 8.0) or later #### Setup Steps 1. Clone the repository: ```bash git clone https://github.com/treasure-data/engage-push-notification-sample.git cd engage-push-notification-sample/android ``` 1. Open project in Android Studio: ```bash # Open Android Studio and select "Open an Existing Project" # Navigate to the android/ directory ``` 1. Configure Firebase: - Download `google-services.json` from your Firebase project - Copy it to `app/google-services.json` - Update `applicationId` in `app/build.gradle.kts` to match your Firebase app 2. Configure Treasure Data: - Copy `local.properties.example` to `local.properties` - Edit `local.properties` with your Treasure Data configuration: ```properties TD_WRITE_KEY=your_write_api_key_here TD_DATABASE=mobile TD_TABLE=push_events TD_ENDPOINT=https://in.treasuredata.com ``` - **Important:** Do not commit `local.properties` to version control 3. Sync Gradle: - Click "Sync Now" when prompted - Or File > Sync Project with Gradle Files 4. Build and run: ```bash # Via Gradle command line ./gradlew assembleDebug # Or use Android Studio Run button (Shift+F10) ``` ### Testing Workflow #### Prerequisites Before testing, ensure you have: - [ ] Firebase project with Android app registered - [ ] `google-services.json` downloaded and placed in `app/` directory - [ ] Treasure Data database and table created - [ ] Write-only API key obtained - [ ] Android emulator or physical device with Google Play Services #### Test on Emulator 1. Create/start Android emulator: ```bash # List available emulators emulator -list-avds # Start emulator emulator -avd Pixel_5_API_34 ``` 1. Install and run app: ```bash ./gradlew installDebug adb shell am start -n com.treasuredata.pushsample/.MainActivity ``` 1. Monitor logs for FCM token: ```bash adb logcat | grep -E "FCM token|FCMService" ``` Expected output: ``` I/FcmTokenService: FCM token: [your-device-token] I/FcmTokenService: Registering FCM token: [token] ``` 1. Send test notification from Firebase Console: - Open Firebase Console > Cloud Messaging - Click "Send your first message" - Enter title: "Test Notification" - Enter body: "This is a test" - Click "Send test message" - Paste your FCM token - Click "Test" 2. Verify notification appears in system tray 3. Tap notification and verify: - App opens (if closed) - `open` event is tracked - Deep link navigates correctly (if configured) #### Test on Physical Device 1. Enable Developer Options: - Settings > About phone > Tap "Build number" 7 times 2. Enable USB Debugging: - Settings > System > Developer options > USB debugging 3. Connect device via USB and install: ```bash # Verify device is connected adb devices # Install app ./gradlew installDebug # Launch app adb shell am start -n com.treasuredata.pushsample/.MainActivity ``` 1. Follow steps 3-6 from emulator testing above #### Test Notification Actions 1. Create test payload with actions in Firebase Console: - Add custom data fields: - `campaign_id`: `test_campaign_001` - `message_id`: `msg_001` - `deeplink`: `myapp://product/12345` - `link`: `https://example.com/promo` 2. Send notification and test: - Tap notification body → Verify `open` event - Tap web link → Verify Chrome Custom Tab opens - Tap deep link → Verify app navigation - Dismiss notification → Verify `dismiss` event #### Verify Event Tracking Query Treasure Data to confirm events are being logged: ```sql SELECT time, type, campaign_id, platform, user_id, value FROM mobile.push_events WHERE platform = 'android' AND time > td_time_add(now(), '-1h', 'JST') ORDER BY time DESC LIMIT 20 ``` Expected event sequence: 1. `token_register` - When app launches 2. `delivery` - When notification is received 3. `open` - When user taps notification 4. `link_open` - When user taps web link 5. `deeplink_open` - When user taps deep link 6. `dismiss` - When user dismisses notification #### Test Deep Links Test deep link handling using ADB: ```bash # Test product deep link adb shell am start \ -W -a android.intent.action.VIEW \ -d "myapp://product/12345" \ com.treasuredata.pushsample # Test category deep link adb shell am start \ -W -a android.intent.action.VIEW \ -d "myapp://category/electronics" \ com.treasuredata.pushsample ``` Verify app opens and navigates to correct screen. ### Implementation Checklist Use this checklist when implementing push notifications in your own app: #### Phase 1: Project Setup - [ ] Create Android project with minimum SDK 26 (Android 8.0) - [ ] Add Firebase dependencies in `build.gradle.kts` - [ ] Add WorkManager, OkHttp, Chrome Custom Tabs dependencies - [ ] Download and add `google-services.json` to `app/` directory - [ ] Apply `com.google.gms.google-services` plugin - [ ] Add required permissions in AndroidManifest.xml #### Phase 2: Manifest Configuration - [ ] Declare `INTERNET` permission - [ ] Declare `POST_NOTIFICATIONS` permission (Android 13+) - [ ] Register `MyFirebaseMessagingService` in manifest - [ ] Register `PushEventReceiver` broadcast receiver - [ ] Add intent filter for deep links in MainActivity - [ ] Configure notification channels (Android 8+) #### Phase 3: Core Components - [ ] Create `MyApplication` class for app initialization - [ ] Initialize Firebase in `onCreate` - [ ] Initialize Treasure Data SDK with endpoint, database, and API key - [ ] Configure TD SDK auto-tracking features (optional) - [ ] Implement `MyFirebaseMessagingService` - [ ] Implement `onMessageReceived` to handle FCM messages - [ ] Implement `onNewToken` to handle token refresh - [ ] Create `FcmTokenService` for token management #### Phase 4: Notification Display - [ ] Create notification channel with importance level - [ ] Build notification with title, body, icon - [ ] Add PendingIntent for notification tap - [ ] Add PendingIntent for notification dismiss - [ ] Download and attach images (if `image_url` present) - [ ] Add action buttons for links (if configured) - [ ] Show notification with NotificationManager #### Phase 5: Event Tracking - [ ] Track `delivery` event in `onMessageReceived` using TD SDK - [ ] Track `open` event when notification is tapped using TD SDK - [ ] Track `dismiss` event when notification is dismissed using TD SDK - [ ] Track `link_open` event for web link taps using TD SDK - [ ] Track `deeplink_open` event for app link taps using TD SDK - [ ] Track `token_register` event on app launch and token refresh using TD SDK #### Phase 6: User Interaction Handling - [ ] Create `PushEventReceiver` to handle broadcast intents - [ ] Handle `PUSH_OPEN` action in receiver - [ ] Handle `PUSH_DISMISS` action in receiver - [ ] Handle `PUSH_ACTION_LINK` action in receiver - [ ] Handle `PUSH_ACTION_DEEPLINK` action in receiver - [ ] Open Chrome Custom Tab for web links - [ ] Parse and navigate deep links in MainActivity #### Phase 7: Configuration and Security - [ ] Create `local.properties` with TD configuration - [ ] Add `local.properties` to `.gitignore` - [ ] Add `google-services.json` to `.gitignore` - [ ] Configure BuildConfig fields from `local.properties` - [ ] Implement error handling for TD SDK operations - [ ] Add ProGuard rules for Treasure Data SDK if using R8/ProGuard #### Phase 8: Testing - [ ] Request `POST_NOTIFICATIONS` permission at runtime (Android 13+) - [ ] Test notification delivery on emulator - [ ] Test notification delivery on physical device - [ ] Test notification images - [ ] Test notification action buttons - [ ] Test deep link navigation - [ ] Test web link opening with Chrome Custom Tabs - [ ] Verify events appear in Treasure Data - [ ] Test background notification handling - [ ] Test foreground notification handling ### Build Troubleshooting #### "google-services.json is missing" Error ```bash # Ensure file is in correct location ls app/google-services.json # Sync Gradle files ./gradlew --refresh-dependencies ``` #### "Manifest merger failed" Error - Check for duplicate permissions or activities in AndroidManifest.xml - Verify all library versions are compatible - Run `./gradlew clean` and rebuild #### Treasure Data SDK Not Uploading Events ```bash # Check SDK initialization logs adb logcat | grep TreasureData # Enable debug logging in MyApplication.kt: TreasureData.enableLogging() # Verify BuildConfig values are set correctly # Check build/generated/source/buildConfig/debug/.../BuildConfig.java ``` #### Notifications Not Appearing - Verify Google Play Services is installed on device/emulator - Check notification permission is granted (Android 13+) - Verify notification channel is created with correct importance - Check logcat for FCM errors: `adb logcat | grep FCM` #### Events Not Uploading to Treasure Data - Verify `TD_WRITE_KEY` in `local.properties` is correct - Check network connectivity - Verify `TD_ENDPOINT` matches your region - Check Treasure Data SDK logs: `adb logcat | grep TreasureData` - Verify SDK is initialized correctly in `MyApplication.onCreate()` - Try calling `TreasureData.sharedInstance().uploadEvents()` manually to force upload #### Deep Links Not Working ```bash # Verify intent filter is registered adb shell dumpsys package com.treasuredata.pushsample | grep -A 5 "scheme" # Test deep link manually adb shell am start -W -a android.intent.action.VIEW -d "myapp://test" ``` ### Gradle Commands Reference ```bash # Clean build ./gradlew clean # Build debug APK ./gradlew assembleDebug # Build release APK (requires signing config) ./gradlew assembleRelease # Install on connected device ./gradlew installDebug # Run unit tests ./gradlew testDebugUnitTest # Run instrumented tests ./gradlew connectedDebugAndroidTest # Check for dependency updates ./gradlew dependencyUpdates # Lint check ./gradlew lintDebug # Generate dependency tree ./gradlew app:dependencies ``` ## Next Steps 1. **Clone the sample repository** and review the implementation 2. **Configure Firebase** following the [Mobile Push Setup](/products/marketing-cloud/engage-studio/channels/mobile-push/mobile-push-setup) guide 3. **Implement the components** in your Android app 4. **Test notification delivery** and event tracking 5. **Review event data** in the [Push Events Table](/products/marketing-cloud/engage-studio/channels/mobile-push/push-events-table) 6. **Create your first campaign** in [Engage Studio](/products/marketing-cloud/engage-studio/channels/mobile-push) ## Related Documentation - [Mobile Push Setup](/products/marketing-cloud/engage-studio/channels/mobile-push/mobile-push-setup) - Firebase and Treasure Data configuration - [iOS Developer Guide](/products/marketing-cloud/engage-studio/channels/mobile-push/developer-guide-ios) - iOS implementation guide - [Push Events Table](/products/marketing-cloud/engage-studio/channels/mobile-push/push-events-table) - Event schema and analytics queries - [Campaign Creation](/products/marketing-cloud/engage-studio/channels/mobile-push) - Create Mobile Push campaigns