POROROCA OTA
Over-the-air updates for native Jetpack Compose apps
The problem, same as iOS: waiting on a release for a screen fix
Jetpack Compose teams face the same release-cycle friction as SwiftUI teams: a screen needs a fix or a variant, and shipping it means a new build and a store rollout. Pororoca applies the same signed, data-only update model to native Android.
A verified, data-only update on Android
The Android runtime targets API 26+ and verifies a document's Ed25519 signature and content hashes before using it, using the same signed manifest model as iOS. The host app retains the last accepted document for offline use today, so a device that can't reach the network still has something to render.
The workflow in four steps
1. Validate the documents against the Android platform schema (Android needs its own bundle, built with --platform android). Validation fails loudly on a field or node type the Android runtime doesn't recognize, so a clean pass here is what should gate signing, not a manual review.
swift run pororoca validate .pororoca/documents --platform android2. Export a signed, immutable update bundle for Android, with its own update ID separate from any iOS bundle for the same screen — IDs are immutable once exported, so pick one you can trace back to this change later.
swift run pororoca export .pororoca/documents \
--output .pororoca/update --update-id paywall-android-1 \
--private-key .pororoca/keys/private.key3. Publish at a conservative rollout percentage to the Android channel, starting at 10% so only a small, deterministic slice of installs by install ID sees the change while you watch how it behaves.
POROROCA_API_TOKEN=pororoca_live_... swift run pororoca publish .pororoca/update \
--server https://pororoca-ota.fly.dev --app your-app-slug \
--channel production --rollout 10 \
--public-key .pororoca/keys/public.key4. Confirm resolution against the same channel before widening the cohort. A 200 means the install is eligible and receives the signed update, a 204 means it's outside the current cohort, and a 404 means the app slug or channel name doesn't match what you published to.
curl -i \
-H "Authorization: Bearer $POROROCA_RUNTIME_TOKEN" \
"https://pororoca-ota.fly.dev/api/v1/apps/your-app-slug/channels/production/resolve?install_id=docs-smoke-0001"As on iOS, rollout is deterministic by install ID, `applied` telemetry appears in the dashboard once a device renders the update, and one command restores the previous known-good update if you need to back out, taking effect the next time an affected device checks in.
Android early-access limits, stated honestly
Storage of the update on Android is host-managed today: the host retains the last accepted document for offline use, but the managed previous-update crash recovery that exists on iOS is not yet in the Android SDK. The Android renderer surface is smaller than SwiftUI's, and full modifier parity between the two platforms isn't there yet.
Also not yet available on either platform: team members and RBAC, usage-based limits, automated alerts, cross-platform expression parity, and a hosted MCP transport. There's one Pro plan, card-required 21-day trial, billed in BRL or USD.