Android
Install the SignalSeal Android SDK in your Kotlin or Java app.
The SignalSeal Android SDK reports installs, sends events, and powers in-app attribution.
Requirements
- Android 5.0 (API 21) or higher
- Kotlin or Java 17 toolchain
Install
Add the SDK to your app module's build.gradle.kts:
dependencies {
implementation("io.github.signalseal:signalseal-android-sdk:0.2.5")
}Or in build.gradle:
dependencies {
implementation 'io.github.signalseal:signalseal-android-sdk:0.2.5'
}The SDK declares INTERNET, ACCESS_NETWORK_STATE, and
com.google.android.gms.permission.AD_ID permissions in its manifest;
they merge into your app automatically.
Initialize
Call configure(...) once in Application.onCreate().
import net.signalseal.attribution.SignalSealSDK
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
SignalSealSDK.configure(
context = this,
apiKey = "ak_android_..."
)
}
}Don't forget to register your Application class in the manifest:
<application android:name=".MyApp" ... >Configuration parameters
fun configure(
context: Context,
apiKey: String,
isDebug: Boolean = false,
endpointBaseUrl: String = DEFAULT_ENDPOINT_BASE_URL,
logLevel: LogLevel = LogLevel.INFO,
listener: InitListener? = null,
customerUserId: String? = null,
environment: SignalSealEnvironment? = null,
respectLimitAdTracking: Boolean = true,
)| Parameter | Type | Description |
|---|---|---|
context | Context | Required. Your Application context. |
apiKey | String | Required. Your Android SDK key (ak_android_…) from Settings → SDK. |
isDebug | Boolean | Defaults to false. When true, every event is tagged is_debug so it's visible in the Live Feed but not forwarded to ad networks. |
endpointBaseUrl | String | Override the ingestion URL. Leave unset unless SignalSeal told you to set it. Must end with /. |
logLevel | LogLevel | Defaults to INFO. One of DEBUG, INFO, WARN, ERROR, OFF. |
listener | InitListener? | Optional callback (see below). |
customerUserId | String? | Your app's stable user ID, if you have one. Helpful for cross-device identity. |
environment | SignalSealEnvironment? | Auto-detected from your build (debuggable → SANDBOX, otherwise PRODUCTION). Pass SANDBOX explicitly when running QA tracks on the Play Console. |
respectLimitAdTracking | Boolean | Defaults to true. Honor the user's "Limit ad tracking" setting on Android. Setting this to false violates Google Play Developer Program Policies for the AD_ID permission - only do it with a clear legal basis. |
configure(...) is idempotent - the second call is logged and ignored.
The SDK fires the INSTALL event automatically the first time
configure(...) runs on a device. Don't send it manually.
InitListener
Optionally, pass an InitListener to be told when initialization
completes or fails:
SignalSealSDK.configure(
context = this,
apiKey = "ak_android_...",
listener = object : InitListener {
override fun onError(t: Throwable) {
Log.e("SignalSeal", "init failed", t)
}
override fun onInitialized(
mainThreadDurationMs: Long,
totalDurationMs: Long
) {
Log.i("SignalSeal", "init ok in $totalDurationMs ms")
}
}
)Send events
SignalSealSDK.sendEvent(
event = EventType.PURCHASE,
parameters = mapOf(
"value" to 9.99,
"proceeds" to 6.99,
"currency" to "USD"
)
)value is the gross amount in the buyer's currency. proceeds is optional -
the net you keep after store commission and tax, in the same currency; pass it
if you know it (e.g. from your receipt-validation backend). currency is the
ISO-4217 code; omit it and value is treated as USD.
For events that don't fit any of the standard types, use
EventType.CUSTOM with a name:
SignalSealSDK.sendEvent(
event = EventType.CUSTOM,
name = "onboarding_completed",
parameters = mapOf("steps" to 5)
)sendEvent(...) is fire-and-forget. Events queue in memory and flush
in the background.
Event types
enum class EventType {
INSTALL,
LOGIN, SIGN_UP, REGISTER,
PURCHASE, ADD_TO_CART, ADD_TO_WISHLIST,
INITIATE_CHECKOUT, START_TRIAL, SUBSCRIBE,
LEVEL_START, LEVEL_COMPLETE,
TUTORIAL_COMPLETE, SEARCH, VIEW_ITEM, VIEW_CONTENT, SHARE,
CUSTOM,
}Set user attributes
Attach known user data to all subsequent events. Pass only the fields you have.
SignalSealSDK.setUserAttributes(
UserAttributes(
email = "alice@example.com",
firstName = "Alice",
country = "US",
externalId = "user_42"
)
)Available fields:
| Field | Type | Notes |
|---|---|---|
email | String? | |
phone | String? | E.164 format recommended. |
firstName, lastName | String? | |
dob | String? | ISO-8601 (YYYY-MM-DD). |
gender | String? | |
city, state, zip, country | String? | country should be ISO-3166-1 alpha-2. |
externalId | String? | Your app's internal user ID after login. |
Helpers
Get the SignalSeal ID
A stable per-install ID, useful for bridging to RevenueCat, SuperWall, or your own backend.
val id: String? = SignalSealSDK.getSignalSealId()Returns null until configure(...) has finished setting up.
Get attribution parameters
Returns the install's attribution data - the campaign that drove it, plus raw click IDs for any further server-side correlation.
val params: Map<String, String> = SignalSealSDK.getAttributionParams()
// {
// "signalseal_id": "...",
// "signalseal_adnetwork": "google",
// "signalseal_campaign_id": "...",
// "gclid": "...",
// ...
// }Organic installs return { "signalseal_id": "..." } only. Attributed
installs add signalseal_* keys plus any raw click IDs the original
ad carried (gclid, fbclid, ttclid, wbraid, etc.).
Flush
Force-flush the in-memory event queue. Useful in tests.
SignalSealSDK.flush()Reset
Wipe all locally-stored SDK state - installation ID, queued events,
cached user data. Use this for "log out" or "forget me" flows. The
SDK re-mints an installation ID and re-fires the INSTALL event on
the next call.
SignalSealSDK.resetData()Status checks
SignalSealSDK.isConfigured() // true once configure() has returned
SignalSealSDK.isEnabled() // true if SDK is up and not killswitched
SignalSealSDK.isSdkDisabled() // true if SDK was disabled (e.g. bad API key)Debug mode
Pass isDebug = true when configuring during development:
SignalSealSDK.configure(
context = this,
apiKey = "ak_android_...",
isDebug = BuildConfig.DEBUG
)In debug mode every event is tagged is_debug - events still appear
in the SignalSeal dashboard so you can verify they look right, but
they won't be forwarded to your ad networks.