Sunday, November 18, 2018

Designing a good on-boarding experience for an Android app

After noticing that most users of one of my apps are uninstalling the app shortly after installing it I set out to redesign the on-boarding experience of the app. Having made good experience there before, I created a competition on 99designs asking for suggestions. Most of the proposals suggested using either a wizard-style introduction or a descriptive landing page that is shown every time the app is opened. After some back and forth with designers participating in the competition I decided to implement both: on first start a three page introduction is shown to the user. On subsequent launches a landing page is shown that tries to summarize the core features of the app to make sure the user remembers why he installed the app in the first place.

During a quick search for libraries AppIntro seemed most up-to-date and offered most of the features that I'd expect. Implementation turned out to be straightforward for the most part, but making the design match what was agreed on during the design competition turned out tricky:

Changing the next-button to show text instead of an image

By default the library shows an arrow to indicate the next-button. The designer intended to show "NEXT" as text instead, which I think makes it a little more obvious for unexperienced users what to do when looking at the introduction screen. Since that was not a feature of the library I had to hack it in: Changing the next-button to show text instead of an image in AppIntro

Show image above description text

Something that surprised me is that by default the library shows your description text at the top and the image below that. At least for my purpose this didn't make much sense as the image was mainly used as decoration to spice up the screen a bit. Again, I came up with a workaround myself: Show image above description text in AppIntro

OutOfMemory crash

As soon as I launched an update with the library included crash reports started to trickle in via Firebase. The stacktrace looked like this:
Fatal Exception: java.lang.OutOfMemoryError
       at android.graphics.BitmapFactory.nativeDecodeAsset(BitmapFactory.java)
       at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:483)
       at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
       at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
       at android.content.res.Resources.loadDrawable(Resources.java:1937)
       at android.content.res.Resources.getDrawable(Resources.java:664)
       at androidx.appcompat.widget.ResourcesWrapper.getDrawable(ResourcesWrapper.java:130)
       at androidx.appcompat.widget.TintResources.getDrawable(TintResources.java:46)
       at androidx.core.content.ContextCompat.getDrawable(ContextCompat.java:479)
       at androidx.appcompat.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:203)
       at androidx.appcompat.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:191)
       at androidx.appcompat.content.res.AppCompatResources.getDrawable(AppCompatResources.java:102)
       at androidx.appcompat.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:86)
       at androidx.appcompat.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:94)
       at com.github.paolorotolo.appintro.AppIntroBaseFragment.onCreateView(AppIntroBaseFragment.java:111)
This is a known issue when using drawables the lazy way: I only added the drawables in one resolution instead of scaling it down for low-end devices. This causes some devices to run out of memory while scaling down the images at runtime. Fortunately I found a plugin called "Android Drawable Importer" that does all of this for you in Android Studio. Here's a tutorial for installing and using the plugin.

Changing color of status bar to match screen background

This turned out to be surprisingly complicated! The background of my introduction was white, so I wanted the status bar to match that, to make the image more of an eye catcher. I quickly found a way to make the status bar transparent, but that left the icons there to be invisible (white on white...). Some research and a lot of trial-and-error later I ended up using a custom theme for the activity, which falls back to a black status bar on old devices, but uses black-on-white icons on newer devices! Here's the necessary XML for newer devices and the one for old ones.

Eventually the redesign turned out fine and I was happy to use the AppIntro library. If you want to see the result take a look at the screenshots for OpenDocument Reader on Google Play.