ReviewOS

craft-native/craft

fix(android): any failed main-frame load switches to the bundled copy for the rest of the session

#254
Closed glennmichael123 opened this 9 days ago ·
9 days ago

The Android half of #252, which is iOS-only and fixed in #253.

MainActivity.kt.template, onReceivedError:

if (request?.isForMainFrame == true && hasBundledFallback && !loadedBundledFallback) {
    loadedBundledFallback = true
    webView.loadUrl(BUNDLED_APP_URL)
}

Same shape as the iOS bug, and both halves of it:

  • It does not look at the error. Any main-frame error falls back, whatever the cause.
  • It is one-way. loadedBundledFallback is set and never cleared, so after one failure the app is on the bundled copy until the process dies. The bundle cannot reach a frontend's API by relative path, so the app loses its API for the rest of the session.

What #253 did on iOS, for reference

  • Fall back only on connectivity errors: not connected, cannot find or connect to the host, timed out, connection lost, DNS. TLS and bad-response errors stay on the remote, since the server was reached and the bundle would hide the fault.
  • Come back when connectivity returns and when the app returns to the foreground.
  • The network trigger fires on a false → true transition only. Retrying whenever the network is merely up loops against a server that is down on a network that is up.

What is different on Android

  • The error codes. WebResourceError.getErrorCode() uses WebViewClient.ERROR_*. The connectivity ones are roughly ERROR_HOST_LOOKUP, ERROR_CONNECT, ERROR_TIMEOUT and ERROR_IO. ERROR_FAILED_SSL_HANDSHAKE and the auth errors should stay on the remote. Worth checking whether Android reports a cancelled navigation through onReceivedError at all, since that was the main trigger on iOS. It may not, and the latch would then matter mostly for real failures.
  • The recovery hooks. ConnectivityManager.NetworkCallback.onAvailable for the network, and onResume for the foreground. The same transition-only rule applies to the network callback.
  • Testing. index.test.ts can pin the wiring. The classifier can be a pure function over the error code and tested directly in the Kotlin compile that android-builder already runs, or its decision table checked from TypeScript.

Sign in to comment on this issue.