Getting Started

Android SDK — Getting Started

SkillDownload

Minimal steps to integrate OAuth sign-in and wallet flows with the CROSSx Android SDK.

Requirements

  • Android API 24+
  • Kotlin + Coroutines
  • App configuration that can receive OAuth callback URLs

1) Dependencies (Maven Central)

Align versions with the BOM, then add the core artifact only.

dependencies {
    implementation(platform("io.crosstoken.cross:crossx-sdk-bom:2.0"))
    implementation("io.crosstoken.cross:crossx-sdk-core")
}

Current version is 2.0. Replace with the latest BOM version published on Maven Central if a newer one is available.

Endpoints are not app configuration

Base URLs for OAuth, the auth API, and the wallet gateway are not in SDKConfig. The host app does not pass URLs; values come from the SDK binary (BuildConfig / SDKEnvironment baked into the build). Match dev / staging / production by which SDK artifact, product flavor, or CI-built variant you depend on.

2) Project ID + callback scheme

Example build.gradle.kts in the app module:

android {
    defaultConfig {
        val projectId = providers.gradleProperty("CROSSX_PROJECT_ID").get()
        val callbackScheme = "crossx-$projectId"

        buildConfigField("String", "CROSSX_CALLBACK_SCHEME", "\"$callbackScheme\"")
        buildConfigField("String", "CROSSX_PROJECT_ID", "\"$projectId\"")
        manifestPlaceholders["CROSSX_CALLBACK_SCHEME"] = callbackScheme
    }

    buildFeatures {
        buildConfig = true
    }
}

Supply CROSSX_PROJECT_ID from your integration contact via ~/.gradle/gradle.properties, the project gradle.properties, or -PCROSSX_PROJECT_ID=.... Do not ship with sample or placeholder IDs.

3) Register the deep link callback

After OAuth completes, the user is redirected to {callbackScheme}://....

Add an intent filter in AndroidManifest.xml (typically on MainActivity):

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTask">
    <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="${CROSSX_CALLBACK_SCHEME}" />
    </intent-filter>
</activity>

Forward the callback URL to the SDK:

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    val url = intent.dataString ?: return
    sdk.handleUrl(url)
}

4) Create the SDK instance

SDKConfig requires projectId and appName. appName is the default app label in signing and sending confirmation UI.

import io.crosstoken.crossxsdk.adapters.logging.AndroidLogcatLogger

val config = SDKConfig(
    context = application,
    projectId = BuildConfig.CROSSX_PROJECT_ID,
    appName = getString(R.string.app_name),
    callbackScheme = BuildConfig.CROSSX_CALLBACK_SCHEME,
    logger = AndroidLogcatLogger() // optional
)

val sdk = CROSSxSDK(
    application = application,
    config = config
)

5) Basic auth flow

// Try to restore session on startup
val restored = sdk.initialize() // AuthResult? (null if restore fails)

// Whether the session is usable (includes restore / refresh)
val ok = sdk.ensureLoggedIn()

// OAuth sign-in (default: provider selection sheet)
val auth = sdk.signIn()

// Sign in and create or migrate wallet in one step
val authWithWallet = sdk.signInWithCreate()

// Start a specific provider directly
val googleAuth = sdk.signIn(SDKSignInProvider.Google)
val appleAuth = sdk.signIn(SDKSignInProvider.Apple)

// Sign out
sdk.signOut()

// Manually refresh access token
val newAccessToken = sdk.refreshToken()

signIn() performs authentication only. First-time users may not have a wallet address yet. If you need an address immediately, use signInWithCreate() or call createWallet() after signIn().

When createWallet() runs, the SDK checks wallet state and branches:

  • exists — Reuses the existing wallet and address. If no wallet password is stored locally, the SDK prompts once and reuses it afterward.
  • migration_required — If migrateAutomatically == true, runs migration and prompts for a wallet password. If false, throws CROSSxError.MigrationRequired.
  • not_found — Creates a new wallet and prompts for a wallet password.

6) Basic wallet flow

val chainId = "eip155:612044"

val created = sdk.createWallet()
val createdManual = sdk.createWallet(migrateAutomatically = false)
val addr = sdk.getAddress()
val balanceHex = sdk.getBalance(address = addr.address.orEmpty(), chainId = chainId)

createWallet() returns the wallet address only. Recovery-share handling is a separate flow outside the public SDK surface.

To control backup migration yourself, use createWallet(migrateAutomatically = false) and handle CROSSxError.MigrationRequired.

7) Minimal Activity integration example

class MainActivity : ComponentActivity() {
    private val sdk by lazy {
        val config = SDKConfig(
            context = application,
            projectId = BuildConfig.CROSSX_PROJECT_ID,
            appName = getString(R.string.app_name),
            callbackScheme = BuildConfig.CROSSX_CALLBACK_SCHEME
        )
        CROSSxSDK(application = application, config = config)
    }

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

        lifecycleScope.launch {
            sdk.initialize()
        }

        findViewById<View>(R.id.signInButton).setOnClickListener {
            lifecycleScope.launch {
                sdk.signInWithCreate()
            }
        }

        findViewById<View>(R.id.googleSignInButton).setOnClickListener {
            lifecycleScope.launch {
                sdk.signIn(SDKSignInProvider.Google)
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        intent.dataString?.let(sdk::handleUrl)
    }
}

The same pattern applies with Compose, Fragments, or DI: call initialize() on startup, sign in from user actions, and always pass callback URLs to handleUrl.

Use signIn() when you only need authentication; use signInWithCreate() when you need a wallet right after login.


© 2025 NEXUS Co., Ltd. All Rights Reserved.