Theme, language, logging, and telemetry
Theme
Supply fixed ARGB color integers in GraffityARTheme:
import android.content.Context
import tech.graffity.android.arcloud.publicapi.*
fun makeBrandedSession(context: Context, accessToken: String): GraffityARCloudSDK {
val theme = GraffityARTheme(
primary = 0xFF3F51B5.toInt(),
surface = 0xFFFFFFFF.toInt(),
onSurface = 0xFF000000.toInt(),
onSurfaceSecondary = 0xFF666666.toInt(),
danger = 0xFFFF3B30.toInt()
)
val configuration = GraffityARCloudConfiguration.Builder(accessToken)
.theme(theme)
.build()
return GraffityARCloudSDK(context, configuration)
}| Slot | Default ARGB | Use |
|---|---|---|
primary | 0xFF19A6B6 | Native accents and affirmative controls. |
secondary | 0xFF002D40 | Companion brand tone. |
surface | 0xFFFFFFFF | Card and sheet backgrounds. |
onSurface | 0xFF1A1A1A | Primary panel text and icons. |
onSurfaceSecondary | 0xFF8A8A8E | Supporting panel text. |
danger | 0xFFFF3B30 | Destructive controls, including exit. |
GraffityARTheme.DEFAULT uses this palette. The constructor defaults every slot to its matching DEFAULT_* constant. The palette is fixed over the camera feed and does not follow the system’s dark/light appearance. It styles native SDK UI; it is not a web-map CSS customization API.
Language and custom strings
The SDK bundles English and Thai. Android selects resources for the device’s configured locale. A GraffityARStringsProvider overrides native SDK copy; return null to use bundled strings.
import android.content.Context
import tech.graffity.android.arcloud.publicapi.*
val appStrings = GraffityARStringsProvider { key, locale ->
if (locale.language == "en" && key == "navigation_exit_button") {
"End route"
} else {
null
}
}
fun makeTranslatedSession(context: Context, accessToken: String): GraffityARCloudSDK {
val configuration = GraffityARCloudConfiguration.Builder(accessToken)
.stringsProvider(appStrings)
.build()
return GraffityARCloudSDK(context, configuration)
}The provider’s localizedString(key, locale) can run on main or background dispatchers; make it thread-safe. Keep format placeholders compatible with the original string. A null result or provider failure falls back to Android resources. Resource lookup failure ultimately returns the key.
For a host-displayed error, pass the provider explicitly: error.localizedMessage(context, appStrings). The error method does not retrieve the SDK configuration’s provider automatically.
Logging
GraffityARLogging.Default uses Logcat. Disabled selects the no-op internal logger. Use custom(logger, minimum) to send messages to your app’s sink:
import android.content.Context
import android.util.Log
import tech.graffity.android.arcloud.publicapi.*
val appARLogger = GraffityARLogger { level, message, throwable ->
val priority = when (level) {
GraffityARLogLevel.DEBUG -> Log.DEBUG
GraffityARLogLevel.INFO -> Log.INFO
GraffityARLogLevel.WARNING -> Log.WARN
GraffityARLogLevel.ERROR -> Log.ERROR
}
Log.println(priority, "AppAR", message)
if (throwable != null) {
Log.println(priority, "AppAR", Log.getStackTraceString(throwable))
}
}
fun makeLoggedSession(context: Context, accessToken: String): GraffityARCloudSDK {
val configuration = GraffityARCloudConfiguration.Builder(accessToken)
.logging(GraffityARLogging.custom(appARLogger, minimum = GraffityARLogLevel.INFO))
.build()
return GraffityARCloudSDK(context, configuration)
}Make sinks thread-safe and keep them fast. The SDK redacts recognized token and coordinate patterns from message strings and prefixes a category tag. Throwable objects are passed through separately.
The custom sink honors its minimum level, but warnings and errors are also mirrored to fallback Logcat even when below that threshold. Default Logcat currently does not apply the configuration’s INFO threshold, so debug records can also appear. For a quiet internal sink, set .logging(GraffityARLogging.Disabled) before constructing the SDK.
setLogger(logger) updates the container’s sink and preserves the configured minimum. With a null logger it selects fallback Logcat, except at an ERROR minimum where it selects the no-op sink. Components already created can retain their original logger; configure logging before hosting the session for consistent behavior.
Telemetry
Analytics defaults to GraffityARTelemetry.Disabled. Opt in with .telemetry(GraffityARTelemetry.Enabled) or sdk.setTelemetryEnabled(true); turn it off with setTelemetryEnabled(false). Connect this setting to your app’s user preference or consent flow where appropriate.
Telemetry controls analytics requests. Required localization, venue/content lookup, map/assets, and player collection requests continue independently of telemetry.