Beta testing a React Native or Flutter app: platform bugs you only find on a device

Beta testing a React Native or Flutter app: platform bugs you only find on a device, from keyboards and safe areas to back gestures and native modules. By betatest.ing team · October 19, 2026 · 8 min read.

Key takeaways

  • Keyboards, safe areas and font scaling are the top three cross-platform beta bugs, and all three are hidden by default simulator and emulator settings.
  • Test the Android back gesture with predictive back enabled and the iOS edge swipe from every screen, including modals and WebViews.
  • Read the merged manifest and Info.plist of the release build: plugins add permissions and need purpose strings you did not write.
  • Every native module is a platform-specific feature: test each on real hardware on both platforms, including devices without Google Play services or Face ID.
  • Run beta rounds on release builds from TestFlight and Play tracks, on a device matrix that includes a small iPhone and an older budget Android.

In this article

  1. Keyboard handling
  2. Safe areas, notches and gesture bars
  3. Font scaling and Dynamic Type
  4. The back gesture
  5. Permissions and purpose strings
  6. Native modules and plugins
  7. Rendering and performance differences
  8. Deep links, universal links and app links
  9. Localization and right-to-left
  10. Build and store differences
  11. A device matrix for a cross-platform beta
  12. Related guides
  13. Doing this on every build

React Native and Flutter let one team ship to both stores from one codebase, and the shared code really is shared: business logic, state, networking and most of the UI behave the same everywhere. What is not shared is the platform underneath. The keyboard, the safe area, the back gesture, the font scaling setting, the permission dialogs and every native module are different on each OS and sometimes on each device. Those differences are where cross-platform apps collect their beta bugs, and most of them are invisible on the simulator or emulator the developer uses all day.

This post is a field guide to those bugs: what they look like, why the framework does not save you, and how to test for each on a device.

Keyboard handling

The single most common cross-platform beta bug is a text field hidden behind the keyboard, or a submit button that moves out of reach when the keyboard opens. Both frameworks give you tools, KeyboardAvoidingView in React Native and the resizeToAvoidBottomInset and viewInsets behavior in Flutter, but both depend on correct configuration per screen and both behave differently on iOS and Android.

Why it slips through: simulators often run with the hardware keyboard enabled, so the on-screen keyboard never appears. Emulators show the keyboard but with a generic height.

Test on a device: turn off hardware keyboard in the simulator settings, then test on a real phone with a third-party keyboard such as Gboard or SwiftKey, which are taller than stock. Open every form, tap the last field, and check that the field and the submit button are visible. Test with the emoji keyboard open and with predictive text enabled.

Safe areas, notches and gesture bars

Modern phones have a status bar cutout at the top and a home indicator or gesture bar at the bottom. Content behind either is unreadable or untappable. React Native's SafeAreaView and the community safe-area-context library, and Flutter's SafeArea widget, handle this when used, but a single screen that forgets it looks broken, and modals and bottom sheets are easy to miss.

Why it slips through: the developer's device has one shape. iPhone SE testers have no notch; Pixel testers have a different inset; Android with three-button navigation has a different bottom inset again.

Test on a device: a notched iPhone, a non-notched iPhone, and an Android with gesture navigation and with three-button navigation. Open every bottom sheet and full-screen modal. Rotate to landscape, where the cutout moves to the side.

Font scaling and Dynamic Type

Users set larger text on both platforms, and both frameworks scale text by default. Layouts built with fixed heights then truncate or overlap. On iOS the setting is Dynamic Type, with accessibility sizes that go far beyond the regular slider. On Android it is Font size and Display size in Settings, and Android 14 added non-linear scaling that affects large text less than small text.

Why it slips through: nobody develops with text at 200 percent.

Test on a device: set text to the largest accessibility size on iOS and the largest font size plus the largest display size on Android. Walk every screen. Pricing, buttons with two words, tab bar labels and table cells are the usual casualties. This is also an accessibility requirement; WCAG 2.2 success criterion 1.4.4 expects content to survive 200 percent text size, and both app stores point to accessibility in their review material.

The back gesture

On Android, back is a system gesture or button that your app must respond to correctly on every screen: close a modal, pop a route, or exit the app from the root. Android 13 introduced predictive back, which previews the destination during the gesture and requires apps to opt in and handle it. React Navigation and Flutter's Navigator both support this but need the right configuration, and custom modals frequently break it. On iOS, the equivalent is the edge swipe, which custom headers and horizontal carousels often intercept.

Why it slips through: developers press the back button in the emulator, which does not exercise predictive back animations, and iOS has no back button at all.

Test on a device: on Android 14 or 15 with predictive back enabled in Developer options, swipe back from every screen, inside dialogs, bottom sheets and WebViews. On iOS, edge-swipe from every screen, including ones with horizontal scrolling at the left edge.

Permissions and purpose strings

Both frameworks wrap permission requests in libraries, but the native requirements remain: iOS needs a purpose string in Info.plist for each resource, Android needs the permission in the manifest and, for restricted permissions, a Play Console declaration. The failure mode on iOS is a crash on request when the plist key is missing. On Android it is a silent denial or a library-added permission you did not know about.

Test on a device: trigger every permission the app can ask for. Deny each, then grant from Settings while the app is backgrounded, then revoke while it is foregrounded. Read the merged Android manifest and the Info.plist of the release build, not the source files, because plugins add entries. Our mobile app beta testing guide has the full permission test matrix.

Native modules and plugins

Every camera, map, payment, biometric and analytics feature in a cross-platform app is a native module or plugin with its own platform code, versioning and setup steps. The three bugs that recur:

  1. Version drift: the plugin's iOS side was updated and the Android side was not, or a React Native upgrade changed the native build settings and a module stopped linking.
  2. Missing configuration: a maps key only set for one platform, a URL scheme registered on iOS but not an intent filter on Android, a Firebase config file in the wrong target.
  3. Platform-only behavior: a plugin that works on Android emulators but needs Google Play services, so it fails on devices without them; or a biometric plugin that handles Face ID but not Android's class 2 biometric fallbacks.

Test on a device: list every plugin, write down the user-facing feature it supports, and test that feature on both platforms on real hardware. Emulators without Google Play services and an iPhone without Face ID enrolled are useful edge cases.

Rendering and performance differences

Flutter draws everything itself, so visual consistency is high, but older or low-end Android devices can show jank on first frames, shader compilation stalls and problems with platform views such as embedded maps and WebViews. React Native uses native views, so platform differences in text rendering, shadows and list performance are the norm, and the New Architecture changes some behavior again.

Test on a device: a budget Android phone from a few years ago. Scroll long lists, open screens with maps or video, and watch for dropped frames and blank frames. Measure cold start.

Deep links, universal links and app links

Both frameworks route deep links through their navigation libraries, but the OS-level setup is native: an Apple App Site Association file for universal links and a Digital Asset Links file for Android App Links, each hosted on your domain and each failing silently when wrong.

Test on a device: tap a link from a messaging app, from an email and from the browser, with the app installed and not installed, on both platforms. Check that the right screen opens, with the right parameters, from a cold start and from the background.

Localization and right-to-left

If you ship more than one language, test on a device with the OS set to each language and to an RTL language such as Arabic. Date formats, pluralization, truncation and mirrored layouts behave differently per platform even with shared strings.

Build and store differences

Release builds behave differently from debug builds: Hermes bytecode and minification on React Native, tree shaking and obfuscation on Flutter, ProGuard or R8 rules on Android. A plugin that depends on reflection can work in debug and crash in release.

Test on a device: always run your beta rounds on a release build installed from TestFlight or a Play testing track, never from a development server. Then run the platform-specific store checklists in our iOS and Android guides, because the store requirements, from account deletion to Play Billing, apply regardless of framework.

A device matrix for a cross-platform beta

DeviceWhy
Small iPhone without a notchKeyboard, truncation, no safe area
Current iPhoneSafe area, Face ID, latest iOS
Recent Pixel with gesture navigationPredictive back, stock Android
Older Samsung or XiaomiOEM keyboard, battery optimizer, performance
Android emulator at minimum API levelOldest supported behavior
Tablet or foldable if supportedLayout at large sizes

Related guides

Doing this on every build

The list above is long, and it has to be repeated when a plugin is updated or a screen is redesigned. That makes it a good candidate for automation. betatest.ing's AI beta tester installs your release build on iOS simulators, Android emulators and real phones, and works through goals such as "complete sign-up with large text enabled, deny then grant notifications, open the app from a shared link". It files each problem with steps, severity, annotated screenshots and a recording, so a keyboard covering a button is a picture rather than a sentence. Use it for the device matrix on every build, and ask your human testers to spend their time on the things that need a real life: their own keyboard, their own notifications, their own commute.

The test case generator can turn the headings in this post into a test case list for your team.

Start for $1 and run your React Native or Flutter build on real devices today.

Related guides

Each ends with a test task you can send to your AI beta tester.

All beta testing guides

Keep reading

All articles

Sources