Skip to content

Android SDK

Android 5.0+ (API 21+) 를 지원하는 단일 .aar 패키지. Compose 및 기존 View 기반 앱 모두 지원하며 UI 프레임워크에 종속되지 않습니다.

GitHub 데모

📦

Captcha-La/android-demo — 모든 통합 단계가 포함된 실행 가능한 예제.

설치

The SDK ships as a single .aar you download from the CaptchaLa dashboard. Drop it into your app module's libs/ folder and reference it from Gradle:

groovy
// settings.gradle (or repositories block)
dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }
}

// app/build.gradle
android {
    defaultConfig {
        minSdk 21
    }
}

dependencies {
    implementation 'la.captcha:captchala:1.0.2'   // Maven Central
}

AAR을 다운로드하여 수동으로 통합할 수도 있습니다:

groovy
// app/build.gradle (drop captchala.aar into app/libs/)
android {
    defaultConfig {
        minSdk 21
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }
}

dependencies {
    implementation files('libs/captchala.aar')
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.code.gson:gson:2.10.1'
    implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
}

Download: dash.captcha.la/downloads (latest AAR).

xml
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Build and install the demo with:

bash
./gradlew installDebug

빠른 시작

kotlin
import la.captcha.sdk.CaptchalaClient
import la.captcha.sdk.CaptchalaConfig
import la.captcha.sdk.CaptchalaError
import la.captcha.sdk.CaptchalaListener
import la.captcha.sdk.CaptchalaResult

class LoginActivity : ComponentActivity() {

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

        // 1. Fetch a one-shot server_token from YOUR backend
        //    (which calls the CaptchaLa server API with X-App-Key + X-App-Secret).
        val serverToken = runBlocking { fetchServerTokenFromYourBackend() }

        // 2. Build config — destroy any prior client so a fresh state is built.
        CaptchalaClient.destroy()
        val client = CaptchalaClient.getClient(applicationContext).init(
            CaptchalaConfig.Builder()
                .appKey("YOUR_APP_KEY")
                .action("login")            // login, register, pay, …
                .lang("en")                 // en, zh-CN, zh-TW, ja, ko, ms, vi, id
                .theme("light")             // "light" | "dark"
                .enableVoice(true)
                .enableOfflineMode(true)
                .serverToken(serverToken)
                .onServerTokenExpired { fetchServerTokenFromYourBackend() }
                .build()
        )

        // 3. Listen for terminal events.
        client.setListener(object : CaptchalaListener {
            override fun onReady() { /* challenge UI ready */ }
            override fun onSuccess(result: CaptchalaResult) {
                // Send result.passToken to your backend for validation.
                sendToBackend(result.passToken)
            }
            override fun onFail(error: CaptchalaError)  { /* recoverable */ }
            override fun onError(error: CaptchalaError) { /* terminal */ }
            override fun onClose() { /* user dismissed */ }
        })

        // 4. Open the CAPTCHA from a button tap.
        findViewById<Button>(R.id.btnVerify).setOnClickListener {
            client.verify(this)
        }
    }
}

주요 API

심볼용도
CaptchalaClient.getClient(ctx)싱글턴 진입점. 앱 컨텍스트에 바인딩된 공유 클라이언트를 반환합니다.
CaptchalaConfig.Builder()appKey, action, lang, theme, enableVoice, enableOfflineMode, serverToken 을 설정하는 빌더.
init(config)빌드된 CaptchalaConfig 로 클라이언트를 초기화합니다. 다시 호출하면 상태를 재구성합니다.
setListener(listener)CaptchalaListener 를 등록하여 onReady / onSuccess / onFail / onError / onClose 콜백을 받습니다.
verify(activity)지정한 Activity 위에 CAPTCHA 를 표시합니다. 결과는 리스너를 통해 전달됩니다.
CaptchalaResultpassToken, challengeId, ttl, isOffline, isClientOnly 를 담습니다. passToken 을 백엔드로 전송하세요.
CaptchalaClient.destroy()싱글턴을 해제(WebView, 네이티브 핸들 정리). 재초기화가 잦다면 Activity.onDestroy 에서 호출하세요.

서버 측 검증

result.passToken(또는 result.token)을 백엔드로 전달하고 CaptchaLa API로 검증합니다. X-App-Secret을 클라이언트 코드에 노출하지 마세요.

bash
POST https://apiv1.captcha.la/v1/validate
X-App-Key: YOUR_APP_KEY
X-App-Secret: YOUR_APP_SECRET
Content-Type: application/json

{ "pass_token": "<result.passToken>", "client_ip": "<end-user IP>" }

전체 검증 엔드포인트와 X-App-Key / X-App-Secret 흐름은 API 레퍼런스를 참고하세요.

문제 해결

  • 시작 시 UnsatisfiedLinkError
    abiFiltersarmeabi-v7a, arm64-v8a, x86, x86_64 를 모두 포함하는지 확인하세요. 데모의 app/build.gradle 에 정확한 설정이 있습니다.

  • ProGuard / R8 가 release 빌드에서 SDK 클래스를 제거
    proguard-rules.pro 에 SDK 패키지 keep 규칙을 추가하세요. 예: -keep class la.captcha.sdk.** { *; }-dontwarn la.captcha.sdk.**.

  • minSdkVersion 이 너무 낮음
    SDK 는 minSdkVersion 21(Android 5.0) 이 필요합니다. 더 낮은 값은 컴파일 단계에서 실패합니다.

  • 평문 HTTP 트래픽이 차단됨
    매니페스트에서 android:usesCleartextTraffic="false" 를 유지하세요(데모가 그렇게 합니다). CaptchaLa 엔드포인트는 HTTPS 만 지원합니다.

요구 사항

  • Android 5.0+ (minSdkVersion 21)
  • AndroidX (compileSdk 33+)
  • Kotlin 1.8+ or equivalent Java toolchain (Java 17 source / target)
  • ABIs: armeabi-v7a, arm64-v8a, x86, x86_64

MIT-licensed examples · CaptchaLa is operated independently