mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
fix(android): recover from WebView init crash via WebViewBlockActivity
Observed on Play Console: AndroidRuntimeException thrown from WebViewFactory.getProvider during FullscreenActivity.initWebView on devices where the system WebView package itself is broken (seen with a WebView Beta build throwing "Already registered a list of actions in this process" from WebViewChromiumFactoryProvider.<init>). The activity had no recovery - the constructor threw and the app died at launch. Mirror the existing CapacitorMainActivity pattern: catch around the WebHelper().instanceView(this) call, and on failure present the existing WebViewBlockActivity using compatibility.copy(status = BLOCK) so the block screen keeps the detected provider/version, then finish(). Also harden lifecycle callbacks that dereference the lateinit webView / javaScriptInterface fields so the new failure path can't trigger an UninitializedPropertyAccessException via OEM-specific lifecycle quirks: ::isInitialized guards in onSaveInstanceState, onRestoreInstanceState, onBackPressed, and callJSInterfaceFunctionIfExists (the last matching the existing guard in CapacitorMainActivity).
This commit is contained in:
parent
b9f91a5327
commit
5a5c3bca89
1 changed files with 34 additions and 7 deletions
|
|
@ -72,7 +72,17 @@ class FullscreenActivity : AppCompatActivity() {
|
|||
return
|
||||
}
|
||||
|
||||
initWebView()
|
||||
if (!initWebView()) {
|
||||
// Reuse the already-computed compatibility info so the block screen
|
||||
// keeps the detected WebView provider/version (useful when a user
|
||||
// on a buggy beta channel needs to identify which package to swap).
|
||||
WebViewBlockActivity.present(
|
||||
this,
|
||||
compatibility.copy(status = WebViewCompatibilityChecker.Status.BLOCK),
|
||||
)
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
// FOR TESTING HTML INPUTS QUICKLY
|
||||
//// webView = (application as App).wv
|
||||
|
|
@ -118,14 +128,18 @@ class FullscreenActivity : AppCompatActivity() {
|
|||
super.onSaveInstanceState(outState)
|
||||
// Save scoped storage permission on Android 10+
|
||||
storageHelper.onSaveInstanceState(outState)
|
||||
webView.saveState(outState)
|
||||
if (::webView.isInitialized) {
|
||||
webView.saveState(outState)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
// Restore scoped storage permission on Android 10+
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
storageHelper.onRestoreInstanceState(savedInstanceState)
|
||||
webView.restoreState(savedInstanceState);
|
||||
if (::webView.isInitialized) {
|
||||
webView.restoreState(savedInstanceState)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
|
@ -151,8 +165,16 @@ class FullscreenActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
private fun initWebView() {
|
||||
webView = WebHelper().instanceView(this)
|
||||
private fun initWebView(): Boolean {
|
||||
try {
|
||||
webView = WebHelper().instanceView(this)
|
||||
} catch (e: Exception) {
|
||||
// WebView construction can fail on devices with a broken, missing,
|
||||
// or misbehaving Android System WebView package (e.g. a buggy beta
|
||||
// channel throwing IllegalStateException during factory init).
|
||||
Log.e("SP-WebView", "Failed to instantiate WebView", e)
|
||||
return false
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Toast.makeText(this, "DEBUG: $appUrl", Toast.LENGTH_SHORT).show()
|
||||
// webView.clearCache(true)
|
||||
|
|
@ -255,10 +277,15 @@ class FullscreenActivity : AppCompatActivity() {
|
|||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
private fun callJSInterfaceFunctionIfExists(fnName: String, objectPath: String, fnParam: String = "") {
|
||||
if (!::javaScriptInterface.isInitialized) {
|
||||
Log.w("TW", "javaScriptInterface not initialized yet. Skipping JS call.")
|
||||
return
|
||||
}
|
||||
val fnFullName = "window.$WINDOW_INTERFACE_PROPERTY.$objectPath.$fnName"
|
||||
val fullObjectPath = "window.$WINDOW_INTERFACE_PROPERTY.$objectPath"
|
||||
javaScriptInterface.callJavaScriptFunction("if($fullObjectPath && $fnFullName)$fnFullName($fnParam)")
|
||||
|
|
@ -266,8 +293,8 @@ class FullscreenActivity : AppCompatActivity() {
|
|||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onBackPressed() {
|
||||
Log.v("TW", "onBackPressed ${webView.canGoBack().toString()}")
|
||||
if (webView.canGoBack()) {
|
||||
if (::webView.isInitialized && webView.canGoBack()) {
|
||||
Log.v("TW", "onBackPressed canGoBack=true")
|
||||
webView.goBack()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue