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.
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.
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
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 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
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
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.
XML syntax
Java code
Using colors in view definitions
XML Syntax (use escape sequences)
Using it in java
Using it in XML
XML syntax
The units could be
Java code
Using it in XML
Using images in XML
These are color rectangles
XML definitions
java code
xml code
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
tbd
Themes are files in the "res/values" sub directory with the following structure
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
Here is how you can apply one of those styles
Setting theme to an activity
Here is how you apply theme in the manifest.xml
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
The defined constants cover the following resource types
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
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
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
(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.
You can use facilities in android to read XML files that you could use as resources. Place these xml files in
Here is an example file "res/xml/test.xml"
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:
Other important methods of XmlPullParser include
Note that using the android.util.AttributeSet interface, this class can use the resource references like "@id/example" in attributes and resolve them.
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
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
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.
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
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.
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.
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
<resources>
<item type="id" name="text"/>
</resources>
<TextView android:id="@id/text">
..
</TextView>
A Recap of Android resources
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
Color Resources
<resources>
<color name="opaque_red">#f00</color>
<color name="translucent_red">#80ff0000</color>
</resources>
int color = getResources.getColor(R.color.opaque_red);
<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
<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>"%2$s"</b>
</string>
// 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);
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAlign="center"
android:text="@string/simple_welcome_message"/>
Dimension Resources
<resources>
<dimen name="one_pixel">1px</dimen>
<dimen name="double_density">2dp</dimen>
<dimen name="sixteen_sp">16sp</dimen>
</resources>
px - pixels
in - inches
mm - millimeters
pt - points
dp - adjusts to screen density
sp - use it for fonts. allows user sizing
float dimen = Resources.getDimen(R.dimen.one_pixel);
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/sixteen_sp"/>
Image resources
<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
<resources>
<drawable name="solid_red">#f00</drawable>
<drawable name="solid_blue">#0000ff</drawable>
<drawable name="solid_green">#f0f0</drawable>
</resources>
// 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);
<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
<?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
Theme Resources
<style name=string [parent=string] >
<item name=string>Hex value | string value | reference</item>+
</style>
<?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>
<!-- 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>
setTheme(R.style.ThemeNew);
<!-- 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
http://code.google.com/android/reference/android/R.html
anim
array
attr
color
dimen
drawable
id
layout
plurals
raw
sting
style
styleable
xml
A discussion on the structure of Android XML convention
<TextView
android:id="@+id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>;
<android.view.TextView
android:id="@+id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>;
<?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?
/>
Working with arbitrary XML Resource files
"res/xml"
<rootelem1>
<subelem1>
Hello World from an xml sub element
</subelem1>
</rootelem1>
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
getAttributeCount
getAttributeName
getAttribute<type>Value
Working with Raw Resources
"res/raw/test.txt"
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();
}
Working with Assets
TypeFace mFace = Typeface.createFromAsset(
getContext().getAssets(),
"font/samplefont.ttf");
//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/*.*/*.*
References