Android SDK

Native Android SDK (Kotlin/Java) for rich push (16 styles), in-app messages, identity, event tracking with offline flush, lifecycle signals, remote variables, and inbox. Package com.growwise:growwise-sdk:1.2.0 · minSdk 21.

Overview

GrowWise initializes device registration (guest_id), analytics + sessions, notification channels, FCM (GrowWiseFirebaseService), and in-app lifecycle tracking.

  • Rich push notifications — 16 visual styles
  • In-app messages — interstitial / cover, screen-targeted
  • Identify users + traits; track events with SQLite offline cache
  • Install / open / update / crash lifecycle signals
  • Remote variables and inbox messages

Important FCM rule

Always send GrowWise campaigns in FCM’s data payload. Do not include a top-level notification block — Android may render the system notification and bypass rich SDK styles.

Prerequisites

  • GrowWise / TheGrowise API key (gk_…)
  • Firebase project with Cloud Messaging enabled
  • google-services.json for your applicationId
  • White notification icon drawable (e.g. ic_notification)

Add the SDK dependency

Maven (app/build.gradle.kts)kotlin
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("com.google.gms.google-services")
}

android {
    defaultConfig {
        minSdk = 21
        targetSdk = 35
    }
}

dependencies {
    implementation("com.growwise:growwise-sdk:1.2.0")
    implementation("com.google.firebase:firebase-messaging:24.1.0")
}
Local AARkotlin
dependencies {
    implementation(files("libs/growwise-release.aar"))
    implementation("com.google.firebase:firebase-messaging:24.1.0")
}

Firebase setup

  • Place google-services.json in the app module root
  • Apply the Google Services plugin
  • Ensure Firebase package name matches applicationId

Permissions

On Android 13+ (API 33+), request POST_NOTIFICATIONS at runtime.

Manifestxml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
Runtime (API 33+)kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    ActivityCompat.requestPermissions(
        this,
        arrayOf(Manifest.permission.POST_NOTIFICATIONS),
        REQUEST_CODE_NOTIFICATIONS
    )
}

Initialize in Application.onCreate()

Initialize as early as possible so background pushes and analytics work.

MyApplication.ktkotlin
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        val config = GrowWiseConfig.Builder(this)
            .setApiKey("YOUR_API_KEY")
            .setSmallIcon(R.drawable.ic_notification)
            .setDefaultChannelId("growwise_default")
            .setDefaultChannelName("General Notifications")
            .setAutoCreateChannels(true)
            .setLoggingEnabled(true) // disable in production
            .setLogLevel(GrowWiseLogLevel.DEBUG)
            .setAutoInitFcm(true)
            .build()

        GrowWise.initialize(this, config)
    }
}
AndroidManifestxml
<application
    android:name=".MyApplication"
    ... >

Identify users

Login / logoutkotlin
GrowWise.logIn(
    userId = "user_12345",
    traits = mapOf(
        "Name" to "Jane Doe",
        "Email" to "jane@example.com",
        "membership" to "Premium"
    )
)

if (GrowWise.isLoggedIn()) { /* identified */ }

GrowWise.logout() // clears identity and rotates guest_id

Track events

Events cache in SQLite, flush in batches (~every 5 events), and flush when backgrounded. Default props: $os, $platform, $app_version, $lib_version.

  • Automatic: app_install, App First Open, App Updated, app_open, notification_received, App Crashed
logEvent / trackkotlin
GrowWise.logEvent("app_opened")

GrowWise.logEvent(
    "product_viewed",
    mapOf(
        "item_id" to "sku_1001",
        "category" to "Electronics",
        "price" to 199.99
    )
)

GrowWise.track("checkout_started", mapOf("cart_value" to 499.0))

Notification callbacks

NotificationCallbackkotlin
GrowWise.setNotificationCallback(object : GrowWise.NotificationCallback {
    override fun onNotificationDisplayed(notificationId: Int, payload: NotificationPayload) { }
    override fun onNotificationClicked(payload: NotificationPayload) { }
    override fun onNotificationDismissed(payload: NotificationPayload) { }
    override fun onNotificationActionClicked(actionId: String, payload: NotificationPayload) { }
})

Optional APIs

Token, location, remote config, inboxkotlin
val token = GrowWise.getDeviceToken()
GrowWise.setPushToken(token ?: return)

GrowWise.setLocation(28.6139, 77.2090)
GrowWise.setOptOut(true)

GrowWise.fetchRemoteVariables("YOUR_PROJECT_ID") { success ->
    if (success) {
        val title = GrowWise.getRemoteVariableString("home_banner_title", "Welcome")
    }
}

GrowWise.getInboxMessages { messages -> /* ... */ }
GrowWise.markInboxMessageRead("message_id")

Custom FirebaseMessagingService

SDK ships GrowWiseFirebaseService. If you already have an FCM service, forward data messages.

Forward to GrowWisekotlin
class MyFirebaseService : FirebaseMessagingService() {
    override fun onMessageReceived(message: RemoteMessage) {
        val data = message.data
        if (data.isNotEmpty()) {
            val handled = GrowWise.handleFcmPayload(data)
            if (!handled) { /* non-GrowWise */ }
        }
    }

    override fun onNewToken(token: String) {
        GrowWise.setPushToken(applicationContext, token)
    }
}

Config builder reference

  • setApiKey(String) — required
  • setSmallIcon(Int) — required status-bar icon
  • setDefaultChannelId / setDefaultChannelName
  • setAutoCreateChannels(Boolean) — default true
  • setLoggingEnabled / setLogLevel
  • setAutoInitFcm(Boolean) — default true
  • setAppVersion / setLocation — optional

Push type values (data payload)

  • BASIC, BIG_TEXT, BIG_PICTURE, INBOX, MEDIA, MESSAGING, PROGRESS
  • CUSTOM_LAYOUT, ACTION_BUTTONS, DIRECT_REPLY, GROUPED
  • HEADS_UP, TIMER, CALL, BUBBLE, SILENT
BASIC data examplejson
{
  "to": "DEVICE_FCM_TOKEN",
  "priority": "high",
  "data": {
    "type": "BASIC",
    "title": "Hello from GrowWise",
    "body": "This is a data-only push.",
    "priority": "1"
  }
}

In-app payloads

Also delivered via FCM data. Types: INTERSTITIAL (modal), COVER (full screen). Optional targetActivity for screen targeting.

INTERSTITIALjson
{
  "data": {
    "campaignId": "inapp_sale_modal",
    "type": "INTERSTITIAL",
    "title": "Exclusive offer",
    "body": "Get 25% off with code GET25.",
    "imageUrl": "https://cdn.example.com/offer.jpg",
    "primaryButtonText": "Shop Now",
    "primaryButtonAction": "myapp://promotions/get25",
    "secondaryButtonText": "Maybe Later"
  }
}

Best practices

  • Initialize in Application.onCreate
  • logIn after auth; logout on sign-out
  • Data-only FCM; priority: high for time-sensitive pushes
  • White/alpha status-bar icon
  • Disable verbose logging in production
  • Request POST_NOTIFICATIONS on Android 13+
  • Test on real devices (OEM behaviour differs)

Troubleshooting

  • No notifications — permission, google-services.json, Logcat FCM
  • Tray but no sound — channel muted; use priority high; clear app data
  • Rich style missing — top-level FCM notification used; send data-only
  • Events missing — wrong API key / opt-out / wait for flush
  • adb logcat -s GrowWise:* FirebaseMessaging:*