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)
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);
}
}
}
Related
We are currently implementing a splashscreen via the new Splashscreen API. We are following the migration guide. The background color is set correctly (by windowSplashScreenBackground), but the icon is not visible, neither on an Emulator, nor on a physical device.
build.gradle
android {
compileSdkVersion 31
...
}
dependencies {
implementation "androidx.core:core-splashscreen:1.0.0-alpha01"
...
}
values-v31/themes.xml
<style name="AppTheme" parent="Theme.SplashScreen">
<item name="postSplashScreenTheme">#style/AppThemeCompat</item>
<item name="windowSplashScreenBackground">#android:color/black</item>
<item name="windowSplashScreenAnimatedIcon">#mipmap/ic_launcher</item>
<item name="windowSplashScreenAnimationDuration">200</item>
</style>
AndroidManifest.xml
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
...
</application>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen()
...
}
I am answering this question directly as we found the solution to our problem within one or two hours that could be saved from other developers:
Icons set by the Splashscreen API do not work when starting an app from Android Studio. If the app gets closed and then restarted, the icon shows correctly.
This bug might exist due to the early alpha status of this library and will allegedly be fixed in a future version of the Splashscreen API.
This question already has answers here:
Android - Prevent white screen at startup
(18 answers)
Closed 4 years ago.
I created a splash screen for my application using an empty activity that stays visible for 3 seconds with a background image.
Usually, the application starts with a white screen before the background image becomes visible, however, some applications are already started with the "real" splash screen image.
How to implement this?
you can use splash screen in this way.
Add style for splash screen activity in styles.xml
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#drawable/yourImageName</item>
</style>
Add that style as theme to your SplashScreenActivity in manifest file
<activity android:name=".SplashScreenActivity"
android:theme="#style/SplashTheme"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Remove setContentView() in SplashScreenActivity's onCreate() Method and use it as a java file which extends AppCompactActivity
The problem is because system process draws initial blank screen when launching the app, from documentation:
A common way to implement a themed launch screen is to use the windowDisablePreview theme attribute to turn off the initial blank
screen that the system process draws when launching the app. However,
this approach can result in a longer startup time than apps that don’t
suppress the preview window. Also, it forces the user to wait with no
feedback while the activity launches, making them wonder if the app is
functioning properly.
You can disable it with windowDisablePreview attribute, something like this:
<application
...
android:windowDisablePreview="true">
...
</application>
Splash Activity usually starts with the background.
Try this code, it might help you.
Code for your splash activity page.
public class SplashScreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
Thread myThread = new Thread(){
#Override
public void run() {
try {
sleep(3000);
Intent intent = new Intent(getApplicationContext(),MainActivity.class);
startActivity(intent);
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
myThread.start();
}}
In layout file, you need to include just Image which you want to see on the splash page.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_splash_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/capture"
/>
</RelativeLayout>
And make sure you add the Splashscreen page before Main activity in Manifest.
<activity android:name=".SplashScreen">
I'm having some issues returning from Immersive Mode in an ActionBarActivity. I have created a simple app to illustrate this issue. There is a layout with a single button to toggle immersive mode. When "returning" from immersive mode, the action bar is offset downwards from its original position, roughly the same distance again that it is usually offset from the top of the screen.
I've tried this on a Nexus 4 running Lollipop. This behavior did not happen pre-Lollipop.
Screenshots before, immersed, after.
A simple ActionBarActivity that illustrates this issue:
public class MainActivity extends ActionBarActivity {
private boolean immersed;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#TargetApi(Build.VERSION_CODES.KITKAT)
private void enterImmersiveMode() {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
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
);
immersed = true;
}
}
#TargetApi(Build.VERSION_CODES.KITKAT)
private void leaveImmersiveMode() {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
immersed = false;
// recreate();
}
}
public void toggleImmersive(View v) {
if (immersed) {
leaveImmersiveMode();
} else {
enterImmersiveMode();
}
}
}
Nothing fancy in the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.immersivetest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="ImmersiveTest"
android:theme="#style/Theme.AppCompat" >
<activity
android:name=".MainActivity"
android:label="ImmersiveTest" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Trivial layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.immersivetest.MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="toggle immersive"
android:onClick="toggleImmersive"
/>
</RelativeLayout>
The workaround I use at the moment is to call recreate() after leaving immersive mode, but it looks a bit "glitchy".
If I up the minSdkVersion and use Activity instead of ActionBarActivity, i.e. don't use the support library, then I do not experience this behavior.
I understand that immersive mode is only available in KitKat+ and that I don't need to use the ActionBarActivity from the support library, but the finished product will have to run on API versions 8+ and the immersive mode is an optional extra.
Some other workarounds I have thought about and dismissed for now:
Have a wrapper launcher Activity which immediately forwards programmatically to an ActionBarActivity for lower API versions.
Have multiple apps by API version.
Either of those options sounds like a lot of added maintenance.
Is there anything else I could try? Are there any glaring mistakes in the code above, with respect to returning from immersive mode?
Update
I have since updated the Nexus 4 to 5.1 and the support library to rev 22.1.1 and the behavior is still the same. I have also updated the code to use the new AppCompatActivity since ActionBarActivity is now deprecated. The behavior is, once more, the same.
public class MainActivity extends AppCompatActivity {
// no changes here
}
Update
This weird behavior also extends to the landscape mode. In addition to the offset at the top of the screen, there also is an offset to the right of the screen between the end of the action bar and the navigation buttons. Interestingly this offset again seems to be the size of the navigation button "bar", i.e. larger than the offset at the top.
Landscape screenshots before, immersed, after.
Had the same problem, fixed with this:
your leaveImmersiveMode() function should use these flags instead:
getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN);
Use a Toolbar ... I had the same problem and switching to a Toolbar instead of a customContentView solved it.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
And set your Activity's theme to #style/Theme.AppCompat.NoActionBar
Notwithstanding the fact that ActionBarActivity was deprecated in the support library from V26, changing your leaveImmersiveMode() method to specify the following flags fixes the problem for me with the test app using your code (which originally showed the extra gap you mentioned).
#TargetApi(Build.VERSION_CODES.KITKAT)
private void leaveImmersiveMode() {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
immersed = false;
// recreate();
}
}
These are the flags recommended in the Android documentation on immersive mode.
iam following the basic beginner Tutorial on the Android Developer Site. Now, i there is described how to bring the app icon as the Up Button (see last text): http://developer.android.com/training/basics/actionbar/adding-buttons.html#UpNav
I put "getSupportActionBar().setDisplayHomeAsUpEnabled(true);" in my activitys onCreate() Methods, but on my Device my App has no App Icon as the Button. Here are my activities
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
and
public class DisplayMessageActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Get the message from the intent
Intent intent = this.getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
// Create the text view
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
// Set the text view as the activity layout
setContentView(textView);
}
And also my Manifest
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DisplayMessageActivity"
android:label="#string/title_activity_display_message"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.andreas.myapplication.MainActivity" />
</activity>
</application>
And Gradle Infos
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.andreas.myapplication"
minSdkVersion 8
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
iam confused because im alredy use the right method for minSdkVersion 8.
Does anyone know, why ma App does not show the Icon as Up-Button?
best Regards
I have encountered the same problem - enabling "display home as up" led to the Up button with an arrow image on it. I have managed to replace arrow with an app icon with the following steps:
Create a new ImageAsset with app icon images in /drawable.
In OnCreate() of child activity, add 2 lines:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_home);
Substitute meta-data value android:value="com.example.andreas.myapplication.MainActivity" for android:value=".MainActivity"
To support older devices with the support library, also include a element that specifies the parent activity as the value for android.support.PARENT_ACTIVITY as shown below:
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
A full explanation is here: http://programmerguru.com/android-tutorial/how-to-add-up-button-on-action-bar/
I believe you need to call getSupportActionBar().setDisplayHomeAsUpEnabled(true); after calling setContentView(textView); in the second activity.
EDIT:
also, main activity should not call getSupportActionBar().setDisplayHomeAsUpEnabled(true); as it leads nowhere. And you should add a button to switch activities or you will never get to DisplayMessageActivity. try something like this:
Intent showmessg = new Intent(getApplicationContext(), DisplayMessageActivity.class);
startActivity(showmessg);
Hope it works for you.
source: http://developer.android.com/training/basics/actionbar/adding-buttons.html#UpNav
I think in android 5 and API 21 we can't use app icon for up action.
if your appcompat support library is v7 rev21 i think you can't use the app icon at least for up action. but u can use it instead of top left caret or you can use app icon right of that caret although if u click it nothing happen.
I have two app completely like that trainings in one of them i use the older appcompat v7 and minSdkVersion="11" and i never added getSupportActionBar().setDisplayHomeAsUpEnabled(true); to it but app have app icon and no problem . but in another app i update my support library a few day ago to rev21 and of course this app's minSdkVersion is "8" but this app hasn't actionBar icon for Up action and if you add top code to it you do nothing.
I search many of sites and just i understand is that in material design google removed app icon for up action because of increasing space on actionbar and etc.
You can see this line in this page.
"When using the Material themes (default in API 21 or newer) the
navigation button (formerly "Home") takes over the space previously
occupied by the application icon. Apps wishing to express a stronger
branding should use their brand colors heavily in the action bar and
other application chrome or use a in place of their standard title
text."
I've got an application written with minSdkVersion="8" and targetSdkVersion="19", because is so simple and I need it to be used on low level android devices.
The problem is when I try to use it in an Android 4+ device. I cannot see the Options menu.
When I use the app in the Emulator, I use the "Menu" button, and I can see it. But not in my tablet or mobile phone (both with 4+ version).
Okay, let's see the code:
In the manifest.xml file I have this (I think the problem is the theme...).
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo.Light" >
<activity
android:name="com.clv.app2.MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme">
And I have a simple OnCreateOptionsMenu like this in MainActivity... (I have defined only two options).
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.option_menu, menu);
return true;
}
Can anyone can help me to see where is the problem with this?
Thank you in advance.
EDIT:
option_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/scan"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/connect"/>
<item
android:id="#+id/discoverable"
android:icon="#android:drawable/ic_menu_mylocation"
android:title="#string/discoverable"/>
EDIT:
Okay. I have been reading other entries in forum, and I see that there are devices that have not a menu key (to show options menu), and from 3+ version it is not required to have it.
When I execute my application in an Android device less than 3 version, I have that physical button, and it works. In an Android device more than 3 version (I have one with 4+ version), that button does not exists, and there are no way to make the options menu visible.
My question is... Do I have to put a button in screen on 3+ devices with no "physical menu button", to use it when I want to see the options menu???
I have found the problem that make the application not work on 4+ devices.
In the onCreate method I have in my MainActivity, I have this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "En onCreate...");
// Preparo texto cabecera de pantalla
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.main);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.custom_title);
If I take all that code out, leaving only setContentView it works.
It think the issue is in your activity schema.
First change schema in AndroidManifest to yours:
<activity
android:name="com.clv.app2.MainActivity"
android:label="#string/app_name"
android:theme="#style/MyTheme">
Create styles_mytheme.xml in values folder with lines:
<resources>
<style name="Theme.MyTheme" parent="#android:style/Theme"/>
</resources>
Or just add next line to any styles files:
<style name="Theme.MyTheme" parent="#android:style/Theme"/>
Create folder values-v11 and create file there styles_mytheme.xml:
<resources>
<style name="Theme.MyTheme" parent="#android:style/Theme.Holo"/>
</resources>
So basically your Activity will use default theme for old devices and Holo for devices from v11.
I think its not a problem of theme, but while creating your project just make changes like:
Minimum Required SDK: API8: Android 2.2(Froyo)
Target SDK: API17:Android 4.2(Jelly Bean)
Compile With: API8: Android 2.2(Froyo)
Theme: None
Hope it will work.