Android SDK (Kotlin)

For account IDs, backend-verified guests, token expiry, property updates, and logout, see the identity integration guide. The lifecycle APIs documented there require 0.1.4 or later.

Production   minSdk 24 · Kotlin 1.9+

com.usergist:feedback provides authenticated anonymous and identified subjects, offline queues, consent controls, locally targeted campaigns, native surveys, feature requests, and host-compatible FCM integration.

Startup presentation readiness

Initialize with presentationPaused = true at app launch. Analytics, consent, identity, and networking continue while campaign UI waits. After the existing startup loading and navigation have finished and the loaded screen is visible, call resumePresentation(). Mount any required UserGist UI provider before that callback. Readiness must work for both anonymous and identified users.

Call pausePresentation() before another flow that must not be interrupted. Pausing does not dismiss an already visible SDK surface. Queued feedback, surveys, and in-app messages are discarded if their consent is withdrawn or the user changes, even if consent is granted again before resuming. Repeated initialization keeps the first readiness setting; repeated resume calls do not show the same queued work twice. The option defaults to false for existing integrations, so upgrading alone does not enable startup deferral.

Do not resume from a splash screen, an app-root mount that still shows loading, a disappearing screen, or a fixed timer. Use the host's existing completion callback; the SDK cannot infer when arbitrary startup navigation has finished.

// After the loaded screen and startup navigation are ready:
UserGist.resumePresentation()

Install

// settings.gradle.kts
dependencyResolutionManagement {
  repositories {
    mavenCentral()
    google()
  }
}
 
// app/build.gradle.kts
dependencies {
  implementation("com.usergist:feedback:0.1.4")
}

Build configuration

SettingRequired value
compileSdk34+
minSdk24+
kotlinVersion1.9+
coreLibraryDesugaringoptional, but recommended

The SDK declares its own ProGuard / R8 keep rules via consumer-rules.pro — you don't need to add anything.

Initialise

Subclass Application (or do it inside your Application class) and call UserGist.initialize once at process start.

import android.app.Application
import studio.usergist.feedback.UserGist
import studio.usergist.feedback.api.Environment
import studio.usergist.feedback.push.Push
 
class MyApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    UserGist.initialize(
      context = this,
      writeKey = "rk_live_REPLACE_ME",
      environment = Environment.PRODUCTION,
      debug = BuildConfig.DEBUG,
      presentationPaused = true,
    )
    Push.registerDefaultChannels(this)
  }
}

Wire the application class in AndroidManifest.xml:

<application
  android:name=".MyApplication"
  ...
>

Init options

OptionTypeDefault
writeKeyString
environmentEnvironmentPRODUCTION
apiUrlString?null
debugBooleanfalse
flushIntervalMsLong15_000
flushBatchSizeInt100
maxQueueSizeInt1000
triggerSyncIntervalMsLong300_000
presentationPausedBooleanfalse

Identity & events

UserGist.identify(
  userId = "user_42",
  subjectToken = subjectToken,
  properties = mapOf("plan" to "pro"),
)
 
UserGist.track("checkout_completed", mapOf("orderId" to "ord_991", "amountUsd" to 49))
 
// On logout
UserGist.reset()
UserGist.setConsent(Consent(
  analytics = true,
  feedback = true,
  push = false,
  survey = true,
))

Surveys

UserGist.getAvailableSurveys { surveys ->
  val first = surveys.firstOrNull() ?: return@getAvailableSurveys
  UserGist.openSurvey(first.id)
}
 
UserGist.onResponse = { info ->
  Log.d("UserGist", "Survey ${info.surveyId} response")
}
override fun onNewIntent(intent: Intent) {
  super.onNewIntent(intent)
  intent.data?.let { UserGist.handleSurveyDeepLink(it) }
}

Push notifications (FCM)

1. Add Firebase to your app

Follow the standard Firebase setup (add google-services.json, apply the Google Services plugin).

2. Forward FCM tokens

In your FirebaseMessagingService:

class MyFcmService : FirebaseMessagingService() {
  override fun onNewToken(token: String) {
    Push.didReceiveFcmToken(token)
  }
 
  override fun onMessageReceived(message: RemoteMessage) {
    if (Push.handleSilentIfPresent(message.data)) return
    Push.handleReceived(
      data = message.data,
      title = message.notification?.title,
      body = message.notification?.body,
    )
  }
}

3. Notification channels

Android 8+ requires channels. The SDK ships defaults that match the userGist push categories — call registerDefaultChannels at startup (as in the init snippet above) or register your own and pass their IDs to dashboard campaigns.

4. Permission (Android 13+)

Request Manifest.permission.POST_NOTIFICATIONS from your Activity on Android 13+ using AndroidX's Activity Result API, then forward each FCM token through Push.didReceiveFcmToken(token).

Theming

UserGist.setThemeOverrides(PromptTheme(
  colors = ThemeColors(primary = "#6C5CE7", background = "#0B1220"),
  radius = 12,
))

Public surface

MethodWhat it does
initialize(...)Boots the SDK.
identify(userId, subjectToken, properties?)Securely link a stable user ID.
track(eventName, properties?)Queue an event.
setConsent(consent)Gate subsystems.
reset()Clear state.
flush()Force flush.
setDebug(enabled)Toggle logs.
setThemeOverrides(theme)Brand the in-SDK UI.
getAvailableSurveys(cb)List targeted surveys.
openSurvey(id, language?)Render a survey.
handleSurveyDeepLink(uri)Deep-link opener.
getRequests(...), submitRequest(...), voteOnRequest(...), followRequest(...), comment APIsFeature request board.
Push.didReceiveFcmToken(token)Register an FCM token.
Push.invalidateDeviceToken(token)Invalidate a rotated or disabled token.
Push.handleSilentIfPresent(data)Ack a silent ping and tell the host to suppress UI.
Push.handleReceived(data, title, body)Forward a received userGist payload.
Push.registerDefaultChannels(context)Create the default Android channels.

What's next