From 3c0c31fe6751df5c5f399a5477380b2a48f915e0 Mon Sep 17 00:00:00 2001 From: Spirit Date: Tue, 3 Feb 2026 15:15:54 +0000 Subject: [PATCH] feat: Add network error handling - error.html: User-friendly error page with retry button - ErrorHandler.kt: Utility for handling WebView errors - ErrorHandlerTest.kt: Unit tests for error handling Shows friendly error page on network failures instead of blank/broken page. Includes error code display and one-tap retry. --- app/src/main/assets/error.html | 88 +++++++++++++++++++ .../farm/hobbs/kioskbrowser/ErrorHandler.kt | 80 +++++++++++++++++ .../hobbs/kioskbrowser/ErrorHandlerTest.kt | 29 ++++++ 3 files changed, 197 insertions(+) create mode 100644 app/src/main/assets/error.html create mode 100644 app/src/main/kotlin/farm/hobbs/kioskbrowser/ErrorHandler.kt create mode 100644 app/src/test/kotlin/farm/hobbs/kioskbrowser/ErrorHandlerTest.kt diff --git a/app/src/main/assets/error.html b/app/src/main/assets/error.html new file mode 100644 index 0000000..3e35b65 --- /dev/null +++ b/app/src/main/assets/error.html @@ -0,0 +1,88 @@ + + + + + + Connection Error + + + +
+
📡
+

Connection Problem

+

Unable to load the page. Please check your internet connection and try again.

+ +
+
+ + + diff --git a/app/src/main/kotlin/farm/hobbs/kioskbrowser/ErrorHandler.kt b/app/src/main/kotlin/farm/hobbs/kioskbrowser/ErrorHandler.kt new file mode 100644 index 0000000..d6d7b9a --- /dev/null +++ b/app/src/main/kotlin/farm/hobbs/kioskbrowser/ErrorHandler.kt @@ -0,0 +1,80 @@ +package farm.hobbs.kioskbrowser + +import android.webkit.WebResourceError +import android.webkit.WebResourceRequest +import android.webkit.WebView + +/** + * Handles WebView errors with user-friendly error pages. + * + * Usage in WebViewClient: + * ``` + * override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { + * ErrorHandler.handleError(view, request, error) + * } + * ``` + */ +object ErrorHandler { + + private const val ERROR_PAGE = "file:///android_asset/error.html" + + /** + * Network error codes that should show the error page + */ + private val NETWORK_ERRORS = setOf( + android.webkit.WebViewClient.ERROR_HOST_LOOKUP, + android.webkit.WebViewClient.ERROR_CONNECT, + android.webkit.WebViewClient.ERROR_TIMEOUT, + android.webkit.WebViewClient.ERROR_IO, + android.webkit.WebViewClient.ERROR_UNKNOWN + ) + + /** + * Handle WebView errors - show error page for main frame network errors + */ + fun handleError( + view: WebView?, + request: WebResourceRequest?, + error: WebResourceError? + ): Boolean { + // Only handle main frame errors + if (request?.isForMainFrame != true) return false + + val errorCode = error?.errorCode ?: return false + + // Show error page for network errors + if (errorCode in NETWORK_ERRORS || errorCode < 0) { + view?.loadUrl("$ERROR_PAGE?code=$errorCode") + return true + } + + return false + } + + /** + * Handle HTTP errors (4xx, 5xx) + */ + fun handleHttpError( + view: WebView?, + request: WebResourceRequest?, + statusCode: Int + ): Boolean { + // Only handle main frame errors + if (request?.isForMainFrame != true) return false + + // Show error page for server errors + if (statusCode >= 500) { + view?.loadUrl("$ERROR_PAGE?code=$statusCode") + return true + } + + return false + } + + /** + * Check if current URL is the error page + */ + fun isErrorPage(url: String?): Boolean { + return url?.startsWith(ERROR_PAGE.substringBefore("?")) == true + } +} diff --git a/app/src/test/kotlin/farm/hobbs/kioskbrowser/ErrorHandlerTest.kt b/app/src/test/kotlin/farm/hobbs/kioskbrowser/ErrorHandlerTest.kt new file mode 100644 index 0000000..e4531e4 --- /dev/null +++ b/app/src/test/kotlin/farm/hobbs/kioskbrowser/ErrorHandlerTest.kt @@ -0,0 +1,29 @@ +package farm.hobbs.kioskbrowser + +import org.junit.Assert.* +import org.junit.Test + +/** + * Unit tests for ErrorHandler utility + */ +class ErrorHandlerTest { + + @Test + fun `isErrorPage returns true for error page URL`() { + assertTrue(ErrorHandler.isErrorPage("file:///android_asset/error.html")) + assertTrue(ErrorHandler.isErrorPage("file:///android_asset/error.html?code=-2")) + } + + @Test + fun `isErrorPage returns false for regular URLs`() { + assertFalse(ErrorHandler.isErrorPage("https://hobbs.farm")) + assertFalse(ErrorHandler.isErrorPage("https://google.com")) + assertFalse(ErrorHandler.isErrorPage(null)) + } + + @Test + fun `isErrorPage returns false for similar but different URLs`() { + assertFalse(ErrorHandler.isErrorPage("file:///android_asset/other.html")) + assertFalse(ErrorHandler.isErrorPage("https://error.html")) + } +}