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
| Setting | Required value |
|---|---|
compileSdk | 34+ |
minSdk | 24+ |
kotlinVersion | 1.9+ |
coreLibraryDesugaring | optional, 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
| Option | Type | Default |
|---|---|---|
writeKey | String | — |
environment | Environment | PRODUCTION |
apiUrl | String? | null |
debug | Boolean | false |
flushIntervalMs | Long | 15_000 |
flushBatchSize | Int | 100 |
maxQueueSize | Int | 1000 |
triggerSyncIntervalMs | Long | 300_000 |
presentationPaused | Boolean | false |
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()Consent
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")
}Deep-link survey
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
| Method | What 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 APIs | Feature 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. |