getSession() when the user performs a sensitive action, and POST the sealed token to your backend for verification.
The mobile SDKs are currently in private beta. Contact support for access credentials and distribution instructions.
Requirements
- Android 5.0 (API 21) and up
- Kotlin 1.9+
- Android Gradle Plugin 8.2+
- NDK r26+ (bundled with Android Studio Hedgehog and later)
Install
android.permission.INTERNET. The SDK declares no permissions of its own.
Configure on startup
Callconfigure() from Application.onCreate() so signal collection is running by the time your first screen mounts.
TripwireConfiguration
| Field | Default | Description |
|---|---|---|
publishableKey | — | Required. Must start with pk_live_ or pk_test_. Secret keys (sk_*) are rejected at configure-time. |
enableBehavioralSignals | true | Accelerometer and touch-stroke observers. Disable if your app has strict motion-sensor policies. |
enableAntiTamper | true | Root, Magisk, debugger, emulator, and hook detection. |
enableHiddenWebView | true | Enables the attach(webView) handoff so an in-app WebView shares this session. |
enableCloudIdentifier | false | Opt-in Google Drive AppData hint. Requires the tripwire-android-gms module. No-op if Play Services are not available. |
Get a session at action time
CallgetSession() from a coroutine right before the sensitive action — not on app launch.
SessionHandoff is a simple data class:
sessionIdis stable acrossgetSession()calls for the life of the client.sealedTokenis fresh on every call. Send the most recent one to your backend.- The SDK never surfaces verdicts, scores, or visitor IDs to the device — verify on your server.
Behavioral capture
Touch-stroke dynamics are opt-in per screen. CallobserveTouches when the view is available — typically from onResume.
observeTouches wraps any existing View.OnTouchListener on the view; it does not consume events, so your gesture and scroll handlers keep working unchanged.
WebView correlation
If your app hosts Tripwire-protected web content in aWebView, attach it so the web SDK reuses the native session instead of creating its own.
window.__TRIPWIRE_NATIVE__, which the browser SDK picks up when loaded from within the WebView.
API reference
| Method | Description |
|---|---|
TripwireClient.configure(context, configuration) | Validates the publishable key and starts the runtime. Safe to call once at app start. Calling again reconfigures the client. |
suspend TripwireClient.getSession(): SessionHandoff | Flushes pending observations and returns a sealed handoff. Every call produces a fresh sealedToken. |
suspend TripwireClient.waitForFingerprint() | Resolves when the durable visitor fingerprint is ready. Optional — getSession() works without it. |
TripwireClient.observeTouches(view, contextId) | Attaches a non-consuming touch observer to the view. Call once per screen. |
TripwireClient.attach(webView) | Shares the current session with a hosted WebView. |
TripwireClient.destroy() | Stops timers and releases resources. Rarely needed outside tests. |
Optional permissions
The SDK itself declares zero permissions. Two signals produce richer entropy if the host app opts in.| Permission | Unlocks | Play Store friction |
|---|---|---|
com.google.android.providers.gsf.permission.READ_GSERVICES | Google Services Framework ID | None. |
android.permission.QUERY_ALL_PACKAGES | Full installed-package enumeration | Requires justification on new submissions. A scoped <queries> tag gives a partial list without justification. |
Error handling
Every SDK-produced error is a subclass of the sealedTripwireError type.
| Code | Retryable | When it happens |
|---|---|---|
config.invalid_publishable_key | no | publishableKey is missing, uses the sk_* secret prefix, or doesn’t match pk_live_* / pk_test_*. |
client.not_configured | no | A client method was called before configure(). |
session.create_failed | varies | Session handshake with the Tripwire API failed. The retryable flag reflects the underlying cause. |
session.handshake_expired | no | The server expired the session. Call configure() again to mint a new one. |
transport.batch_post_failed | varies | A signal batch upload failed. |
transport.rate_limited | yes | HTTP 429 from the API. Back off and retry. |
transport.upgrade_required | no | HTTP 410/426. The SDK version is too old — upgrade the app. |
transport.network | yes | DNS, TLS, or connectivity failure. |
crypto.failure | no | A crypto primitive failed. Usually a platform issue worth reporting. |
internal | no | Unexpected state. File a support ticket with the message and cause. |
code values are stable. Category prefixes (config.*, transport.*) are safe to branch on with a wildcard — new codes within a category keep the same retry semantics.
Fallback policy
If Tripwire fails, your app should still work. Log the error and continue without a handoff; treat the missing server-side signal according to the sensitivity of the action.Best practices
- Configure in
Application.onCreate()so signals are collecting before any screen opens. - Call
getSession()late — right before the sensitive action, inside a coroutine. - Wrap errors — degrade gracefully when the SDK can’t produce a handoff.
- Reuse the singleton —
TripwireClientis a process-wide singleton. Do not hold per-screen copies.
What’s next
Server verification
Verify the sealed token on your backend
Browser SDK
Equivalent guide for the web surface
iOS SDK
Native iOS integration
Going to production
Rollout checklist and monitoring