Android-Specific React Native Problems That Never Show Up on iOS
TIL that a React Native feature working perfectly in the iOS simulator is not evidence it'll work on Android — cleartext traffic, back-button handling, and permission dialogs all diverge silently.
The Problem #
Features that worked cleanly in the iOS simulator kept surfacing new failures once tested on an Android device: a network request that silently failed, a hardware back-button press that closed the app instead of navigating back, a permission dialog that never appeared at all.
Context #
I was developing primarily on iOS (faster simulator iteration) and treating Android testing as a final check before release rather than something to do continuously — which meant a backlog of Android-only bugs surfaced all at once, late.
What I Tried #
Fixing each Android bug as a one-off patch when QA or a store review flagged it.
What Went Wrong #
The bugs kept coming from the same handful of root causes — Android's stricter cleartext HTTP policy, its hardware back button having no iOS equivalent, its runtime permission model differing from iOS's — but I was treating each symptom individually instead of recognizing the pattern.
The Solution #
Built an explicit Android-testing pass into every feature, not just before release, and fixed the root causes directly: usesCleartextTraffic configured explicitly rather than relying on defaults, a shared BackHandler listener for navigation instead of assuming default OS behavior, and permission requests checked against Android's runtime model specifically.
import { BackHandler } from "react-native";
useEffect(() => {
const sub = BackHandler.addEventListener("hardwareBackPress", () => {
if (canGoBack) { goBack(); return true; }
return false; // let the OS handle it (e.g. exit app)
});
return () => sub.remove();
}, [canGoBack]);Why It Works #
Android and iOS aren't two skins on the same platform — they have genuinely different networking security defaults, navigation models, and permission systems. Testing only on iOS doesn't test "the app," it tests one of two platforms with materially different failure modes.
Lessons Learned #
"It works in the simulator" needs a platform qualifier. A feature that's fine on iOS can be silently broken on Android for reasons that have nothing to do with the feature's logic and everything to do with platform defaults.
What I Would Do Differently #
I'd test on a real Android device from the first feature, not the last week before submission, so these root causes surface (and get fixed structurally) early instead of as a late pile of one-off patches.
Related Concepts #
Android cleartext traffic policy, hardware back-button handling, Android runtime permissions.
Related content
Designing a Delivery App for Unreliable Networks, Not Just Offline
TIL that 'handle offline' undersold the actual problem — the failure mode that hurt drivers most was a flaky, half-connected state, not a clean offline/online boundary.
Understanding UnknownHostException in Android (and Why the API 'Worked Locally')
TIL that an Android UnknownHostException on a hostname that resolved fine everywhere else usually isn't a DNS problem at all — it's the app pointed at a hostname that only ever existed on my dev machine.
Debugging an Android-Only FormData Upload Failure
TIL an upload that worked reliably on iOS and failed intermittently on Android came down to a missing file extension on the filename I was generating — Android's multipart parsing cared, iOS's didn't.