Skip to content

Repository files navigation

Chatty Android SDK

Native Jetpack Compose chat UI for Chatty — zero WebView, zero compromise.

Drop a fully native, on-brand support chat into any Android app in minutes. Talks directly to the same /api/widget/* backend as the Chatty web widget, and renders every bubble, avatar, and composer with real Compose UI — fast, themeable, and indistinguishable from the rest of your app.

CI Release License: MIT minSdk 24 Kotlin Stars

Install · Quick start · Design gallery · API reference · Example app


Why this SDK

No WebView, anywhere Every bubble, avatar, and the composer are real @Composables — no iframe, no JS bridge, no WebView memory overhead.
Matches your dashboard automatically Fetches the bot's theme and renders with the exact colors, corner radii, and launcher shape chosen in the dashboard — no manual styling.
Two integration shapes A floating ChattyLauncher bubble + dialog, or an embedded ChattyChatScreen inside your own layout.
A real composer, not a stub Emoji picker, animated attach menu (camera + gallery), and mic-to-text voice notes — built in, not bolted on.
Small dependency footprint OkHttp, Coil, and Jetpack Compose Material3. Nothing else.

Install

Note

Use v1.0.6 or later. v1.0.0v1.0.2 predate fixes that were needed for the SDK, the example app, and CI to actually build cleanly. Full history in the releases — every tag from v1.0.3 onward is CI-verified green before it ships.

Via JitPack — works today, no account needed

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }
    }
}
// app/build.gradle.kts
dependencies {
    implementation("com.github.PersonaliAI:chatty-android-sdk:v1.0.6")
}
Via Maven Central (configured, publish pending Sonatype verification)

Publishing is fully wired up (com.vanniktech.maven.publish, see chatty-sdk/build.gradle.kts, and the tag-triggered release.yml workflow) but not yet live — it needs a verified Sonatype account for the com.personaliai namespace. Once published:

dependencies {
    implementation("com.personaliai:chatty-android-sdk:1.0.6")
}
As a local module (building from source)
// settings.gradle.kts
include(":chatty-sdk")
project(":chatty-sdk").projectDir = file("../chatty-android-sdk/chatty-sdk")
// app/build.gradle.kts
dependencies {
    implementation(project(":chatty-sdk"))
}

Quick start

Find your bot ID in the Chatty dashboard under Embed & Integrate → Android SDK.

Floating launcher (recommended) — a bubble that expands into a full-screen chat dialog, the native equivalent of the web widget's launcher button:

@Composable
fun AppRoot() {
    Box(Modifier.fillMaxSize()) {
        // ...your app content...
        ChattyLauncher(botId = "YOUR_BOT_ID")
    }
}

Embedded full-screen chat — place it directly in your own navigation, e.g. as a "Support" tab:

@Composable
fun SupportScreen() {
    ChattyChatScreen(botId = "YOUR_BOT_ID", modifier = Modifier.fillMaxSize())
}

Design gallery

The SDK ships all 10 Chatty widget designs as Compose color/radius tokens, ported 1:1 from the web widget's globals.css, so a native screen looks like whatever design is chosen in the dashboard rather than one generic look. No configuration required — the SDK fetches the bot's theme and resolves the matching token set automatically, including legacy widget_style IDs from older presets.

Design Accent
minimal #1c1a15
playful #ff8a5c
corporate #1c2e4a
dark-sleek #00e5c7
gradient-glow #a855f7
glassmorphism #8f6ff0
ecommerce #0f9d8c
healthcare-calm #6f9c7d
neubrutalism #ff3d67
luxury-editorial #161412

Font pairing (each web design uses a distinct Google Font) is intentionally out of scope for this release; color, radius, and header/bubble treatment carry most of a design's identity.

API reference

ChattyLauncher

@Composable
fun ChattyLauncher(
    botId: String,
    baseUrl: String = CHATTY_DEFAULT_BASE_URL,
    host: String? = null,
    position: ChattyPosition = ChattyPosition.BOTTOM_END,
    color: Color? = null,
    onVoiceCallPress: (() -> Unit)? = null,
    onNotificationBellPress: (() -> Unit)? = null,
)
Param Description
botId Required. Your bot's ID from the dashboard.
baseUrl Chatty backend base URL. Defaults to the production API.
host Advisory only — sent to the backend but not used for access control. See Notes.
position Corner the bubble docks to. Default BOTTOM_END.
color Overrides the launcher color. Defaults to the active design's accent color.
onVoiceCallPress Forwarded to ChattyChatScreen's header voice-call button. See Notes.
onNotificationBellPress Forwarded to ChattyChatScreen's header notification bell. See Notes.

ChattyChatScreen

@Composable
fun ChattyChatScreen(
    botId: String,
    baseUrl: String = CHATTY_DEFAULT_BASE_URL,
    host: String? = null,
    hostKey: String = "app",
    modifier: Modifier = Modifier,
    onMessage: ((ChattyMessage) -> Unit)? = null,
    onVoiceCallPress: (() -> Unit)? = null,
    onNotificationBellPress: (() -> Unit)? = null,
    onClose: (() -> Unit)? = null,
)
Param Description
botId Required. Your bot's ID from the dashboard.
baseUrl Chatty backend base URL. Defaults to the production API.
host Advisory only — sent to the backend but not used for access control. See Notes.
hostKey Storage key used to namespace the locally persisted conversation.
modifier Standard Compose Modifier for sizing/placement.
onMessage Called for every inbound message — useful for unread badges or analytics.
onVoiceCallPress Header voice-call button tapped. Only shown when the bot's dashboard has voice enabled. See Notes.
onNotificationBellPress Header notification-bell button tapped, after the OS permission prompt resolves. See Notes.
onClose Renders a close (✕) button in the header when set. ChattyLauncher passes this for you; set it yourself only if you're embedding ChattyChatScreen directly inside your own dialog/sheet.

Notes

Security — bot_id and domain restriction

bot_id is not a secret — it's extractable from any client, web or mobile. Domain restriction (allowed_domains in the dashboard) is enforced by the backend as a rate-limit tier, not a hard reject: verified web traffic gets 30 msgs/60s per bot+IP, everything else (including all mobile SDK traffic — there's no way for a native app to obtain a "verified" token the way a browser's Referer allows) gets throttled to 5 msgs/120s. The host param this SDK sends is advisory only and isn't used for access control. If your bot is mobile-primary, leave allowed_domains empty to get the normal 30/60s tier instead.

Notification bell — what it does and doesn't do

Tapping it requests the OS notification permission (Android 13+ only — older versions grant it at install time) and then calls onNotificationBellPress. That's as far as this SDK goes. Actually delivering a push when a reply arrives while the app is backgrounded needs a push provider wired up at the app level — either Firebase Cloud Messaging directly (free, no third party) or a wrapper like OneSignal (adds a dashboard/API for managing sends, at the cost of another vendor). Either way it's the same shape of work: register the device's push token, send it to your own backend, store it against the session/user, and have your backend call FCM/OneSignal's send API when a new assistant/agent message lands for a session that isn't actively polling. None of that exists yet — it's backend work in chatty-backend, not something this client SDK can add on its own.

Voice-call button

Only shown when the bot's dashboard has voice enabled, and only fires onVoiceCallPress — this SDK doesn't bundle a voice-call implementation (that's a separate LiveKit integration, out of scope here).

  • Lead capture and meeting booking happen conversationally (the assistant decides to ask/act) — there's no separate REST call to trigger them from the SDK.
  • Polling for human-agent takeover messages runs every 4s while ChattyChatScreen is composed, matching the web widget's behavior.
  • Conversation history is persisted locally (SharedPreferences), mirroring the web widget's localStorage cache, so a returning user sees their prior messages.

Example app

example-app/ is a minimal, runnable Compose app demonstrating both integration styles side by side — open it in Android Studio, hit run, and try the floating launcher and the embedded full-screen chat against a live demo bot.

./gradlew :example-app:installDebug

Requirements

  • minSdk 24+

  • Kotlin, Jetpack Compose (Material3)

  • OkHttp, Coil (image loading) — pulled in automatically as transitive dependencies

  • Core library desugaring enabled in your app module — the SDK uses java.time APIs desugared down to minSdk 24, and the Android Gradle Plugin enforces that any consumer of an AAR built this way opts in too:

    // app/build.gradle.kts
    android {
        compileOptions {
            isCoreLibraryDesugaringEnabled = true
        }
    }
    dependencies {
        coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.3")
    }

Contributing — bug reports, design-parity fixes, and PRs are welcome.

Licensed under MIT © PersonaliAI

About

Official Android SDK for Chatty AI chatbots — native Kotlin + Jetpack Compose, no WebView

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages