Gabe Giro

Android Parity / Cross-Platform Port

Port your app to Android without forking the source of truth.

Rust core, iOS app, or web codebase: I bring it to native Android parity, then keep both sides aligned. Wire-contract bridges, Kotlin Multiplatform, or native rewrites — pick the shape that fits.

What you get

One source of truth where it counts

Domain logic in Rust through JNI, in a Kotlin Multiplatform shared module, or behind a thin contract. The Android side extends the source, never forks it.

Native Android UX

Jetpack Compose, Material 3, platform conventions. Users get an Android app, not a transplant. No hidden WebView, no second-class affordances.

Parity that holds after I leave

Wire-format contracts, unit tests on the bridge, CI on every PR to both repos. The port stays aligned as the source evolves, instead of drifting into a fork.

Three port shapes

Every port collapses into one of these once you look at where the source of truth lives. The shape determines the bridge, the test seam, and the ongoing-drift story.

Rust core to Android

Your domain logic stays in Rust; a JNI workspace wraps it for the JVM. Kotlin shims (MemoryBridge, BridgeRepository) live alongside Compose UI. Real-world reference: a 10-shim CRUD bridge with serial-mutex contention guarantees, materialized DTOs, and full-state-rebuild sync.

iOS app to Android

Two paths. Kotlin Multiplatform (commonMain owns domain, expect/actual at the platform seam) when the iOS side is willing to migrate too. Or a clean Android rewrite against a shared wire contract when iOS stays Swift-native. Pick based on team appetite, not ideology.

Web codebase to native Android

Lift the API contract, not the React tree. Compose UI, native navigation, platform-correct lifecycle. Reusable: schema validators, business rules expressed as pure functions, server-driven feature flags. Discarded: anything that assumes a DOM.

How a port engagement runs

Vertical slices, not horizontal layers. Each slice is independently mergeable so the Android side stays deployable from week 2 onward, and you can pause the engagement at any slice boundary without leaving half-shipped state.

  1. 1

    Week 1

    Source-of-truth audit

    I read your existing codebase end-to-end before proposing anything. Identify what is domain, what is platform glue, what is presentation. The audit output is a concrete recommendation on the boundary: what stays shared, what gets ported, what gets rewritten.

  2. 2

    Weeks 2-3

    Bridge + scaffolding

    JNI workspace, KMM module, or wire contract, whichever the audit picked. Plus the Android-side scaffolding: Compose theme, navigation skeleton, DI graph, CI workflow with the build matrix the bridge needs (cargo-ndk, common-main publication, codegen).

  3. 3

    Weeks 4+

    Feature parity in slices

    One vertical slice at a time: a single user-visible feature, port the domain access, ship the Compose UI, write the integration test on the bridge. Each slice is independently mergeable. No big-bang flag-flip at the end.

  4. 4

    Final week

    Hand-off + drift guards

    Documentation in the repo, not in a PDF. CI checks that catch wire-format drift before it ships. A runbook for the next engineer covering the bridge build, the test seams, and the conventions that keep parity from rotting.

What stays shared, what goes native

The single biggest port decision is where the shared / native boundary sits. The default I propose, unless your audit surfaces a reason to deviate:

Layer Default posture Why
Domain logic / business rules Share (Rust or KMM commonMain) Don't port; the source is the source
Data persistence schema Share the schema; platform-native ORM Port the migration tooling, not the runtime
Network contracts (REST/gRPC/wire) Share (codegen from a single IDL) Don't port; generate
Navigation / app structure Don't share Port: Android has its own conventions
UI components Don't share Native Compose, no cross-platform UI layer
Platform integrations (push, biometrics, share sheets) Don't share Native, per-platform

The audit in week 1 confirms or revises this posture per layer for your specific stack. Rule of thumb: share what costs you correctness when it drifts (domain, schemas, contracts), keep native what costs you UX when it doesn\'t (navigation, components, platform glue).

Already on Android?

Need senior ownership on an existing Android product?

Rebuilds, replatforms off fragile code, and sole-senior ownership engagements live on the Android Lead Engineering page. Not a port from another platform; you are already on Android.

See Android Lead Engineering

Broader Android Dev

Looking for Kotlin migration, architecture, or performance tuning?

Modernization work that embeds with your existing Android team — Java to Kotlin, MVC to MVVM, RecyclerView to Compose, build pipeline, performance — lives on the Android Development page.

See Android Development

Questions about the port

How is this different from your /services/android page?

/services/android is the broader Android Development surface: Kotlin migration, architecture work, performance, embedding with an existing Android team. This page is the narrower "I already have a working app on another platform and I want Android" engagement. If you are already on Android and want to modernise, start there.

Do you do React Native or Flutter ports?

No. The premise here is native Android: Compose, Material 3, Kotlin. If you want a cross-platform UI framework, that is a different engagement and not what I recommend for an app where the Android experience matters.

What if my source isn't Rust, iOS, or web?

Most ports collapse into one of those three shapes once you look at the source-of-truth question. If yours genuinely doesn't (e.g. a Java desktop app, an Electron-only stack, a custom DSL), book the discovery call and we will scope it from first principles.

Does the source app keep evolving while you port?

Yes, that is the normal case. The bridge contract is what protects you. When the source ships a change, the CI on the Android side fails loudly if the contract drifted; you fix it once in the bridge, not in every screen. Recall ships Rust changes weekly while the Android port is in flight; the JNI workspace is the seam that absorbs it.

Can I keep my existing Android team and have you lead the port?

Yes, and that is often the best shape. I bring the port architecture and the bridge work; your team owns the Compose UI and the long-term ownership.

What does an engagement cost?

Scoped per port. A small Rust-to-Android JNI bridge with a single feature might be a 4-week fixed-scope sprint (see /services/scalable-mvp). A multi-month iOS-to-Android parity program runs on a Builder retainer (see /services/fractional-cto for the tier shape). The audit step is always paid + fixed-scope so you have a real recommendation before committing.

Ready to talk?

Start with a free 15-minute discovery call. No commitment, no pitch deck, just an honest conversation about your problem and how I can help.