Skip to main content
The Android SDK mirrors the browser SDK: configure it on startup, call getSession() when the user performs a sensitive action, and POST the sealed token to your backend for verification.
New Android integrations are temporarily paused while the SDK moves to Foil’s unified session transport. The Android SDK remains supported, but the currently published release will receive transport.upgrade_required until that update ships.
The Android SDK is distributed through Maven Central as protected binary AAR artifacts. The public metadata repository is https://github.com/abxy-labs/foil-android.

Requirements

  • Android 6.0 Marshmallow (API 23) and up
  • Kotlin 1.9+
  • Android Gradle Plugin 8.2+
  • Java 17 toolchain
  • A Foil publishable key created with the Android client, starting with pk_live_ or pk_test_

Create a publishable key for Android

In the Foil dashboard, open API Keys, choose New publishable key, and set Client to Android. Foil admits native sessions only when the publishable key’s client matches the SDK’s platform. A key created with the Web or iOS client is rejected, and the SDK reports config.invalid_publishable_key. In the other direction, the browser SDK doesn’t accept a key created with the Android client.

Install

Foil publishes two Android artifacts:
Your app must declare android.permission.INTERNET. The SDK’s own manifest declares no permissions. See Manifest entries and permissions for what the SDK and its dependencies add to your merged manifest.

Optional Google helpers

The foil-android-gms artifact contains three standalone helpers in the com.usefoil.foil.gms package. The core SDK doesn’t depend on this artifact or call these helpers, so adding it doesn’t change what Foil collects or what getSession() returns. Add it only if your app calls the helpers directly.
The artifact depends on the Play Integrity and Advertising ID client libraries. The Advertising ID library adds the com.google.android.gms.permission.AD_ID permission to your merged manifest, so review your Play Console advertising ID declaration before you add the artifact.

Configure on startup

Call configure() from Application.onCreate() so signal collection is running by the time your first screen mounts.

FoilConfiguration

Runtime integrity and anti-tamper collection is always enabled. It is part of the baseline SDK behavior, not an integration option.

Backup configuration

When enableCloudIdentifier = true, the SDK stores a per-install UUID in a SharedPreferences file named foil_cloud_identifier. Android Auto Backup can restore that file for the same Google account after reinstall, factory reset, or device migration, giving Foil a noisy continuity hint. Most apps do not need extra setup. If your app declares custom backup rules with android:fullBackupContent or android:dataExtractionRules, include the SDK preferences file:
The value is a random non-PII UUID. It is intentionally not encrypted because Keystore-protected data cannot be restored from backup.

Get a session at action time

Call getSession() from a coroutine right before the sensitive action - not on app launch.
SessionHandoff is a simple data class:
  • sessionId is stable across getSession() calls for the life of the client.
  • getSession() posts the native snapshot, performs a bounded best-effort behavioral flush, and returns the handoff your backend should verify.
  • The SDK never surfaces verdicts, scores, or visitor IDs to the device - verify on your server.
Your backend verifies a native handoff the same way it verifies a browser handoff. getSession() returns the same sessionId and sealedToken pair as the browser SDK, so you verify the sealedToken with your Foil server SDK and your secret key. See Server verification for the verification methods and examples in each server language.

Behavioral capture

When enableBehavioralSignals is true, the SDK starts zero-config Android behavioral capture automatically. It records the native equivalents of the browser’s behavioral events: app lifecycle, hashed screen navigation, viewport and scroll, form focus and input, selection and clipboard, and motion. No raw form text, raw hints, or raw view identifiers are sent. Field identity is hashed, and geometry is rounded to the active window’s coordinate space so the dashboard can show timing and replay context without collecting user-entered values. Touch-stroke dynamics are still opt-in per screen for higher-fidelity gesture data. Call observeTouches 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 Foil-protected web content in a WebView, attach it so the web SDK reuses the native session instead of creating its own.
The native bridge exposes the session handoff as window.__FOIL_NATIVE__, which the browser SDK picks up when loaded from within the WebView.

Native identity and attestation

Native visitor continuity is resolved server-side from the SDK’s encrypted observations. install_id tracks the app install, device_id tracks the device continuity layer, and native visitor_id represents the same device within your organization. None of those identifiers are exposed to the app. Android Key Attestation is optional and positive-only by default. When hardware-backed attestation is available, Foil can use SDK-managed Android Keystore keys to strengthen native identity. When it is unsupported, unavailable, unconfigured, or fails verification, Foil falls back to the other native continuity signals unless your organization explicitly enables strict attestation.
To verify Android Key Attestation in production, add your Android app identity on the Native Attestation card of the dashboard’s Settings page. Baseline native continuity still works without this setup, but hardware-backed attestation doesn’t upgrade identity confidence until the app identity is configured.

Add your app identity

Only organization owners and admins can change attestation settings. On the Native Attestation card, under Add app identity:
  1. Set Platform to Android.
  2. Enter your Android package name, such as com.example.app.
  3. Enter the Signing cert SHA-256, which is the SHA-256 fingerprint of the certificate that signs the release build your users install. Foil stores it as lowercase hex and also accepts colon-separated fingerprints. If you use Play App Signing, use the app signing key certificate, not the upload certificate.
  4. Select Add identity.
The Attestation policy setting on the same card controls how Foil treats attestation:

API reference

Manifest entries and permissions

The SDK’s own manifest declares no permissions. Your app declares android.permission.INTERNET so the SDK can reach the Foil API. The SDK and its dependencies add the following entries to your merged manifest:
  • <queries> block. Six <provider> entries that let the SDK check, on Android 11 and later, whether known app-cloning and virtualization frameworks are installed. You don’t need QUERY_ALL_PACKAGES for these checks.
  • Dependency permissions. AndroidX Biometric adds android.permission.USE_BIOMETRIC and android.permission.USE_FINGERPRINT. The Play Install Referrer library adds com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE.

Optional permissions

Optional host-app permissions can unlock additional direct OS facts, but they are not required for verdicts or native continuity. The SDK never prompts for a permission. It reads these facts only when your app already holds the permission, so don’t add a runtime permission only for Foil. Foil does not collect advertising IDs, serial numbers, IMEI/MEID, raw MAC addresses, SSID/BSSID, precise location, raw proxy hostnames, or broad installed-app inventories. Android package and tooling checks are bounded to fixed allowlists and are used as soft corroboration, not standalone identity anchors.

Error handling

Every SDK-produced error is a subclass of the sealed FoilError type.
The 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 Foil fails, log the error and continue without a handoff, then decide on your server how to treat a request that has no Foil signal. For low-risk actions you can fail open. For sensitive actions such as signup, payment, or account recovery, fail closed or step up verification.
See Signup & account creation for an example of failing closed when verification fails, and Going to production for the rollout sequence.

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.
  • Set a fallback policy per action - when the SDK can’t produce a handoff, fail open on low-risk actions and fail closed on sensitive ones.
  • Reuse the singleton - FoilClient is 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