From bcf3c9b9e456738d35889cdfab8c0fd49fd58681 Mon Sep 17 00:00:00 2001 From: dimitris Date: Sat, 16 May 2026 01:31:40 +0200 Subject: [PATCH] fix(webview): guard external-link launches with try/catch DocsViewerActivity and BackupWebView both route tapped links to the system browser with raw context.startActivity(intent) inside shouldOverrideUrlLoading. If the device has no app that can handle the link the call raises ActivityNotFoundException and the host crashes mid-tap. In BackupWebView the call sits inside a Dispatchers.IO coroutine, so the failure brings the process down even more abruptly. Wrap both in try/catch (ActivityNotFoundException) and fall back to a Toast (no_app_to_open_link). On the BackupWebView side the Toast is wrapped in withContext(Dispatchers.Main) since the catch fires on Dispatchers.IO. --- .../applistbackup/docs/DocsViewerActivity.kt | 12 +++++++++++- .../applistbackup/reader/BackupWebView.kt | 15 ++++++++++++++- app/src/main/res/values/strings.xml | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/androidlabs/applistbackup/docs/DocsViewerActivity.kt b/app/src/main/java/org/androidlabs/applistbackup/docs/DocsViewerActivity.kt index 7ed0d01..f0131e1 100644 --- a/app/src/main/java/org/androidlabs/applistbackup/docs/DocsViewerActivity.kt +++ b/app/src/main/java/org/androidlabs/applistbackup/docs/DocsViewerActivity.kt @@ -1,10 +1,12 @@ package org.androidlabs.applistbackup.docs +import android.content.ActivityNotFoundException import android.content.Intent import android.os.Bundle import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient +import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize @@ -66,7 +68,15 @@ fun WebViewComposable(filename: String, modifier: Modifier = Modifier) { ): Boolean { request?.url?.let { url -> val intent = Intent(Intent.ACTION_VIEW, url) - context.startActivity(intent) + try { + context.startActivity(intent) + } catch (e: ActivityNotFoundException) { + Toast.makeText( + context, + R.string.no_app_to_open_link, + Toast.LENGTH_SHORT + ).show() + } return true } return false diff --git a/app/src/main/java/org/androidlabs/applistbackup/reader/BackupWebView.kt b/app/src/main/java/org/androidlabs/applistbackup/reader/BackupWebView.kt index 4ff5ec3..7636edd 100644 --- a/app/src/main/java/org/androidlabs/applistbackup/reader/BackupWebView.kt +++ b/app/src/main/java/org/androidlabs/applistbackup/reader/BackupWebView.kt @@ -1,6 +1,7 @@ package org.androidlabs.applistbackup.reader import android.annotation.SuppressLint +import android.content.ActivityNotFoundException import android.content.Intent import android.graphics.Bitmap import android.net.Uri @@ -9,6 +10,7 @@ import android.webkit.WebResourceRequest import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient +import android.widget.Toast import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator @@ -27,6 +29,7 @@ import androidx.compose.ui.viewinterop.AndroidView import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.androidlabs.applistbackup.R @SuppressLint("SetJavaScriptEnabled") @Composable @@ -72,7 +75,17 @@ fun BackupWebView( coroutineScope.launch(Dispatchers.IO) { val intent = Intent(Intent.ACTION_VIEW, url) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(intent) + try { + context.startActivity(intent) + } catch (e: ActivityNotFoundException) { + withContext(Dispatchers.Main) { + Toast.makeText( + context, + R.string.no_app_to_open_link, + Toast.LENGTH_SHORT + ).show() + } + } } return true } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74a2c4a..ded7895 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ AppListBackup + No app available to open this link Backup now Backing up This widget allow you to create backup immediately.