Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Splash screen on Android jumps down during startup #47634

Closed
Hixie opened this issue Dec 22, 2019 · 24 comments
Closed

Splash screen on Android jumps down during startup #47634

Hixie opened this issue Dec 22, 2019 · 24 comments
Assignees
Labels
a: existing-apps Integration with existing apps via the add-to-app flow a: quality A truly polished experience engine flutter/engine repository. See also e: labels. platform-android Android applications specifically
Milestone

Comments

@Hixie
Copy link
Contributor

Hixie commented Dec 22, 2019

Steps to reproduce:

  1. flutter create splash_bug
  2. cd splash_bug
  3. edit android/app/src/main/res/drawable/launch_background.xml as follows:
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <!-- You can insert your own image assets here -->                                                                                             
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher" />                                                                                                   
    </item>
</layer-list>
  1. flutter run

Expected result: Flutter logo centered on the screen and steady for a while, followed by counter app.

Actual result: Flutter logo centered on the screen, then suddenly Flutter logo centered slightly differently on the screen, then counter app.

cc @matthew-carroll and @jason-simmons since you're probably the most knowledgeable about this area...

@Hixie Hixie added platform-android Android applications specifically engine flutter/engine repository. See also e: labels. a: quality A truly polished experience a: existing-apps Integration with existing apps via the add-to-app flow labels Dec 22, 2019
@Hixie Hixie added this to the Goals milestone Dec 22, 2019
@DragonYuu
Copy link

I also encountered this problem, this problem will not occur in lower versions

@xster xster added this to To do in Add-to-app 2020Q1 via automation Jan 8, 2020
@jmagman jmagman added this to Awaiting triage in Add-to-app - Android engine review Jan 9, 2020
@matthew-carroll matthew-carroll added this to On Radar in Matt's WIP Jan 14, 2020
@matthew-carroll matthew-carroll moved this from On Radar to In progress in Matt's WIP Jan 14, 2020
@matthew-carroll matthew-carroll self-assigned this Jan 14, 2020
@matthew-carroll matthew-carroll modified the milestones: Goals, March 2020 Jan 14, 2020
@matthew-carroll
Copy link
Contributor

I was unable to reproduce on an emulator Pixel 2 API 28. The icon appears to remain in the same place (though I did see a flicker of black between the launch screen and the splash screen that shouldn't be there).

I'll try to reproduce on a physical device.

@tfalvo
Copy link

tfalvo commented Jan 14, 2020

Same problem for me. a little relieved to see that I'm not alone. ;-)

@tfalvo
Copy link

tfalvo commented Jan 14, 2020

I encountered the problem both with physical device or emulators.

By adding a drawable splash screen, the problem doesn't occur any more.
(I followed Flutter doc - Drawable splash screen :

<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" />

But I think it's not the real answer.

@matthew-carroll
Copy link
Contributor

matthew-carroll commented Jan 14, 2020

@tfalvo would you mind posting a gif or a short video of the issue happening?

I just tried to repro on a physical Pixel device on API 28 and the launch screen and splash screen matched perfectly.

@matthew-carroll
Copy link
Contributor

Actually, I take that back. Upon closely looking at a video of my repro attempt, I do think the logo is jumping slightly. I'll dig deeper into my repro case.

@matthew-carroll
Copy link
Contributor

Here is what I think is happening...

In the current "new project" structure for a Flutter app, the FlutterActivity is not configured to show a launch image, nor a "normal theme" after the launch screen, nor a Flutter splash screen.

By making the change that @Hixie posted originally, the app places an image in the "launch theme", but there is still no "normal theme". As a result, after Android gets past the launch screen, the FlutterActivity is still using the "launch theme", which places a logo in the center of the window background. So while the FlutterActivity prepares the Dart isolate and the Flutter UI, you're still looking at the "launch theme" when you really shouldn't.

Presently, if you want to use a launch screen in Flutter you are expected to:

  1. Configure the "launch theme" background as desired.
  2. Define a "normal theme" that appears immediately after the launch screen but before Flutter renders its 1st frame.
  3. (Optional, but recommended) Create an Android SplashScreen that will be displayed until Flutter renders its first frame.

Directions are here:
https://flutter.dev/docs/development/add-to-app/android/add-splash-screen

Only step 1 was taken in the case of this reported issue.

I am able to achieve the desired splash behavior by extending @Hixie's original steps as follows:

  1. As mentioned in the original post, edit android/app/src/main/res/drawable/launch_background.xml as follows:
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <!-- You can insert your own image assets here -->                                                                                             
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher" />                                                                                                   
    </item>
</layer-list>
  1. Add a normal theme to `styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             Flutter draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>

    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <item name="android:windowBackground">@android:color/white</item>
    </style>
</resources>
  1. Add meta-data to AndroidManifest.xml so that the new NormalTheme is used. Also, specify that we want to use a splash screen with meta-data, too:
<activity
            android:name=".MainActivity"
           ...>
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme"
                />
            <meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/launch_background"
                />
</activity>

So, technically, I think the issue here is incomplete configuration of splash behavior. However, this issue probably indicates that the process is too confusing, so we should do something to prevent easy mistakes.

Possible Improvements

  1. Add documentation in relevant places to point developers towards the steps they should follow.
  2. Remove the commented out launch_background reference and instead leave a comment in code that refers developers to the entire splash screen document. This should make it more difficult to follow Step 1 without following Steps 2 and 3.
  3. Refactor the "new project" structure so that it comes with a fully capable splash screen built-in. This should make it easy for developers to configure a splash screen, but it also generates work for every project that wants to opt-out of a splash screen. To eliminate the opt-out work, we could also make this a flag at project creation time.

@Hixie @xster do you have any opinions about the possible improvements above?

@matthew-carroll matthew-carroll added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jan 14, 2020
@workerbee22
Copy link

This issue seems to have been around for a few stable releases of flutter. It was present with 1.9.x also. I suspect it crept in when much of the enhancement of AddToApp was added.

@matthew-carroll I repeated your test and it works. In fact if you remove the normal theme meta data completely, leaving only the SplashScreenDrawable meta data, it also works. So this will also achieve desired behaviour:

<application
        android:name="io.flutter.app.FlutterApplication"
        android:label="flutter_launch_new"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
<!--            <meta-data-->
<!--                android:name="io.flutter.embedding.android.NormalTheme"-->
<!--                android:resource="@style/NormalTheme" />-->
            <meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/launch_background" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>

So the least effort to remove the 'jump' of a centered graphic on the launch screen is to just add this section to the AndroidManifest.xml:

<meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/launch_background" />

The new documentation on this page here is pretty good and it does correctly say this (which explains why above works without normal theme):

To display a splash screen with the same visual as a launch screen, reference the same @drawable/launch_background in the io.flutter.embedding.android.SplashScreenDrawable meta-data.

Possible Improvements

  • I agree with your point 3. The default new Flutter project still reflects the old launch screen approach and has not been updated but should be.

  • But I also think the documentation page here needs some more information. For example when we might want to use a normal theme, perhaps by providing a fully example vs when we might want to just see the launch screen right up to Flutter first frame. Some animated gifs or short videos here would help.

@workerbee22
Copy link

Note previously in the AndoidManifest.xml I was using this meta data section:

<meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />

But with this section there is still a 'jump' of a centered logo image.

@tfalvo
Copy link

tfalvo commented Jan 15, 2020

In fact I was trying to make a smooth transition between a static android launch screen image and a Flutter + Rive (Flare) animation (SplashScreen) which starts with the same image (as launch screen)... not sure I'm clear. ;-).

But if must add io.flutter.embedding.android.SplashScreenDrawable to avoid image jumping, there is a drawback : a fade out to white screen before my animation appears.
But I probably missed something...

@Hixie
Copy link
Contributor Author

Hixie commented Jan 16, 2020

@matthew-carroll That page is on the "add-to-app" part of the Web site; should it be moved to the Android section in general?

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jan 16, 2020
@workerbee22
Copy link

After experimenting I can cause the skip on demand. This is one cause, but it may not be the only cause of the 'jump'. So add to your theme the line android:windowDisablePreview to true:

    <style name="LaunchTheme" parent="Theme.MaterialComponents.DayNight">
        <item name="android:windowDisablePreview">true</item>
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>

@blasten blasten moved this from To do to In progress in Add-to-app 2020Q1 Jan 16, 2020
@matthew-carroll matthew-carroll moved this from Awaiting triage to Engineer reviewed in Add-to-app - Android engine review Jan 17, 2020
@matthew-carroll
Copy link
Contributor

@tfalvo I think what you want is a custom SplashScreen implementation that leaves your UI in the desired visual state when switching to your Rive animation. Please see this guide:
https://flutter.dev/docs/development/add-to-app/android/add-splash-screen#creating-a-custom-splashscreen

The standard SplashScreenDrawable implementation is provided as an out-of-the-box option for developers who are happy with the simplest solution.

@matthew-carroll
Copy link
Contributor

matthew-carroll commented Jan 18, 2020

@workerbee22 do you think it's a good idea to use windowDisablePreview? The docs state the following:

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.

Edit: I tried using windowDisablePreview, anyway, and it works fine for me. Are you sure that you followed all 3 steps in the splash screen instructions?

@workerbee22
Copy link

@matthew-carroll disabling the window preview is not great, because there is a slight but noticeable longer startup time before you see the Launch screen. But it is 'less' noticeable than a 'jump' of a logo in the center of the screen.

I can't find any other solutions to remove the 'jump' at the moment, so disableWindowPreview set to true is my best workaround at the moment. But I'll re-check the splash screen instructions in my simplified template project.

Note I'm still also having problems seeing a black blank screen in some projects as well, despite having a NormalTheme. But this may be because I am using the Android Material Components DayNight as the parent Theme for both launch and normal themes which is currently still 1.2.0-alpha03. So I have this line for both themes:

<style name="LaunchTheme" parent="Theme.MaterialComponents.DayNight">

https://github.com/material-components/material-components-android

Reason I'm using using this theme as the parent, is because on Android 10 it adapts to the current devices background color being light or dark themed. I don't think there is any other Android theme that current does this?

@matthew-carroll
Copy link
Contributor

@workerbee22 can you post a minimal project that causes the jump?

@workerbee22
Copy link

workerbee22 commented Jan 18, 2020

@matthew-carroll Ok I have a minimal project here that shows the jump of the flutter logo when running on a Pixel 3 Xl physical device. See zip file in here: https://drive.google.com/open?id=1fkpDPq7ckU6f2KygxmUcrK_Ud_haZgyi

As per the documentation here: https://flutter.dev/docs/development/add-to-app/android/add-splash-screen#showing-a-drawable-splash-screen

Which says:

To display a splash screen with the same visual as a launch screen, reference the same @drawable/launch_background in the io.flutter.embedding.android.SplashScreenDrawable meta-data.

So you will see in this project both the LaunchTheme and the Flutter SplashScreenDrawable use the same @drawable/launch_background

Interestingly if you use the <item name="android:windowDisablePreview">true</item> then the sample project is fine and there is NO jump.

@matthew-carroll matthew-carroll moved this from In progress to In Review in Matt's WIP Jan 21, 2020
@matthew-carroll
Copy link
Contributor

@workerbee22 thanks for sending that example, I was able to repro what you described.

In your case, what you'll want to add to your launch theme is:

<item name="android:windowDrawsSystemBarBackgrounds">false</item>

The above configuration causes the window to display content beneath the status bar, instead of stopping at the status bar. By flowing content beneath the status bar, the screen becomes slightly taller, which impacts the alignment of a "centered" splash image.

FlutterActivity automatically sets

window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

in code because Flutter wants to draw all of the screen's content, including the part beneath the status bar.

That's why your splash image appears slightly lower in your launch theme than it does once FlutterActivity takes over.

The issue you experienced in a specific case of a more general situation where developers will need to ensure that their launch theme is congruent with their splash View, so I won't consider this case to be a bug with the embedding.

@workerbee22
Copy link

workerbee22 commented Jan 21, 2020

@matthew-carroll Thanks that explains it 👍 And I've now re-tested and that does indeed fix it, thank you 🎉

So just for anyone else, this is what I did:

1 - That is remove this line:

<item name="android:windowDisablePreview">true</item>

2 - and replace it with this line for just the LaunchTheme:

<item name="android:windowDrawsSystemBarBackgrounds">false</item>

Also yep isn't a bug but probably a common use case, so perhaps consider adding to documentation somewhere because as Flutter Devs we can't easily know what the framework has and has not set by default. So this section of the new splash screen Flutter.dev page, last paragraph? https://flutter.dev/docs/development/ui/splash-screen/android-splash-screen#showing-a-drawable-splash-screen

This goes for a few of these android settings in styles, layouts etc. we have to find the Android info and then try them out to see behaviour, because we don't know what the Flutter framework is doing exactly at its interface with Android. Sure we can dive into the framework code, but that would take quite a bit of digging.

So same also probably applies to iOS or any platform ie. how do we know what Flutter is doing by default at this interface to the operating system.👍

@matthew-carroll
Copy link
Contributor

To handle this ticket I have done the following:

  1. Moved splash screen documentation to a higher level in the website guides:

flutter/website#3556

  1. Changed the default Android project structure to opt-in to splash screen behavior:

#49096

  1. Filed a ticket to consider adding more info about expected theme styles WRT to splash screens:

https://github.com/flutter/flutter/issues/49267

With these changes I'm going to close this issue.

@knaeckeKami
Copy link
Contributor

This gets rid of the jump, but the drawback is, that the status bar color is black for a few frames, right? or is there a war to avoid that?

See behaviour with <item name="android:windowDrawsSystemBarBackgrounds">false</item>: https://streamable.com/noyy5

and with <item name="android:windowDrawsSystemBarBackgrounds">true</item>:, the jump:
https://streamable.com/bmj31

@hectorAguero
Copy link

I know this issue is closed but with the current documentation and framework behaviour there are some problems that doesn't happens in native.

  1. If you use <item name="android:windowDrawsSystemBarBackgrounds">false</item>: you can't use dark icons and light statusbar in LaunchTheme splash screen.
    <item name="android:windowLightStatusBar">true</item>
  2. In v2 Embedding NormalTheme' SplashScreen you cant use lightStatusBar and Dark Icons, even if are you using other themes like material or material components.
    <item name="android:windowLightStatusBar">true</item>
  3. Documentation and default projects use @android:style/Theme.Black.NoTitleBar and that show the animation that @knaeckeKami comment, the workaround is use android:Theme.Material.NoActionBar but LaunchTheme needs
    <item name="android:windowDisablePreview">true</item>
    PS: You don't need to import material-components in build.gradle to use this.
  4. Default projects set the NormalTheme with white background, instead of set the same @drawable/launch_background, I think this is better for a default behaviour, even that the documentation that user other drawable element.
  5. Splash Screen Documentation need to say something about v2 embedding, for example: Check if you are using v2 Embedding

@chornbe
Copy link

chornbe commented Mar 19, 2020

FWIW, I'm getting this on iOS too in flutter 1.16.1-pre.20, dart 2.8.0, where it did not do it on previous versions (though I honestly can't remember how far back this started).

@lock
Copy link

lock bot commented Apr 2, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@lock lock bot locked and limited conversation to collaborators Apr 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: existing-apps Integration with existing apps via the add-to-app flow a: quality A truly polished experience engine flutter/engine repository. See also e: labels. platform-android Android applications specifically
Projects
Development

No branches or pull requests

8 participants