SDK GUIDE / SOURCE PREVIEW
Android native / Kotlin
Native Chat, encrypted app history, Relay and host tools
1. Set up your project
Start from sdk/android in the Cloud repository. These commands use the local source package, not a registry release.
# From sdk/, with Android SDK and Gradle installed:
gradle :android:testDebugUnitTest :android:assembleDebug :android-local:assembleDebug
# Include the android module and optionally android-local in your app.2. Prepare authentication
Server examples read MULTIVIBE_BASE_URL and MULTIVIBE_TOKEN from the environment. Use an origin without /v1. Never ship a project key in a browser or mobile bundle.
For client applications, use a user-authorized OAuth access-token provider and OS-secure storage. Browser refresh and exchange require a backend. Backendless publisher-funded sessions are not implemented.
Android applications should use ApplicationSession, ApplicationBrowserSignIn and the reusable ApplicationConnectButton. The coordinator owns PKCE, Keystore persistence and refresh rotation; forward the exact verified App Link to handleCallback.
Use ApplicationChatController.create and ApplicationChatView.bind for the prebuilt native Chat, or ApplicationHistory without UI. Conversation scopes add a Keystore-backed public key to OAuth; recovery is entered only on MultiVibe. The app receives only its own derived history keys. Pending saves have explicit retry/abandon controls; the host can read displayed messages.
For strict host isolation, ApplicationIsolatedChat opens the application-scoped Chat in Custom Tabs and sends only the public client UUID. Tokens, recovery codes, history keys and messages remain in the MultiVibe browser surface; host tools are unavailable.
3. Make your first request
This example discovers models and demonstrates optional local execution after an availability check. Mobile snippets belong in your authenticated application; they are not standalone app projects.
// Keep these objects in an application-owned ViewModel.
import android.app.Activity
import cloud.multivibe.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
fun connect(activity: Activity, scope: CoroutineScope, button: ApplicationConnectButton): ApplicationSession {
val session = ApplicationSession.create(activity, "YOUR_PORTAL_UUID")
val signIn = ApplicationBrowserSignIn(session)
scope.launch { signIn.state.collectLatest(button::render) }
button.setOnClickListener { scope.launch {
signIn.start(activity, "https://app.example.com/multivibe/callback")
} }
return session
}
suspend fun models(session: ApplicationSession) =
ApplicationClient(token = session::token).models()Next steps
Choose a compatible model from the catalog before inference. Handle expired access, insufficient scope and unavailable models separately. Never retry a billable inference blindly after a timeout or partial stream.
Operations, streaming and usage →