From bacab81915a9ab640437b7d674bf9e29e701b1f1 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Mon, 5 Oct 2026 02:37:13 +0200 Subject: feat(android): launch icon stays up for at least half a second Co-Authored-By: Claude Opus 5.5 --- .../main/kotlin/org/meshbay/client/MainActivity.kt | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'packages/meshbay-android/app') diff --git a/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt b/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt index fc446b9..0fa63d6 100644 --- a/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt +++ b/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt @@ -6,9 +6,11 @@ import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle +import android.os.SystemClock import android.util.Log import android.view.View import android.view.ViewGroup +import android.view.ViewTreeObserver import android.view.WindowInsets import android.webkit.ConsoleMessage import android.webkit.PermissionRequest @@ -66,6 +68,7 @@ class MainActivity : Activity() { root = FrameLayout(this) setContentView(root) applyInsets(root) + if (savedInstanceState == null && Build.VERSION.SDK_INT >= 31) holdSplash() // A WebView too old for the page's crypto would fail at the first // handshake; say so before loading anything. @@ -255,6 +258,22 @@ class MainActivity : Activity() { catch (e: android.content.ActivityNotFoundException) { Log.w(Bridge.TAG, "no browser for $url") } } + /** + * Android 12+ shows the launcher icon until the first frame is drawn, which + * on a warm process is a flash. Holding that frame keeps it up long enough + * to be seen; the WebView loads underneath in the meantime. + */ + private fun holdSplash() { + val until = SystemClock.uptimeMillis() + SPLASH_MS + root.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { + override fun onPreDraw(): Boolean { + if (SystemClock.uptimeMillis() < until) return false + root.viewTreeObserver.removeOnPreDrawListener(this) + return true + } + }) + } + /** Edge-to-edge is enforced from Android 15: keep the page clear of the bars and the keyboard. */ private fun applyInsets(view: View) { view.setOnApplyWindowInsetsListener { v, insets -> @@ -296,4 +315,8 @@ class MainActivity : Activity() { if (::web.isInitialized) { root.removeView(web); web.destroy() } super.onDestroy() } + + companion object { + private const val SPLASH_MS = 500L + } } -- cgit v1.2.3