diff --git a/packages/client-android/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/packages/client-android/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock index ab144f9..954802b 100644 Binary files a/packages/client-android/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/packages/client-android/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/packages/client-android/android/app/src/main/assets/frame.html b/packages/client-android/android/app/src/main/assets/frame.html new file mode 100644 index 0000000..e0668e0 Binary files /dev/null and b/packages/client-android/android/app/src/main/assets/frame.html differ diff --git a/packages/client-android/android/app/src/main/assets/skeleton.html b/packages/client-android/android/app/src/main/assets/skeleton.html new file mode 100644 index 0000000..0c465ac Binary files /dev/null and b/packages/client-android/android/app/src/main/assets/skeleton.html differ diff --git a/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt b/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt index af7dc16..45e1563 100644 --- a/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt +++ b/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt @@ -3,7 +3,6 @@ package dev.yuzu.gca import android.os.Bundle import android.util.Log import android.webkit.WebView -import android.webkit.WebViewClient import androidx.appcompat.app.AppCompatActivity import java.io.File import java.net.HttpURLConnection @@ -11,29 +10,18 @@ import java.net.URL class MainActivity : AppCompatActivity() { - private val cacheFile: File by lazy { File(filesDir, "gca_hot.html") } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val wv = WebView(this).apply { - if (0 != (applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE)) { - WebView.setWebContentsDebuggingEnabled(true) - } settings.javaScriptEnabled = true settings.domStorageEnabled = true settings.allowFileAccess = true addJavascriptInterface(Bridge(this@MainActivity), "Android") - webViewClient = object : WebViewClient() {} - if (cacheFile.exists()) { - val html = cacheFile.readText() - loadDataWithBaseURL("file:///android_asset/", html, "text/html", "UTF-8", null) - Log.i(TAG, "Loaded cached HTML (${cacheFile.length()}B)") - } else { - loadUrl("file:///android_asset/index.html") - Log.i(TAG, "Loaded embedded index.html") - } + val html = assets.open("frame.html").bufferedReader().readText() + loadDataWithBaseURL("about:blank", html, "text/html", "UTF-8", null) + Log.i(TAG, "Loaded frame.html (${html.length}B)") } setContentView(wv) } @@ -41,66 +29,43 @@ class MainActivity : AppCompatActivity() { inner class Bridge(private val ctx: MainActivity) { @android.webkit.JavascriptInterface fun saveCache(html: String) { - if (html.length > 500_000) { - Log.w(TAG, "Cache rejected: too large (${html.length}B)") - return - } - ctx.cacheFile.writeText(html) - Log.i(TAG, "Hot-update HTML saved (${html.length}B)") + if (html.length > 500_000) { Log.w(TAG, "Cache too large"); return } + File(ctx.filesDir, "gca_hot.html").writeText(html) + Log.i(TAG, "Saved ${html.length}B") } @android.webkit.JavascriptInterface fun clearCache() { - ctx.cacheFile.delete() - Log.i(TAG, "Cache cleared") + File(ctx.filesDir, "gca_hot.html").delete() } @android.webkit.JavascriptInterface fun sha256(input: String): String { val md = java.security.MessageDigest.getInstance("SHA-256") - val digest = md.digest(input.toByteArray(Charsets.UTF_8)) - return digest.joinToString("") { "%02x".format(it) } + return md.digest(input.toByteArray(Charsets.UTF_8)).joinToString("") { "%02x".format(it) } } - /** Fetch manifest JSON from Gitea and return channel's section */ @android.webkit.JavascriptInterface fun fetchManifest(channel: String): String { - val manifestUrl = "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/raw/branch/main/ota/manifest.json" - Log.i(TAG, "Bridge fetching $manifestUrl → $channel") + val url = "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/raw/branch/main/ota/manifest.json" return try { - val conn = URL(manifestUrl).openConnection() as HttpURLConnection - conn.connectTimeout = 10_000; conn.readTimeout = 10_000 - conn.instanceFollowRedirects = true - if (conn.responseCode != 200) throw Exception("HTTP ${conn.responseCode}") + val conn = URL(url).openConnection() as HttpURLConnection + conn.connectTimeout = 10000; conn.readTimeout = 10000 val raw = conn.inputStream.bufferedReader().readText() - val json = org.json.JSONObject(raw) - json.getJSONObject(channel).toString() - } catch (e: Exception) { - Log.e(TAG, "Bridge fetchManifest($channel) failed: ${e.message}") - """{"error":"${e.message}"}""" - } + org.json.JSONObject(raw).getJSONObject(channel).toString() + } catch (e: Exception) { """{"error":"${e.message}"}""" } } - /** Fetch text file from Gitea — proxy for version.txt etc */ @android.webkit.JavascriptInterface fun fetchText(path: String): String { val safe = path.replace("..", "").replace("\\", "/") val url = "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/raw/branch/main/ota/$safe" - Log.i(TAG, "Bridge fetching $url") return try { - val conn = URL(url).openConnection() as HttpURLConnection - conn.connectTimeout = 10_000 - conn.readTimeout = 10_000 - conn.instanceFollowRedirects = true - val code = conn.responseCode - if (code != 200) throw Exception("HTTP $code") - conn.inputStream.bufferedReader().readText() - } catch (e: Exception) { - Log.e(TAG, "Bridge fetchText($path) failed: ${e.message}") - "ERROR: ${e.message}" - } + URL(url).openConnection().apply { connectTimeout = 10000; readTimeout = 10000 } + .getInputStream().bufferedReader().readText() + } catch (e: Exception) { "ERROR: ${e.message}" } } } - companion object { private const val TAG = "GCA-H5" } + companion object { private const val TAG = "GCA" } }