- 5 tips for preparing for Multi-Window in Android N
- Pro-tip 1: Use the right Context
- Pro-tip 2: Handle configuration changes correctly
- Pro-tip 3: Handle all orientations
- Pro-tip 4: Build a responsive UI for all screen sizes
- Pro-tip 5: Activities started by other apps must always support multi-window
- Test all the things!
- 🕐 Revisited — 📚 A Guide on Splash Screen in Android in 2020
- 👀 A fresh look on the splash screen in Android in Kotlin and Coroutines
- 🎨 Using Activity Theme
- ⏰ Using Handler / Runnable / Timer
- 🎯 Using Kotlin Coroutines
- 💻 Show Me The Code
- wajahatkarim3/SplashScreen
- github.com
- 📄 Making The Decision
- Add Push Notifications to Your Android Chat App Using Kotlin
- November 24, 2019
- 🚀 Launching Activities in Easier Way Using Kotlin Extensions 💻
- March 4, 2019
5 tips for preparing for Multi-Window in Android N
If you’ve been digging through What’s New in Android N, you probably stumbled across multi-window support.
With split-screen multi-window, two apps will be visible side-by-side. Excited to see how this works, I know I immediately scanned through the documentation, looking for what new APIs made this sorcery work.
Turns out, there aren’t many new APIs. A few XML attributes for customizing whether you support multi-window at all and a few Activity methods to check whether you are currently in multi-window mode. So where’s the magic? The magic has been there all along.
And by magic, we mean Android’s resource system. One of the most powerful parts of the resource system is the ability to provide alternate resources — change dimensions, layouts, drawables, menus, etc. based on different qualifiers.
Multi-window takes advantage of the resource system by adjusting the configuration based on the size of your window — screen size is the obvious one, but the smallest width (i.e., the minimum of the width or height) and the orientation are also updated when resizing.
This takes us to the first tip.
Pro-tip 1: Use the right Context
Loading the proper resources requires the proper Context. If you’re using the Activity context for inflating your layouts, retrieving resources, etc, then you’re good to go.
However, if you’re using your Application context for anything UI related, you’ll find that the resources that are loaded are blissfully unaware of multi-window. Besides issues with not using your Activity’s theme, you may be loading the wrong resources entirely! Best to keep your UI stuff with the Activity Context.
Pro-tip 2: Handle configuration changes correctly
With the correct context in hand, you’ll be sure to get the right resources given the size of your window (whether it is full screen as before or split between your app and another). The process for reloading those resources is based on how you handle runtime changes.
The default case is that your whole activity is destroyed and recreated, restoring any state you saved in onSaveInstanceState() and reloading all of the resources/layouts. This has the nice property that you know everything is consistent with the new configuration and that every type of configuration is handled.
It should go without saying that each configuration change should be fast and seamless. Make sure you aren’t doing a lot of work in onResume() and consider using loaders to ensure your data survives configuration changes.
You can still handle the configuration change yourself in which case your Activity (and Fragments) will receive a callback to onConfigurationChanged() instead of being destroyed and recreated and you will need to manually update your views, reload resources, etc.
To catch the multi-window related configuration changes, you’d need to add an android:configChanges attribute to your manifest with at least these values:
Make sure you’re handling every resource that might be changing (as is your responsibility when you take on handling configuration changes yourself).
This includes reloading resources that might have been considered a constant before. Consider the case where you had a dimension in values and in values-sw600dp. In the non-multi-window world, you’d never switch between these two at runtime as the smallest width would never change (it would always be the smallest width of your device). However, with multi-window, you can and will have to switch between these resources as your app resizes.
Pro-tip 3: Handle all orientations
Remember way back in the intro where we talked about the orientation changing while the window resizes? That’s right: even if the device is in landscape, your app might be in ‘portrait’ orientation.
Turns out: “portrait” really just means the height is greater than the width and “landscape” means the width is greater than the height. So it certainly makes sense, with that definition in mind, that your app could transition from one to the other while being resized.
That also means that transitions between orientations should be as smooth as possible. Quoting the split screen material design specs:
Changing a device’s orientation should not cause the UI to change unexpectedly. For example, an app displaying a video in one of the split screens (in portrait mode) should not begin playback in full-screen if the device rotates to landscape mode.
Note: if you’d still want this type of functionality when your app is fullscreen, you’ll be able to use the inMultiWindowMode() method to check exactly which case you’re in.
Locking your screen orientation by using android:screenOrientation is also affected by multi-window. For apps not targeting Android N, adding android:screenOrientation means you will not support multi-window at all — you’ll always force the user out of multi-window mode. Things change a little when you target N — instead of not supporting multi-window at all, any orientation you set via android:screenOrientation is ignored when in multi-window mode.
Keep in mind that locking your orientation at runtime using setRequestedOrientation() will have no effect in multi-window mode, whether you target N or not.
Adding the android:immersive attribute to your Activity’s manifest also disables multi-window on apps not targeting N, with the same rules as android:screenOrientation above.
Pro-tip 4: Build a responsive UI for all screen sizes
Orientation isn’t the only thing that goes into designing for split screen. Multi-window is the first time your tablet UI (you have a tablet UI right? After all, 12.5% of 1.4 billion devices is a lot of devices…) is going to be shrunk down to a miniature size.
If you’ve been building a responsive UI that reacts to the available space and has relatively similar phone and tablet layouts, you’ll find you’ll be well prepared for multi-window. As suggested, scaling the UI down to 220dp wide/tall and building up from that size to the fullscreen size is a something you can do now.
However, if your mobile and tablet UIs are vastly different, don’t overwhelm users by switching between the two — stick with the tablet UI and work on scaling it down. There’s a number of responsive UI patterns you might consider employing to make resizing a seamless experience for your users — again, no N APIs needed.
Pro-tip 5: Activities started by other apps must always support multi-window
In the multi-window world, your whole task is represented by a single window. That’s why if you want to launch an adjacent activity you need to start a new task — new task, new window.
It also means the reverse is true, quoting that same page:
If you launch an activity within a task stack, the activity replaces the activity on the screen, inheriting all of its multi-window properties.
That means if you have an Activity that can be started by other apps, your activity will inherit the same multi-window properties as the calling Activity. This includes attributes such as minimal size. In cases of startActivityForResult(), your Activity must be part of the same task stack and even in the case of an implicit intent, you can’t guarantee that they’ll also include a FLAG_ACTIVITY_NEW_TASK.
Therefore every one of those activities (and any activities started by that Activity) must support multi-window, all the way down the smallest size. Test thoroughly!
Test all the things!
The best way to prepare for multi-window is to test your app. Even without any code changes or going through the process of setting up the Android N SDK, installing your existing app on an Android N device or emulator is a fantastic first step and an easy way to catch low hanging fruit and #BuildBetterApps.
Источник
🕐 Revisited — 📚 A Guide on Splash Screen in Android in 2020
👀 A fresh look on the splash screen in Android in Kotlin and Coroutines
Splash screen is a very popular methodology in Android app development. Almost all major apps contain some sort of splash screen for many different reasons from brand awareness to loading heavy resources before app start. Some apps even add splash screens just because everyone else is adding it to follow the paradigm, even though their apps don’t need it.
Its a very debatable topic on whether apps should contain splash screen or not as this wastes few (important) seconds of user’s time. In this article, we will not be focusing on that debate. Rather, this topic is about technical details on creating splash screens with the modern Android development approaches followed in 2019 or upcoming 2020. So, without further ado, let’s start ordering from the old way to new way.
🎨 Using Activity Theme
When any app is launched, Android system will try to draw the first screen as fast as it can. But for the new launches, this may take few moments. During these moments, Android by default shows a empty placeholder screen filled with your app’s windowBackground color. You can extend this placeholder from just a color to your splash screen using the Activity theme approach.
Create a separate theme for your splash Activity and set its windowBackground to your custom splash drawable.
You can see that we have set windowBackground to our splash screen drawable in file splash_drawable.xml file. Here’s that file.
Now, set this theme to your splash Activity in the AndroidManifest.xml file.
And this will give you an Amazon-like splash screen.
Now, whatever time Android System is supposed to show a black placeholder screen while starting up your app and allocating memory resources for it, the system will show this screen instead of that placeholder. And once your app is ready and launched, then still you will be seeing this. And your whole layout passed in setContentView() method will be drawn on top of this screen. So, you will have to reset your original app’s theme in your Activity . You can do this easily by adding setTheme() before the setContentView() method call in your Activity class.
Now, as your app’s ready, it will change to your original app’s theme like the normal apps do. The code for this approach is available in the SplashThemeActivity class at the Splash Screen Demo repository.
Overall, this approach is good from the user experience as it doesn’t waste time. It only takes time to load the app. So, if your app is already in the memory, you won’t see the splash theme much. This approach is applied in Google’s apps a lot.
But the problems with this approach are that if your splash contains fancy animations or even a simple loading progress bar, you can’t add this. You can only add an image through tag in your theme and change the position of it on the screen.
If you want to add multiple starting points based on some logic, like whether to show login or the home screen, then this approach can work a little trick. Instead of setting splash theme to your home screen, create a separate dedicated Activity for your splash and apply the theme to it. Then write your business logic in that Activity . You can check the the code in SplashLogicActivity.kt class at the Splash Screen Demo repository.
⏰ Using Handler / Runnable / Timer
A huge number of apps follow this approach to create splash screen. The idea is to create a separate Activity for splash screen and then launch the main screen either fixed or based on some logic after some scheduled time of like 2–3 seconds. This splash screen doesn’t do anything except show the user some screen and make user wait for few seconds. This is achieved by commonly using the Handler and Runnable classes.
This is quite similar to the separate Activity with the theme approach. But we get many advantages in this method over the themed activity. You can add animations, or any sort of customizations in your layout for the splash screen. You can also add business logic to redirect user to any specific screen. But there’s a problem. The code for this is available in CommonSplashActivity at the Splash Screen demo repository.
If the user presses the hard back button while splash screen, it won’t cancel the Handler instance, and you will see some screen popup randomly because it was scheduled to launch. This can cause memory leak or if you’re storing some data in memory in your splash screen, then that data will be lost. Because Android system will launch your home screen as a new task.
One way to fix this is using the Timer class because we can cancel the Timer instance in either onPause() or onDestroy() methods to stop the scheduled launch of the home / login screens. You can get check this code in TimerSplashActivity at the Splash Screen demo repository.
This approach will avoid you the memory leaks or the sudden popping up of the screen because timer is cancelled in onPause() and because of it the launch of home screen task is also terminated.
It must be noted that Timer creates a whole new thread in background. And you cannot interact with UI elements, View objects etc. in this thread. For example, you cannot update animations of views, or change TextView ‘s text values etc in the TimerTask object. Memory-wise this is a heavy operation approach and due to thread-switching it can also be slow.
I have seen some places where a Thread is used instead of timer. And Thread.sleep() is used for delay purposes. I would highly recommend you to avoid this method as this will not only cause memory leaks and is almost similar to the previous Handler approach we discussed.
🎯 Using Kotlin Coroutines
Yes, you read that right. I would only recommend this method if you already have Kotlin Coroutines in your project or you plan to add in near future. Because it wouldn’t be a good approach to just add Kotlin Coroutines for splash screen.
Conceptually, this is a lot similar to Timer approach, but we will use coroutines, instead of Timer objects. Here’s the code for this. (You can also check this code in the SplashActivity in the Splash Screen repository on Github.
Since the activityScope we created is of Dispatchers.Main , so this will run on the main UI thread. And being a coroutine, there will be no thread switching as coroutines run on the same thread. This will help in the performance speed as opposed to the Timer approach.
As the Activity gets paused or destroyed, the coroutine will be cancelled automatically. This will avoid the sudden popping of the home/login screen. And surprisingly, since this coroutine is running on Dispatchers.Main , we can easily update UI elements, view animations etc. without any tension.
Overall, the coroutines approach is fast, reliable, less-memory consuming, gives the advantage of main UI thread access, and supports the custom launch logic.
💻 Show Me The Code
The code is available on my Github profile at Splash Screen repository. It contains all the splash screen approaches discussed in this article in separate Activity classes. You need to launch any of the Activity as launcher in AndroidManifest.xml to check the behavior of that approach.
wajahatkarim3/SplashScreen
A demo project showcasing different methods to create splash screen in Android and discusses the det.
github.com
📄 Making The Decision
The best approaches are theme approach and coroutines approach.
If your app has fixed home screen, then use the splash theme on that home screen.
If your app needs business logic to decide the home screen, use the separate Activity with theme approach.
If your app has fancy animations and / or complex splash UI, then create a separate Activity and use Kotlin Coroutines. If your app doesn’t intend to use Coroutines, then you should switch it the the Handler approach, but be aware of the memory leaks.
Finally, do not use Timer , or Thread at all for splash screen and try to avoid Handler approach too.
If you liked this article, you can read my new articles below:
Add Push Notifications to Your Android Chat App Using Kotlin
This story was originally published with collaboration with CometChat Pro, and Alex Booker on their tutorials blog. For any kind of chat apps, notifications are the driver behind whole chat concept.
November 24, 2019
🚀 Launching Activities in Easier Way Using Kotlin Extensions 💻
Kotlin Extensions for simpler, easier and fun way of launching Activities in Android Reposted on my Medium profile. Few days ago, I was reading this awesome article by Elye about a Kotlin keyword reified .
March 4, 2019
7 years experience. 💻 Creator of various Open Source libraries on Android . 📝 Author of two technical books and 100+ articles on Android. 🎤 A passionate Public Speaker giving talks all over the world.
Источник