From 81f0f342a9cad23a8ecab278b2822db0d5f281b1 Mon Sep 17 00:00:00 2001 From: Booker Date: Tue, 26 May 2026 15:15:46 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9B=BE=E6=A0=87?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E9=99=90=E5=88=B6=E5=92=8C=E6=97=A0=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E8=AF=B7=E6=B1=82=E5=A4=B4=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20WebView=20=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/openim/flutter/openim/MainActivity.kt | 17 +++++++++- lib/main.dart | 31 +++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/kotlin/io/openim/flutter/openim/MainActivity.kt b/android/app/src/main/kotlin/io/openim/flutter/openim/MainActivity.kt index 21ca782..6fe1592 100644 --- a/android/app/src/main/kotlin/io/openim/flutter/openim/MainActivity.kt +++ b/android/app/src/main/kotlin/io/openim/flutter/openim/MainActivity.kt @@ -24,6 +24,7 @@ class MainActivity : FlutterActivity() { private val CHANNEL = "io.openim.flutter.openim/apk_info" private val SHELL_BRANDING_CHANNEL = "io.openim.flutter.im_webview_app/shell_branding" private val TAG = "MainActivity" + private val MAX_BRANDING_ICON_SIZE = 192 override fun onCreate(savedInstanceState: android.os.Bundle?) { // 华为/荣耀/OPPO 等国产设备:在任意网络请求之前同步安装 Conscrypt,修复 SSL 握手失败(无 GMS 时系统 SSL 实现不完整) @@ -115,13 +116,27 @@ class MainActivity : FlutterActivity() { private fun getCurrentAppIconDataUrl(): String { val icon = packageManager.getApplicationIcon(packageName) - val bitmap = drawableToBitmap(icon) + val bitmap = resizeBitmap(drawableToBitmap(icon), MAX_BRANDING_ICON_SIZE) val output = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.PNG, 100, output) val base64 = Base64.encodeToString(output.toByteArray(), Base64.NO_WRAP) return "data:image/png;base64,$base64" } + private fun resizeBitmap(bitmap: Bitmap, maxSize: Int): Bitmap { + val width = bitmap.width + val height = bitmap.height + val longestSide = maxOf(width, height) + if (longestSide <= maxSize) { + return bitmap + } + + val scale = maxSize.toFloat() / longestSide.toFloat() + val scaledWidth = (width * scale).toInt().coerceAtLeast(1) + val scaledHeight = (height * scale).toInt().coerceAtLeast(1) + return Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true) + } + private fun drawableToBitmap(drawable: Drawable): Bitmap { if (drawable is BitmapDrawable && drawable.bitmap != null) { return drawable.bitmap diff --git a/lib/main.dart b/lib/main.dart index 3b10fd7..ab010cf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,6 +15,11 @@ const _shellBackground = Color(0xFFF8FBFF); const _shellAccent = Color(0xFF0089FF); const _shellSubText = Color(0xFF8E9AB0); const _resumeCoverDuration = Duration(milliseconds: 700); +const _noCacheHeaders = { + 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', + 'Pragma': 'no-cache', + 'Expires': '0', +}; const _shellBrandingChannel = MethodChannel('io.openim.flutter.im_webview_app/shell_branding'); const _shellMediaPermissionBridgeScript = r''' @@ -221,7 +226,8 @@ class _H5ShellPageState extends State with WidgetsBindingObserver { appName: widget.shellBranding.appName, appLogo: widget.shellBranding.appLogo, ); - _controller = _buildController()..loadRequest(Uri.parse(_homeUrl)); + _controller = _buildController(); + unawaited(_loadHome()); } @override @@ -439,6 +445,27 @@ class _H5ShellPageState extends State with WidgetsBindingObserver { return _runJavaScriptSafely(_stopWebMediaScript); } + Future _loadHome() async { + if (mounted) { + setState(() { + _loadError = null; + _progress = 0; + _showShellCover = true; + }); + } + + try { + await _controller.clearCache(); + } catch (_) { + // Some WebView implementations can reject cache operations during setup. + } + + await _controller.loadRequest( + Uri.parse(_homeUrl), + headers: _noCacheHeaders, + ); + } + Future _handleNavigationRequest( NavigationRequest request, ) async { @@ -568,7 +595,7 @@ class _H5ShellPageState extends State with WidgetsBindingObserver { if (_loadError != null) _ErrorPanel( message: _loadError!, - onRetry: () => _controller.loadRequest(Uri.parse(_homeUrl)), + onRetry: () => unawaited(_loadHome()), ), ], ),