Sample Android application demonstrating the Gate/AI SDK integration with Jetpack Compose.
- π¨ Modern Jetpack Compose UI with configuration overview, actions, and response inspector
- π Gate/AI SDK integration example
- π± Material Design 3 components with custom theming
- ποΈ MVVM architecture with ViewModel
- βοΈ BuildConfig-based configuration
- π Analytics properties (
userIdentifier,appFeature,userStatus) set once on the client - π Usage limits:
userTierandquotaAnchorDay, per-metric quota meters fromRawResponse.quotaStatus, and structured 429 handling viaGateApiException.rateLimitInfo
From this directory:
cp sample.local.properties.example sample.local.propertiesEdit sample.local.properties with your settings (no quotes around values):
APPLICATION_ID=com.yourcompany.gateaisample
GATE_BASE_URL=https://your-gate.in.gate-ai.net
DEBUG_SIGNING_CERT_SHA256=YOUR_DEBUG_SHA256_FINGERPRINT
RELEASE_SIGNING_CERT_SHA256=YOUR_RELEASE_SHA256_FINGERPRINT
CLOUD_PROJECT_NUMBER=0
DEV_TOKEN=This file is ignored by Git. You do not need to edit app/build.gradle.kts or rename the source package. APPLICATION_ID controls the installed app's package name; the code namespace stays com.gateai.sample. Register your application ID and signing certificate with your gate.
Set CLOUD_PROJECT_NUMBER to the numeric Google Cloud project number linked to Play Integrity in your Play Console (without an L suffix). 0 means unset. This is required for device testing with development builds (Android Studio / adb).
If the file is absent, builds use a generic application ID and placeholder gate URL with no credentials. Configure the file before making requests. Keep Android SDK paths in Android Studio's separate local.properties file.
Debug keystore:
keytool -list -v -keystore ~/.android/debug.keystore \
-alias androiddebugkey \
-storepass android \
-keypass android | grep SHA256Release keystore:
keytool -list -v -keystore /path/to/your/release.keystore \
-alias your-key-aliasCopy the SHA256 value (e.g., AA:BB:CC:...) to DEBUG_SIGNING_CERT_SHA256 or RELEASE_SIGNING_CERT_SHA256 in sample.local.properties. The debug build uses the standard Android debug keystore. Setting a release fingerprint does not configure release signing; release APKs still need to be signed with that certificate.
For testing on emulators where Play Integrity is unavailable:
- Generate a development token in the Gate/AI Portal.
- Set
DEV_TOKEN=your-dev-token-hereinsample.local.properties.
The token is included only in debug builds; release builds always use an empty token. Local properties are compiled into the app, so keep token-bearing debug APKs private.
./gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apkOr open in Android Studio, sync Gradle, and click Run. Sync/rebuild after changing local settings.
app/src/main/
βββ AndroidManifest.xml
βββ java/com/gateai/sample/
β βββ GateSampleApp.kt # Application class, SDK initialization
β βββ GateSampleActivity.kt # Main activity
β βββ ui/
β βββ GateSampleScreen.kt # Compose UI with config/actions/response sections
β βββ GateSampleViewModel.kt # Business logic and Gate/AI interactions
βββ res/
βββ values/
βββ themes.xml # Material theme
βββ strings.xml # String resources
class GateSampleApp : Application() {
lateinit var gateAIClient: GateAIClient
private set
lateinit var gateAIConfiguration: GateAIConfiguration
private set
override fun onCreate() {
super.onCreate()
gateAIClient = setupGateAIClient()
}
private fun setupGateAIClient(): GateAIClient {
val config = GateAIConfiguration(
baseUrl = BuildConfig.GATE_BASE_URL,
packageName = packageName,
signingCertSha256 = BuildConfig.SIGNING_CERT_SHA256,
developmentToken = BuildConfig.DEV_TOKEN.takeIf { it.isNotBlank() },
logLevel = if (BuildConfig.DEBUG) {
GateAIConfiguration.LogLevel.DEBUG
} else {
GateAIConfiguration.LogLevel.INFO
}
)
gateAIConfiguration = config
return GateAIClient.create(
context = this,
configuration = config
)
}
}The ViewModel exposes convenient actions that the UI can trigger:
fun testAuthentication() { /* request auth headers & show preview */ }
fun testProxyRequest() { /* call proxy with sample payload */ }
fun clearCache() { /* clear cached Gate/AI state */ }Each action updates GateSampleUiState, which contains configuration metadata, loading indicators, and response/error strings for display.
The Compose UI mirrors the iOS sample with distinct sections:
- Header with icon and description
- Configuration card showing base URL, package name, environment, dev token status, and log level
- Action buttons for auth test, proxy request, and cache clearing
- Response card with progress indicator, success and error styling
Modify the request path in GateSampleViewModel.kt:
val response = gateAIClient.performProxyRequest(
path = "v1beta/models/gemini-2.5-flash:generateContent",
method = HttpMethod.POST,
body = requestBody,
additionalHeaders = mapOf("Content-Type" to "application/json")
)Use the headers with your preferred HTTP client:
// With OkHttp
val request = Request.Builder()
.url("${BuildConfig.GATE_BASE_URL}/v1/models")
.apply {
headers.forEach { (key, value) -> addHeader(key, value) }
}
.build()
// With Ktor
val response = client.get("${BuildConfig.GATE_BASE_URL}/v1/models") {
headers {
headers.forEach { (key, value) -> append(key, value) }
}
}Edit app/src/main/java/com/gateai/sample/ui/theme/ to adjust colors and typography.
- Check that
GATE_BASE_URLis valid - Verify
SIGNING_CERT_SHA256is correct - Ensure your package name and cert are registered in Gate/AI Portal
- Your app's package name must be registered in Gate/AI Portal
- SHA-256 certificate fingerprint must match registration
- App must be signed with the registered certificate
- Use development token for emulator testing
- Set
DEV_TOKENin debug build variant - Ensure dev token is valid and not expired
- Check that your Gate/AI base URL is correct
- Verify device clock is synchronized
- Check logs for DPoP nonce handling
This sample uses:
- Gate/AI SDK
com.github.GateAI-net:gate-android:v1.1.0via JitPack (seesettings.gradle.kts) - Jetpack Compose for UI
- ViewModel for state management
- Kotlin Coroutines for async operations
- Integrate with real AI API endpoints (OpenAI, Anthropic, etc.)
- Add error handling UI feedback
- Implement streaming responses
- Add conversation history
- Customize theme and branding
For more information, see the main SDK documentation.