Android SDK
Drop-in support SDK for Android apps. Jetpack Compose, Activity launches, or headless API.
Android SDK
Drop-in support SDK for Android apps. Replace Zendesk with a few lines of code.
Requirements
- Min SDK 24 (Android 7.0+)
- Kotlin 2.0+
- Jetpack Compose (BOM 2024.12.01+)
- OkHttp 4.12
- kotlinx-serialization
Installation
Add the Premex artifact repository and the dependency to your module-level build.gradle.kts:
API Reference
All public classes and their full import paths:
| Class | Import | Description |
|---|---|---|
PremexSupport | se.premex.support.PremexSupport | Singleton entry point — initialize, show UI, or access lower-level clients |
PremexSupportConfig | se.premex.support.PremexSupportConfig | Configuration data class (baseUrl, productSlug) |
FormType | se.premex.support.model.FormType | Enum of form types (see Form Types) |
FormSubmission | se.premex.support.model.FormSubmission | Sealed interface for typed programmatic form data |
FormSubmission.Support | se.premex.support.model.FormSubmission | Support request form data |
FormSubmission.FeatureRequest | se.premex.support.model.FormSubmission | Feature request form data |
FormSubmission.BugReport | se.premex.support.model.FormSubmission | Bug report form data |
PremexApiClient | se.premex.support.api.PremexApiClient | REST API client (OkHttp + Coroutines) |
ApiResult | se.premex.support.api.ApiResult | Sealed result type (Success / Error) |
SseEventSource | se.premex.support.api.SseEventSource | Real-time SSE event stream as Flow<ConversationEvent> |
CustomerIdentityManager | se.premex.support.identity.CustomerIdentityManager | Encrypted customer identity storage |
ConversationEvent | se.premex.support.model.ConversationEvent | Sealed class for real-time events (NewComment, StateUpdate, etc.) |
ConversationSummary | se.premex.support.model.ConversationSummary | Lightweight conversation list item |
ConversationDetail | se.premex.support.model.ConversationDetail | Full conversation with messages |
PremexChatScreen | se.premex.support.ui.chat.PremexChatScreen | Compose chat screen |
PremexFormScreen | se.premex.support.ui.form.PremexFormScreen | Compose form screen |
PremexSupportTheme | se.premex.support.ui.theme.PremexSupportTheme | Material 3 theme wrapper |
Initialization
Call PremexSupport.initialize() once, as early as possible — typically in Application.onCreate() or your main Activity:
import se.premex.support.PremexSupport
import se.premex.support.PremexSupportConfig
// Application.kt
PremexSupport.initialize(
context = applicationContext,
config = PremexSupportConfig(
baseUrl = "https://support.premex.se",
productSlug = "your-product-slug",
),
)
Jetpack Compose Integration (Recommended)
Embed the SDK's composables directly in your Compose navigation graph for the most seamless experience.
import se.premex.support.ui.chat.PremexChatScreen
import se.premex.support.ui.form.PremexFormScreen
import se.premex.support.model.FormType
// Chat screen
PremexChatScreen(
modifier = Modifier.fillMaxSize(),
onNavigateBack = { navController.popBackStack() },
)
// Form screen
PremexFormScreen(
formType = FormType.BUG_REPORT,
modifier = Modifier.fillMaxSize(),
onNavigateBack = { navController.popBackStack() },
onSubmitted = { navController.popBackStack() },
)
A full NavHost example with chat and form routes:
import se.premex.support.ui.chat.PremexChatScreen
import se.premex.support.ui.form.PremexFormScreen
import se.premex.support.model.FormType
NavHost(navController, startDestination = "home") {
composable("home") {
HomeScreen(
onOpenChat = { navController.navigate("chat") },
onOpenBugReport = { navController.navigate("form/bug_report") },
onOpenFeatureRequest = { navController.navigate("form/feature_request") },
onOpenSupport = { navController.navigate("form/support") },
)
}
composable("chat") {
PremexChatScreen(
modifier = Modifier.fillMaxSize(),
onNavigateBack = { navController.popBackStack() },
)
}
composable("form/{formType}") { backStackEntry ->
val formType = FormType.valueOf(
backStackEntry.arguments?.getString("formType")
?.uppercase() ?: "SUPPORT",
)
PremexFormScreen(
formType = formType,
modifier = Modifier.fillMaxSize(),
onNavigateBack = { navController.popBackStack() },
onSubmitted = { navController.popBackStack() },
)
}
}
Wrap in PremexSupportTheme for the SDK's default Material 3 styling, or use your own MaterialTheme to customise colours, typography, and shapes.
Activity Integration (Quick Start)
For apps that don't use Compose navigation, launch the SDK's built-in activities directly:
import se.premex.support.PremexSupport
import se.premex.support.model.FormType
// Launch chat
PremexSupport.showChat(context)
// Launch form — formType defaults to FormType.SUPPORT when omitted
PremexSupport.showForm(context)
PremexSupport.showForm(context, FormType.SUPPORT)
PremexSupport.showForm(context, FormType.FEATURE_REQUEST)
PremexSupport.showForm(context, FormType.BUG_REPORT)
Method signature:
fun showForm(context: Context, formType: FormType = FormType.SUPPORT)
| Parameter | Type | Default | Description |
|---|---|---|---|
context | Context | — | Android context used to start the Activity |
formType | FormType | FormType.SUPPORT | Which form to display |
Form Types
The FormType enum (se.premex.support.model.FormType) determines which fields are presented to the user. Each value has a displayName property used as the form heading.
| Value | displayName | Use case | Fields |
|---|---|---|---|
FormType.SUPPORT | "Support Request" | General help requests and questions | Subject, Message |
FormType.FEATURE_REQUEST | "Feature Request" | Suggest new features or improvements | Title, Use Case, Proposed Solution (optional), Priority |
FormType.BUG_REPORT | "Bug Report" | Report defects with reproduction steps | Title, Steps to Reproduce, Expected Behavior, Actual Behavior, Environment (optional) |
Programmatic Form Submission
Submit forms without showing any UI. The SDK builds the same structured markdown body as the built-in form screens and sends it via the REST API.
Each form type has a dedicated data class with named, typed properties — no string keys to remember.
import se.premex.support.PremexSupport
import se.premex.support.model.FormSubmission
import se.premex.support.api.ApiResult
// All submitForm() calls are suspend functions — call from a coroutine scope
lifecycleScope.launch {
// Support request
val result = PremexSupport.submitForm(
FormSubmission.Support(
name = "Jane Doe",
email = "jane@example.com",
subject = "Login not working",
message = "I cannot log in after resetting my password.",
),
)
when (result) {
is ApiResult.Success -> Log.d("Support", "Created: ${result.data.conversationId}")
is ApiResult.Error -> Log.e("Support", "Error: ${result.message}")
}
// Feature request
PremexSupport.submitForm(
FormSubmission.FeatureRequest(
name = "Jane Doe",
email = "jane@example.com",
featureTitle = "Dark mode",
useCase = "The app is too bright at night.",
proposedSolution = "Add a toggle in Settings.", // optional
priority = "Important", // optional, defaults to "Nice to have"
),
)
// Bug report
PremexSupport.submitForm(
FormSubmission.BugReport(
name = "Jane Doe",
email = "jane@example.com",
bugTitle = "Login button unresponsive",
stepsToReproduce = "1. Go to login\n2. Click Login",
expectedBehavior = "Should log in.",
actualBehavior = "Nothing happens.",
environment = "Pixel 8, Android 15", // optional
),
)
}
You can also use the lower-level PremexApiClient.submitForm() directly if you need to supply a custom customerId:
import se.premex.support.PremexSupport
import se.premex.support.model.FormSubmission
lifecycleScope.launch {
val client = PremexSupport.apiClient
client.submitForm(
customerId = "cust_custom-id",
form = FormSubmission.Support(
name = "Jane",
email = "jane@example.com",
subject = "Help",
message = "Details here.",
),
)
}
Headless API
Build a fully custom UI on top of the SDK's networking and identity layers:
import se.premex.support.PremexSupport
import se.premex.support.model.ConversationEvent
val client = PremexSupport.apiClient
val customerId = PremexSupport.identityManager.customerId
// List conversations
val result = client.listConversations(customerId)
// Create conversation (raw, without form structure)
val created = client.createConversation(
customerId = customerId,
subject = "Need help",
message = "I can't find the settings page",
)
// Real-time events
PremexSupport.sseEventSource
.observeEvents(conversationId, customerId)
.collect { event ->
when (event) {
is ConversationEvent.NewComment -> { /* new message */ }
is ConversationEvent.StateUpdate -> { /* status changed */ }
else -> { /* other events */ }
}
}
The observeEvents function returns a Flow<ConversationEvent> backed by an SSE connection. It reconnects automatically on network failures.
Theming
PremexSupportTheme provides Material 3 defaults with full light/dark mode support. To match your app's brand, wrap the SDK composables in your own MaterialTheme:
MaterialTheme(
colorScheme = YourColorScheme,
) {
PremexChatScreen(...)
}
The SDK reads colours, typography, and shapes from the nearest MaterialTheme in the composition tree, so no additional configuration is required.
Customer Identity
- A unique
cust_<UUID>identifier is auto-generated on first use. - Stored in encrypted SharedPreferences (AndroidX Security).
- Persists across app sessions and app updates.
- Clear it manually when needed:
PremexSupport.identityManager.clear()
Migration from Zendesk
Switching from the Zendesk SDK is straightforward. The API surface maps almost one-to-one:
| Zendesk | Premex Support |
|---|---|
Zendesk.initialize(...) | PremexSupport.initialize(...) |
MessagingActivity.show(...) | PremexSupport.showChat(context) |
RequestActivity.show(...) | PremexSupport.showForm(context) |
Architecture
The SDK is organised in layers, each of which can be used independently:
se.premex.support.PremexSupport— Singleton entry point. Owns the lifecycle of all other components.se.premex.support.api.PremexApiClient— REST API client built on OkHttp + Kotlin Coroutines.se.premex.support.api.SseEventSource— Real-time event stream that converts SSE into aFlow<ConversationEvent>.se.premex.support.identity.CustomerIdentityManager— Encrypted identity storage backed by AndroidX Security.se.premex.support.model.*— Data models:FormType,FormSubmission,ConversationEvent,ConversationSummary,ConversationDetail.se.premex.support.ui.*— Compose UI:PremexChatScreen,PremexFormScreen,PremexSupportTheme, and supporting composables.