> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go.gbgplc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting Started

> Install GBGBridge and build your first integration in minutes.

This guide walks you through adding GBGBridge to your Android project, configuring it, and loading your first web-based identity journey.

## Requirements

| Requirement                | Minimum              | Notes                                           |
| -------------------------- | -------------------- | ----------------------------------------------- |
| Android (`minSdk`)         | API 24 (Android 7.0) | Covers the vast majority of active devices      |
| `compileSdk` / `targetSdk` | 34                   | Your app should compile against API 34 or later |
| JDK                        | 17                   | Required by the Android Gradle Plugin toolchain |
| Kotlin                     | 2.x                  | The SDK is built with Kotlin 2.2.10             |
| Artifact                   | AAR                  | Published to Maven Central                      |

Unlike the iOS SDK, GBGBridge for Android is **not zero-dependency**. It depends on `androidx.annotation` and `kotlinx-serialization-json`, and exposes `kotlinx-coroutines-android` as an `api` dependency — coroutine types appear on the public surface of `CaptureCapability`, so your app needs coroutines available (which any modern Android project already has).

## Installation

GBGBridge is published to [Maven Central](https://central.sonatype.com/artifact/com.gbg/gbgbridge-sdk) as `com.gbg:gbgbridge-sdk`. Add the dependency to your module's `build.gradle.kts`:

```kotlin theme={null}
dependencies {
  implementation("com.gbg:gbgbridge-sdk:0.1.0-alpha01")
}
```

No repository setup is needed beyond `mavenCentral()`, which most projects already declare in `settings.gradle.kts`:

```kotlin theme={null}
dependencyResolutionManagement {
  repositories {
    google()
    mavenCentral()
  }
}
```

You can also add the dependency through the Android Studio UI (**File** > **Project Structure...** > **Dependencies**), but the Gradle snippet above is the canonical path. Sync the project and you're ready to go.

## Minimal Integration

The steps below take you from an empty screen to a running journey: create a `BridgeHost`, declare a capability, attach a WebView, and load the journey URL.

### 1. Add the Imports

```kotlin theme={null}
import com.gbg.gbgbridge.core.BridgeHost
import com.gbg.gbgbridge.capabilities.CaptureResult
import com.gbg.gbgbridge.capabilities.CameraDetector
```

### 2. Initialize the Bridge Host

The `BridgeHost` manages message routing between the WebView and your native code. The simplest way to create one is with a host version string. In Compose, hold it in `remember` so it survives recomposition:

```kotlin theme={null}
val host = remember { BridgeHost(hostVersion = "1.0.0") }
```

`BridgeHost` is a main-thread-only class — construct it and call its methods on the main thread.

### 3. Declare Capabilities via Typed Slots

`BridgeHost` exposes typed capability slots for well-known capture operations. Setting a handler on a slot declares support — no separate configuration step needed:

```kotlin theme={null}
// Declare document capture support by setting a handler
host.documentCapture.handler = { request ->
  // Your capture logic here — return a CaptureResult
  CaptureResult.Cancelled(reason = "Not yet implemented")
}

// Optionally detect and report camera permission state
val camera = CameraDetector.check(context)
host.documentCapture.permissionState = camera.permissionState
```

`CameraDetector.check(context)` needs a `Context` — in Compose, use `LocalContext.current`. It reports `GRANTED` or `NOT_DETERMINED`; if your app runs its own permission flow, set the richer `DENIED`/`RESTRICTED` states on the slot yourself.

### 4. Display the Journey

There is no prebuilt WebView component on Android — you create a standard `WebView` and attach the host to it. `attach()` configures the WebView internally (JavaScript, DOM storage, bootstrap injection, message interface), so there is no separate configure step. In Compose, wrap the WebView in `AndroidView`:

```kotlin theme={null}
@Composable
fun JourneyScreen(journeyUrl: String) {
  val host = remember { BridgeHost(hostVersion = "1.0.0") }

  AndroidView(
    modifier = Modifier.fillMaxSize(),
    factory = { context ->
      WebView(context).also { webView ->
        host.documentCapture.handler = { request ->
          host.documentCapture.awaitCompletion()
        }
        host.attach(webView)
        webView.loadUrl(journeyUrl)
      }
    }
  )

  DisposableEffect(Unit) {
    onDispose { host.detach() }
  }
}
```

Call `host.attach(webView)` **before** `loadUrl()` so the bootstrap script is in place when the page loads, and call `host.detach()` when the screen leaves composition. If you use the View system rather than Compose, the wiring is the same: create a `WebView` in your Activity or Fragment, attach, load, and call `detach()` (or `dispose()` for terminal teardown) in `onDestroy()`.

### 5. Run Your App

Build and run. The web journey loads inside the native WebView. When the journey sends a `capability.query` request, GBGBridge automatically responds with the capabilities derived from your typed slots — including which are supported and their permission state.

### Alternative: Configuration-Based Initialization

If you need explicit control over the capability map (e.g., for custom capabilities or static declarations), use the configuration-based constructor:

```kotlin theme={null}
val configuration = BridgeConfiguration(
  hostVersion = "1.0.0",
  capabilities = mapOf(
    "camera.document" to BridgeCapabilityInfo(supported = true, version = "1.0"),
    "camera.selfie" to BridgeCapabilityInfo(supported = true, version = "1.0")
  )
)

val host = BridgeHost(configuration = configuration)
```

Android additionally accepts an optional `capabilitiesProvider` lambda as a second constructor argument. It is re-evaluated on every capability read, so you can reflect dynamic state (such as permission changes) without polling — this replaces the mutable capability map the iOS SDK exposes.

Both initialization paths support `register(handler)` for custom `BridgeCapabilityHandler` implementations. See the [Capability Handling Guide](/docs/go-v2/developer-integration/sdks/android/capability-handling) for details.

## What Happens Under the Hood

When you call `host.attach(webView)`, several things happen automatically:

1. **WebView configuration**: JavaScript and DOM storage are enabled, and a bootstrap-injecting `WebViewClient` plus a plain `WebChromeClient` are installed. This overwrites any clients you set earlier — if you need a custom `WebChromeClient`, set it *after* `attach()`; for a custom `WebViewClient`, subclass `BootstrapInjectingWebViewClient` and pass it via `attach(webView, client = ...)`.
2. **Bootstrap script injection**: A JavaScript snippet is evaluated in `onPageStarted` (main frame only) that initializes `window.GBGBridge` with a `receive()` function.
3. **JavaScript interface registration**: The host is exposed to the page via `addJavascriptInterface` under the name `GBGBridge`. Web content sends messages to native via `window.GBGBridge.postMessage(jsonString)` — note this differs from iOS, where the channel is `window.webkit.messageHandlers.gbgBridge`.
4. **Capability query handler**: A built-in handler for the `capability.query` action is registered. The query response is built dynamically from typed slots and custom capabilities, including permission state metadata.

<Note>
  Bootstrap timing diverges from iOS. On iOS the bootstrap is injected via `WKUserScript` at document start, guaranteed to run before any page JavaScript. On Android, injection happens in `onPageStarted` on a best-effort basis — a head script that synchronously calls `window.GBGBridge.receive` could race the injection. Keep this in mind if your web content interacts with the bridge during initial page load.
</Note>

## Required App Configuration

GBGBridge itself does not force any entries into your app — the library manifest declares nothing. However, depending on the capabilities you expose, your host app will need appropriate manifest entries:

```xml theme={null}
<!-- Always required: the journey loads over the network -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Only if you host camera capture -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
  android:name="android.hardware.camera"
  android:required="false" />
```

Declaring the camera feature as `android:required="false"` keeps your app installable on devices without a camera; check availability at runtime with `CameraDetector.check(context)`.

### Local development over HTTP

Android blocks cleartext HTTP traffic by default (API 28+). If your journey URL points at a local development server (e.g., `http://10.0.2.2:3000`), add a network security config that permits cleartext for development hosts only. Create `res/xml/network_security_config.xml`:

```xml theme={null}
<network-security-config>
  <base-config cleartextTrafficPermitted="false" />
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="false">10.0.2.2</domain>
    <domain includeSubdomains="false">localhost</domain>
    <domain includeSubdomains="false">127.0.0.1</domain>
  </domain-config>
</network-security-config>
```

Then reference it from the `<application>` element in your manifest:

```xml theme={null}
<application
  android:networkSecurityConfig="@xml/network_security_config"
  ... >
```

For production, always use HTTPS. Never ship `android:usesCleartextTraffic="true"` unscoped — keep cleartext exceptions limited to local development hosts (or to a debug source set override, so release builds stay locked down).

## Common Integration Pitfalls

A handful of issues catch most teams when first wiring up the bridge — wrong WebView setup, missing capability declarations, cleartext policy rejecting non-HTTPS dev URLs, and malformed messages on the web side. The notes below explain what to check.

### WebView not receiving messages

Ensure you call `host.attach(webView)` before `loadUrl()` — a plain `WebView` without `attach()` has no bootstrap script and no `GBGBridge` JavaScript interface. Also avoid replacing the `WebViewClient` after attaching: that removes the bootstrap injection. If you need custom navigation handling, subclass `BootstrapInjectingWebViewClient` and pass it to `attach(webView, client = ...)`, calling `super.onPageStarted` to keep the bootstrap.

### Capability query returns empty

If using `BridgeHost(hostVersion = ...)`: check that you set a `handler` on at least one typed slot, or registered a custom capability via `registerCustomCapability()`. If using `BridgeHost(configuration = ...)`: check that you passed capabilities in your `BridgeConfiguration` (or supplied a `capabilitiesProvider`).

### Cleartext HTTP blocked

If your journey URL uses `http://` and the page fails to load (typically `net::ERR_CLEARTEXT_NOT_PERMITTED`), add the [network security config](#local-development-over-http) shown above. On the emulator, remember that your host machine is `10.0.2.2` — `localhost` refers to the emulator itself. Alternatively, forward the port with `adb reverse tcp:3000 tcp:3000` and use `http://localhost:3000`.

### Messages not decoding

GBGBridge expects messages in the [Bridge Message Protocol](/docs/go-v2/developer-integration/sdks/android/concepts#message-protocol) format. If you see decode errors in `host.lastError` (or via `delegate.onError`), verify that the web content is sending correctly structured JSON.

## Next Steps

* [Concepts](/docs/go-v2/developer-integration/sdks/android/concepts) — Understand the architecture and mental model
* [Messaging Guide](/docs/go-v2/developer-integration/sdks/android/messaging) — Learn to send events and handle requests
* [Capability Handling Guide](/docs/go-v2/developer-integration/sdks/android/capability-handling) — Register handlers for camera and custom capabilities
* [API Reference](/docs/go-v2/developer-integration/sdks/android/api-reference) — Detailed reference for every public symbol
