---
title: Android
description: Custom Tabs를 사용하여 Android 앱에 Human Token Journey를 통합하세요 — 가볍고 안전하며 WebView가 필요 없습니다.
canonical: https://developer.unico.io/ko/human-token/integrations/app/android/link-integration
locale: ko
generated_by: markdown-export
---

# Android

Custom Tabs를 사용하여 Android 앱에 Human Token Journey를 통합하세요.

Custom Tabs는 앱 내부의 브라우저 탭에서 Human Token Journey를 실행합니다. 여정이 완료되면 브라우저가 사용자 지정 URL 스킴으로 리디렉션하고 앱이 이를 가로챕니다.

### 사전 요구 사항

- Android 8 (API 26) 이상
- `androidx.browser:browser:1.5.0`
- 앱의 고유한 URL 스킴 (예: `myapp`)

### 단계 1: 의존성 추가

`build.gradle`에서:

```groovy
implementation("androidx.browser:browser:1.5.0")
```

### 단계 2: URL 스킴 정의

고유한 스킴을 선택하세요 (예: `myapp`). 프로세스 생성 시 `callbackUri`로 사용됩니다:

```
callbackUri: myapp://callback
```

### 단계 3: 액티비티 생성

```kotlin
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.browser.customtabs.CustomTabsIntent

class HumanTokenActivity : AppCompatActivity() {

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

        val url = intent.getStringExtra(EXTRA_PROCESS_URL) ?: return finish()

        CustomTabsIntent.Builder()
            .build()
            .launchUrl(this, Uri.parse(url))
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        intent.data?.let { uri ->
            if (uri.scheme == "myapp") {
                // Journey completed — send processId to your backend
                val processId = uri.getQueryParameter("id")
                handleResult(processId)
            }
        }
    }

    private fun handleResult(processId: String?) {
        // Fetch the result from your backend via Get Process
        finish()
    }

    companion object {
        const val EXTRA_PROCESS_URL = "process_url"
    }
}
```

### 단계 4: AndroidManifest.xml 구성

```xml
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />

<activity
    android:name=".HumanTokenActivity"
    android:launchMode="singleTop"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="myapp" android:host="callback" />
    </intent-filter>
</activity>
```

`singleTop`은 Android가 새 액티비티를 생성하는 대신 기존 액티비티에서 `onNewIntent()`를 호출하도록 보장합니다.

### 단계 5: 여정 시작

```kotlin
val intent = Intent(this, HumanTokenActivity::class.java)
    .putExtra(HumanTokenActivity.EXTRA_PROCESS_URL, processLink)
startActivity(intent)
```

### 파일 요약

| 파일 | 목적 |
|---|---|
| `build.gradle` | `androidx.browser` 의존성 |
| `HumanTokenActivity.kt` | Custom Tabs 실행 + 리디렉션 처리 |
| `AndroidManifest.xml` | URL 스킴용 Intent 필터 |

---

### Custom Tabs 대신 WebView 사용

> **경고:** Custom Tabs가 권장되는 접근 방식입니다. 더 안전하고, 리다이렉트를 네이티브로 처리하며, 설정이 적게 필요합니다. 프로젝트에서 Custom Tabs를 사용할 수 없는 경우에만 WebView를 사용하세요.

`WebView`를 사용해야 하는 경우, 저니에서 JavaScript, DOM 스토리지, 미디어 자동 재생, 카메라/위치 권한을 명시적으로 부여해야 합니다. 이러한 설정이 없으면 캡처 프레임이 로드되지 않거나 카메라가 활성화되지 않습니다.

```kotlin
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.settings.mediaPlaybackRequiresUserGesture = false
webView.settings.setGeolocationEnabled(true)

webView.webChromeClient = object : WebChromeClient() {
    override fun onPermissionRequest(request: PermissionRequest) {
        if (PermissionRequest.RESOURCE_VIDEO_CAPTURE in request.resources) {
            request.grant(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE))
        } else {
            request.deny()
        }
    }

    override fun onGeolocationPermissionsShowPrompt(
        origin: String,
        callback: GeolocationPermissions.Callback
    ) {
        callback.invoke(origin, true, false)
    }
}
```

`AndroidManifest.xml`에 `CAMERA`, `INTERNET`, `ACCESS_FINE_LOCATION` 권한을 선언하고, 여정 URL을 로드하기 전에 런타임에서 카메라 및 위치 권한을 요청해야 합니다.

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```