Readme · Guides · Reference · Contributing
Pre-release. API surface is not yet stable.
This is the native Android reference implementation for the
Contentful Optimization Android SDK. It demonstrates the
integration pattern for both Jetpack Compose (:compose) and XML Views (:views), and is the
target for the shared Maestro E2E suite (see
maestro/README.md).
OptimizationRoot initialization with mock server configurationOptimizedEntry personalization with view and click trackingScreenTrackingEffectPreviewPanelConfig preview panel with audience/variant override controlsThe app configures native SDK contentfulLocales and an app/content locale, then uses
client.locale in the raw CDA fetch helper. Experience API calls use that resolved locale by
default unless nested api.locale is configured as an explicit API override. Entries passed to
OptimizedEntry use the standard single-locale CDA entry shape. Do not use all-locale CDA responses
or locale=*, because SDK entry resolution expects direct single-locale fields such as
fields.nt_experiences and fields.nt_variants. See
Locale handling in the Optimization SDK Suite
for the broader locale model and
Entry personalization and variant resolution
for the entry contract.
This mock app uses one Contentful locale, so ContentfulLocales(default = "en-US") is enough. Add
supported only when a production app needs device-locale matching across multiple Contentful
locales.
ANDROID_HOME setadb in PATHpnpm install)pnpm --filter @contentful/optimization-js-bridge buildFrom the monorepo root:
pnpm install
pnpm --filter @contentful/optimization-js-bridge build
The bootstrap script starts the mock server, builds the app, and launches it on an emulator:
cd implementations/android-sdk
./scripts/bootstrap.sh
Or manually:
# Terminal 1: Start mock server
pnpm serve:mocks
# Terminal 2: Build and install (the app reaches the host mock via 10.0.2.2 — no adb reverse needed)
cd implementations/android-sdk
./gradlew :compose:assembleDebug
adb install -r compose/build/outputs/apk/debug/compose-debug.apk
adb shell am start -n com.contentful.optimization.app/.MainActivity
To launch with a clean SDK state (clears the persisted profile on cold start):
adb shell am start -n com.contentful.optimization.app/.MainActivity --ez reset true
Open this directory (implementations/android-sdk/) as an Android Studio project. After Gradle
sync, build and launch either app on the selected device (MainActivity in :compose or :views),
set breakpoints in the app or SDK source, and run the JVM unit tests from the gutter.
Before running the app from the IDE, in a separate terminal:
# From the monorepo root, build the bridge once (or after bridge source changes):
pnpm --filter @contentful/optimization-js-bridge build
# Then start the mock server and leave it running:
pnpm --dir lib/mocks serve
The E2E suite is Maestro, run from the command line rather than an IDE run
configuration — pnpm test:e2e (both apps) or see maestro/README.md.
Use this app when you need a debuggable native Android surface for changes in
packages/android/ContentfulOptimization or the shared JS bridge. The Gradle project includes the
SDK module from the workspace through a composite build, so app builds compile the Kotlin source and
package the local bridge asset rather than a published AAR.
The normal loop is:
Edit Kotlin in packages/android/ContentfulOptimization/src/main/kotlin/... or bridge TypeScript
in packages/universal/optimization-js-bridge/src/....
Build the changed app or both app shells from implementations/android-sdk/:
./gradlew :compose:assembleDebug :views:assembleDebug
Run the Compose or Views app locally, then validate with the matching Maestro flow.
If bridge source changed, rebuild the bridge before treating app results as meaningful:
pnpm --filter @contentful/optimization-js-bridge build
Run the smallest check that covers the changed surface:
| Change area | Suggested validation |
|---|---|
| Bridge TypeScript only | pnpm --filter @contentful/optimization-js-bridge typecheck and pnpm --filter @contentful/optimization-js-bridge build |
| Kotlin SDK or UI adapter behavior | ./gradlew :compose:assembleDebug :views:assembleDebug |
| Compose or Views user flow | pnpm test:e2e:compose -- --flow <suite> or pnpm test:e2e:views -- --flow <suite> |
| Shared preview-panel behavior | Run the affected Maestro suite against both apps |
| Documentation-only README changes | Prettier on touched Markdown and git diff --check |
Common local pitfalls:
http://10.0.2.2:8000; no manual adb reverse setup is
required for normal local runs.