The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Some Words About Resources

It is quite likely that by this point in time, you are “chomping at the bit” to get into actually writing some code. This is understandable. That being said, before we dive into the Java source code for our stub project, we really should chat briefly about resources.

Resources are static bits of information held outside the Java source code. As we discussed previously, resources are stored as files under the res/ directory in your source set (e.g., app/src/main/res/). Here is where you will find all your icons and other images, your externalized strings for internationalization, and more.

These are separate from the Java source code not only because they are different in format. They are separate because you can have multiple definitions of a resource, to use in different circumstances. For example, with internationalization, you will have strings for different languages. Your Java code will be able to remain largely oblivious to this, as Android will choose the right resource to use, from all candidates, in a given circumstance (e.g., choose the Spanish string if the device’s locale is set to Spanish).

We will cover all the details of these resource sets later in the book. Right now, we need to discuss the resources in use by our stub project, plus one more.

This chapter will refer to the res/ directory as a shorthand for the app/src/main/res/ directory of the project.

String Theory

Keeping your labels and other bits of text outside the main source code of your application is generally considered to be a very good idea. In particular, it helps with internationalization (I18N) and localization (L10N). Even if you are not going to translate your strings to other languages, it is easier to make corrections if all the strings are in one spot instead of scattered throughout your source code.

Plain Strings

Generally speaking, all you need to do is have an XML file in the res/values directory (typically named res/values/strings.xml), with a resources root element, and one child string element for each string you wish to encode as a resource. The string element takes a name attribute, which is the unique name for this string, and a single text element containing the text of the string:

<resources>
  <string name="quick">The quick brown fox...</string>
  <string name="laughs">He who laughs last...</string>
</resources>

One tricky part is if the string value contains a quote or an apostrophe. In those cases, you will want to escape those values, by preceding them with a backslash (e.g., These are the times that try men\'s souls). Or, if it is just an apostrophe, you could enclose the value in quotes (e.g., "These are the times that try men's souls.").

For example, a project’s strings.xml file could look like this:

<resources>
  <string name="app_name">EmPubLite</string>
</resources>

We can reference these string resources from various locations, in our Java source code and elsewhere. For example, the app_name string resource often is used in the AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.commonsware.empublite"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools">

  <supports-screens
    android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="false"
    android:xlargeScreens="true" />

  <application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:ignore="GoogleAppIndexingWarning">
    <activity android:name=".EmPubLiteActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>

Here, the android:label attribute of the <application> element refers to the app_name string resource. This will appear in a few places in the application, notably in the list of installed applications in Settings. So, if you wish to change how your application’s name appears in these places, simply adjust the app_name string resource to suit.

The syntax @string/app_name tells Android “find the string resource named app_name”. This causes Android to scan the appropriate strings.xml file (or any other file containing string resources in your res/values/ directory) to try to find app_name.

Um, Wait, My Manifest Does Not Look Like That

When you view a manifest like that in Android Studio, it may appear as though you are not using resources, as you may not see @string/... references:

AndroidManifest.xml, As Initially Viewed in Android Studio
Figure 49: AndroidManifest.xml, As Initially Viewed in Android Studio

Here, android:label looks as though it is the hard-coded value “EmPubLite”.

However, notice that the attribute value is formatted differently than the others. The rest are green text with a white background, while this one is gray text with a shaded background.

That is because Android Studio is lying to you.

If you hover your mouse over the value, you will see the real attribute appear just below it:

AndroidManifest.xml, With Mouse Hovering Over EmPubLite
Figure 50: AndroidManifest.xml, With Mouse Hovering Over “EmPubLite”

And, if you click on the fake value, you will see the real XML, with the real string resource value.

What is happening is that Android Studio, by default, will substitute a candidate value for the resource in its presentation of the manifest, other resources that refer to resources, and even Java code. Any time you see that gray-on-light-blue formatting, remember that this is not the real value, and that you have to uncover the real value via hovering over it or clicking on it.

Styled Text

Many things in Android can display rich text, where the text has been formatted using some lightweight HTML markup: <b>, <i>, and <u>. Your string resources support this, simply by using the HTML tags as you would in a Web page:

<resources>
  <string name="b">This has <b>bold</b> in it.</string>
  <string name="i">Whereas this has <i>italics</i>!</string>
</resources>

CDATA. CDATA Run. Run, DATA, Run.

Since a strings resource XML file is an XML file, if your message contains <, >, or & characters (other than the formatting tags listed above), you will need to use a CDATA section:

<string name="report_body">
<![CDATA[
<html>
<body>
<h1>TPS Report for: {{reportDate}}</h1>
<p>Here are the contents of the TPS report:</p>
<p>{{message}}</p>
<p>If you have any questions regarding this report, please
do <b>not</b> ask Mark Murphy.</p>
</body>    
</html>
]]>
  </string>

The Directory Name

Our string resources in our stub project are in the res/values/strings.xml file. Since this directory name (values) has no suffixes, the string resources in that directory will be valid for any sort of situation, including any locale for the device. We will need additional directories, with distinct strings.xml files, to support other languages. We will cover how to do that later in this book.

Editing String Resources

If you double-click on a string resource file, like res/values/strings.xml, in Android Studio, you are presented the XML and edit it that way. There is an option for entering a dedicated string translation view, covered later in this book.

Multi-Locale Support

Android 7.0+ users can indicate that they support more than one language:

Android 7.0 Language Settings
Figure 51: Android 7.0 Language Settings

The user can choose the relative priorities of these languages, by grabbing the handle on the right side of the row and dragging the language higher or lower in the list.

This has impacts on resource resolution for any locale-dependent resources, such as strings. Now Android will check multiple languages for resource matches, before falling back to the default language (e.g., whatever you have in res/values/strings.xml). Hence, it is important that you ensure that you have a complete set of strings for every language that you support, lest the user perhaps wind up with a mixed set of languages in the UI.

You can find out what languages the user has requested via a LocaleList class and its getDefault() static method. This, as the name suggests, has a list of Locale objects representing the user’s preferred languages. If you had previously been using Locale alone for this (e.g., for specialized in-app language assistance beyond resources), you will want to switch to LocaleList for Android 7.0 and beyond.

Got the Picture?

The preview of this section is sleeping in.

Dimensions

The preview of this section took that left turn at Albuquerque.

The Resource That Shall Not Be Named… Yet

The preview of this section is in an invisible, microscopic font.