From 2024b17be9d2efe65436b638e5f0da6a56cae008 Mon Sep 17 00:00:00 2001 From: Yu-ga <74749461+yuga-hashimoto@users.noreply.github.com> Date: Fri, 30 Oct 2026 23:56:47 +0900 Subject: [PATCH 1/2] fix(browser): explain instead of crashing when the system WebView cannot start Crashlytics (v1.2.25-v1.2.27, 2 events / 2 users) has a fatal AndroidRuntimeException caused by Resources$NotFoundException "failed to redirect ResourcesImpl" on a vivo phone (Android 16). It is thrown by WebView.setWebContentsDebuggingEnabled in GuestBrowserScreen's AndroidView factory: the first WebView call starts the system WebView provider, whose resource registration failed. The exception escaped the Compose view factory and took the whole app down. Nothing in the app can repair a provider that will not start, so creation is now guarded. viewOrNull builds the WebView (including the debugging flag and its configuration) and returns null on any Exception; the screen then shows a short explanation, translated into all eight locales, instead of the page. Only Exception is caught, so an OutOfMemoryError is not reported as a missing WebView. PlatformViewTest covers the three outcomes; it did not compile before the change. The Compose wiring and the fallback text are not unit-testable here, and the provider failure cannot be reproduced without the affected device. Co-Authored-By: Claude Sonnet 5.5 --- .../feature/browser/GuestBrowserScreen.kt | 89 +++++++++++++------ .../andcode/feature/browser/PlatformView.kt | 23 +++++ app/src/main/res/values-ar/strings.xml | 1 + app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-ja/strings.xml | 1 + app/src/main/res/values-pt-rBR/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + .../feature/browser/PlatformViewTest.kt | 36 ++++++++ 11 files changed, 127 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt create mode 100644 app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt diff --git a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt index e40c049c5..b5b7dcb74 100644 --- a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt +++ b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt @@ -1,11 +1,14 @@ package com.yugahashimoto.andcode.feature.browser import android.annotation.SuppressLint +import android.util.Log +import android.view.View import android.view.ViewGroup import android.webkit.WebChromeClient import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -20,6 +23,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -31,14 +35,18 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.yugahashimoto.andcode.BuildConfig import com.yugahashimoto.andcode.R +private const val TAG = "GuestBrowser" + /** In-app browser for pages served inside the guest runtime (e.g. http://127.0.0.1:PORT/). */ @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -51,6 +59,7 @@ fun GuestBrowserScreen( var canGoBack by remember { mutableStateOf(false) } var canGoForward by remember { mutableStateOf(false) } var webView by remember { mutableStateOf(null) } + var webViewUnavailable by remember { mutableStateOf(false) } BackHandler { val view = webView @@ -82,40 +91,62 @@ fun GuestBrowserScreen( if (progress in 1..99) { LinearProgressIndicator(progress = { progress / 100f }) } - AndroidView( - // WebView can draw its background outside its measured bounds, covering the URL - // field even while that field still accepts focus and keyboard input. - modifier = Modifier.weight(1f).clipToBounds(), - factory = { context -> - // Lets the in-guest agent drive this WebView over CDP (the devtools abstract - // socket is reachable from the guest, which shares the app's UID), so a page - // can be shown to the user and operated by human and agent at the same time. - WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG) - WebView(context).apply { - layoutParams = - ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - ) - configure( - onProgress = { progress = it }, - onNavigationStateChange = { url, back, forward -> - urlInput = url - canGoBack = back - canGoForward = forward + if (webViewUnavailable) { + WebViewUnavailableNotice(modifier = Modifier.weight(1f).fillMaxWidth()) + } else { + AndroidView( + // WebView can draw its background outside its measured bounds, covering the URL + // field even while that field still accepts focus and keyboard input. + modifier = Modifier.weight(1f).clipToBounds(), + factory = { context -> + viewOrNull( + create = { + // Lets the in-guest agent drive this WebView over CDP (the devtools abstract + // socket is reachable from the guest, which shares the app's UID), so a page + // can be shown to the user and operated by human and agent at the same time. + WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG) + WebView(context).apply { + layoutParams = + ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, + ) + configure( + onProgress = { progress = it }, + onNavigationStateChange = { url, back, forward -> + urlInput = url + canGoBack = back + canGoForward = forward + }, + ) + webView = this + if (initialUrl.isNotBlank()) { + loadUrl(normalizeUrl(initialUrl)) + } + } }, - ) - webView = this - if (initialUrl.isNotBlank()) { - loadUrl(normalizeUrl(initialUrl)) - } - } - }, - ) + onFailure = { error -> Log.w(TAG, "The system WebView could not start", error) }, + ) ?: View(context).also { webViewUnavailable = true } + }, + ) + } } } } +/** Shown instead of the page when the system WebView cannot start, which the app cannot repair. */ +@Composable +private fun WebViewUnavailableNotice(modifier: Modifier = Modifier) { + Box(modifier = modifier.padding(24.dp), contentAlignment = Alignment.Center) { + Text( + text = stringResource(R.string.guest_browser_webview_unavailable), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center, + ) + } +} + @OptIn(ExperimentalMaterial3Api::class) @Composable private fun GuestBrowserTopBar( diff --git a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt new file mode 100644 index 000000000..ba0d06085 --- /dev/null +++ b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt @@ -0,0 +1,23 @@ +package com.yugahashimoto.andcode.feature.browser + +/** + * Builds a view the platform may refuse to build, returning null instead of throwing. + * + * WebView needs the system's WebView provider, and starting it can fail on a given device: on one + * vivo phone the provider's resource registration threw `Resources.NotFoundException`, which + * surfaced as an `AndroidRuntimeException` inside the Compose view factory and took the whole app + * down. Nothing the app does can repair that, so the caller shows an explanation instead. + * + * Only [Exception] is caught: an [OutOfMemoryError] is not a missing provider, and hiding it would + * leave the screen blaming WebView for a memory problem. + */ +internal fun viewOrNull( + create: () -> T, + onFailure: (Exception) -> Unit = {}, +): T? = + try { + create() + } catch (error: Exception) { + onFailure(error) + null + } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 38689c6f0..8a05bfb86 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1219,6 +1219,7 @@ رجوع تقدم إعادة تحميل + يتعذّر تشغيل المتصفح المدمج لأن WebView لم يُحمَّل على هذا الجهاز. قد يحل تحديث Android System WebView أو إعادة تفعيله المشكلة. أدوات التطوير يتم تثبيت مكونات التشغيل الضرورية فقط افتراضيًا، ويمكنك إضافة مجموعة أدوات التطوير الكاملة. سيتم دائمًا تثبيت Linux والوكلاء المحددين وGit وأدوات الدعم التي يستخدمها AndCode. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 427d1f990..b0993ef92 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1210,6 +1210,7 @@ Atrás Avanzar Recargar + El navegador integrado no puede iniciarse porque WebView no se pudo cargar en este dispositivo. Actualizar o volver a activar Android System WebView puede solucionarlo. Herramientas de desarrollo De forma predeterminada solo se instala lo necesario para ejecutar el entorno, o puedes incluir toda la cadena de desarrollo. Linux, los agentes seleccionados, Git y las herramientas de soporte que usa AndCode. Siempre se instalan. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index cbd9bac45..790478e2a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1210,6 +1210,7 @@ Retour Avancer Recharger + Le navigateur intégré ne peut pas démarrer, car WebView n\'a pas pu se charger sur cet appareil. Mettre à jour ou réactiver Android System WebView peut résoudre le problème. Outils de développement Installe uniquement le nécessaire par défaut, ou incluez la chaîne complète d’outils. Linux, les agents sélectionnés, Git et les outils requis par AndCode. Ils sont toujours installés. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 8931d058c..9dcb160c3 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1224,6 +1224,7 @@ 戻る 進む 再読み込み + この端末の WebView を読み込めないため、内蔵ブラウザを開けません。Android System WebView を更新するか、有効にし直すと解決する場合があります。 開発ツール 既定では実行に必要なものだけをインストールします。完全な開発ツールチェーンも選択できます。 Linux、選択したエージェント、Git、および AndCode が使用するサポートツールです。これらは常にインストールされます。 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index a5b402fee..0303a321b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1210,6 +1210,7 @@ Voltar Avançar Recarregar + O navegador integrado não pode ser iniciado porque o WebView não foi carregado neste dispositivo. Atualizar ou reativar o Android System WebView pode resolver o problema. Ferramentas de desenvolvimento Por padrão, instale apenas o necessário para executar, ou inclua a cadeia completa de desenvolvimento. Linux, os agentes selecionados, Git e as ferramentas de suporte usadas pelo AndCode. São sempre instalados. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d0e70387d..02db1e5ce 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1213,6 +1213,7 @@ Назад Вперёд Обновить + Встроенный браузер не запускается: на этом устройстве не удалось загрузить WebView. Обновление или повторное включение Android System WebView может помочь. Инструменты разработки По умолчанию устанавливаются только необходимые компоненты. При желании можно добавить полный набор инструментов. Linux, выбранные агенты, Git и вспомогательные инструменты AndCode. Они устанавливаются всегда. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 229c827bb..c880774be 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1204,6 +1204,7 @@ 后退 前进 重新加载 + 无法启动内置浏览器,因为此设备上的 WebView 加载失败。更新或重新启用 Android System WebView 可能会解决此问题。 开发工具 默认只安装运行所需组件,也可以一并安装完整开发工具链。 Linux、所选智能体、Git 以及 AndCode 功能依赖的支持工具,将始终安装。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 46d822f6b..37fcd04a1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1229,6 +1229,7 @@ Back Forward Reload + The built-in browser cannot start because the WebView on this device failed to load. Updating or re-enabling Android System WebView may fix this. Development tools Install only the runtime by default, or include the complete development toolchain. Linux, the selected agents, Git, and the support tools used by AndCode. These are always installed. diff --git a/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt b/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt new file mode 100644 index 000000000..2f58144a4 --- /dev/null +++ b/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt @@ -0,0 +1,36 @@ +package com.yugahashimoto.andcode.feature.browser + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Assert.assertSame +import org.junit.Assert.assertThrows +import org.junit.Test + +class PlatformViewTest { + @Test + fun `returns the view when the platform builds it`() { + val view = Any() + + assertSame(view, viewOrNull(create = { view })) + } + + @Test + fun `returns null and reports the cause when the platform refuses to build the view`() { + // The WebView provider's resource registration failed on a vivo device and surfaced as a + // RuntimeException wrapping a Resources.NotFoundException. + val refusal = RuntimeException("failed to redirect ResourcesImpl", IllegalStateException("not found")) + val reported = mutableListOf() + + val view = viewOrNull(create = { throw refusal }, onFailure = { reported += it }) + + assertNull(view) + assertEquals(listOf(refusal), reported) + } + + @Test + fun `does not hide an error that is not a missing view`() { + assertThrows(OutOfMemoryError::class.java) { + viewOrNull(create = { throw OutOfMemoryError() }) + } + } +} From eec26bf0069c737a0eba032d1b3f07a0564ca1f8 Mon Sep 17 00:00:00 2001 From: Yu-ga <74749461+yuga-hashimoto@users.noreply.github.com> Date: Sat, 31 Oct 2026 00:03:58 +0900 Subject: [PATCH 2/2] fix(browser): guard only the provider start, and handle linkage failures Pre-PR review of the previous commit raised four points, all addressed here: - The guard wrapped the whole WebView setup, so an exception thrown by configure() or loadUrl() after the view existed returned null and left a half-built WebView that was never attached or destroyed. Only starting the system provider (the debugging flag and the WebView constructor) can fail for reasons the app cannot fix, so only that is guarded now; the rest runs on a WebView that exists, where a failure is a real bug. - A provider whose classes or native libraries fail to load surfaces as a LinkageError rather than an Exception. viewOrNull now treats it as a missing view as well. Other Errors, an OutOfMemoryError above all, still propagate. - With no WebView the address bar, Open and history buttons did nothing, so the address bar is hidden while the explanation is shown. - The explanation called the screen the "built-in browser" while its title is "Guest Browser" in each locale; it now uses the screen's own name. PlatformViewTest gains the LinkageError case, which failed before this change. Co-Authored-By: Claude Sonnet 5.5 --- .../feature/browser/GuestBrowserScreen.kt | 74 +++++++++++-------- .../andcode/feature/browser/PlatformView.kt | 13 +++- app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- .../feature/browser/PlatformViewTest.kt | 19 ++++- 11 files changed, 77 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt index b5b7dcb74..558031d70 100644 --- a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt +++ b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/GuestBrowserScreen.kt @@ -83,11 +83,13 @@ fun GuestBrowserScreen( }, ) { padding -> Column(modifier = Modifier.padding(padding).fillMaxSize()) { - GuestBrowserUrlBar( - urlInput = urlInput, - onUrlChange = { urlInput = it }, - onGo = { webView?.loadUrl(normalizeUrl(urlInput)) }, - ) + if (!webViewUnavailable) { + GuestBrowserUrlBar( + urlInput = urlInput, + onUrlChange = { urlInput = it }, + onGo = { webView?.loadUrl(normalizeUrl(urlInput)) }, + ) + } if (progress in 1..99) { LinearProgressIndicator(progress = { progress / 100f }) } @@ -99,34 +101,44 @@ fun GuestBrowserScreen( // field even while that field still accepts focus and keyboard input. modifier = Modifier.weight(1f).clipToBounds(), factory = { context -> - viewOrNull( - create = { - // Lets the in-guest agent drive this WebView over CDP (the devtools abstract - // socket is reachable from the guest, which shares the app's UID), so a page - // can be shown to the user and operated by human and agent at the same time. - WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG) - WebView(context).apply { - layoutParams = - ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - ) - configure( - onProgress = { progress = it }, - onNavigationStateChange = { url, back, forward -> - urlInput = url - canGoBack = back - canGoForward = forward - }, + // Only starting the system WebView provider can fail for reasons the app cannot + // fix; everything after it runs on a WebView that exists, so a failure there is + // a real bug and must not leave a half-built view behind. + val created = + viewOrNull( + create = { + // Lets the in-guest agent drive this WebView over CDP (the devtools abstract + // socket is reachable from the guest, which shares the app's UID), so a page + // can be shown to the user and operated by human and agent at the same time. + WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG) + WebView(context) + }, + onFailure = { error -> Log.w(TAG, "The system WebView could not start", error) }, + ) + if (created == null) { + webViewUnavailable = true + View(context) + } else { + created.apply { + layoutParams = + ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ) - webView = this - if (initialUrl.isNotBlank()) { - loadUrl(normalizeUrl(initialUrl)) - } + configure( + onProgress = { progress = it }, + onNavigationStateChange = { url, back, forward -> + urlInput = url + canGoBack = back + canGoForward = forward + }, + ) + webView = this + if (initialUrl.isNotBlank()) { + loadUrl(normalizeUrl(initialUrl)) } - }, - onFailure = { error -> Log.w(TAG, "The system WebView could not start", error) }, - ) ?: View(context).also { webViewUnavailable = true } + } + } }, ) } diff --git a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt index ba0d06085..3b3887dc6 100644 --- a/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt +++ b/app/src/main/java/com/yugahashimoto/andcode/feature/browser/PlatformView.kt @@ -6,18 +6,23 @@ package com.yugahashimoto.andcode.feature.browser * WebView needs the system's WebView provider, and starting it can fail on a given device: on one * vivo phone the provider's resource registration threw `Resources.NotFoundException`, which * surfaced as an `AndroidRuntimeException` inside the Compose view factory and took the whole app - * down. Nothing the app does can repair that, so the caller shows an explanation instead. + * down. A provider whose classes or native libraries cannot be loaded fails the same way as a + * [LinkageError]. Nothing the app does can repair either, so the caller shows an explanation instead. * - * Only [Exception] is caught: an [OutOfMemoryError] is not a missing provider, and hiding it would - * leave the screen blaming WebView for a memory problem. + * Only [Exception] and [LinkageError] are caught. Any other [Error], an [OutOfMemoryError] above + * all, is not a missing provider, and hiding it would leave the screen blaming WebView for a memory + * problem. */ internal fun viewOrNull( create: () -> T, - onFailure: (Exception) -> Unit = {}, + onFailure: (Throwable) -> Unit = {}, ): T? = try { create() } catch (error: Exception) { onFailure(error) null + } catch (error: LinkageError) { + onFailure(error) + null } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 8a05bfb86..790fa2ab9 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1219,7 +1219,7 @@ رجوع تقدم إعادة تحميل - يتعذّر تشغيل المتصفح المدمج لأن WebView لم يُحمَّل على هذا الجهاز. قد يحل تحديث Android System WebView أو إعادة تفعيله المشكلة. + يتعذّر تشغيل المتصفح الضيف لأن WebView لم يُحمَّل على هذا الجهاز. قد يحل تحديث Android System WebView أو إعادة تفعيله المشكلة. أدوات التطوير يتم تثبيت مكونات التشغيل الضرورية فقط افتراضيًا، ويمكنك إضافة مجموعة أدوات التطوير الكاملة. سيتم دائمًا تثبيت Linux والوكلاء المحددين وGit وأدوات الدعم التي يستخدمها AndCode. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index b0993ef92..b7ef33fd2 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1210,7 +1210,7 @@ Atrás Avanzar Recargar - El navegador integrado no puede iniciarse porque WebView no se pudo cargar en este dispositivo. Actualizar o volver a activar Android System WebView puede solucionarlo. + El navegador invitado no puede iniciarse porque WebView no se pudo cargar en este dispositivo. Actualizar o volver a activar Android System WebView puede solucionarlo. Herramientas de desarrollo De forma predeterminada solo se instala lo necesario para ejecutar el entorno, o puedes incluir toda la cadena de desarrollo. Linux, los agentes seleccionados, Git y las herramientas de soporte que usa AndCode. Siempre se instalan. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 790478e2a..f81ba3159 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1210,7 +1210,7 @@ Retour Avancer Recharger - Le navigateur intégré ne peut pas démarrer, car WebView n\'a pas pu se charger sur cet appareil. Mettre à jour ou réactiver Android System WebView peut résoudre le problème. + Le navigateur invité ne peut pas démarrer, car WebView n\'a pas pu se charger sur cet appareil. Mettre à jour ou réactiver Android System WebView peut résoudre le problème. Outils de développement Installe uniquement le nécessaire par défaut, ou incluez la chaîne complète d’outils. Linux, les agents sélectionnés, Git et les outils requis par AndCode. Ils sont toujours installés. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 9dcb160c3..4cbc51e90 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1224,7 +1224,7 @@ 戻る 進む 再読み込み - この端末の WebView を読み込めないため、内蔵ブラウザを開けません。Android System WebView を更新するか、有効にし直すと解決する場合があります。 + この端末の WebView を読み込めないため、ゲストブラウザを開けません。Android System WebView を更新するか、有効にし直すと解決する場合があります。 開発ツール 既定では実行に必要なものだけをインストールします。完全な開発ツールチェーンも選択できます。 Linux、選択したエージェント、Git、および AndCode が使用するサポートツールです。これらは常にインストールされます。 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 0303a321b..d8711a238 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1210,7 +1210,7 @@ Voltar Avançar Recarregar - O navegador integrado não pode ser iniciado porque o WebView não foi carregado neste dispositivo. Atualizar ou reativar o Android System WebView pode resolver o problema. + O navegador convidado não pode ser iniciado porque o WebView não foi carregado neste dispositivo. Atualizar ou reativar o Android System WebView pode resolver o problema. Ferramentas de desenvolvimento Por padrão, instale apenas o necessário para executar, ou inclua a cadeia completa de desenvolvimento. Linux, os agentes selecionados, Git e as ferramentas de suporte usadas pelo AndCode. São sempre instalados. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 02db1e5ce..bf6e8cfc5 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1213,7 +1213,7 @@ Назад Вперёд Обновить - Встроенный браузер не запускается: на этом устройстве не удалось загрузить WebView. Обновление или повторное включение Android System WebView может помочь. + Гостевой браузер не запускается: на этом устройстве не удалось загрузить WebView. Обновление или повторное включение Android System WebView может помочь. Инструменты разработки По умолчанию устанавливаются только необходимые компоненты. При желании можно добавить полный набор инструментов. Linux, выбранные агенты, Git и вспомогательные инструменты AndCode. Они устанавливаются всегда. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index c880774be..853b2b229 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1204,7 +1204,7 @@ 后退 前进 重新加载 - 无法启动内置浏览器,因为此设备上的 WebView 加载失败。更新或重新启用 Android System WebView 可能会解决此问题。 + 无法启动访客浏览器,因为此设备上的 WebView 加载失败。更新或重新启用 Android System WebView 可能会解决此问题。 开发工具 默认只安装运行所需组件,也可以一并安装完整开发工具链。 Linux、所选智能体、Git 以及 AndCode 功能依赖的支持工具,将始终安装。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 37fcd04a1..f649d394f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1229,7 +1229,7 @@ Back Forward Reload - The built-in browser cannot start because the WebView on this device failed to load. Updating or re-enabling Android System WebView may fix this. + The Guest Browser cannot start because the WebView on this device failed to load. Updating or re-enabling Android System WebView may fix this. Development tools Install only the runtime by default, or include the complete development toolchain. Linux, the selected agents, Git, and the support tools used by AndCode. These are always installed. diff --git a/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt b/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt index 2f58144a4..3541a4c58 100644 --- a/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt +++ b/app/src/test/java/com/yugahashimoto/andcode/feature/browser/PlatformViewTest.kt @@ -19,12 +19,27 @@ class PlatformViewTest { // The WebView provider's resource registration failed on a vivo device and surfaced as a // RuntimeException wrapping a Resources.NotFoundException. val refusal = RuntimeException("failed to redirect ResourcesImpl", IllegalStateException("not found")) - val reported = mutableListOf() + val reported = mutableListOf() val view = viewOrNull(create = { throw refusal }, onFailure = { reported += it }) assertNull(view) - assertEquals(listOf(refusal), reported) + assertEquals(listOf(refusal), reported) + } + + @Test + fun `a provider whose native code fails to load is also a missing view`() { + // The provider's classes and libraries can fail to load, which arrives as a LinkageError. + val reported = mutableListOf() + + val view = + viewOrNull( + create = { throw UnsatisfiedLinkError("libwebviewchromium.so") }, + onFailure = { reported += it }, + ) + + assertNull(view) + assertEquals(1, reported.size) } @Test