Android UI Design - Sample Chapter
Android UI Design - Sample Chapter
ee
P U B L I S H I N G
C o m m u n i t y
$ 39.99 US
25.99 UK
pl
Jessica Thornsby
Android UI Design
Android UI Design
Sa
m
D i s t i l l e d
Android UI Design
Plan, design, and build engaging user interfaces for your
Android applications
E x p e r i e n c e
Jessica Thornsby
Preface
Your UI is your most direct communication with your users, but all too often in app
development, design is an afterthought, or something that "just happens" along the way.
In order to develop a great app, you need to take your UI design seriously. Even if your app
delivers great functionality, if its user interface is clunky, laggy, difficult to navigate, or just
an all-around eyesore, then no one is going to want to use it.
Android isn't the easiest platform to design for. Creating an app that looks great across
countless different devices, all with different combinations of hardware, software, and
screens, is no mean feat. But if you put some thought into the design process, you can create
a UI that delivers a great experience across the entire Android ecosystem.
This book will help you become a design-minded developer. Over the course of 10 chapters,
you'll learn how to design, refine, test, and develop an effective, engaging UI that people
will love using and that delivers the best possible experience regardless of device specifics.
From the fundamentals of layouts and views right through to creating responsive, multipane layouts, and from sketching your screens, through to using Android Studio's tools to
scrutinise your view hierarchy and hunt out memory leaks, this book covers everything you
need to create the perfect Android UI.
Preface
Chapter 5 , Turning Your Bright Idea into a Detailed Sketch, helps you become a design-minded
developer by introducing roadmaps, flowcharts, screen lists, and screen maps to your
Android app "To Do" list.
Chapter 6 , Turning Your Sketches into Wireframes, shows you how to transform the high-level
plans from the previous chapter into detailed screen designs using paper prototypes and
wireframes.
Chapter 7 , Building a Prototype, put your plan to the test! By the end of this chapter, you'll
have created a complete digital prototype.
Chapter 8 , Reaching a Wider Audience Supporting Multiple Devices, teaches you how to attract a
wider audience with an app that supports a wide range of hardware, software, screen sizes,
screen densities, orientations, versions of the Android platform, and even different
languages.
Chapter 9 , Optimizing Your UI, shows you how to create a smooth and responsive UI that
people will love using. If your app is laggy, prone to crashing, gobbles up data and
memory, or drains the user's battery, then no one is going to want to use it!
Chapter 10, Best Practices and Securing Your Application, guides you through putting the
finishing touches to your UI, including using notifications from the upcoming Android N
release.
All these variations on hardware, software, and screen configuration mean lots of
opportunities to innovate and come up with a truly original app. However, it also poses a
massive challenge, as you'll need to create an app that provides a consistent experience
across all the different hardware, software, and screen configurations that your app might
encounter.
Unfortunately, there's no quick fix. Essentially, the key to creating a flexible UI is to provide
a wide range of alternate resources that are optimized for all the different hardware,
software, screen configurations, languages, and region settings that your app may
encounter, which is arguably the most time-consuming part of Android app development.
In this chapter, I'm going to cover all the major aspects you need to bear in mind, if you're
going to create a flexible app that's compatible with as many different Android devices as
possible.
[ 234 ]
Chapter 8
To identify the point at which supporting older versions of Android becomes more trouble
than it's worth, you'll need to look at the current Android marketespecially how many
devices are running each version of the Android operating system. Once you have this
information in front of you, you can make an informed decision about the point at which it
no longer makes sense to keep supporting the older versions of Android.
One source of this information is Google's Dashboard (http://developer.android.com
/about/dashboards/index.html), which gives you a percentage of the relative number
of devices running each version of Android. Just be aware that this information is gathered
in a very specific way. It's essentially a snapshot of all the devices that visited the Google
Play store in the previous 7 days. This data is collected from the Google Play app, and is not
necessarily representative of the current state of the entire Android market. It's also worth
noting that the Google Play app is only compatible with Android 2.2 and higher, so any
device running versions of Android lower than 2.2 aren't included in this data; although
according to Google way back in August 2013, devices running versions lower than
Android 2.2 only accounted for about 1% of devices, so we're talking about a very small
percentage here.
Spend some time exploring the Dashboard data, and come to a decision about which
versions of Android you're going to support and which versions you aren't.
minSdkVersion
This attribute identifies the lowest API level that your app is compatible with, for example,
minSdkVersion 16. Google Play will use your app's minSdkVersion attribute to
determine whether a user can install it on device.
[ 235 ]
When debating your app's minSdkVersion value, make sure you consult the Dashboard
stats as this provides a snapshot of your potential audience. Ultimately, you'll need to
decide whether supporting each additional slice of this audience is worth additional time
and effort.
targetSdkVersion
This attribute identifies the highest API level that you've tested your app against.
The targetSdkVersion value is particularly important for forward compatibility, as the
system won't apply any behavior changes introduced in new Android releases until you
update your app's targetSdkVersion value. To ensure your app benefits from the latest
Android features, you should aim to set your app's targetSdkVersion value to the very
latest version of Android. Updating your app to target a new SDK should always be a high
priority whenever Google release a new version of Android, but you should only do this
after thoroughly testing your app against the latest SDK release. Never blindly update
your targetSdkVersion value without testing it first.
Ideally your targetSdkVersion and compileSdkVersion value should always
correspond to the very latest version of the Android SDK.
compileSdkVersion
This attribute tells Gradle what version of Android SDK it should compile your app with.
Your compileSdkVersion value is not included in your published APK; it's purely used at
compile time. Changing your compileSdkVersion value does not change the runtime
behavior, so it's recommended you always compile with the latest SDK.
Chapter 8
available to users who are running Android 5.0 or a lower version, but these users will still
be able to install and use your app.
You achieve this using the Build constants class to specify when the related code should
run; for example, the following code verifies whether your app is running on Lollipop or a
higher version:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
Android provides a unique code for each platform version, which you should use alongside
the Build constants class (in this example, the code is LOLLIPOP). You'll find a complete list
of these codes at the official Android docs (http://developer.android.com/referenc
e/android/os/Build.VERSION_CODES.html).
[ 237 ]
In this section, I'll show you how to create an app that can handle a wide range of different
sizes and densities. The underlying theme you'll encounter time and time again is that your
app's layout and drawables must render at a size that's appropriate for the current screen.
The Android system is clever enough to handle most of this rendering work automatically,
and it will scale your layouts and resources to fit the current size and density, but you
shouldn't rely on the Android system to do all the hard work for you.
Android's automatic rendering alone won't provide the best possible user experience. You'll
need to give it a hand by providing multiple versions of your app's resources that are
optimized for different screen sizes and densities. These resources could be strings, layouts,
graphics, or any other static resources that your app requires.
To add these resources to your project, you'll need to create alternate versions of your
project's directories, and then tag them with the correct configuration qualifiers; for
example, if you have a layout that's optimized for landscape orientation, you'll need to
create a res/layout-land directory, and then place your landscape layout file inside this
directory. Then, when a user runs your app, the Android system will automatically load the
resource that best matches the current screen configuration, whether that's the default
layout or your landscape-optimized res/layout-land layout.
Configuration qualifiers
Android supports a wide range of configuration qualifiers that you can append to your
project's resource directories. These configuration qualifiers are the key to controlling which
version of a resource the system displays.
Configuration qualifiers specify the characteristics that a resource was designed for, such as
an image that was designed for a particular screen size or screen density. You'll find a
complete list of valid configuration qualifiers in the official Android docs, specifically Table
2 of the Providing Resources page (http://developer.android.com/guide/topics/r
esources/providing-resources.html#AlternativeResources).
The configuration qualifiers you'll need to use will vary depending on your app and the
kind of devices you're targeting, but as a minimum, you'll typically use size, density, and
screen orientation qualifiers to provide drawable resources and layouts that are optimized
for different screen configurations.
To use a configuration qualifier, create a new directory in your project's res/ directory and
name it using the following format:
<resources_name>-<config_qualifier>
[ 238 ]
Chapter 8
So, if you were creating a directory to hold layouts that were optimized for devices held in
landscape mode, you'd use the land qualifier and create a res/layout-land directory,
then place your layout-optimized layouts inside this directory.
Never place any resources directly inside your project's res/ directory as
this will cause a compiler error. You also cannot nest alternative resources,
so you cannot create a res/drawable/drawable-xxhdpi/ directory.
You can use more than one qualifier at a time by separating each qualifier with a dash; for
example, a res/drawable-en-hdpi directory would contain drawable resources that are
designed for devices set to the English language (en) with a screen density that falls into the
high-density bucket. If you do use multiple qualifiers, the order they appear in your
directory name is crucial. They must appear in the same order as in the Providing
Resources page (http://developer.android.com/guide/topics/resources/provid
ing-resources.html#AlternativeResources). If you use qualifiers in the wrong
order, the Android system won't recognize the directory, and will subsequently ignore all
the resources that it contains.
Don't worry about the case you use for your directory names, as the resource compiler
converts directory names into lowercase before processing anyway. If your project includes
directories with long-winded names consisting of multiple configuration qualifiers, then
you may want to take advantage of this automatic conversion, and use capitalization to
make your directory names easier to read.
Naming is also important for the resources that you place inside your directories. When you
create multiple versions of the same resource, they must all have exactly the same name as
the default resource. Any variation and the Android system won't recognize them as
alternate versions of the same resource.
If your project contains resources that the system should never scale to suit
the current screen configuration, place these resources in a directory with
the nodpi configuration qualifier, for example, res/drawable-nodpi.
[ 239 ]
When the Android system is looking for a resource based on the screen size or density, it
starts by searching for an exact match that it can display without scaling. If it can't find a
suitable size or the density-specific version, then Android switches to plan B and searches
for a version that's designed for screens smaller than the current screen.
If the only available resources are larger than the current screen, the system will use the
default version of the resource instead. The Android system assumes that your project's
default resources are designed for the baseline screen size and density, which is a normal
size and medium-density. Therefore, the system scales default resources up for high-density
or larger screens, and down for low-density screens.
If the system can't find a suitable density-specific resource, or even a default version of the
required resource, then your app will crashwhich is why it's essential that you provide a
default version of every resource.
Even if you're confident that you've provided all the alternative resources your project
could ever need, it's possible that your app may wind up on a device that has hardware,
software, screen size, screen density, or language settings that you hadn't anticipated and
therefore didn't provide specific resources for. In this scenario, the system may fall back on
your project's default resources, and if your app doesn't include these default resources,
then your app will crash.
Default resources are all the resources that are stored in a directory
without a configuration qualifier, such as res/drawable.
[ 240 ]
Chapter 8
Imagine you have a scene.png drawable that you want to use for both hdpi and xhdpi
screens; this is the perfect opportunity to use an alias. In this scenario, you need to place the
default version inside your project's res/drawable folder as normal. Then, save the
version of the image you want to use for hdpi and xhdpi screens inside
the res/drawable folder, but give it a different name to the default resource, for
example, scenery_alias.png.
At this point, you have two drawables:
res/drawable/scenery.png
res/drawable/scenery_alias.png
Next, create an XML file inside both of the density-specific directories. Inside these XML
files, add some code that points toward your project's
res/drawable/scenery_alias.png resource:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/scenery_alias" />
When the Android system tries to load the scenery resource from res/drawable-hdpi
or res/drawable-xhdpi, it'll recognize the alias and
display res/drawable/scenery_alias.png instead. In this way, you can replace
memory-hogging and inefficient duplicate resources with small XML files.
You can also use the alias function to reuse the same layout resource files in multiple
directories, as follows:
1. Create a default layout (main.xml), and place it in your project's res/layout
directory.
2. Create the layout you want to use across multiple directories. Give this layout a
different name to the default layout (I'm going to use main_alias.xml), and
place it inside your project's res/layout directory.
3. Create XML files in all the directories where you want to use
the layout_alias.xml file.
4. Add some XML code that references layout_alias.xml:
<?xml version="1.0" encoding="utf-8"?>
<merge>
<include layout="@layout/main_alias"/>
</merge>
[ 241 ]
Although less commonly used, you can also create aliases for strings and other simple
values, as follows:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="yellow"> #ffff00
</color>
<color name="highlightColor">@color/yellow</color>
</resources>
In this example, highlightColor is now an alias for yellow. You can also create aliases
for strings:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title">Student Recipe</string>
<string name="appTitle">@string/title</string>
</resources>
Screen density
When designing your UI, you should aim to achieve density independence. This is where
the Android system preserves the physical size of your UI elements across screens with
different densities.
Density independence is crucial to providing a good user experience. A high-density screen
has more pixels per inch, which means the same amount of pixels fits into a smaller area.
Low-density screens have less pixels, so the same amount of pixels fits into a much larger
area. If you use absolute units of measure, such as specifying UI elements in pixels, then
your UI elements are going to appear larger on low-density screens and smaller on highdensity screens.
It's a common misconception that devices with the same screen resolution
automatically have the same screen density. Even if two devices have the
same screen resolution, these screens may be different sizes. This means
the screens are displaying their content in a different amount of space,
which equates to a different number of dpi.
If your UI elements change sizes on different devices, then this is going to lead to problems
in your layout and usability issues, and this will make for a generally poor user experience.
[ 242 ]
Chapter 8
In most cases, you can ensure density independence by specifying your layout dimensions
in density-independent pixels, and by replacing static, hardcoded sizes with more flexible
elements such as "wrap_content" and "match_parent".
When it comes to drawables, Android automatically scales each drawable based on the
current screen's density, so your drawables render at the appropriate physical size for the
current device. However, this automatic scaling can result in blurry or pixelated images. To
make sure your drawables look their very best, you need to create alternate versions of each
drawable, which are optimized for different screen densities.
The problem is that the Android marketplace includes more screen densities than you could
ever hope to support; and even if you could, providing so many alternate drawables would
cause the size of your project to balloon out of control, to the point where it's unlikely it'd
even fit onto your average Android smartphone or tablet.
This is why Android groups screen densities into the following generalized density
buckets:
ldpi (low-density): 120dpi
mdpi (medium-density): 160dpi
hdpi (high-density): 240dpi
xhdpi (extra-high-density): 320dpi
xxhdpi (extra-extra-high-density): 480dpi
xxxhdpi (extra-extra-extra-high-density): 640dpi
The first step to a flexible layout is to create a directory for each of these density buckets, for
example, res/drawable-ldpi, res/drawable-mdpi, and so on. Then, just create a
version of each resource that targets these different density buckets, and the Android
system will handle the rest.
To create optimized drawables for each density bucket, you need to apply the 3:4:6:8:12:16
scaling ratio across the six generalized densities. For the best results, start by creating a
version of the image at the largest supported density, and then scale this graphic down
proportionally for each subsequent density bucket.
Most of the time, creating a graphic at the largest supported density means
creating an image for the xxhdpi density bucket and not the xxxhdpi
bucket. This is because the xxxhdpi directory is reserved for launcher
icons.
[ 243 ]
[ 244 ]
Chapter 8
If you thoroughly test your app across a range of different screen sizes using the emulator
and multiple Android Virtual Devices (AVDs), you may encounter your app struggling to
display or function correctly on certain screens. For example, you may discover that
Android's automatic scaling makes your UI look cramped once the device's screen dips
below a certain dpi value; or at the other end of the scale, you may find that your UI has
large areas of empty space on larger, tablet-sized screens.
If your UI is having problems with certain screen sizes, you should create layouts that are
optimized for these screens.
The process for providing alternate layouts is the same as providing any alternate resource:
create directories that have the appropriate configuration qualifiers. Then, create layout
resource files that are optimized for specific screen sizes, and make sure these layouts have
the same name as the corresponding default layout. The Android system will then select the
appropriate layout based on the current screen configuration.
However, the screen size configuration qualifiers aren't as straightforward as the density
configuration qualifiers, as Android 3.2 introduced some new configuration qualifiers that
allow you to define the specific width and/or height required by each of your layouts, in dpi
units. These new configuration qualifiers give you greater control over your resources, but
they are a bit more difficult to get your head around.
Prior to version 3.2, Android supported screen-size groups:
small, normal, large, and xlarge. In order to accommodate a greater
variety of screen sizes, the Android team replaced these groups with new
configuration qualifiers. This chapter focuses on the new configuration
qualifiers, but if you want to find out more about the now-deprecated
screen size groups, you can find more information at the official Android
docs at (http://developer.android.com/guide/practices/screen
s_support.html).
These powerful new qualifiers are discussed in the next sections.
smallestWidth sw<N>dp
As the name suggests, you use the smallestWidth qualifier to define the minimum width
in dpi that must be available before the Android system can use a particular layout. For
example, if your layout requires a minimum of 700dpi, the smallestWidth configuration
qualifier would be sw700dp. In this scenario, you'd create a res/layout-sw700dp
directory and place your layout inside. The system will only use this layout when the
current device has at least 700dpi of available width.
[ 245 ]
This qualifier is particularly useful as width is often a major factor when designing your
layouts. Many apps scroll vertically, but it's pretty rare to encounter a UI that scrolls
horizontally. Most apps have strict constraints about the minimum space they need
horizontally, and this configuration qualifier gives you a way of specifying that minimum
as a dpi value.
A device's width is a fixed characteristic that doesn't change when the user switches
between portrait and landscape mode. The user's perception of their screen's width and
height may change, but the system's perception of a device's smallestWidth never does,
even when users switch their device from portrait to landscape mode and vice versa.
Chapter 8
Not all versions of Android support all qualifiers, for example sw<N>dp
was introduced in API level 13. However, when you use a qualifier in
your project, the system automatically and implicitly adds the platform
version qualifier, so older versions of Android can at least recognize
unsupported qualifiers and subsequently ignore them.
[ 247 ]
When it's time to test your app, make sure you test it in both landscape
and portrait mode across a range of screen configurations.
[ 248 ]
Chapter 8
//This is where you'd define your app's multi-pane behavior//
} else {
//If this view isn't visible, then we're in single-pane mode//
...
...
//This is where you'd define your app's single-pane behavior//
To retrieve the device's current screen orientation and act on the results, run the following
code:
if (getResources().getConfiguration().orientation
//If the screen is currently in landscape mode...//
== Configuration.ORIENTATION_LANDSCAPE) {
...
...
//This is where you'd define your app's landscape behavior//
} else
//If not, then the device is in portrait orientation//
...
...
//This is where you'd define your app's portrait behavior//
[ 249 ]
When you launch the AVD Manager and select Create Virtual Device, you can choose
from a wide range of ready-made Android Virtual Devices (AVDs) that are based on reallife devices, or you can create your own by selecting New Hardware Profile. When creating
a new AVD, you can then choose whether your AVD supports landscape and/or portrait
mode, but you should typically test your app in both landscape and portrait orientation
on every AVD you create.
You can also enter the screen size and resolution of your choice. As you enter these settings,
you'll see the Density of this particular device displayed in the window's right-hand pane:
To test your app's screen support, you'll need to create multiple AVDs that represent all the
most common Android screen configurations. There's no shortcut here, and generally
speaking, the more time you spend testing your app, the better the user experience will be,
regardless of the device it winds up on.
I'll be using the emulator that comes as a part of the Android SDK
throughout this book, but if you're not a fan of this default emulator, there
are alternatives available. One popular alternative is Genymotion (https:
//www.genymotion.com).
[ 250 ]
Chapter 8
[ 252 ]
Chapter 8
Place all your translated string resources inside the corresponding strings.xml file (we'll
look at some options for getting your text translated in a moment).
Continuing with our Spanish theme, our res/values-es/strings.xml file may look
something like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello_world">Hola Mundo</string>
</resources>
At runtime, the Android system logs the device's locale settings, checks your project for any
suitable locale-specific resources, and then loads either the resources from the
corresponding locale-specific directory or falls back on your project's default resources.
Keep your text separate from your application code
It's good practice to keep the localized aspects of your app separate from
your application code and to never hardcode any text into your app, as this
will make your text far more difficult to localize. Instead, declare all your
text as string resources, as it's easy to extract strings from your project,
send them to a translator, and then integrate them back into your app
without making any changes to your compiled code.
[ 253 ]
[ 254 ]
Chapter 8
If you don't provide a default version of every string resource, then your app will crash
whenever it winds up on a device with locale settings that you haven't provided a specific
string resource for. Even if the user doesn't understand your app's default language, this is
still preferable to your app crashing or refusing to open.
You'll also need to provide a default version of every other locale-specific resources you use
in your app, because if your project is missing one default resource, then it may not run on
devices with unsupported locale settings.
Default string resources are also crucial when there's some text you want to keep consistent
across your app, regardless of the device's locale settings. One common example is your
app's title, which you may want to keep consistent across all versions of your app.
To use text consistently across locales, you just need to define the string once in your
project's default strings.xml file, and then omit it from all your localespecific strings.xml files. Then, when the system tries to load your app's title from a
locale-specific strings file, it'll realize that this string is missing and fall back on the default
version. The end result is that the same string resource will be used in every version of your
app.
Should I translate my app's title?
There's no straightforward answer to this tricky question. Having multiple
titles makes an app more difficult to maintain, and it can make usually
straightforward decisions more complex; if your app goes by multiple
names, then what should your app's Twitter handle be? Do you need to
create multiple versions of your app's logo and app icon? Do you need to
create multiple support e-mail addresses?
You'll also have to work much harder to promote a product that goes by
several different names, particularly when it comes to things such as
Search Engine Optimisation (SEO).
Despite all these drawbacks, there are a few good reasons why you might
want to publish your app under multiple names. The most common
reason is that your app's title may not make much sense to people who
aren't fluent in your app's default language. If we decided to call our
recipe app Best Student Recipes, English-speaking users would instantly
know what to expect, but for users who speak different languages, best
student recipes could be completely meaningless. A nonsensical title isn't
particularly appealing to potential users who stumble across your app in
the Google Play store, so you may want to consider releasing your app
under multiple names.
There's no real right or wrong answer here. All that matters is that you
make the best decision based on the app you're developing and your
[ 255 ]
target locales.
Whatever decision you do make, make sure you stick to it! Changing your
app's name after you've launched it is only going to confuse your users.
Which drawable will the system use? When Android is spoilt for choice, it follows a strict
set of rules. Of all the qualifiers you can use, locale almost always gets preferential
treatment. In this example, the device is configured to use Spanish, so Android would load
the graphic from the res/drawable-es directory even though the device in question also
has a high-density screen and is currently in landscape mode.
The only qualifiers that take precedence over locale qualifiers are mobile
country codes (MCC) and mobile network codes (MNC). If you use any
of these codes in your project's directories, they'll always take precedence
over your locale qualifiers.
[ 256 ]
Chapter 8
Although you may be tempted to go down the quick and easy route of a machine translator,
services such as Google Translate can never compare to a human translator, and relying on
machine translators will almost always result in a bad experience for your international
users.
If you do decide to hire a professional translator, you should start contacting translators as
early as possible, so you can get an idea of turnaround time and incorporate this
information into your development plan. It also gives you time to shop around and find the
best possible translator for your budget.
You can find translators online, or you may want to explore the Google Play app
Translation service, which is offered through Developer Console.
To access these services, perform the following steps:
1. Log in to the Developer Console (https://play.google.com/apps/publish).
2. If you haven't already done so, upload your APK by selecting Add new
application.
3. Once you've uploaded your app, it'll appear in your All Applications dashboard.
Select the app you want to purchase translation services for.
4. Make sure APK is selected in the left-hand menu.
5. Under APK Translation Service, select Start.
6. Select the source language used in your original text.
7. Under Translate API, add the XML source file that contains the strings that you
want to translate.
8. Select your target languages.
9. Choose a translation vendor.
Just be aware that even though you're making a purchase through the Developer Console,
this is a direct business agreement between you and your chosen vendor, so you'll need to
work with the translator directly. After purchasing a translation through the Developer
Console, you will receive an e-mail from your vendor, and it's your responsibility to
manage the project from there.
[ 257 ]
In this section, I'll show you how to increase your chances of receiving a high quality,
accurate translation.
If your app features any specialist language or technical terms, then you should thoroughly
explain what each term means. If this turns out to be too much text to fit into a comment, or
you find yourself explaining multiple strings, then you may want to create a separate
glossary document that explains the meaning and use of all the specialist terms used
throughout your strings.xml file. You can then send this additional document to the
translator along with your strings.
[ 258 ]
Chapter 8
[ 259 ]
Imagine you want to display a welcome message that includes your app's title. You want
the actual welcome text to be translated, but you want the app's title to remain consistent
across all locales. In this scenario, you'd use the following XML:
<string name="welcomeMessage"> Welcome to the<xliff:g id="appTitle">Student
Recipes</xliff:g>app.</string>
Finally, to prevent your project from throwing an error, you need to update the resources
tag in your strings.xml file:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
[ 260 ]
Chapter 8
Then, change all your app's left/right layout properties to the start/end equivalents:
If you're targeting Android 4.2 and higher, use start and end instead of left
and right, for example, android:paddingRight
becomes android:paddingEnd
If you're targeting versions of Android lower than 4.2, you should use start and
end in addition to left and right; for example, you should use
both android:paddingRight and android:paddingEnd
Formatting values
Keep in mind that not every locale formats values, such as dates and numbers, in the same
way. You should never hardcode formats based on assumptions about the user's locale as
this can cause problems when the user switches to another locale.
Instead, always use the system-provided formats and utilities such as follows:
DateUtils (http://developer.android.com/reference/android/text/fo
rmat/DateUtils.html) and DateFormat (http://developer.android.com/
reference/java/text/DateFormat.html) for dates
[ 261 ]
String.format (http://developer.android.com/reference/java/lang/St
ring.html#format(java.lang.String,%20java.lang.Object) or
DecimalFormat (http://developer.android.com/reference/java/text/D
ecimalFormat.html) for numbers and currency
PhoneNumberUtils (http://developer.android.com/reference/android/
telephony/PhoneNumberUtils.html) for phone numbers
Chapter 8
Simple, straight-to-the-point text typically means less variation during the translation
process, so if you're struggling with text that shrinks or expands dramatically, start at the
root of the problemyour app's default text. Look for any opportunities to simplify this
text, any unnecessary text you can remove from your UI, plus any words that you can
replace with a universally understood picture or symbol, such as replacing the OK text with
a checkmark or Cancel with a cross.
Simplifying your app's text and removing any words that aren't strictly
necessary will provide a better user experience all round, regardless of
whether the user is viewing a localized version of your app or accessing
your app in its default language.
Depending on the amount of text you need to display and the locales your app supports, it
may be impossible to create a single layout that can accommodate text across all your target
languages. Layouts can only flex so far after all!
As a final resort, you can create alternate layouts specifically for the language (or languages)
that are causing your app so many problems, which leads onto the next point.
[ 263 ]
When testing your app across different locales, be sure to check for the following:
Your project is displaying the correct string resources, layouts, and any other
locale-specific resources for the device it's currently installed on. Placing
a strings.xml file in the wrong directory and missing a configuration qualifier
or even a simple typo is all it takes for your app to display Korean text
(res/values-ko/strings.xml) when it should really be displaying Kurdish
text (res/values-ku/strings.xml).
Your locale-specific resources are displaying correctly in the current layout and
aren't causing any usability problems.
You should also be aware that some screen configurations, hardware, and software may be
more common in certain locales. Make sure you research the most popular devices in all
your target locales to see whether you need to incorporate support for specific hardware,
software, or screen configurations into the localized versions of your app.
Once your AVD is up and running, you can change its locale by issuing adb commands. To
do this, you'll need the ISO code of the language you're targeting (ISO 639-1), and any
country or region code (ISO 3166-1) you're using.
[ 264 ]
Chapter 8
After a few moments, you will see a # prompt. At this point, you can enter the following
command:
setprop persist.sys.locale [ISO language code, with optional country/region
code] ;stop;sleep 5;start
For example, if you wanted to test your app on a device that's set to Spanish (es), you'd run
the following:
setprop persist.sys.locale es;stop;sleep 5;start
If you wanted to check your app on a device that's set to use the Spanish language in the
Mexican locale, you'd run the following:
setprop persist.sys.locale es-Rmex;stop;sleep 5;start
At this point, the emulator will restart with the new locale settings. Relaunch your app and
that's ityou're ready to test your app against your new locale settings.
You should also look for any instances where text or other locale-specific resources don't fit
with your current layout. This could be the following:
Resources that are smaller than the default version, such as the text that shrinks
dramatically during the translation process. Shrinking resources can leave gaping
holes in your layout, or they can throw other UI elements off balance and create a
layout that, while not completely broken, does look pretty odd.
Resources that are present in some versions of your UI and missing in others.
Again, this can cause awkward gaps and aesthetic problems in your layout. If
you're intentionally omitting certain resources, you might want to look for
something to fill the gap this resource leaves behind, or as a last resort, supply an
alternative layout that's designed specifically for this locale.
Resources that are much larger than the default version, which can result in a
cluttered, cramped-looking UI or usability problems, such as touchable areas that
are pushed too close to one another.
Resources that aren't appropriate for the current screen configuration. As already
mentioned, different locales may also mean different hardware, software, and
screen configurations. If you're targeting multiple countries and regions, make
sure you research the most popular Android devices within these specific
demographics, and then test your app across AVDs that reflect the hardware,
software, and screen configurations that are most commonly used within these
different areas.
Chapter 8
[ 267 ]
6. Copy Beta opt-in URL. You can then share this link with your testers. When a
potential tester clicks this link, they'll see an explanation about what being a beta
tester entails. They can then decide whether to participate in the test or not.
7. After copying Beta opt-in URL, you'll need to enter an e-mail address or URL
that you'll use to collect feedback from your testers. Enter this information in
the Feedback channel field, then click on Save.
Gathering tester feedback
Since testers can't leave reviews on your app's Google Play page, you'll
need to provide them with an alternative way of sending you their
feedback. Whenever you launch a testing program through Developer
Console, it's crucial you complete the Feedback channel field as this is
your testers' primary way of communicating with you.
This feedback channel could take the form of an address or URL, but you
may also want to consider setting up a Google+ page or Google Group for
your testers. Whatever your preferred method of gathering feedback, it's
important to recognize that anyone who tests your app is doing you a
favor, so you should make it as easy as possible for them to send you their
feedback.
If providing feedback feels like hard work, then your testers simply won't
botherthey'll keep their thoughts to themselves, and your project will
suffer as a result.
After a round of closed beta testing, you may want to move on to open beta testing, where
you specify a maximum number of testers but don't specify their e-mail addresses.
To launch an open beta testing program, make sure you're logged into Developer Console,
and then select APK from the left-hand side menu. Select Beta testing, open the drop-down
menu, select Set up Open Beta Testing, and then specify the maximum number of users
who'll be able to beta test your app.
Copy Beta opt-in URL and share it with your testers. Again, make sure you enter an e-mail
address or URL in Feedback channel, and then click on Save.
[ 268 ]
Chapter 8
This may sound like the kind of thing that requires a massive budget and a dedicated
marketing team, but you can tailor the scope of your campaign to suit your budget and how
much free time you have to promote your app. Even if your app is a one-person project,
there's no end to budget-friendly (and in some cases, free) ways of promoting your app to
an international audience, especially when you're promoting your app online.
A marketing campaign could be as simple as writing a press release announcing the release
of your app, and then arranging for this text to be translated into the various languages
your app supports. You could then spread your press release across the World Wide Web
via social networks, free news and press release websites, your own blog, or any other
places where you can post content for free.
Don't get carried away and post your marketing materials absolutely
everywhere just for the sake of it. Spamming is only going to hurt your
app's reputation in the long run.
You should also translate any other promotional materials you create, such as banners,
virtual badges, adverts, or memes.
Even if your promotional graphics don't feature any text, you should still look for
opportunities to tweak these graphics, so they're more likely to resonate with each of your
target locales. For example, could you include any geographical or cultural references that
would make your graphics more appealing to users in specific regions? In our recipe app
example, this might mean identifying recipes that are more likely to appeal to sections of
our target audience and then featuring these recipes more prominently in the app's
promotional banners and adverts.
If you create any promotional videos, you should also create localized versions of these
videos for every language your app supports. This may mean recording entirely new audio
for every video or providing subtitles.
Remember, the key to attracting an international audience is to create the illusion that your
app was designed with each user's specific locale in mind.
[ 269 ]
You can create multiple localized versions of your app's Google Play listing via Developer
Console. Then, when a user opens your app's listing, Google Play will automatically
determine that user's location, and it'll display the version of your listing that's the most
appropriate for their language, country, or region settings. If Google Play can't find a
suitable locale-specific version of your app's listing, it'll display your app's default Google
Play page instead.
To create localized Google Play listings, log into your Developer Console account, and
select App applications from the left-hand side menu. Select the app you want to work
with, followed by Store listing.
To create a new, localized version, click on the Manage translations button. At this point,
you can purchase a translation by clicking on Purchase translations and following the
onscreen instructions:
If you already have some translated text you want to add to your localized store listing,
select Add your own translation. Select all the languages you want to create a localized
listing for (don't worry, you can always add more later on), and click on Add.
[ 270 ]
Chapter 8
At this point, Developer Console will take you back to the store listing form, but now, if you
click on the Languages button, you'll see a drop-down list of all the languages you've just
added. Clicking on any of these languages will take you to a separate form where you can
craft an entirely new store listing, which will be displayed whenever someone views your
app in Google Play with these locale settings.
If you need to delete one of your localized pages at any point, simply click on the Manage
Translations button, followed by Remove translations, and then choose the language you
want to remove. If you want to change what version of your Google Play page is considered
the default, click on the Manage Translations button again, and select Change default
language.
Creating a localized store listing isn't just about translating your app's description; you
should also supply alternate graphics. Even when a user is viewing a localized version of
your Google Play page, they may still be unsure whether your app actually supports their
language. Don't leave any room for doubt; take screenshots of your UI in all the languages it
supports, and then upload these screenshots to the corresponding version of your app's
Google Play page.
As you're building your app's Google Play page, Developer Console will
offer hints about how your app can reach the widest possible audience.
These tips contain some useful information, so make sure you check them
out by selecting Optimization Tips from the left-hand side menu.
At the very least, you should monitor your app's Google Play reviews. The Google Play
store helpfully translates all reviews for you, and you should try and respond to any
question or suggestions that come in via Google Play, regardless of the language they're
written in.
Wherever possible, you should respond to Google Play reviews in the poster's language,
even if it means resorting to an online translation tool. Just be aware that translation tools
tend to generate responses that are a little off, so it's a good idea to let users know that
you're using a translation tool, just so they know to overlook any clunky phrasing or
grammatical errors.
Create a Google Play badge
Once you app is live, your goal is to drive as many people to its Google
Play page as possible. One way of doing this is to create a Google Play
badge. Whenever someone clicks on this badge, it'll take them direct to
your app's Google Play listing.
You can post this badge anywhere you wanton your website, blog,
social media accounts, or you can incorporate it into your e-mail signature.
Just don't get carried away; no-one likes a spammer, and spamming your
app's Play badge isn't going to earn your app a loyal following in the long
run.
You can create a badge using the Google Play Badges generator (https:/
/play.google.com/intl/en_us/badges).
[ 272 ]
Chapter 8
So, how do you identify locales where users love your app? Developer Console provides
stats about the number of downloads, installs, and uninstalls that your app is racking up
across all the different locales it supports. To access this information, log in to
your Developer Console account, select the app you want to investigate, and then
select Statistics from the left-hand side menu.
But, let's be realistic, these stats aren't always going to be good news, and sometimes they
may reveal that your app is struggling to attract users in certain locales. If this is the case,
then you should try and figure out what might be hindering your app's success.
It might be something that you can fix, such as a less-than-perfect translation, or the fact
that your app has hardware, software, or screen configuration requirements that aren't
representative of the Android devices commonly used in this locale. However, the problem
may be something that isn't quite so easy to fix, such as a lack of interest in your app's genre
or subject matter, or a rival app that's already dominating the marketplace.
Depending on the reasons behind your app's poor performance, you may decide to try and
address the issue, or you may decide that it makes more sense to drop support for this
particular locale and redirect the time and effort into areas where your app has already
found an enthusiastic audience.
Just remember that launching your app internationally is only phase one. If your app is
going to find global success, then you'll have to make an ongoing effort to support users
from all over the world, as well as continuously monitor how your app is faring in all the
different locales.
Summary
In this chapter, we looked at how to reach the widest possible audience, from supporting
different versions of the Android operating system, to optimizing your app for different
hardware, software, screen sizes, screen densities, and orientations. We even covered
translating our app into different languages. We also touched on how to promote your app
via advertising and marketing campaigns.
Now that you know how to attract an audience, in the next chapter, we'll look at how to
wow this audience by optimizing our app's UI.
[ 273 ]
www.PacktPub.com
Stay Connected: