Replace app icon with Joykoo brand logo and improve WebView error handling
Some checks failed
APK-BUILD/pipeline/head There was a failure building this commit
Use the Jk logo from smart.joykoo.mx as the launcher icon (legacy PNGs and adaptive icon foreground at all densities). Add SSL/HTTP error handling so failures show the error overlay instead of a silent white screen. Add JS console logging to logcat and WebView debugging for debug builds. Relax mixed content mode to compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ -9,16 +9,20 @@ import android.net.NetworkCapabilities
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.view.WindowInsetsController
|
import android.view.WindowInsetsController
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import android.webkit.ConsoleMessage
|
||||||
import android.webkit.CookieManager
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.SslErrorHandler
|
||||||
import android.webkit.ValueCallback
|
import android.webkit.ValueCallback
|
||||||
import android.webkit.WebChromeClient
|
import android.webkit.WebChromeClient
|
||||||
import android.webkit.WebResourceError
|
import android.webkit.WebResourceError
|
||||||
import android.webkit.WebResourceRequest
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
@ -98,9 +102,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
domStorageEnabled = true
|
domStorageEnabled = true
|
||||||
databaseEnabled = true
|
databaseEnabled = true
|
||||||
|
|
||||||
// Allow mixed content only if absolutely necessary for the target site.
|
mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
|
||||||
// Default to the safest option.
|
|
||||||
mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW
|
|
||||||
|
|
||||||
// Cache and storage for session persistence
|
// Cache and storage for session persistence
|
||||||
cacheMode = WebSettings.LOAD_DEFAULT
|
cacheMode = WebSettings.LOAD_DEFAULT
|
||||||
@ -129,6 +131,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setAcceptThirdPartyCookies(webView, true)
|
setAcceptThirdPartyCookies(webView, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG)
|
||||||
|
|
||||||
webView.webViewClient = ScannerWebViewClient()
|
webView.webViewClient = ScannerWebViewClient()
|
||||||
webView.webChromeClient = ScannerWebChromeClient()
|
webView.webChromeClient = ScannerWebChromeClient()
|
||||||
}
|
}
|
||||||
@ -315,21 +319,44 @@ class MainActivity : AppCompatActivity() {
|
|||||||
request: WebResourceRequest,
|
request: WebResourceRequest,
|
||||||
error: WebResourceError
|
error: WebResourceError
|
||||||
) {
|
) {
|
||||||
// Only show error overlay for main-frame navigation failures
|
|
||||||
if (request.isForMainFrame) {
|
if (request.isForMainFrame) {
|
||||||
|
Log.e(TAG, "WebView error: ${error.description} (${error.errorCode})")
|
||||||
showError()
|
showError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do NOT override onReceivedSslError to proceed — let TLS
|
override fun onReceivedHttpError(
|
||||||
// errors fail as they should for security.
|
view: WebView,
|
||||||
|
request: WebResourceRequest,
|
||||||
|
errorResponse: WebResourceResponse
|
||||||
|
) {
|
||||||
|
if (request.isForMainFrame) {
|
||||||
|
Log.e(TAG, "HTTP error ${errorResponse.statusCode} for ${request.url}")
|
||||||
|
showError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReceivedSslError(
|
||||||
|
view: WebView,
|
||||||
|
handler: SslErrorHandler,
|
||||||
|
error: android.net.http.SslError
|
||||||
|
) {
|
||||||
|
Log.e(TAG, "SSL error: ${error.primaryError} for ${error.url}")
|
||||||
|
handler.cancel()
|
||||||
|
showError()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── WebChromeClient ─────────────────────────────────────────────────
|
// ── WebChromeClient ─────────────────────────────────────────────────
|
||||||
|
|
||||||
private inner class ScannerWebChromeClient : WebChromeClient() {
|
private inner class ScannerWebChromeClient : WebChromeClient() {
|
||||||
|
|
||||||
// File upload support: <input type="file"> in the webpage
|
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
|
||||||
|
Log.d(TAG, "JS [${consoleMessage.messageLevel()}] ${consoleMessage.message()} " +
|
||||||
|
"(${consoleMessage.sourceId()}:${consoleMessage.lineNumber()})")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onShowFileChooser(
|
override fun onShowFileChooser(
|
||||||
webView: WebView,
|
webView: WebView,
|
||||||
filePathCallback: ValueCallback<Array<Uri>>,
|
filePathCallback: ValueCallback<Array<Uri>>,
|
||||||
@ -366,6 +393,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val TAG = "JoykooScanner"
|
||||||
private const val FILE_CHOOSER_REQUEST = 1001
|
private const val FILE_CHOOSER_REQUEST = 1001
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,6 @@
|
|||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#1565C0"
|
android:fillColor="#FFFFFF"
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<!-- QR code icon outline -->
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M30,30h18v18h-18z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M60,30h18v18h-18z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M30,60h18v18h-18z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M33,33h12v12h-12z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M63,33h12v12h-12z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M33,63h12v12h-12z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M36,36h6v6h-6z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M66,36h6v6h-6z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M36,66h6v6h-6z" />
|
|
||||||
<!-- Data dots -->
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M54,54h6v6h-6z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M60,60h6v6h-6z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M66,60h6v6h-6z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M54,66h6v6h-6z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#1A237E"
|
|
||||||
android:pathData="M72,66h6v6h-6z" />
|
|
||||||
</vector>
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<item android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</layer-list>
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 538 B After Width: | Height: | Size: 5.2 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 735 B After Width: | Height: | Size: 6.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 12 KiB |