Understanding R.java

R.java

R.java is neat. R.java is elegant. Due to its subversiveness (in a good way) its makings are implicit. It is fun to learn about Android.R.

At a mile high level, every application has resouces. Familiar example of resources are strings, colors, and bitmaps. Instead of hard coding strings in an application one will use an id for a string.

Let's start with strings and see how they are used.

Create a file called "/res/values/srings.xml"


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">hello</string>
    <string name="app_name">hello appname</string>
</resources>

This file will automatically update a "java" class in your root package called R.java


package com.ai.android.helloworld;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int b1=0x7f050001;
        public static final int text1=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
   
        public static final int app_name=0x7f040001;
        public static final int app_name1=0x7f040003;
      
        public static final int hello=0x7f040000;
        public static final int hello1=0x7f040002;
    }
}

For now focus on the static definition for "static final class string". You will see two final static "int's" defined with "hello" and "app_name".

we could have used these any where in the source code using the structure


R.string.hello

But interestingly this is an "int" and not a "String". Most methods that take strings also take these resource identifiers.

Some of these conventions are reserved and some are not. For example it is just a convention that most sample applications define all strings in one file "strings.xml". But Android takes any number of arbitrary files as long as the structure of the xml file is as follows


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">hello</string>
    <string name="app_name">hello appname</string>
</resources>

So before copying the R.java here for a demonstration, I have placed another file called strings1.xml that has the following entries


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello1">hello</string>
    <string name="app_name1">hello appname</string>
</resources>

Eclipse android plugin will validate the uniqueness of these ids at compile time.

This pattern applies to all the files that are in the "values" sub directory.

It is important that the files are placed under "res/values" sub directory. All string resources identified by the element "string" are collected into a single java name space called R.string.

Layout Resources

Let us take a look at the next resource that is most often used. Take a look at the following code in He


public class HelloWorldActivity extends Activity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = (TextView)this.findViewById(R.id.text1);
        tv.setText("Try this text instead");
    }

This code here demonstrates a few important things about resources and R.java. The following line


setContentView(R.layout.main)

is pointing out that there is static class by the name of "layout" and there is a constant in there called "main" (an integer) pointing to a "View" defined by an xml file. This statement would expect the following file to be there


"/res/layout/main.xml"

However it is still a bit of mystery around what is


R.id.text1

What are "ids?" you could ask.

So let us untangle this thread by looking at the "main.xml"


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView 
   android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
 <Button 
   android:id="@+id/b1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@+string/hello"
   />   
</LinearLayout>

Files of this kind defines "Views" or "Pages" or "Layouts" for applications. In this case this file here lays out two controls or "views": a TextView and a "Button" in a top down fashion (because of vertical LinearLayout).

Each file in the "res/layout" sub directory generates a unique constant unlike string resources where irrespective of the number of files what matters is how many individual string resources are inside. In the case of layouts it is the number of files. For example if I have two files under "res/layout" called "file1.xml" and "file2.xml" then I will have the following entries in R.java


    public static final class layout {
      .... any other files 
        public static final int file1=0x7f030000;
        public static final int file2=0x7f030001;
    }

The views that are defined in these layout files can be accessed in code by referencing their ids from R.java file. Here is an example:


TextView tv = (TextView)this.findViewById(R.id.text1);
tv.setText("Try this text instead");

In this example the TextView is located by using the findViewById method of the Activity class. The constant R.id.text1 corresponds to the id defined for the TextView. The "id" for the TextView in the layout file is


<TextView android:id="@+id/text1"
..
</TextView>

The attribute value for attribute "id" is indicating that a constant called "text1" will be usd to uniquely identify this view among other views hosted by that activity. The id "text1" will be created if it doesn't exist already.

Resource Reference Syntax

The attribute syntax above "@+id/text1" is called a resource reference. It has the following formal structure


@[package:]type/name

The "type" will be one of the resource types availabe in R.java. It is worth reviewing what these are


drawable
id
layout
string
attr

"name" is the name given to the resource and also gets represented as an "int" constant in R.java. Now we come to the most important part of this syntax: The "package".

If you dont specify any package then the pair "type/name" will be resolved based on local resources and local R.java of this application or more precisely package.

If you say "android:type/name" then it will look in the package identified by "android" to be more precise "android.R.java" file. By that logic it is conceivable that you can use any java package name in its place to locate the right R.java to resolve the reference.

Based on this let us analyze a examples


<TextView id="text"> 
// Compile error, as id will not take raw text strings

<TextView id="@text"> 
// wrong syntax. It is missing a type name
// you will get an error "No resource type specified

<TextView id="@id/text"> 
//Error: No resource found that matches id "text"

<TextView id="@android:id/text"> 
// Error: Resource is not public
// indicating that there is no such id in android.R.id

<TextView id="@+id/text"> 
//Success: Creates an id called "text" in the local package

Defining your own ids

The following code segment


<TextView id="@+id/text"> 

indicates that (as pointed out) an id by name "text" is going to be used if one already exists. If it doesn't then a new one is going to be created. So when would an id like "text" might already exist in R.java for that to be reused.

One might be inclined to put a constant like "R.id.text" in R.java. But R.java is not editable, even if it were it gets regenerated all the time.

However there is a resource tag called that can be used to define an id with out attaching to any particular resource. Here is an example


<resources>
<item type="id" name="text"/>
</resources>

The "type" refers to the type of resource in this case an "id". Once this id is in place then the following View definition would work


<TextView android:id="@id/text">
..
</TextView>

A Recap of Android resources

Every Android programmer is first exposed to Resources through R.java and most likely to use String and Layout resources. Android supports many other types of resources. It is worth while to understand the general nature of these resources before enumerating each one of them in detail.

Android supports XML files, bitmap files for images, and raw files (examples of which could include audio and video). With in the set of XML files there are two type. One kind of XMLs gets compiled into binary format and the other set just gets copied as they are.

Here are some important sub directories in the "res" folder


anim - compiled animation files
drawable - bitmaps
layout - ui/view definitions
values - arrays, colors, dimens, strings, styles
xml  - compiled arbitrary raw xml files
raw - un compiled raw files

All these resources are compiled by "aapt" resource compiler and placed into the final "apk" file. "aapt" stands for Android Asset Packaging Tool. The tool that generates the final ZIP file of application assets. In addition to collecting raw assets together, it also parses resource definitions into binary asset data.

Color Resources

XML syntax


<resources>
   <color name="opaque_red">#f00</color>
   <color name="translucent_red">#80ff0000</color>
</resources>

Java code


int color = getResources.getColor(R.color.opaque_red);

Using colors in view definitions


<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAlign="center"
          android:textColor="@color/translucent_red"
          android:text="Some Text"/>

String Resources

XML Syntax (use escape sequences)


<string name="good_example">"This'll work"</string>
<string name="good_example_2">This\'ll also work</string>
<string name="styled_welcome_message">We are <b><i>so</i></b> glad to see you.</string>
<string name="search_results_resultsTextFormat">
 %1$d results for <b>&quot;%2$s&quot;</b>
</string>

Using it in java


// Assign a styled string resource to a TextView
// on the current screen.
CharSequence str = getString(R.string.styled_welcome_message);
TextView tv = (TextView)findViewByID(R.id.text);
tv.setText(str);

//using formatted strings
String resultsTextFormat = getContext().getResources().getString
                  (R.string.search_results_resultsTextFormat);
String resultsText = String.format(resultsTextFormat, count, escapedTitle);
CharSequence styledResults = Html.fromHtml(resultsText);

Using it in XML


<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAlign="center"
          android:text="@string/simple_welcome_message"/> 

Dimension Resources

XML syntax


<resources>
    <dimen name="one_pixel">1px</dimen>
    <dimen name="double_density">2dp</dimen>
    <dimen name="sixteen_sp">16sp</dimen>
</resources>

The units could be


px - pixels
in - inches
mm - millimeters
pt - points
dp - adjusts to screen density
sp - use it for fonts. allows user sizing

Java code


float dimen = Resources.getDimen(R.dimen.one_pixel);

Using it in XML


<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="@dimen/sixteen_sp"/>

Image resources

Using images in XML


<ImageView id="@+id/icon"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:tint="#FF000000"
   android:src="@drawable/chat_icon"/>

Color drawble Resources

These are color rectangles

XML definitions


<resources>
    <drawable name="solid_red">#f00</drawable>
    <drawable name="solid_blue">#0000ff</drawable>
    <drawable name="solid_green">#f0f0</drawable>
</resources>

java code


// Assign a PaintDrawable as the background to
// a TextView on the current screen.
Drawable redDrawable = Resources.getDrawable(R.drawable.solid_red);
TextView tv = (TextView)findViewByID(R.id.text);
tv.setBackground(redDrawable);

xml code


<TextView android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textAlign="center"
          android:background="@drawable/solid_red"/>

Stretchable images


<Button id="@+id/tiny"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:text="Tiny"
        android:textSize="8sp"
        android:background="@drawable/my_button_background"/>

<Button id="@+id/big"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerInParent="true"
        android:text="Biiiiiiig text!"
        android:textSize="30sp"
        android:background="@drawable/my_button_background"/>

Layout Resource oddities

Each xml node for an object supports both its own properties and also parents properties. The names of xml attributes for each class is documented in R.Stylable class.

The xml also supports attributes that look like "layout_abcAttrbitue". The word "layout" is reserved. It will get stripped off and the word after "_" (abcAttribute) is used to set the properties of the contained lay out object of a View.

Some examples


<?xml version="1.0" encoding="utf-8"?>
<!-- res/main_screen.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"    // The object's own orientation property
              android:padding="4"               // Inherited View property
              android:gravity="center"          // The object's own property
              android:layout_width="fill_parent"  // Parent object's LinearLayout.LayoutParams.width
              android:layout_height="fill_parent"> // Parent object's LinearLayout.LayoutParams.height

   <TextView android:layout_width="fill_parent"   // TextView.LayoutParams.width
             android:layout_height="wrap_content" // TextView.LayoutParams.height
             android:layout_weight="0"            // TextView.LayoutParams.weight
             android:paddingBottom="4"            // TextView.paddingBottom
             android:text="@string/redirect_getter"/> // TextView.text

   <EditText id="@+id/text"
             android:layout_width="fill_parent"   // EditText.LayoutParams.width
             android:layout_height="wrap_content" // EditText.LayoutParams.height
             android:layout_weight="0"            // EditText.LinearLayoutParams.weight
             android:paddingBottom="4">           // EditText.paddingBottom
       <requestFocus />
   </EditText>

   <Button id="@+id/apply"
           android:layout_width="wrap_content"  // Button.LayoutParams.width
           android:layout_height="wrap_content" // Button.LayoutParams.height
           android:text="@string/apply" />      // TextView.text
</LinearLayout>

Custom Layout Resources

tbd

Theme Resources

Themes are files in the "res/values" sub directory with the following structure


<style name=string [parent=string] >
   <item name=string>Hex value | string value | reference</item>+
</style>

where parent is the parent theme. item is an attribute name, with a value that is a color value or a string or a resource. Here are some examples


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="SpecialText">
        <item name="android:textSize">18sp</item>
        <item name="android:textColor">#008</item>
    </style>

<style name="ThemeNew">
   <item name="windowFrame">@drawable/screen_frame</item>
   <item name="windowBackground">@drawable/screen_background_white</item>
   <item name="panelForegroundColor">#FF000000</item>
   <item name="panelBackgroundColor">#FFFFFFFF</item>
   <item name="panelTextColor">?panelForegroundColor</item>
   <item name="panelTextSize">14</item>
   <item name="menuItemTextColor">?panelTextColor</item>
   <item name="menuItemTextSize">?panelTextSize</item>
</style>
</resources>

Here is how you can apply one of those styles


<!-- MainPageLayout.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_height="fill_parent"
              android:layout_width="fill_parent"
              android:orientation="vertical"
              android:scrollbars="vertical"
              id="main_frame">
    <EditText id="@+id/text1"
              style="@style/SpecialText"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Hello, World!" />
</LinearLayout>

Setting theme to an activity


setTheme(R.style.ThemeNew);

Here is how you apply theme in the manifest.xml


<!-- AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.codelab.rssexample">
       <activity class="AddRssItem" 
            android:label="@string/add_item_label" 
         android:theme="@android:style/Theme.Dialog"/>
</manifest>

Android.R

Just like R.java in a local package defines constants, Android has a set of constants for common resources that it defines. These constants can be seen at


http://code.google.com/android/reference/android/R.html

The defined constants cover the following resource types


anim
array
attr
color
dimen
drawable
id
layout
plurals
raw
sting
style
styleable
xml

A discussion on the structure of Android XML convention

If you notice the XML files in android closely you will that elements do not carry a namespace. But the attributes do carry a namespace caleld "android:". Usually elements carry a namespace in other xml parlance.

Consider the following TextView


<TextView 
   android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />;

Android XML is there to facilitate specification of objects in XML and not there for the purity of XML. Primary goal is to go between objects and XML seamlessly. To this end some of the XML seems odd.

So the above XML is truly


<android.view.TextView 
   android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />;

allowing an instantiation of class "android.view.TextView". We already have seen the explnation for the attribute value syntax starting with "@" or "@+".

The attributes need to be namespaced to allow


<?xml version=?1.0? encoding=?UTF-8??>
<com.me.myapp.MyTextView
xmlns:android=?http://schemas.android.com/apk/res/android?
xmlns:app=?http://schemas.android.com/apk/res/com.me.myapp?
android:layout_width=?fill_parent?
android:layout_height=?wrap_content?
android:text=?Hello World?
app:mySpecialFeature=?true?
/>

(Borrowed from notes from Diane Hackborn). Notice how MyTextView (having derived from TextView) specifies its own attributes through a name space of "app"

These XML documents are parsed at build time into a binary representation that is what is really read on the device. In addition to turning the XML structure into a binary format, android also does pre-processing such as assigning unique identifiers to attribute names based on their namespaces to avoid string comparisons, looking up attribute values like ?@string/mystring? to the resource identifier they are referencing, converting integer and color values like ?#fff? to 32-bit ints, stripping unnecessary things like comments, etc. So in a way you can look at the XML as our current way to generate the ?real? raw resource data, which happens to be designed to map directly to the facilities XML provides.

Working with arbitrary XML Resource files

You can use facilities in android to read XML files that you could use as resources. Place these xml files in


"res/xml"

Here is an example file "res/xml/test.xml"


<rootelem1>
   <subelem1>
      Hello World from an xml sub element
   </subelem1>
</rootelem1>

aapt will compile them into efficient xml resources. Then you can use XmlPullParser to parse these files. You can get the XmlPullParser implementation using the following code from any context including activity:


   Resources res = this.getResources();
   XmlResourceParser xpp = res.getXml(R.xml.test);

private String getEventsFromAnXMLFile()
throws XmlPullParserException, IOException
{
   StringBuffer sb = new StringBuffer();
   Resources res = this.getResources();
   XmlResourceParser xpp = res.getXml(R.xml.test);
   
   xpp.next();
   int eventType = xpp.getEventType();
    while (eventType != XmlPullParser.END_DOCUMENT) 
    {
        if(eventType == XmlPullParser.START_DOCUMENT) 
        {
           sb.append("******Start document");
        } 
        else if(eventType == XmlPullParser.START_TAG) 
        {
           sb.append("\nStart tag "+xpp.getName());
        } 
        else if(eventType == XmlPullParser.END_TAG) 
        {
           sb.append("\nEnd tag "+xpp.getName());
        } 
        else if(eventType == XmlPullParser.TEXT) 
        {
           sb.append("\nText "+xpp.getText());
        }
        eventType = xpp.next();
    }//eof-while
    sb.append("\n******End document");
    return sb.toString();
}//eof-function

Other important methods of XmlPullParser include


getAttributeCount
getAttributeName
getAttribute<type>Value

Note that using the android.util.AttributeSet interface, this class can use the resource references like "@id/example" in attributes and resolve them.

Working with Raw Resources

Raw resources are arbitrary file resources like audio, video, or text files that require localization or referenced through id's. These files are placed in "res/raw". Each file will have an identifier generated in R.java.

Consider the following text file


"res/raw/test.txt"

Imagine you put the following in that text file Hello world in raw resource test.txt

you can then read that file into a text string as follows


String getStringFromRawFile()
{
	Resources r = getResources();
	InputStream is = r.openRawResource(R.raw.test);
	String myText = convertStreamToString(is);
	is.close();
	return myText;
}

String convertStreamToString(InputStream is)
{   
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	int i = is.read();
	while (i != -1)
	{
		baos.write(i);
		i = baos.read();
	}
	return baos.toString();
}

However if you want to process XML files like this then you want to keep them in the "res/xml" directory and not in the "res/raw" directory. The files in this "raw" directory are not compiled and included in the package as they are.

Working with Assets

There is one more directory in Android where you can keep files to be included in the package. This directory is at the same level as "res". This means "assets" is not part of the "res" sub directories. The files in "assets" do not generate ids in R.java. One has to specify the file path to read them.

Consider the following example from one of the api demos


TypeFace mFace = Typeface.createFromAsset(
                          getContext().getAssets(),
                                  "font/samplefont.ttf");

you will notice that an asset is referenced using its directory path and not a specific id. More over the file path is a relative path starting at "assets/".

One will use AssetManager class to access these files.


//Note: Exceptions are not shown in the code
String getStringFromAssetFile()
{
		AssetManager am = getAssets();
		InputStream is = am.open("test.txt");
		String s = convertStreamToString(is);
		is.close();
		return s;
}

Complete directory structure


/res/values/strings.xml
           /colors.xml
           /dimens.xml
           /attrs.xml
           /styles.xml
    /drawable/*.png
             /*.jpg
             /*.gif
             /*.9.png
    /anim/*.xml`
    /layout/*.xml
    /raw/*.*
    /xml/*.xml
/assets/*.*/*.*   

Notice that only the non resource directory of "assets" can contain an arbitrary list of sub directories. Every other directory can only have files at the level of that directory and no deeper. This is how R.java generates identifiers for those files.

References

1. Resources and Internationalization from SDK documentation

http://code.google.com/android/devel/resources-i18n.html

2. Available Resource Types from SDK documentation

http://code.google.com/android/reference/available-resources.html

3. System Resource Identifiers

http://code.google.com/android/reference/android/R.html

4. Resources API

http://code.google.com/android/reference/android/content/res/Resources.html

5. AssetManager API

http://code.google.com/android/reference/android/content/res/AssetManager.html