Rohan Yeole - Homepage Rohan Yeole

How to Hire an Android Developer: Native vs Cross-Platform Decision First

May 27, 20261 min read

Before posting an Android developer job listing, decide whether you need a native Android developer or a cross-platform developer. A native Android developer (Kotlin, Jetpack Compose, Android SDK) is the right hire when your app requires deep Android platform integration — custom camera processing, Bluetooth/NFC hardware access, background services with specific wake-lock requirements, or UI complexity that benefits from Compose's full native rendering. For most standard apps targeting both iOS and Android, Flutter or React Native delivers equivalent output at lower total cost than hiring two native developers. Make this decision first.

Native Android vs Cross-Platform: The Decision

Choose native Android development when:

  • The app's core feature is a hardware API. Bluetooth GATT protocol operations (custom BLE device communication), USB OTG, advanced camera APIs (Camera2 or CameraX for RAW capture, custom ISP processing) require native Android code. Cross-platform frameworks expose wrappers around a subset of these APIs; anything outside the wrapper requires a native module anyway.
  • Background processing is complex. Android's battery optimisation (Doze mode, App Standby Buckets, WorkManager constraints) is platform-specific. An app that needs to reliably process data in the background — health monitoring, file sync, real-time audio — requires Android-specific background task management that a native Android developer handles without workarounds.
  • The UI is the core product. Jetpack Compose gives Android developers access to the complete Material Design 3 system, custom drawing with Canvas, and GPU-accelerated animations via RenderEffect. A native developer building with Compose on Android gets more of the platform's rendering capabilities than a cross-platform developer working within a framework's abstraction layer.

Choose cross-platform (Flutter or React Native) when:

  • The app needs both iOS and Android and neither requires deep platform-specific features.
  • The team is small — one developer managing both platforms through a shared codebase is operationally simpler.
  • Budget constrains you to one developer rather than two specialists.

What Makes a Strong Android Developer

Kotlin fluency beyond syntax

Kotlin is the modern Android language, but Kotlin fluency means more than syntax familiarity. A strong Android developer understands Kotlin's coroutine model: how suspend functions integrate with the Android lifecycle (viewModelScope, lifecycleScope), how coroutines differ from threads (coroutines are suspended and resumed, not blocked — the underlying thread is released during suspension), and when Flow (cold, produces values on collection) is appropriate versus StateFlow (hot, always has a current value, shared across collectors).

The coroutine vs thread distinction matters for performance: 100,000 coroutines on a single thread is achievable; 100,000 threads is not (OS context switch overhead, stack memory). Android apps that use Thread() or AsyncTask (deprecated) instead of coroutines are using patterns that predate Kotlin's coroutine system and have higher overhead.

Jetpack Compose recomposition

Compose builds the UI through composable functions — functions annotated with @Composable that emit UI nodes. When state changes, Compose reruns the affected composable functions to recalculate the UI. This process is called recomposition.

The key invariant: Compose tracks which composables read which state variables. When a state variable changes, only the composables that read it are recomposed — not the entire tree. A developer who understands this writes composables that read the minimum state necessary, which limits recomposition scope. A developer who doesn't creates composables that read parent-level state unnecessarily, triggering recompositions that reach too many nodes in the tree.

The practical test: "What happens when a composable reads from a mutableStateOf variable and that variable changes?" Expected answer: the composable is scheduled for recomposition by the Compose runtime; other composables that did not read the variable are not affected.

Android lifecycle awareness

Android's activity and fragment lifecycle (created → started → resumed → paused → stopped → destroyed, plus configuration change destruction/recreation on rotation) is a source of memory leaks and stale data if not handled correctly. A developer who stores a reference to an Activity from a ViewModel (which survives configuration changes) creates a memory leak — the old Activity cannot be garbage collected even after the user rotated the screen.

Modern Android uses ViewModel + LiveData/StateFlow to separate state from the UI lifecycle. A developer who cannot explain why ViewModel survives rotation (it is scoped to the ViewModelStoreOwner, which is the back stack entry, not the Activity) has not worked with the Jetpack architecture components in depth.

Five Interview Questions That Filter Effectively

"Explain the difference between suspend functions and threads in Kotlin."

Expected: suspend functions can be suspended without blocking the underlying thread — when a suspend function calls another suspend function that needs to wait (for a network response, a disk read), it yields the thread back to the coroutine dispatcher. A new coroutine can then run on that thread. Threads block the OS thread when waiting. Result: thousands of concurrent coroutines on a small thread pool, vs thousands of threads which exhaust memory and OS scheduler capacity.

"What is recomposition in Jetpack Compose and how do you minimise it?"

Expected: state change triggers recomposition of composables that read the changed state; minimise by reading state in the lowest composable possible, by using remember to cache expensive calculations, and by hoisting state to the correct level so unrelated composables don't read state they don't need.

"How would you implement a reliable periodic background sync that works under Doze mode?"

Expected: use WorkManager with a PeriodicWorkRequest — WorkManager handles Doze mode by batching work into maintenance windows, persists the request across reboots, and retries on failure. AlarmManager with exact alarms requires the SCHEDULE_EXACT_ALARM permission and is battery-intensive. Service running continuously is killed by the OS under low memory and battery optimisation.

"Walk me through how you'd implement in-app purchases on Android."

Expected: Google Play Billing Library, BillingClient, product types (one-time purchases vs subscriptions), queryProductDetailsAsync to get current price/metadata, launchBillingFlow to show the purchase UI, purchasesUpdatedListener to receive the result, and server-side purchase token verification (critical: verify with Google Play Developer API on your backend before granting entitlement — client-side verification is bypassable).

"You have a memory leak. What's your process for finding it?"

Expected: reproduce the leak (rotate screen multiple times to trigger configuration change leaks, navigate to/from a screen to trigger fragment leaks), capture a heap dump in Android Studio Profiler, use the Memory Profiler to identify retained objects and their reference chain to GC roots. LeakCanary automates this in development — it detects retained Activity/Fragment/ViewModel/View objects and shows the reference chain.

Red Flags in Android Portfolios

Only AsyncTask or Thread() usage.AsyncTask was deprecated in API level 30 (Android 11). Production code using it in 2026 is a developer who has not updated their Android knowledge since 2020.

UI logic in Activity/Fragment. Business logic in the Activity class means it is destroyed on rotation, which resets state. This pattern was standard before MVVM became the recommended architecture. A portfolio where every screen has its logic in the Activity file indicates a developer who has not adopted the architectural recommendations from Jetpack.

No release APK/AAB in the portfolio. If the developer cannot point to an app in the Play Store, they may not have dealt with release signing, Proguard configuration, or the Play Store review process. Ask: "Have you dealt with Proguard stripping native module references?"

Rates for Android Developers in 2026

RegionMid (3–5 yrs)Senior (6+ yrs)
India$22–38/hr$35–55/hr
Eastern Europe$42–68/hr$62–90/hr
Latin America$28–48/hr$42–68/hr
UK / Western Europe$65–105/hr$88–135/hr
USA / Canada$90–130/hr$110–160/hr

Native Android developers command roughly the same rates as React Native developers at equivalent experience levels. The supply is comparable. See Android vs React Native vs Flutter for the hiring implications of each platform choice.

Frequently Asked Questions

Should I hire a native Android developer or a cross-platform developer? Cross-platform (Flutter or React Native) for most new consumer apps targeting both platforms. Native Android when you need deep hardware integration, background processing with specific platform constraints, or a UI that uses the full Compose rendering capability. See Android vs React Native vs Flutter for a full decision framework.

Can a React Native developer learn native Android? Kotlin syntax is not difficult for a JavaScript developer. The challenge is Android's lifecycle model, background processing constraints, and the Compose rendering mental model — these take 6–12 months of production Android work to internalise. A React Native developer can handle simple Android native modules relatively quickly; they cannot handle complex background processing or advanced camera APIs without significant ramp time.

What's the difference between Kotlin and Java for Android? Kotlin is the recommended language for new Android development since 2019. It has null safety (variables cannot hold null unless explicitly declared nullable), coroutines for async operations, and cleaner syntax than Java. New Android projects should use Kotlin. Existing Java codebases are commonly mixed-language; Kotlin and Java interoperate within the same project.

Chat with me on WhatsApp