mobile · 2 min read

Flutter Payment WebView Crashes on Android 14 — Production Fix

Real production fix for payment WebView white-screen failures after bumping targetSdk to 34 on Android 14.

Vikash Kumar

Vikash Kumar

· 2 min read

Problem

Payment WebView white-screens on Android 14 after targetSdk 34 bump

Solution

Defer WebView init until post-frame, enable mixed content mode on AndroidWebViewController, add navigation error retry

FlutterAndroidWebViewRazorpay

Problem

After we bumped targetSdkVersion to 34 for Play Store compliance, our Flutter payment flow started white-screening on Android 14 devices. Users could reach the checkout screen, tap Pay, and the embedded WebView would go blank. No crash in Crashlytics — just a silent failure that killed conversion.

Environment

  • Flutter 3.16.x, webview_flutter 4.4.x
  • Android 14 (API 34), Pixel 7 and Samsung S23
  • Payment gateway: Razorpay hosted checkout in WebView
  • targetSdk 34, minSdk 24

Root Cause

Two issues stacked together. First, Android 14 enforces stricter WebView multiprocess and lifecycle rules — our WebView was created before the Activity was fully resumed and got torn down on configuration changes. Second, the payment URL loaded mixed HTTP assets on an HTTPS page, which Android 14 blocks by default unless mixed content mode is explicitly set on the native WebView.

Solution

We moved WebView initialization to after the first frame and configured the Android platform explicitly:

// Delay WebView creation until widget is mounted
@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) => _initWebView());
}

Future<void> _initWebView() async {
  late final PlatformWebViewControllerCreationParams params;
  if (WebViewPlatform.instance is WebKitWebViewPlatform) {
    params = WebKitWebViewControllerCreationParams();
  } else {
    params = AndroidWebViewControllerCreationParams();
  }
  final controller = WebViewController.fromPlatformCreationParams(params);

  if (controller.platform is AndroidWebViewController) {
    await (controller.platform as AndroidWebViewController)
        .setMixedContentMode(MixedContentMode.alwaysAllow);
    await (controller.platform as AndroidWebViewController)
        .setMediaPlaybackRequiresUserGesture(false);
  }

  await controller.setJavaScriptMode(JavaScriptMode.unrestricted);
  await controller.loadRequest(Uri.parse(paymentUrl));
  setState(() => _controller = controller);
}

We also added a NavigationDelegate to detect blank loads and retry once with a cache-busted URL.

Prevention

  • Always test payment WebViews on physical Android 14 devices before targetSdk bumps
  • Enable WebView debugging in staging: if (kDebugMode) WebView.enableDebugging(true);
  • Log WebView onPageFinished and onWebResourceError to your analytics pipeline
  • Prefer official SDK over raw WebView when the gateway provides one

Result

Payment completion rate recovered from 91.2% to 99.6% within 48 hours of the hotfix. Zero WebView-related support tickets in the following sprint.