dotnet / android

.NET for Android provides open-source bindings of the Android SDK for use with .NET managed languages such as C#
MIT License
1.92k stars 525 forks source link

Splash screen that works in both Xamarin Android 12 and lower #7239

Closed developer9969 closed 2 years ago

developer9969 commented 2 years ago

Android application type

Classic Xamarin.Android (MonoAndroid12.0, etc.)

Affected platform version

VS 2022 17.2.2

Description

Hi I have few xamarin forms applications and users will range between Ver 9 to 12 of android. Despite many posts scattered on the internet , it is still not clear what you have to do to make sure that the splash screen works both in Android <12 and Android >=12

I have looked at this close issue https://github.com/xamarin/xamarin-android/issues/6517 but still not clear what people/solution is the right one.

I have created a value-31 folder and stuck a style in there but still does not work.

    <style name="Theme.Splash" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/splash_background</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/...</item>
    <item name="windowSplashScreenAnimationDuration">200</item>
    <item name="postSplashScreenTheme">@style/MainTheme</item>
</style>

I get all sorts of errors displaying in visual studio

What is the solution to have a xamarin android project that can display a splash screen in different version of android?

Any suggestions?

Steps to Reproduce

Add a value-31 folder with a splash screen style to an existing xamarin android project and I get many errors like image

Did you find any workaround?

No response

Relevant log output

No response

gmck commented 2 years ago

@developer9969 Take a look at https://github.com/gmck/NavigationGraph5. It uses the standard Xamarin Application Icon and the splash screen has been tested on Android versions 7.0 through 12. All you need to do is replace the Xamarin icons with your own. See the word doc in the project.

developer9969 commented 2 years ago

@gmck hi thanks for your reply - I am a bit confused and hopefully you or someone can clarify the following:

  1. Emulator Android 12 Run your https://github.com/gmck/NavigationGraph5 you get a blank screen.
  2. Emulator Android 11 Run your https://github.com/gmck/NavigationGraph5 you see the xamarin icon.

Run the built app on the emulator and you see the xamarin icon on android 12

What Am I missing?

Also I am now getting when adding just C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1489,3): error MSB6006: "java.exe" exited with code 1.

Many thanks

gmck commented 2 years ago

@developer9969 All my apps use Bluetooth and since emulators don't handle Bluetooth I always deploy to real devices. If you look at the end of the doc file you'll see all the devices I've successfully deployed and tested NavigationGraph5 on.

I just now created the default emulator pixel5-_api_32:5554 (Android 12.1 Api 32) and the Xamarin icon showed up just fine. I'm building it with VS 2022 17.3.0 Preview 6.

I've also reverted to VS 2022 17.2.2 and it is fine on that as well when I build/deploy to the same emulator.

What Am I missing? I'm not sure what you mean when you say in point 1 "run your ... " you get a blank screen as compared to the comment under point 2 - Run the built app on the emulator and you see the Xamarin icon on android 12. Can you expand on that because those statements seem to contradict each other - or I'm just misunderstanding what you've written?

Also in the email, I received which has additional info compared to here, you mention Xamarin.Forms 5.0.0.2337 etc. I can't help you with any questions re Xamarin.Forms as I've never done any work with forms, so someone with forms experience would have to answer those extra questions. The one thing I did notice in your error message is the Package Xamarin.Android.Core.SplashScreen 1.0.0. NavigationProject5 is using Xamarin.AndroidX.Core.SplashScreen 1.0.0.1-rc01, which is a pre-release version. I'm not aware that a full release version is available. I know Google has released it, but I think we are still waiting for Xamarin to release their version.

Also I am now getting when adding just C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1489,3): error MSB6006: "java.exe" exited with code 1.

Seems to be something missing here - also this is not in the email I received. Looks like you edited your message and some stuff made it and other stuff was deleted.

developer9969 commented 2 years ago

@gmck thanks for your extensive answer . Yes I edited the reply because I did not want to confuse things..

I really appreciate your input/help on this. Let me run few tests on my side and see if I can make it work.

developer9969 commented 2 years ago

@gmck I have now tested your NavigationGraph5 on physical device Samsung A21s Android 12 installed and when launching the app in debug/Release you cannot see the icon in the splash screen.

But again when launching the installed app than it works.

Does it work in debug for you?

gmck commented 2 years ago

@developer9969 I don't think I've ever bothered checking while debugging. I just checked now and you are correct it doesn't show the icon while debugging.

I don't know the exact explanation for that because until now I wasn't aware that was the behavior. However, I suspect start-up is way different on a debug build as compared to a release build and who gives a stuff about a splash screen when you are debugging?

Don't forget that even with a release build you won't see the icon on a warm start. It will only be visible when you do a cold start.

You can test that by launching the app, after killing the app by flicking it out of most recents. It should then do a cold start and you should see the icon. Now just exit the app and then relaunch it and since it is still in memory you won't see the icon as that is a warm start.

At the moment I'm testing on a Samsung Galaxy Tab S7 tablet which is a real kick-ass device. I barely see the icon on this device even on a cold start. My Pixel 6 is much slower and therefore I get a good look at the icon before the MainActivty is shown.

Don't forget NavigationGraph5 is a very small app, so you expect it to load quickly and it is optimized to load quickly, Basically, the measure is the display time. Look for "displayed com.companyname.navigationgraph5" or even just "Displayed" in logcat. You'll find it will display the time taken in millisecs. This S7 gives me +94ms. That is really fast... So the icon doesn't hang around too long on this thing. The Pixel 6 is +281ms, so I get a pretty good look at it.

If you really want to slow things down to check the icon - uncomment the line System.Threading.Thread.Sleep(500) line in OnCreate. Change that value to whatever you want.

developer9969 commented 2 years ago

@gmck thank you so much for taking the time to reply. Let me see how you did in details . I have a splash activity which is no longer required I believe, hopefully I will manage it too.. What a pain!!!!

developer9969 commented 2 years ago

Hi Can anyone see why my noddy attached project does not show the icon in the splash screen in either android 11 or 12? I have spent all day on it- reading -etc.. I cannot spot what I am doing wrong?

Many thanks for your time!

XamAndroid12.zip

gmck commented 2 years ago

@developer9969 I had a look at your XamAndroid12. The splash screen is working on my Android 12 devices, but no splash screen on any devices running less than Android12.

As I said earlier I know very little about Forms as I've never written a Forms app so I may be barking up the wrong tree. However, the first thing I noticed was that your colorPrimary and colorPrimaryDark colors were being ignored, then I noticed Theme.App.Base has a parent MainTheme.Base. However, I can't find any MainTheme.Base anywhere in your that project.

An Android12 device will automatically show a splash screen, so in effect your splashscreen theme is not working, the proof being that it doesn't display on devices less than 12.

My suggestion would be get the splash screen working correctly first on a simple Xamarin.Android app using the template Blank App which only has a simple MainActivity. Strip the app of unnecessary stuff such as Xamarin.Essentials, update the appCompat and android.material nugets to 1.4.2.1 and 1.6.1.1 respectively. Build and deploy in release mode to an Android 12 device and you should see a splash screen with the Xamarin icon. Do the same with devices lower than Android 12 and this time you wont see the Xamarin icon.

Now you are ready to added the code for the splash screen code above the base.OnCreate of the MainActivity. Notice that the AppTheme parent in styles.xml is parent=Theme.MaterialComponents.Light.DarkActionBar. The only difference then between NavigationGraph5 is that its theme's parent is Theme.MaterialComponents.DayNight.DarkActionBar because I'm preparing the NavigationGraph projects to support light and dark themes. Light and dark themes aren't important for this simple test app, so you can stick with the default.

You should now be able to copy from NavigationGraph5 all the splashscreen stuff. Build and deploy and ensure it works on all Android versions that you want to support. I think it goes down to API 21, but you should check the google docs for that.

If that is successful, you will then need to work it back into a forms app using your icons. If you still have problems let me know.

One last tip always check the obj\Release\120\android or \debug\ folder for the generated androidmanifest.xml to confirm that the correct application apptheme style name is what you expect it should be.

PS To answer your earlier question - Yes you do need to get rid of the excluded SplashActivity.cs

developer9969 commented 2 years ago

@gmck based on your example I think I have built something that works in both Android 12 and lower. If you do get a chance have a look , I have taken your advice and just stripped it to barebone.

Now have the requirements changed in terms of size of the icon in android 12?

Some of the icons I used to have for splash screens for android 11 or lower show all cut in android 12!.

Anyway if someone can confirm that this works we have a noddier example of how to implement splash screen in android 12.

Huge thanks for your replies .

SimpleSplash.zip

gmck commented 2 years ago

@developer9969 The problem with your toolbar is that you changed the App.Theme. The original would have been Theme = @style/AppTheme.NoActionBar in the MainActivity. The exception you get tells you what is wrong. When using the Splash API we are now setting the AppTheme via @style/AppTheme. So effectively as you have it, you have 2 AppThemes. So move the two lines of the original into the new AppTheme, so that you can use SetSupportActionBar and then delete the original AppTheme and uncomment your toolbar stuff. Perhaps before you do that, debug it and step into SetSupportActionBar(toolbar). Once you read the exception I reckon you'll then understand your mistake.

Parent theme for SplashScreen should be Theme.SplashScreen.IconBackground

I mentioned yesterday it is always important to check your androidmanifest.xml. Best to check the generated one in the obj folder, but at least first check the one in the Properties folder. Another good tip is to use com.companyname.appname as your default namespace, which means you need to modify the generated Resource.Designer.cs in two places at the top of the file - namespace and the attribute assembly: global. Just make sure you clean the project before you build, then of course change the main activity's namespace.

Some of the icons I used to have for splash screens for android 11 or lower show all cut in android 12!.

Yes, I agree your splash icon looks awful on all devices. What do you mean by some of the icons etc, do you mean the icon from your forms app which I downloaded yesterday or the Xamarin icons? Have you read that doc file re generating new icons using Android Studio?

Yesterday I did a quick build based on the blank app template and the Xamarin icon looks normal on its splash screen. If you want that to do a comparison I can zip it up. I'm a bit pushed for time today to check why the icon looks so bad.

Now have the requirements changed in terms of size of the icon in android 12?

No, the size requirements haven't changed. What has changed is the ability to animate the icon - if you want such a feature!! If you do then you need change the icon, like you saw in the other thread that you mentioned https://github.com/xamarin/xamarin-android/issues/6517 e.g. @jeduseei's vector drawable icon.

The NavigationGraph3 contains that implementation of the Xamarin Icon.

gmck commented 2 years ago

@developer9969

I've just got back to it.

I found the reason why your Xamarin icon looked so bad. You screwed up with your copy/paste of the Splash Theme. You had the wrong value for windowSplashScreenAnimatedIcon. I can't believe I didn't notice that earlier this morning!! Maybe 4am was a bit too early. Don't forget to change it in both values and values-31 styles. Values-31 is not really required, I'm just assuming it will be when/if the Splash API changes in the future with Android 13+ etc.

<style name="Theme.SimpleSplash.Starting" parent="Theme.SplashScreen.IconBackground">

        <!--<item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>-->
        <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher_foreground</item>
        <item name="windowSplashScreenIconBackgroundColor">@color/ic_launcher_background</item>
        <item name="windowSplashScreenBackground">?android:colorBackground</item>
        <item name="postSplashScreenTheme">@style/AppTheme</item>
</style>
developer9969 commented 2 years ago

@gmck Hi With your help I am getting there... and the IconBackground fixed the issue.

However I think something is missing because all the apps I have the splash screen no longer displays they are all cut. Let me explain

In Android 10-11 etc.. I would built the splash screen using thes

  1. image

  2. I would have a splash activity
  3. and in the style I would have something like `

      <style name="MainTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">          
      <item name="android:windowBackground">@drawable/splash_screen</item>
      <item name="android:windowNoTitle">true</item>
      <item name="android:windowFullscreen">true</item>
      <item name="android:windowContentOverlay">@null</item>
      <item name="android:windowActionBar">true</item>
    </style>

    ` Given the above and icon like this one below for example would just display properly - now it now longer does. image

Is it because we were using "layer-list"??

            <?xml version="1.0" encoding="utf-8" ?>
            <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
              <item android:drawable="@color/launcher_background"/>
              <item>
                <bitmap android:gravity="center"
                        android:src="@drawable/icon" />
              </item>
            </layer-list>

Below is an xamarin forms blank template ( using splash and the icon - same icon when copied and pasted in the android 12 no longer shows properly and this applies to all the apps I have, obviously different splash screens..

you can totally ignore any stuff in forms as does not matter.

PrismSplashScreen.zip

I did try to add the layer list but no luck! see attached below ..

SimpleSplash.zip

Am I missing something here ?

gmck commented 2 years ago

@developer9969

... and the IconBackground fixed the issue.

No, it didn't. I'd already corrected that. What fixed it was using the correct icon. I was staring at it and not seeing it.

<item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher_foreground</item>

That is why I left your line in there and commented it out.

I also used the layer-list technique for years as my splash screen and it still worked when I moved to Android 12. I remember posting something here and stating that it still worked. At the time though I'm not sure if I tested on devices less than 12.

However, to get the effect that you want i.e. to use the rectangular Prism icon you would need to consider also adding windowSplashScreenBrandingImage in conjunction with your splash screen icon.

A while back I found a tutorial on raywenderlich.com that did cover windowSplashScreenBrandingImage that you could check out https://www.raywenderlich.com/32555180-splash-screen-tutorial-for-android but personally, I'm not interested because what I'm always looking for is the fastest possible startup time i.e. the "Displayed" time I mentioned earlier. The layer-list technique didn't affect start-up time and neither does the Splash API necessarily. That is one of the reasons why I've never used forms - some of the Xamarin forms samples were taking second(s) to start. Maybe that's ok for an enterprise app, where the user doesn't have a choice of what app they use, but not ok for what I want.

I've just hit a problem myself after upgrading Navigation.Fragment and Navigation.Ui and now I've got a heap of warnings because Google has deprecated OnCreateOptionsMenu, OnOptionsItemSelected and OnPrepareOptionsMenu 85 warnings - wow that is terrific news Google. Why do they do this stuff??? I guess we won't be releasing this app right now.. This shit just never ends. It gets worse, I think the next release of AppCompat will also cop it.

developer9969 commented 2 years ago

@gmck Hi I have looked at those tutorials that you mentioned, and at the windowSplashScreenBrandingImage

however the point I am making is that what was working before as a splash image using the layer- list technique does not work now. The prism rectangular image is just an example and that loads fine in android 11(see sample I loaded earlier) but for android 12 it doesnt - it gets cut out without the need of a Branding Image , so something has changed there .

We are building enterprise apps and the start app for forms in android is terrible but with MAUI got better.

Back to the point - what worked before as image on the splash screen - no longer works in android 12 . I could be totally wrong here but there is hardly any example out there and an input from one of the Xamarin team would be good on the subject, but hey... we are where we are.

gmck commented 2 years ago

@developer9969 Back to the point - what worked before as image on the splash screen - no longer works in android 12

The reason the old layer-list stuff worked prior to Android 12 was that Android didn't provide anything to prevent it. At start up you just got a blank screen until your activity_main was rendered. However, with Android 12 if you don't supply anything you automatically get a splash screen being your app icon. So if you are only supporting Android 12 and up you are done, nothing to do you get a splash screen by default.

But obviously, that doesn't help for prior versions. So they introduced the Splashscreen API really so that prior versions could have a similar uniform experience. I think it's pretty reasonable to assume then if Android is now taking over the startup of your app, that whatever we developers came up with as a splash screen was no longer going to work, so I'm sort of surprised that you would still expect the old layer-list stuff to still work.

I'd really suggest that you read that article again, read on from the heading Adding the Adaptive Icon. By the time you get to the next heading Adding More Customization you are done if you don't want any further customization. You literally cut and paste her code from that article, which is what I did in NavigationGraph5. You've now got a splash screen for all versions of Android from 13 and up down to 21. Not sure about 21, but who cares anyway? I'm pretty sure your enterprise users wouldn't be using devices as old as that.

The previous thread #6517 got all hung up on using a vector drawable for the icon and that guy who was trying to use the framework api, rather than androidx.core:core-splashscreen and couldn't see "the wood from the trees" - a bit like me yesterday morning.

Strictly speaking, the addition of the values-31 folder is not even necessary. Also, note the parent theme is only Theme.SplashScreen not Theme.SplashScreen.IconBackground which is only required if you want the icon to have a backgroundColor.

<item name="windowSplashScreenIconBackgroundColor">@color/yellow6</item>

From what I've read you can only use windowSplashScreenBrandingImage on Android 12+. She puts her branding stuff (layer-list) in values-31. The following is another link to an article that may help and it also uses a layer-list https://itnext.io/a-comprehensive-guide-to-android-12s-splash-screen-api-644609c811fa

Let me know if it helps.

developer9969 commented 2 years ago

@gmck Thanks to your help I now have a clear picture of what's going .

I'm sort of surprised that you would still expect the old layer-list stuff to still work.

As a developer does not surprise me at all and I will adapt but wearing a manager's hat I have to explain to all the clients that

  1. Apps in the wild their splashscreen will no longer display their belowed "artwork" on android 12 - and they will see just the app's icon.
  2. They have to redo it so that it conforms to the new google splashscreen api, and might be some what limited to what they used to have and we have to redeploy the app.

It has been a great learning experience and I definetely know more now that I used to ,(I didnt need to).

Personally I think the new api is somewhat limited if what you can do, may be that is the intention!!

Hey - thank you so much for the help on this thread

gmck commented 2 years ago

@developer9969

Apps in the wild their splashscreen will no longer display their belowed "artwork" on android 12

I'm not following why with Android 12 can't you use windowSplashScreenBrandingImage for that Prism Library icon if you convert it from png as that guy did in the link above.

developer9969 commented 2 years ago

@gmck I think if I summarize here it will help me to finalize what I have to say to my manager about this splash screen api and once again correct me if I am wrong

Android12 Do nothing and your icon will display - your old fancy splash screen is gone

Android 9-10-11-12 if you implement the new api - I have not found a way to do if(9 to 11) display as before if 12 then use splash screen api . If there is that is what I am after for now. But being a forms dev (mainly c#) i have not mucked around all the permutations you can do in native android.

Guidelines in short

  1. You can have an image in the middle as per size requirements of google.
  2. you can have a branding image at the bottom using windowSplashScreenBrandingImage
  3. Your old splash image will not work and will be cut off.

Real world clients

All these clients in the real world have created their own splash image, and many have an image with some text that will not longer fit anymore or be legible. Is not a case me the dev doing it , they will have to rebrand /redo the splash screen design etc..

windowSplashScreenBrandingImage
Yes clients can use this space too , to possibly put then name on it etc..

gmck commented 2 years ago

@developer9969

Android12 Do nothing and your icon will display - your old fancy splash screen is gone I agree with that one. But I would add, that I think it should read Android 12 and above.

Android 9-10-11-12 I disagree here. I have tested on all devices Android 7 to Android 12, and they all display the splash screen. Just run NavIgationGraph5 on each of those devices. For that matter, you should be able to run your own app that you got working on the same devices. See the list of devices I tested with at the end of my docx file in the project. If not, then you have still screwed up something.

Text from the end of the docx. This means that any Xamarin.Android project can use their existing application icons with the new SplashScreen API, by utilizing the contents of mipmap-anydpi-v26 folder of the application.

Guidelines in short. I'd revise this

  1. You can use the contents of your existing the mipmap-anydpi-v26 folder to allow all supported devices to have a standard splash screen. 3 I agree with.

  2. I'm not sure as I don't know enough.

All the examples I've seen are using svg images, specifically one that works with Google's version of svg. If you look at the source of the raywenderlich project you will see that she already had a svg icon. Her ic_launcher_foreground.xml is a vector drawable. Our ic_launcher_foreground are pngs, but inside the any-dpi folder, it refers to a drawable.xml. Her project didn't have the usual bunch of mipmap folders. That was what gave me the idea of using exactly her code in my style.xml and it worked straight off. The Adaptive icons work as is, because they pick up the correct icon for whatever density. That is the part that the Google docs don't explain well if at all, but they do refer you to adaptive icons as required by Android 8, but they don't go any further. Typical Google docs..

I think if you want a more elaborate splash screen including animation etc you will need new svg icons that comply with Google's specification which is not the standard svg specification. If you want branding then I think (I haven't confirmed) that was why I was suggesting you try, that it will also require a svg icon. Read the other article - it gets very hairy when it comes to vector and vector drawables and what he does to fix the problems. However, he does use layer-list as she did too in her branding example.

I watch a friend of mine a few weeks ago stuffing around with Illustrator with one of my icons. He doesn't pretend to be an expert, but he fancies himself as a designer, a bloody good coder though. I was bored senseless after the first hour. He eventually got there, but it was still not right according to Android Studio. My advice is to give that stuff to the graphic designers and let them get it right.

It's not all doom and gloom. Pngs take up a lot of space in your app. A single scalable svg for your icon would reduce apk and aab sizes considerably, so I think the time has come for icons and all images where possible to be converted. A good example is that AS now generates webp icons rather than png icons when creating a new app. A webp is smaller than png. Looks like a small intermediate step to me. Just don't expect the Xamarin app templates to change to webp anytime soon, because those templates are still stuck in a time warp of 2018-19 and Android 9-10.

Real world clients

I'm not sure I understand what you mean by your real world clients. I don't know the business you are in. Can you please explain further?

developer9969 commented 2 years ago

@gmck sorry I have been off - Interrestingly enough there is this article on how to splash screen in android 12 for xamarin forms. The xamarin form bit plays no part whatsoever but its' interesting how he is not using the splash api and still manage to show the image. https://codetraveler.io/2022/08/16/supporting-android-splash-screens-in-xamarin-forms/

gmck commented 2 years ago

I hope you're not suggesting that you go down that path. I'm struggling to see his point.

As soon as he said, to create new icons, then what is the advantage? Then on top of that why would you create them as pngs? He did get right the recommendations at the end of his post, but then he totally ignores what she recommends. I said before that Jemma's icons are all svgs. Therefore if you have to create svgs for animations and branding etc, then stay with the SplashAPI.

The whole point of my version (the idea from Jemma) is that the any-dpi folder already contains all that is needed, so that if you only want a splash screen that works from Android 13 down to at least Android 7 for any Xamarin.Android project then you are done. If you want more then you (or your icon designer person) will have to create the resources as svgs.

Is it normal for a xamarin.forms app to refer to the old support libs (looks like just for the toolbar) as that project does? Did you notice how big that app is? Is that normal too for forms?

developer9969 commented 2 years ago

I do agree with the all svgs 100%. Xamarin forms will always be a bit bigger - Regarding what path to take, for xamarin which is only maintaned I dont mind and by this december I will have moved to MAUI, but for MAUI which I will be concentrating on next I will do what you suggested.

Your help on this has been fantastic. I think what would have been helpful at the beginning if your sample project did not contain all that extra good stuff but just the splash screen, I would have stripped out all the rest, as it would have been a tad easier to follow especially if you mainly do forms and dont really touch android much.

gmck commented 2 years ago

@developer9969 I took your last suggestion and created a new project XamarinBasicSplashScreen, based on the standard Blank app template. I hope that helps out other Forms developers such as yourself. Did you notice that the SplashScreen nuget has now been updated to release 1.0.0?

developer9969 commented 2 years ago

@gmck that is great and will definitely help more people as soon as they realise that their splash screen in android 12 is broken .