I'm trying to upgrade my application to target android 31 which introduces splash screen API so I followed the migration process mentioned here, but after migration the application doesn't run because splash screen API only supports android version 21 and above so what is the process to support older versions than 21?
Androidx SplashScreen class works as following:
On API 31+ (Android 12+) this class calls the platform methods.
Prior API 31, the platform behavior is replicated with the exception of the Animated Vector Drawable support on the launch screen.
the problem is Animated Vector Drawable class was introduced with Android 21 so the current Androidx SplashScreen class backward compatible with Android +21 so i figured out some solution. I created two different splash screen activities one to handle the old versions and the second which use Androidx SplashScreen API. and I made the system lunches splash screen based on the current android version, so I did the following
1- to allow application compiling and build, I had to add this line to my manifest file
<uses-sdk tools:overrideLibrary="androidx.core.splashscreen"/>
2- create the new Splash screen activity which uses Androidx SplashScreen API by following the migration steps from documentation.
3- create bools.xml under values folder
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="new_splash_enabled">false</bool>
<bool name="old_splash_enabled">false</bool>
</resources>
4- override bools.xml in values-vX (X is the minSdkVersion) in my case was 16 so i created values-v16 folder in the same level of values folder and create bools.xml under it like below
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="new_splash_enabled">false</bool>
<bool name="old_splash_enabled">true</bool>
</resources>
5- override bools.xml in values-vX (X is the min version you want to apply the new SplashScreen so it is any number between 21 and 31)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="new_splash_enabled">true</bool>
<bool name="old_splash_enabled">false</bool>
</resources>
6- in your manifest, i made the system decides which splash activity to launch based on values in bools.xml file
<activity
android:name=".NewSplash"
android:theme="@style/Theme.App.Starting"
android:enabled="@bool/new_splash_enabled"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".OldSplash"
android:enabled="@bool/old_splash_enabled">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
If you're using the Androidx Compat Library make sure you're using the attributes without the android tag. For example:
This will work fine
<item name="windowSplashScreenBackground">?colorPrimary</item>
This will give you a "require API 31" error
<item name="android:windowSplashScreenBackground">?colorPrimary</item>
Lazy approach: in short programmatically set theme -> done.
- Advantage: Only one activity. Basically a one liner
- Disadvantage: SDK <=21 No splash, but everyone else
Long answer, I don't like the two Activities logic. So:
Follow step 1 to 2 of @Ramy-Ibrahim's answer.
set in application block of your manifest:
android:theme="@style/Theme.App.Starting"
My launcher activity has no theme set anymore instead in onCreate():
//v6.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setTheme(R.style.Theme_App_Starting); SplashScreen.installSplashScreen(this); }else{ setTheme(R.style.AppTheme); } //mind everything BEFORE super.onCreate() super.onCreate(savedInstanceState);
Tested in Android 11(SDK30) and Android 4.4 (SDk19) and Android 12.2 (SDK32)
Unfortunately as you say SplashScreen is only available from API 21 (Android 5.0 Lollipop). You can force the implementation of the library as Wow Ot said, although it is not recommended since for Google these versions are already being deprecated.
However, in API 21-22 there is a compatibility problem in which the icon is not drawn, only the background works (See the documentation). Also the animated icon only works from API 31 (Android 12). So I recommend creating different Themes for each case:
themes
This will be the base theme from API 21 to the new themes file that we specify later.
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="android:windowBackground">@drawable/splash_scream</item>
<item name="postSplashScreenTheme">@style/Theme.App</item>
</style>
Remember that @drawable/splash_scream must be a bitmap to work, for example .png) It goes like this:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/light"/>
<item>
<bitmap android:gravity="center"
android:src="@drawable/logo_base_v21"/>
</item>
</layer-list>
themes-v23
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/light</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/logo_base</item>
<item name="windowSplashScreenAnimationDuration">1000</item>
<item name="postSplashScreenTheme">@style/Theme.App</item>
</style>
themes-v31
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="android:windowSplashScreenAnimatedIcon">@drawable/logo_base_anim</item>
<item name="android:windowSplashScreenBackground">@color/light</item>
<item name="android:windowSplashScreenAnimationDuration">1000</item>
<item name="postSplashScreenTheme">@style/Theme.App</item>
</style>
To use it in the MainActivity it would be like this:
override fun onCreate(savedInstanceState: Bundle?) {
val screenSplash = installSplashScreen()
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
screenSplash.setKeepOnScreenCondition{false}
}
What worked for me , and inspired by @Ramy Ibrahim
answer
in your manifest file before <application>
tag add
<uses-sdk tools:overrideLibrary="androidx.core.splashscreen" />
in your theme/style
<style name="ThemeStarting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/_background_color</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/icon</item>
<item name="windowSplashScreenAnimationDuration">1000</item>
<item name="postSplashScreenTheme">@style/YOUR_THEME</item>
</style>
NewSplashActivity
public class NewSplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
super.onCreate(savedInstanceState);
Intent intent = new Intent(getBaseContext(), MainActivity.class);
startActivity(intent);
finish();
}
else {
setTheme(R.style.OldSplashTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.new_spl);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(getBaseContext(), MainActivity.class);
startActivity(intent);
finish();
}
}, 1999);
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
}
© 2022 - 2025 — McMap. All rights reserved.