Android String Resources Gotchas
When using the Android SDK to program Android devices you are encouraged to keep the Graphical User Interface (GUI) definition separate from the code. In Applications (Apps) a layout defines the GUI and the code is contained in an Activity. This helps the design and mainteinance for future App releases. Allowing the App to be quickly adapted to future devices. The same applies to any text that appears on a screen in the App. Separating the strings from the layouts and activities helps future maintenance and support for additional languages. This article shows how the strings in an App can be centralised into one resource file to ease maintenance. More importantly it covers some little known issues that can occur with strings in resource files. A developer aware of such issues will save time by implementing workarounds immediately rather than by trial and error. Examples are given for the various problems, or gotchas, that can occur.
Displaying Text with a TextView
When some text is required on a screen it can be displayed in a
TextView via code in the activity:
TextView tview = (TextView) findViewById(R.id.textView1); tview.setText("This is text");
In Android Studio the text for a screen widget can be access via the Properties pane:
In the Extensible Markup Language (XML) file that stores the layout the text is stored using the android:text attribute:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" />
Defining Text in Studio Resource Files
If there are several layout files defined to support a variety of screens then the text is being defined in several places. Changing the text in future releases means ensuring several locations are changed correctly. The same applies if the text is set in several source code files, adding unneccessary maintenance. Instead, text in a project can be centralized into a strings.xml resource file. The file is located in the directory values under res in the project folders.
Centralizing text means only one place to go to change it. It also makes localization (supporting different languages) easier. Here is an example of a strings.xml file:
<!--?xml version="1.0" encoding="utf-8"?--> <resources> <string name="app_name">Strings XML</string> <string name="text1">This is text</string> <string name="text2">And so is this</string> </resources>
To access a string declared as a resource ring use @ (the at symbol) followed by string then a slash and the string's name. Using the strings.xml example above, the text for two TextViews is set from string resources in the following example XML layout file:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.stringsxml.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/text1" android:id="@+id/textView1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/text2" android:id="@+id/textView2" android:layout_below="@+id/textView1" /> </RelativeLayout>
In Studio using the browse (ellipses) button for the text property allows values stored in strings.xml files to be accessed (and defined):
(When strings.xml, or any resource file including a layout, is saved Java classes are generated by Studio under the build directory. The R.java class, think R for resources, under the generated directory provides a static int. This can be used to reference a resource. For example R.id.textview1 is the id resource for the above first TextView, and R.string.text1 is used to reference the text1 string.)
Cross Referencing and Escaping String Resources
In strings.xml an entry can duplicate another string by referencing it the same way as a layout file:
<string name="text1">This is text</string> <string name="text2">@string/text1</string>
Since @ is used to indicate another string resource trying to set text to a single @, with
<string name="text1">@</string> will not work. Neither will text that starts with an @, for example:
<string name="text2">@mytwittername</string>, Studio displays an error:
The @ needs to be escaped with a \ (backslash), i.e. \@ and \@mytwittername. If the @ does not start a string or is being set in code it does not need to be escaped, e.g.
This problem of @ as the first character, or only character, also applies to the ? (question mark). If it appears at the start of a string it also needs escaping, \?. An alternative to escaping the @ or ? is to use quotes (speech marks), the closing quote mark is optional:
<string name="text1">"@"</string> <string name="text2">"?"</string>
Any number of quotes or white space before and after text is dropped. The two lines above produce an identical result to these two lines:
<string name="text1">""""""""""@"""""""</string> <string name="text2"> "?" </string>
Handling XML Sensitive Characters
There are characters for which escaping or wrapping the string in quotes will not work:
<string name="text1">War & Peace</string> <string name="text2">War and Peace</string>
The first line will error because of the & (ampersand). Why does & cause a problem in Android string resources? It is the XML format itself. Why? XML requires balanced pairs of tags, e.g.
</string>, and each start tag and end tag are enclosed in opening, < and closing > (angle brackets). Once a start tag is encountered the SDK is on the lookout for the opening angle bracket of the end tag. This produces a problem if the content of the tags contains the opening bracket itself:
<string name="question">Is 5 < 6?</string>
This will not work. The solution is to use an XML internal entity, this is similar to using an escape character but is in a specific format for XML. The format is an ampersand, &, followed by the entity name and then a semi-colon. For the open angle bracket, or less than symbol, the name is lt, therefore the full entity is < as in:
<string name="question">Is 5 < 6?</string>
Depending upon what is required in an XML file at a particular point there are five internal entities defined for XML that can be used, they are:
List of XML Entities
|left angle bracket||<||lt||<|
|right angle bracket||>||gt||>|
|single quote or apostrophe||'||apos||'|
|double quote or speech mark||"||quot||"|
Now we can see why the ampersand causes a problem. It is used to define an internal entity and thus when one is required the amp entity itself must be used. Therefore
<string name="text1">War & Peace</string> becomes
<string name="text1">War & Peace</string>.
However, the XML internal entity apos, while valid for XML, is reported as an error:
<string name="text1">This isn't working</string> <string name="text2">This isn't working either</string>
It is another character that requires escaping or wrapping in quotes:
<string name="text1">This\'ll work</string> <string name="text2">"This'll work as well"</string>
The same for quotes (speech marks), including the XML entity version:
<string name="text1">Quote: \"to be, or not to be\"</string> <string name="text2">Quote: \"to be, or not to be\"</string>
To see the escape character (backslash), use two of them:
<string name="text1">Backlash:\\</string> <string name="text2">Slash:/</string>
Formatting Android TextView String Resources
When defining a string that requires pre or post space again use quotes:
<string name="text1"> No spaces before and after </string> <string name="text2">" Two spaces before and after "</string>
Strings will support a new line by escaping the letter n:
<string name="text1">Split over\ntwo lines</string> <string name="text2">2 TextViews\n4 Lines</string>
Escaping a t adds tabs to the defined string:
<string name="text1">Tab stops\t\ta\t\tb</string> <string name="text2">\t\t\t\t\t\tc\t\td</string>
Visual String Attributes
The android:textstyle attribute of a TextView can be used to set the text to bold or italic, or both (also accessible via Properties in Studio):
android:textStyle="bold" android:textStyle="italic" android:textStyle="bold|italic"
This can be achieved in strings.xml using a bold (<b>) or italic (<i>) tag, plus there is an underline (<u>) tag. However, instead of applying to the whole text of the TextView it can be used for individual portions of the text:
<string name="text1">Hey look: <b>bold</b> and <i>italic</i>.</string> <string name="text2">And look: <u>underline</u> and <b><i><u>bold italic underline</u></i></b>.</string>
However, visual aspects in strings.xml are limited to bold and italic. To change other visual appearances of a string change the other text attributes or add styles in the layout files. For example, to increase text size use the textSize attribute in the layout, setting the required size in scaled pixels (sp).
Additional Information on String Resources
When a new Android project is created the strings.xml file is added automatically. Yet it does not need to be called strings.xml, it can have any name and there can be multiple files containing string definitions (a string name must be unique across all resource files). For large projects this helps organise the source code.
This article has provided some coverage of string resource functionality within an Android project. The example string resources shown here can be seen in an example program, also available from our Android Example Projects page. It can be imported into Studio for executing on a device (virtual or otherwise).
- Add a Simple List to an App for an example of using arrays of strings from the resource file.
- String resources at Android Developers: https://developer.android.com/guide/topics/resources/string-resource.html.
- A version of this article appears in the Android Cookbook.
Author:Daniel S. Fowler Published: Updated: