You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 12+及低版本动态适配启动页失败,求问题排查

Flutter Android启动页适配Android 12+失败问题排查

问题描述

我尝试添加一张图片作为启动页,已在mipmap目录放入不同密度的splash.png文件。需要同时适配Android 12及以上版本和Android 12以下版本,尝试了以下实现但未生效:

现有代码

res/value/styles.xml

<!-- For devices below Android 12 -->
<style name="SplashTheme" parent="@android:style/Theme.Light.NoTitleBar">
    <item name="android:windowBackground">@mipmap/splash</item>
</style>

<!-- For devices Android 12 or higher -->
<style name="SplashTheme_S" parent="@android:style/Theme.Light.NoTitleBar">
    <item name="windowSplashScreenBackground">@mipmap/splash</item>
</style>

AndroidManifest.xml

<activity
        android:name=".MainActivity"
        android:exported="true"
        android:launchMode="singleTop"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize">
        <!-- Specifies an Android theme to apply to this Activity as soon as
             the Android process has started. This theme is visible to the user
             while the Flutter UI initializes. After that, this theme continues
             to determine the Window background behind the Flutter UI. -->
        <meta-data
          android:name="io.flutter.embedding.android.NormalTheme"
          android:resource="@style/NormalTheme"
          />
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

MainActivity.kt

package com.myorg.mynotes

import android.os.Build
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        Log.d("MainActivity", "SDK_INT: ${Build.VERSION.SDK_INT}")
        // Dynamically set splash screen theme based on Android version
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            Log.d("MainActivity", "Using SplashTheme_S for Android 12 or higher")
            setTheme(R.style.SplashTheme_S)
            Log.d("MainActivity", "After setTheme function")
        } else{
            Log.d("MainActivity", "Using SplashTheme for Android versions below 12")
            setTheme(R.style.SplashTheme)
            Log.d("MainActivity", "After setTheme function")
        }
        super.onCreate(savedInstanceState) 
    }
}

错误原因分析

  1. 主题设置时机太晚:系统在进程启动时就会读取Manifest中指定的Activity主题并显示启动页,onCreate方法调用时已经过了启动主题加载的关键阶段,动态设置的主题无法作用于启动页。
  2. Android 12+主题父类错误:windowSplashScreenBackground属于SplashScreen API专属属性,必须配合Theme.SplashScreen作为父主题才能生效,沿用旧的Theme.Light.NoTitleBar会导致系统无法识别该属性。
  3. Manifest未指定启动主题:当前启动Activity没有配置android:theme属性,系统会使用默认主题,而非你定义的Splash主题。

正确实现步骤

1. 分版本配置主题文件

  • Android 12以下版本(res/values/styles.xml):
<style name="SplashTheme" parent="@android:style/Theme.Light.NoTitleBar">
    <item name="android:windowBackground">@mipmap/splash</item>
    <!-- 可选:隐藏状态栏和导航栏 -->
    <item name="android:windowFullscreen">true</item>
</style>
  • Android 12及以上版本(res/values-v31/styles.xml):
<style name="SplashTheme" parent="Theme.SplashScreen">
    <!-- 启动页背景图 -->
    <item name="windowSplashScreenBackground">@mipmap/splash</item>
    <!-- 启动页消失后过渡到的主题 -->
    <item name="postSplashScreenTheme">@style/NormalTheme</item>
    <!-- 可选:隐藏状态栏和导航栏 -->
    <item name="android:windowFullscreen">true</item>
</style>

2. 修改Manifest指定启动主题

在启动Activity标签中添加android:theme="@style/SplashTheme":

<activity
        android:name=".MainActivity"
        android:exported="true"
        android:launchMode="singleTop"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize"
        android:theme="@style/SplashTheme"> <!-- 添加此配置 -->
        <meta-data
          android:name="io.flutter.embedding.android.NormalTheme"
          android:resource="@style/NormalTheme"
          />
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

3. 调整MainActivity代码(Android 12+适配)

Android 12+需要手动处理启动屏与Flutter UI的过渡,修改MainActivity.kt:

package com.myorg.mynotes

import android.os.Build
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen

class MainActivity: FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // Android 12+安装启动屏,处理过渡逻辑
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            installSplashScreen()
        }
        super.onCreate(savedInstanceState)
    }
}

关键说明

  • 系统会根据设备API版本自动加载对应values目录下的主题,无需动态判断,确保启动阶段就应用正确主题。
  • Android 12+的Theme.SplashScreen是专门为启动屏设计的主题,必须使用它作为父主题才能让相关属性生效,postSplashScreenTheme用于指定启动屏消失后的过渡主题。
  • installSplashScreen()方法会自动处理启动屏与Flutter UI的过渡,避免出现白屏或闪烁问题。

内容的提问来源于stack exchange,提问作者Shivang Sorout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:27:02