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

# Android Kotlin 本人確認SDK：KYC

> DiditのネイティブAndroid Kotlin SDKで、本人確認、ライブネス検出、NFCによるICパスポート読み取りを実装。フルKYCチェック1件$0.33から、毎月$10の無料枠、契約不要。



Android SDK連携用プロンプト
        プロンプトをクリップボードにコピー



      
      

\<pre>

\`Integrate Didit identity verification into my Android app using the native Kotlin SDK.

\## Requirements
\- Android API 23+ (Android 6.0 Marshmallow). ML-based auto-detection (document/face) requires API 24+ and falls back to manual capture below that.
\- Kotlin 1.9+
\- NFC reading requires NFC-capable device hardware

\## Installation

\### Step 1: Add Maven Repository
In settings.gradle.kts:
dependencyResolutionManagement {
repositories {
    google()
    mavenCentral()
    maven { url = uri("https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository") }
}
}

\### Step 2: Add Dependency
(!) Regarding the version ensure you check the [GitHub repository](https://github.com/didit-protocol/sdk-android) for the latest version.
In app/build.gradle.kts:
dependencies {
implementation("me.didit:didit-sdk:4.9.1")
}

\### Step 3: Add Packaging Exclusion (required to avoid build conflicts)
In the android { } block of app/build.gradle.kts:
android {
packaging {
    resources {
        excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
    }
}
}

\## Permissions (auto-merged from SDK manifest)
\- INTERNET (required) — API communication
\- ACCESS_NETWORK_STATE (required) — Network availability
\- CAMERA (required) — Document scanning and face verification
\- NFC (optional) — Read NFC chips in passports/IDs

Camera and NFC are declared as optional features (android:required="false"), so the app installs on all devices.

\## Initialization (required)
In your Application class:
import me.didit.sdk.DiditSdk

class MyApp : Application() {
override fun onCreate() {
    super.onCreate()
    DiditSdk.initialize(this)
}
}

Register in AndroidManifest.xml:
\<application android:name=".MyApp" ...>

\## Backend: Create Session (your server)
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "vendor_data": "user-id" }
Response: { "session_id": "uuid", "session_token": "short-token", "url": "https://verify.didit.me/session/short-token", "status": "Not Started" }
Send session_token to the Android app (never expose DIDIT_API_KEY to the device).

\## Jetpack Compose Integration
import me.didit.sdk.DiditSdk
import me.didit.sdk.DiditSdkState
import me.didit.sdk.VerificationResult

// Observe SDK state and launch UI when ready
LaunchedEffect(Unit) {
DiditSdk.state.collect { state ->
    when (state) {
        is DiditSdkState.Ready -> DiditSdk.launchVerificationUI(activity)
        is DiditSdkState.Error -> Log.e("Didit", "Error: state.message")
        else -> { /* Loading, Idle, CreatingSession */ }
    }
}
}

// Start verification with session token from backend
import me.didit.sdk.VerificationStatus

fun startVerification(token: String) {
DiditSdk.startVerification(token = token) { result ->
    when (result) {
        is VerificationResult.Completed -> when (result.session.status) {
            VerificationStatus.APPROVED -> { /* grant access */ }
            VerificationStatus.DECLINED -> { /* show retry */ }
            VerificationStatus.PENDING  -> { /* under review */ }
        }
        is VerificationResult.Cancelled -> { /* user cancelled */ }
        is VerificationResult.Failed    -> { /* show error: result.error.message */ }
    }
}
}

\## Result Statuses (VerificationStatus enum; .rawValue gives "Approved" / "Pending" / "Declined")
\- VerificationStatus.APPROVED — user identity verified, grant access
\- VerificationStatus.DECLINED — verification failed, show retry or contact support
\- VerificationStatus.PENDING  — needs manual review by your compliance team

\## Full Verification Results
The SDK only returns the status. Full decision data (document fields, face match scores, AML hits, etc.) arrives via webhook to your backend.
Set up webhooks: https://docs.didit.me/integration/webhooks

\## Rate Limits (session creation)
\- 600 session-create requests / minute per x-api-key (see https://docs.didit.me/integration/rate-limiting)
\- On 429, retry honouring Retry-After / X-RateLimit-* headers

\## Environment Variables (backend only — never expose in the Android app)
\- DIDIT_API_KEY — from Didit Console > API & Webhooks
\- DIDIT_WORKFLOW_ID — from Didit Console > Workflows

\## Docs
\- Android SDK: https://docs.didit.me/integration/native-sdks/android-sdk
\- GitHub: https://github.com/didit-protocol/sdk-android
\- Webhooks: https://docs.didit.me/integration/webhooks
\- API Reference: https://docs.didit.me/api-reference/overview`

\</pre>



      
      

貼り付け先

最小限の設定で利用できる、サーバー駆動型の軽量な本人確認用Android SDKです。> [card] [GitHubリポジトリ](https://github.com/didit-protocol/sdk-android)
>
> GitHubでソースコードとサンプルを確認できます> [!NOTE]
>
> ### **ネイティブSDK**: Androidアプリにはこの方法を推奨します。ネイティブSDKは最適なユーザー体験、最適化されたカメラ処理、そして完全なNFC対応を提供します。***## 要件| 要件 | 最小バージョン |
| - | - |
| Android API | 23+（Android 6.0 Marshmallow）。MLによる自動検出にはAPI 24+が必要です（下記参照）。 |
| Kotlin | 1.9+ |
| Jetpack Compose | 推移的依存関係として含まれます |> [!NOTE]
>
> **APIレベル別の機能の利用可否**: 書類と顔の自動検出にはAPI 24+が必要です（同梱のMLランタイムまたはGoogle Play開発者サービスのランタイムのいずれかを使用します。詳しくはSDKのバリアントを参照してください）。API 23のデバイスでは、SDKはタイマー付きのシャッターボタンによる手動撮影に切り替わります。その他の機能はすべてAPI 23+の全範囲で動作します。> [!NOTE]
>
> **生体情報の同意にはネイティブSDK 4.10.0以降が必要です。** イリノイ州、テキサス州、コロラド州の法律が適用される人に対して、Diditは最初の顔撮影の前に明示的な[生体情報の同意](https://docs.didit.me/ja/getting-started/biometric-consent.md)を求めることができます。Android SDK 4.10.0以降ではこのステップが表示されます。それより前のバージョンではこのステップを表示できません。それらのセッションは従来どおり実行され、判定では同意が取得されていないものとして報告されます（`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`）。これらの州の人を認証する場合は、アップグレードしてください。***## インストール### ステップ1: リポジトリを追加する`settings.gradle.kts`の`repositories`ブロックにDidit Mavenリポジトリを追加します。```kotlin theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository") }
    }
}
````settings.gradle` (Groovy)を使用している場合は次のとおりです。```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```### ステップ2: 依存関係を追加するアプリの`build.gradle.kts`にSDKの依存関係を追加します。
(!) バージョンについては、必ず[GitHubリポジトリ](https://github.com/didit-protocol/sdk-android)で最新バージョンを確認してください。```kotlin theme={null}
dependencies {
    implementation("me.didit:didit-sdk:4.9.1")
}
````build.gradle` (Groovy)を使用している場合は次のとおりです。```groovy theme={null}
dependencies {
    implementation "me.didit:didit-sdk:4.9.1"
}
```#### SDKのバリアントAndroid SDKは**5つの個別のアーティファクト**として提供されるため、アプリのバイナリサイズは使用する
機能の分だけで済みます。上記の`me.didit:didit-sdk`はフルバンドルです。必ず1つだけを選択してください。
ただし例外が1つあり、後述のとおり2つの自動検出アーティファクトは併用できます。| アーティファクト | 自動検出 (ML) | NFCチップ読み取り | 用途 |
| - | :-: | :-: | - |
| `me.didit:didit-sdk-core` | – | – | 最小ビルド。書類の手動撮影のみ |
| `me.didit:didit-sdk-autodetection` | ✓ | – | 自動撮影。パスポートや身分証のチップ読み取りなし |
| `me.didit:didit-sdk-autodetection-play` | ✓ | – | Play services MLランタイムによる自動撮影。同梱ランタイムと比べてデバイスあたりのインストールサイズが約9.85 MB小さい (arm64、後述) |
| `me.didit:didit-sdk-nfc` | – | ✓ | ML自動撮影ランタイムなしのチップ読み取り |
| `me.didit:didit-sdk` | ✓ | ✓ | すべての機能 (フルバンドル) |##### Google Play servicesによる小型のMLランタイム (オプトイン、4.7.0以降)`me.didit:didit-sdk-autodetection-play`は、`didit-sdk-autodetection`と同じ書類と顔の自動撮影を提供しますが、
MLランタイムをAPKに同梱する代わりに、デバイス上のGoogle Play servicesがすでに提供しているMLランタイムで
推論を実行します。
検出の動作は同一です。リリース前に、2つのエンジンを実機のマトリクス上でフレーム単位で相互に検証しています。
また、推論は通常Playランタイムのほうが高速です。オプトインするには、アーティファクトを置き換えます。```kotlin theme={null}
// before
implementation("me.didit:didit-sdk-autodetection:4.9.1")
// after
implementation("me.didit:didit-sdk-autodetection-play:4.9.1")
```変更点は次のとおりです。- **サイズ**: MLランタイムがアプリに含まれなくなるため、**デバイスあたりのインストールされるネイティブコードが約9.85 MB小さく**なります (arm64)。
  (縮小していない4 ABIユニバーサルAPKで比較すると約43 MBというより大きな差が出ますが、この数値には
  1台のデバイスではインストールされないアーキテクチャが重複して含まれています。
  実際にユーザーが目にするのは上記のデバイスあたりの数値です。)
- **要件**: Google Play servicesが必要です。これがないデバイス (たとえばGMSを搭載していないHuaweiデバイス) や、
  Playランタイムの初期化に失敗した場合、SDKは自動的にフォールバックします。
  `didit-sdk-autodetection`もインストールされていれば同梱ランタイムに、そうでなければ手動撮影に切り替わります。
  ランタイムが利用できないことが原因でクラッシュすることはありません。
- **カバレッジの選択**: アプリを最小にするには`-play`のみを組み込みます (GMS非搭載のユーザーは手動撮影になります)。
  GMS非搭載のデバイスでもML自動撮影を維持したい場合は、両方のアーティファクトを組み込みます (サイズは
  従来と同じです)。どちらのアーティファクトも`didit-sdk-core` 4.7.0以降が必要です。> [!NOTE]
>
> `didit-sdk-autodetection-play`は現在オプトインです。Diditはリリース後1リリースサイクルの間、
> 実環境でのパフォーマンスを同梱ランタイムと比較して追跡します。そのデータで同等性が確認されれば、
> Playアーティファクトが自動検出の推奨インストール方法になる見込みです。それまでは
> `didit-sdk-autodetection` (同梱版)が引き続きデフォルトの推奨です。`4.6.0`以降、ネイティブのWalletConnectによるウォレット署名は、独立したオプションのアドオン`me.didit:didit-sdk-wallet`として提供されています。
フルバンドルの`me.didit:didit-sdk`にはすでに含まれているため、バンドルをインストールしている場合は何も変わりません。
軽量なアーティファクトのいずれかを使用していて、ウォレット所有権の確認をアプリ内でネイティブに実行したい場合は、`me.didit:didit-sdk-wallet`を併せて追加してください。アドオンがない場合、SDKは代わりに安全なブラウザフローでウォレット所有権の確認を完了するため、どちらの場合でも機能は動作し続けます。
WalletConnectを`didit-sdk-core`から切り離したことで、それを必要としないすべてのビルドから数MBのウォレット関連の依存関係も取り除かれました。すべてのアーティファクトは同じバージョンで公開されているため、`4.9.1`に揃えてください。#### ダウンロードサイズを小さく保つ自動撮影に使用する検出モデルは実行時にダウンロードされてキャッシュされるため、アプリのサイズには含まれません。
自動撮影によってアプリに追加されるのはMLランタイムのネイティブライブラリで、そのサイズはCPUアーキテクチャごとにかかります。目安として`arm64-v8a`で約10 MB、`armeabi-v7a`で約7 MB、2つのx86エミュレーター用アーキテクチャでそれぞれ約13 MBです。このコストを1回分だけに抑えるには、次のようにします。1) **Android App Bundle (AAB)で公開します。** Google Playはデバイス自身のアーキテクチャと言語のみを配信するため、arm64のスマートフォンにインストールされるネイティブコードは約10 MB (圧縮ダウンロードで約4 MB)です。一方、ユニバーサルAPKには4つのアーキテクチャがすべて含まれ、40 MBを超えます。これが、想定外に大きなサイズが計測される最も一般的な原因です。

2) **単一のAPKで配布する場合**、対象がARMのスマートフォンやタブレットであれば、同梱するアーキテクチャを限定します。

   ```kotlin theme={null}
   android {
       defaultConfig {
           ndk { abiFilters += listOf("arm64-v8a", "armeabi-v7a") }
       }
   }
   ```

   ユーザーが実際に使用するABIはすべて残してください。Chromebookやその他のx86デバイスを対象とする場合は`x86_64`を追加するか、ABIごとに分割したAPKを公開して、どのデバイスもサポート対象から外れないようにします。

3) **R8を有効にします。** リリースビルドタイプで`isMinifyEnabled = true`と`isShrinkResources = true`を設定します (Groovyの`build.gradle`を使用している場合は`minifyEnabled true` / `shrinkResources true`)。SDKには独自のコンシューマールールが含まれているため、追加の設定なしで未使用のSDKコードが削除されます。

4) APKビルドでSDKの48のロケールすべてが不要な場合は、`resConfigs(...)`で**同梱する言語を限定します**。Google PlayではAABの言語分割によって自動的に処理されます。### ステップ3: パッケージングの除外設定を追加するビルドの競合を避けるため、アプリの`android`ブロックに次を追加します。```kotlin theme={null}
android {
    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
        }
    }
}
```以上で完了です。推移的な依存関係はすべてGradleが自動的に解決します。***## 権限SDKには次の権限が必要です。これらはSDKの`AndroidManifest.xml`で宣言されており、アプリのマニフェストに自動的にマージされます。| 権限 | ソースAAR | 説明 | 必須 |
| - | - | - | - |
| `INTERNET` | `didit-sdk-core` | API通信のためのネットワークアクセス | はい |
| `ACCESS_NETWORK_STATE` | `didit-sdk-core` | ネットワークの利用可否の検出 | はい |
| `CAMERA` | `didit-sdk-core` | 書類のスキャンと顔認証 | はい |
| `NFC` | `didit-sdk-nfc` | パスポートや身分証明書のNFCチップの読み取り | `didit-sdk-nfc`から自動マージ(`me.didit:didit-sdk`の推移的依存関係) |### カメラとNFCの機能SDKは`android.hardware.camera`と`android.hardware.nfc`を任意の機能(`android:required="false"`)として宣言しています。これにより、カメラやNFCハードウェアを搭載していないデバイスにもアプリをインストールできます。ハードウェアがない場合、SDKは実行時に適切に処理します。***## クイックスタート### ステップ1: SDKを初期化する`Application.onCreate()`でSDKを初期化します。```kotlin theme={null}
import me.didit.sdk.DiditSdk

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        DiditSdk.initialize(this)
    }
}
```### ステップ2: 認証を開始して結果を処理する```kotlin theme={null}
import me.didit.sdk.DiditSdk
import me.didit.sdk.DiditSdkState
import me.didit.sdk.VerificationResult

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Observe SDK state to launch UI when ready
        lifecycleScope.launch {
            DiditSdk.state.collect { state ->
                when (state) {
                    is DiditSdkState.Ready -> DiditSdk.launchVerificationUI(this@MainActivity)
                    is DiditSdkState.Error -> Log.e("Didit", "Error: ${state.message}")
                    else -> { /* Loading, Idle, CreatingSession */ }
                }
            }
        }
    }

    private fun startVerification() {
        // Method 1: UniLink (no backend required)
        DiditSdk.startVerification(
            workflowId = "your-workflow-id",
            vendorData = "user-123"
        ) { result ->
            handleResult(result)
        }

        // Method 2: Backend Session (recommended for production)
        // DiditSdk.startVerification(
        //     token = "your-session-token"
        // ) { result ->
        //     handleResult(result)
        // }
    }

    private fun handleResult(result: VerificationResult) {
        when (result) {
            is VerificationResult.Completed -> {
                Log.d("Didit", "Session: ${result.session.sessionId}")
                Log.d("Didit", "Status: ${result.session.status}")
            }
            is VerificationResult.Cancelled -> {
                Log.d("Didit", "User cancelled")
            }
            is VerificationResult.Failed -> {
                Log.e("Didit", "Failed: ${result.error.message}")
            }
        }
    }
}
```***## 連携方法SDKは2つの連携方法に対応しています。### 方法1: UniLink(最も簡単)バックエンドは不要です。SDKはDidit ConsoleのワークフローIDを使って、セッションを直接作成します。指定できるのは`vendorData`のみです。```kotlin theme={null}
DiditSdk.startVerification(
    workflowId = "your-workflow-id",
    vendorData = "user-123"
) { result ->
    handleResult(result)
}
```### 方法2: バックエンドセッション(本番環境に推奨)バックエンドが[Create Verification Session API](https://docs.didit.me/ja/sessions-api/create-session.md)(`POST /v3/session/`)を使い、すべてのパラメーター(`contact_details`、`expected_details`、`metadata`、`callback`など)を指定してセッションを作成し、その`session_token`をSDKに渡します。```kotlin theme={null}
// Your backend creates a session and returns the token
val sessionToken = yourBackend.createVerificationSession(userId = currentUser.id)

// Pass the token to the SDK
DiditSdk.startVerification(
    token = sessionToken
) { result ->
    handleResult(result)
}
```この方法では、次の項目を完全に制御できます。- セッションとユーザーの関連付け(`vendor_data`)
- カスタムメタデータの設定
- セッションごとのコールバックの設定
- 照合用の連絡先情報と期待情報の指定***## 設定SDKの動作をカスタマイズします。```kotlin theme={null}
import me.didit.sdk.Configuration
import me.didit.sdk.core.localization.SupportedLanguage

val configuration = Configuration(
    languageLocale = SupportedLanguage.SPANISH,  // Force Spanish language
    showLanguageSelector = true,                  // Let the user change language
    fontFamily = "my_custom_font",                // Custom font (must be in res/font/)
    loggingEnabled = true                         // Enable debug logging
)

DiditSdk.startVerification(
    token = "your-session-token",
    configuration = configuration
) { result ->
    handleResult(result)
}
```### 設定オプション| プロパティ | 型 | デフォルト | 説明 |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | デバイスのロケール | 特定の言語を強制する |
| `showLanguageSelector` | `Boolean` | `false` | ウェルカム画面にWeb版と同じ形式の言語セレクターを表示する |
| `fontFamily` | `String?` | システムフォント | カスタムフォントのリソース名(`res/font/`内) |
| `loggingEnabled` | `Boolean` | `false` | SDKのデバッグログを有効にする |
| `showCloseButton` | `Boolean` | `true` | 認証ステップの画面に閉じる(X)ボタンを表示する |
| `showExitConfirmation` | `Boolean` | `true` | ユーザーが終了しようとしたときに確認ダイアログを表示する |
| `closeOnComplete` | `Boolean` | `false` | 完了時に認証UIを自動的に閉じる(Web SDKでの対応オプション: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `CameraLens.BACK` | 書類撮影画面を開いたときに使うレンズ |
| `defaultLivenessCamera` | `CameraLens` | `CameraLens.FRONT` | 顔(ライブネス)撮影画面を開いたときに使うレンズ |
| `showDocumentCameraSwitchButton` | `Boolean` | `true` | 書類撮影画面に撮影中のカメラ切り替えボタンを表示する |
| `showLivenessCameraSwitchButton` | `Boolean` | `true` | 顔撮影画面に撮影中のカメラ切り替えボタンを表示する |### カメラオプションカメラオプションは[Web SDKのカメラオプション](https://docs.didit.me/ja/integration/web-sdks/javascript-sdk.md#カメラオプション)と同じです。
各レンズは`CameraLens.FRONT`または`CameraLens.BACK`です。
指定したレンズがデバイスにない場合、SDKは利用可能な最初のカメラを使用します。
カメラが1台しかないデバイスでも、カメラ切り替えボタンは非表示になります。
切り替えボタンのオプションを`false`に設定すると、ユーザーはそのステップのデフォルトレンズに固定されます。```kotlin theme={null}
val configuration = Configuration(
    defaultLivenessCamera = CameraLens.BACK,
    showLivenessCameraSwitchButton = false
)
```> [!NOTE]
>
> `showLanguageSelector`、`showCloseButton`、`showExitConfirmation`、`closeOnComplete`の各オプションは、Web SDKの`DiditSdkConfiguration`と同じです。モバイル固有のオプションである`languageLocale`と`fontFamily`が存在するのは、モバイルSDKが認証UI全体をネイティブで描画するためです(Web SDKはiframe内のホスト型フロントエンドに処理を委ねます)。> [!NOTE]
>
> **テーマと色**: 色、背景、イントロ画面の設定は、SDKの設定ではなく、Didit Consoleの[ホワイトラベル設定](https://business.didit.me)で行います。これにより、すべてのプラットフォームで一貫したブランディングが保たれます。***## 言語サポートSDKは**54言語**に対応しています。言語を指定しない場合、SDKはデバイスのロケールを使用し、フォールバックとして英語を使用します。```kotlin theme={null}
// Use device locale (default)
val config = Configuration()

// Force specific language
val config = Configuration(languageLocale = SupportedLanguage.FRENCH)

// Let the user change language on the welcome screen
val config = Configuration(showLanguageSelector = true)
```**[対応言語の一覧を見る →](https://docs.didit.me/ja/integration/supported-languages.md)*****## 高度なオプション高度なセッションパラメーター(`contact_details`、`expected_details`、`metadata`、`callback`)を使うには、**Backend Session**メソッドを利用してください。バックエンドがすべてのパラメーターを指定して[Create Verification Session API](https://docs.didit.me/ja/sessions-api/create-session.md)を呼び出し、その`session_token`をSDKに渡します。***## 結果の処理`VerificationResult` sealed classは、認証の結果を返します。### 結果のケース| ケース | 説明 |
| - | - |
| `Completed(session)` | 認証フローが完了しました(結果は`session.status`で確認します) |
| `Cancelled(session)` | ユーザーが認証フローをキャンセルしました |
| `Failed(error, session)` | 認証中にエラーが発生しました |### SessionDataのプロパティ| プロパティ | 型 | 説明 |
| - | - | - |
| `sessionId` | `String` | セッションの一意な識別子 |
| `status` | `VerificationStatus` | `APPROVED`、`PENDING`、または`DECLINED` |### エラーの種類すべてのエラーは`me.didit.sdk.VerificationError`のsealed subclassです。| エラー | 説明 |
| - | - |
| `SessionExpired` | セッションの有効期限が切れています |
| `NetworkError` | ネットワーク接続の問題 |
| `CameraAccessDenied` | カメラの権限が付与されていません |
| `NotInitialized` | SDKが初期化されていません。先に`DiditSdk.initialize(context)`を呼び出してください |
| `ApiError` | バックエンドがエラーレスポンスを返しました |
| `RetryBlocked` | 認証を再試行できません(例: 最大試行回数に達した場合) |
| `Unknown(message)` | メッセージ付きのその他のエラー |### 接続が切れた場合認証中にデバイスの接続が切れると、SDKはステップを読み込み中のままにせず、認証フローを「No internet connection」画面で覆います。
SDKはバックグラウンドで確認を続け、Diditに再び接続できるようになるとすぐにこの画面を自動で閉じます。ユーザーは中断したステップからそのまま続行できます。
この画面には**Try Again**が表示され、`showCloseButton`が`true`(デフォルト)の場合は**Exit Verification**も表示されます。
終了すると、認証は`VerificationResult.Failed(error = VerificationError.NetworkError, session = ...)`で終了するため、アプリはユーザーが接続の問題により離脱したことを把握できます。### 結果処理の完全な例```kotlin theme={null}
DiditSdk.startVerification(token = "your-token") { result ->
    when (result) {
        is VerificationResult.Completed -> {
            when (result.session.status) {
                VerificationStatus.APPROVED -> {
                    Log.d("Didit", "Approved! Session: ${result.session.sessionId}")
                    // User is verified - grant access
                }
                VerificationStatus.PENDING -> {
                    Log.d("Didit", "Under review. Session: ${result.session.sessionId}")
                    // Show "verification in progress" UI
                }
                VerificationStatus.DECLINED -> {
                    Log.d("Didit", "Declined. Session: ${result.session.sessionId}")
                    // Handle declined verification
                }
            }
        }
        is VerificationResult.Cancelled -> {
            Log.d("Didit", "Cancelled: ${result.session?.sessionId ?: "unknown"}")
            // User chose to cancel - maybe show retry option
        }
        is VerificationResult.Failed -> {
            Log.e("Didit", "Error: ${result.error.message}")
            // Handle error - show retry or contact support
        }
    }
}
```***## SDKの状態を監視する独自の読み込みUIを表示するために、SDKの状態を監視できます。```kotlin theme={null}
lifecycleScope.launch {
    DiditSdk.state.collect { state ->
        when (state) {
            is DiditSdkState.Idle -> {
                // Ready to start verification
            }
            is DiditSdkState.CreatingSession -> {
                // Show "Creating session..." progress
            }
            is DiditSdkState.Loading -> {
                // Show loading indicator
            }
            is DiditSdkState.Ready -> {
                // Verification UI is ready - launch it
                DiditSdk.launchVerificationUI(this@MainActivity)
            }
            is DiditSdkState.Error -> {
                // Show error message
                Log.e("Didit", "Error: ${state.message}")
            }
        }
    }
}
```***## ProGuard / R8SDKには独自のconsumer ProGuardルールが含まれています。追加の設定は必要ありません。R8のfull modeを使用する場合は、`gradle.properties`に次の設定を追加する必要がある場合があります。```properties theme={null}
android.enableR8.fullMode=false
```***## エンドツーエンドの例 (バックエンドのセッション → Android SDK → 結果)このパターンは本番環境向けの連携です。バックエンドがセッションを作成し、Androidアプリが`session_token`を受け取り、SDKがフローを実行します。### 1. バックエンドでセッションを作成する```ts theme={null}
// Node.js / Express example. Run on your server. NEVER ship DIDIT_API_KEY to the device.
import express from "express";

const app = express();
app.use(express.json());

app.post("/api/verification/start", async (req, res) => {
  const response = await fetch("https://verification.didit.me/v3/session/", {
    method: "POST",
    headers: {
      "x-api-key": process.env.DIDIT_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: req.body.userId, // your stable user id
    }),
  });

  if (!response.ok) {
    return res.status(500).json({ error: `Didit ${response.status}` });
  }

  const { session_id, session_token } = await response.json();
  // Persist session_id <-> userId so you can match the webhook later.
  res.json({ session_id, session_token });
});
```### 2. Androidでトークンを交換してSDKを起動する```kotlin theme={null}
import android.app.Activity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.didit.sdk.DiditSdk
import me.didit.sdk.VerificationResult
import me.didit.sdk.VerificationStatus
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.MediaType.Companion.toMediaType
import org.json.JSONObject

class VerificationFlow(private val activity: ComponentActivity) {
    private val http = OkHttpClient()
    private val json = "application/json".toMediaType()

    fun start(userId: String) {
        activity.lifecycleScope.launch {
            val token = withContext(Dispatchers.IO) {
                val body = JSONObject().put("userId", userId).toString().toRequestBody(json)
                val req = Request.Builder()
                    .url("https://your-backend.example.com/api/verification/start")
                    .post(body)
                    .build()
                http.newCall(req).execute().use { resp ->
                    JSONObject(resp.body!!.string()).getString("session_token")
                }
            }

            DiditSdk.startVerification(token = token) { result ->
                when (result) {
                    is VerificationResult.Completed -> when (result.session.status) {
                        VerificationStatus.APPROVED -> { /* optimistic UI; rely on webhook for source of truth */ }
                        VerificationStatus.PENDING  -> { /* show "under review" */ }
                        VerificationStatus.DECLINED -> { /* show retry/contact support */ }
                    }
                    is VerificationResult.Cancelled -> { /* user cancelled */ }
                    is VerificationResult.Failed    -> { /* show error: result.error.message */ }
                }
            }
        }
    }
}
```### 3. バックエンドでWebhook経由で最終的な判定を受け取るSDKの結果はUIでのフィードバックには便利ですが、最終的な判定はWebhook経由で届きます。HMACによる検証については[Webhookガイド](https://docs.didit.me/ja/integration/webhooks.md)を参照してください。```ts theme={null}
app.post("/api/webhooks/didit", express.raw({ type: "application/json" }), (req, res) => {
  // 1. Verify the X-Signature header (see Webhooks docs)
  // 2. Parse the body
  const event = JSON.parse(req.body.toString());
  if (event.webhook_type === "status.updated") {
    // event.session_id, event.status ("Approved" | "Declined" | "In Review" | ...)
    // Look up the user by session_id and update their verification state.
  }
  res.sendStatus(200);
});
```***## 完全な例```kotlin theme={null}
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import me.didit.sdk.Configuration
import me.didit.sdk.DiditSdk
import me.didit.sdk.DiditSdkState
import me.didit.sdk.VerificationResult
import me.didit.sdk.VerificationStatus
import me.didit.sdk.core.localization.SupportedLanguage

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Observe SDK state
        lifecycleScope.launch {
            DiditSdk.state.collect { state ->
                when (state) {
                    is DiditSdkState.Ready -> DiditSdk.launchVerificationUI(this@MainActivity)
                    is DiditSdkState.Error -> Log.e("Didit", "Error: ${state.message}")
                    else -> { /* Idle, Loading, CreatingSession */ }
                }
            }
        }
    }

    fun startVerification() {
        val config = Configuration(
            languageLocale = SupportedLanguage.ENGLISH,
            loggingEnabled = true
        )

        // Method 1: UniLink (no backend required)
        DiditSdk.startVerification(
            workflowId = "your-workflow-id",
            vendorData = "user-123",
            configuration = config
        ) { result ->
            handleResult(result)
        }

        // Method 2: Backend Session (recommended for production)
        // DiditSdk.startVerification(
        //     token = "your-session-token",
        //     configuration = config
        // ) { result ->
        //     handleResult(result)
        // }
    }

    private fun handleResult(result: VerificationResult) {
        when (result) {
            is VerificationResult.Completed -> {
                when (result.session.status) {
                    VerificationStatus.APPROVED -> {
                        Log.d("Didit", "Approved! Session: ${result.session.sessionId}")
                    }
                    VerificationStatus.PENDING -> {
                        Log.d("Didit", "Under review")
                    }
                    VerificationStatus.DECLINED -> {
                        Log.d("Didit", "Declined")
                    }
                }
            }
            is VerificationResult.Cancelled -> {
                Log.d("Didit", "Cancelled: ${result.session?.sessionId ?: "unknown"}")
            }
            is VerificationResult.Failed -> {
                Log.e("Didit", "Error: ${result.error.message}")
            }
        }
    }
}
```***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.