diff --git a/frontend/mobile-app/android/app/build.gradle.kts b/frontend/mobile-app/android/app/build.gradle.kts
index e3b7382a..ec8b7f21 100644
--- a/frontend/mobile-app/android/app/build.gradle.kts
+++ b/frontend/mobile-app/android/app/build.gradle.kts
@@ -43,6 +43,11 @@ fun getAutoVersionName(): String {
return "$flutterVersionName.$autoVersionCode"
}
+dependencies {
+ // SplashScreen API for Android 12+ compatibility
+ implementation("androidx.core:core-splashscreen:1.0.1")
+}
+
android {
namespace = "com.rwadurian.rwa_android_app"
compileSdk = flutter.compileSdkVersion
diff --git a/frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt b/frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt
index e6442502..e715c3ef 100644
--- a/frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt
+++ b/frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt
@@ -3,7 +3,9 @@ package com.rwadurian.rwa_android_app
import android.content.Intent
import android.net.Uri
import android.os.Build
+import android.os.Bundle
import androidx.core.content.FileProvider
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
@@ -13,6 +15,22 @@ class MainActivity : FlutterActivity() {
private val INSTALLER_CHANNEL = "com.rwadurian.app/apk_installer"
private val MARKET_CHANNEL = "com.rwadurian.app/app_market"
+ override fun onCreate(savedInstanceState: Bundle?) {
+ // Install splash screen - must be called before super.onCreate()
+ val splashScreen = installSplashScreen()
+
+ // Keep splash screen visible until Flutter is ready
+ var keepSplashScreen = true
+ splashScreen.setKeepOnScreenCondition { keepSplashScreen }
+
+ super.onCreate(savedInstanceState)
+
+ // Dismiss splash screen after a short delay to ensure smooth transition
+ window.decorView.postDelayed({
+ keepSplashScreen = false
+ }, 300)
+ }
+
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
diff --git a/frontend/mobile-app/android/app/src/main/res/drawable-v21/launch_background.xml b/frontend/mobile-app/android/app/src/main/res/drawable-v21/launch_background.xml
index 1cb7aa2f..2c0a0da2 100644
--- a/frontend/mobile-app/android/app/src/main/res/drawable-v21/launch_background.xml
+++ b/frontend/mobile-app/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -1,12 +1,13 @@
-
+
-
+
+
-
-
+ -
-
-->
+ android:src="@mipmap/ic_launcher" />
+
diff --git a/frontend/mobile-app/android/app/src/main/res/drawable/launch_background.xml b/frontend/mobile-app/android/app/src/main/res/drawable/launch_background.xml
index 84037589..b93fd222 100644
--- a/frontend/mobile-app/android/app/src/main/res/drawable/launch_background.xml
+++ b/frontend/mobile-app/android/app/src/main/res/drawable/launch_background.xml
@@ -1,12 +1,13 @@
-
+
-
+
+
-
-
+ -
-
-->
+ android:src="@mipmap/ic_launcher" />
+
diff --git a/frontend/mobile-app/android/app/src/main/res/values-night-v31/styles.xml b/frontend/mobile-app/android/app/src/main/res/values-night-v31/styles.xml
new file mode 100644
index 00000000..e6550830
--- /dev/null
+++ b/frontend/mobile-app/android/app/src/main/res/values-night-v31/styles.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/frontend/mobile-app/android/app/src/main/res/values-night/styles.xml b/frontend/mobile-app/android/app/src/main/res/values-night/styles.xml
index 360a1605..5240c7a5 100644
--- a/frontend/mobile-app/android/app/src/main/res/values-night/styles.xml
+++ b/frontend/mobile-app/android/app/src/main/res/values-night/styles.xml
@@ -1,17 +1,16 @@
-
-
-
+
diff --git a/frontend/mobile-app/android/app/src/main/res/values-v31/styles.xml b/frontend/mobile-app/android/app/src/main/res/values-v31/styles.xml
new file mode 100644
index 00000000..31fe29f8
--- /dev/null
+++ b/frontend/mobile-app/android/app/src/main/res/values-v31/styles.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/frontend/mobile-app/android/app/src/main/res/values/colors.xml b/frontend/mobile-app/android/app/src/main/res/values/colors.xml
index cfa9be08..bad34663 100644
--- a/frontend/mobile-app/android/app/src/main/res/values/colors.xml
+++ b/frontend/mobile-app/android/app/src/main/res/values/colors.xml
@@ -1,4 +1,6 @@
#FFFFFF
+
+ #FFF5E6
\ No newline at end of file
diff --git a/frontend/mobile-app/android/app/src/main/res/values/styles.xml b/frontend/mobile-app/android/app/src/main/res/values/styles.xml
index 5fac6796..162d1070 100644
--- a/frontend/mobile-app/android/app/src/main/res/values/styles.xml
+++ b/frontend/mobile-app/android/app/src/main/res/values/styles.xml
@@ -1,17 +1,16 @@
-
-
-
+
diff --git a/frontend/mobile-app/assets/videos/splash.mp4 b/frontend/mobile-app/assets/videos/splash.mp4
index e75b01cf..7ef5a402 100644
Binary files a/frontend/mobile-app/assets/videos/splash.mp4 and b/frontend/mobile-app/assets/videos/splash.mp4 differ
diff --git a/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart b/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart
index 40e0c95f..04527313 100644
--- a/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart
+++ b/frontend/mobile-app/lib/features/auth/presentation/pages/splash_page.dart
@@ -44,11 +44,30 @@ class _SplashPageState extends ConsumerState {
/// 初始化视频播放器
Future _initializeVideo() async {
+ debugPrint('[SplashPage] ========== 开始初始化视频 ==========');
+ debugPrint('[SplashPage] 视频路径: assets/videos/splash.mp4');
+
try {
// 从 assets 加载视频
+ debugPrint('[SplashPage] 创建 VideoPlayerController...');
_videoController = VideoPlayerController.asset('assets/videos/splash.mp4');
+ debugPrint('[SplashPage] 开始 initialize()...');
+ final stopwatch = Stopwatch()..start();
await _videoController!.initialize();
+ stopwatch.stop();
+ debugPrint('[SplashPage] initialize() 完成,耗时: ${stopwatch.elapsedMilliseconds}ms');
+
+ // 打印视频信息
+ final value = _videoController!.value;
+ debugPrint('[SplashPage] 视频信息:');
+ debugPrint('[SplashPage] - 尺寸: ${value.size.width} x ${value.size.height}');
+ debugPrint('[SplashPage] - 时长: ${value.duration.inMilliseconds}ms');
+ debugPrint('[SplashPage] - 是否已初始化: ${value.isInitialized}');
+ debugPrint('[SplashPage] - 是否有错误: ${value.hasError}');
+ if (value.hasError) {
+ debugPrint('[SplashPage] - 错误信息: ${value.errorDescription}');
+ }
if (mounted) {
setState(() {
@@ -59,7 +78,9 @@ class _SplashPageState extends ConsumerState {
_videoController!.addListener(_onVideoStateChanged);
// 开始播放视频
+ debugPrint('[SplashPage] 开始播放视频...');
await _videoController!.play();
+ debugPrint('[SplashPage] play() 调用完成,isPlaying: ${_videoController!.value.isPlaying}');
// 1秒后显示跳过按钮
Future.delayed(const Duration(seconds: 1), () {
@@ -70,8 +91,23 @@ class _SplashPageState extends ConsumerState {
}
});
}
- } catch (e) {
- debugPrint('[SplashPage] 视频初始化失败: $e');
+ } catch (e, stackTrace) {
+ debugPrint('[SplashPage] ========== 视频初始化失败 ==========');
+ debugPrint('[SplashPage] 错误类型: ${e.runtimeType}');
+ debugPrint('[SplashPage] 错误信息: $e');
+ debugPrint('[SplashPage] 堆栈跟踪:\n$stackTrace');
+
+ // 检查 controller 状态
+ if (_videoController != null) {
+ final value = _videoController!.value;
+ debugPrint('[SplashPage] Controller 状态:');
+ debugPrint('[SplashPage] - 是否已初始化: ${value.isInitialized}');
+ debugPrint('[SplashPage] - 是否有错误: ${value.hasError}');
+ if (value.hasError) {
+ debugPrint('[SplashPage] - 错误描述: ${value.errorDescription}');
+ }
+ }
+
// 如果视频加载失败,直接进行跳转
_navigateToNextPage();
}