Android Application Development in step by step info
Part 02
Android Fragments
A Fragment is a piece of an application's user interface or behavior that can be placed in an Activity which enable more modular activity design. It will not be wrong if we say, a fragment is a kind of sub-acitivity. Following are important points about fragment:
A fragment has its own layout and its own behavior with its own lifecycle callbacks.
You can add or remove fragments in an activity while the activity is running.
You can combine multiple fragments in a single activity to build a multi-pane UI.
A fragment can be used in multiple activities.
Fragment life cycle is closely related to the lifecycle of its host activity which means when the activity is paused, all the fragments available in the acivity will also be stopped.
A fragment can implement a behavior that has no user interface component.
Fragments were added to the Android API in Honeycomb version of Android which API version 11.
You create fragments by extending Fragment class andYou can insert a fragment into your activity layout by declaring the fragment in the activity's layout file, as a<fragment> element.
Prior to fragment introduction, we had a limitation because we can show only a single activity on the screen at one given point in time. So we were not able to divide device screen and control different parts separately. But with the introduction of fragment we got more flexibility and removed the limitation of having a single activity on the screen at a time. Now we can have a single acitivity but each acitivity can comprise of multiple fragments which will have their own layout, events and complete lifecycle.
Following is a typical example of how two UI modules defined by fragments can be combined into one activity for a tablet design, but separated for a handset design.
The application can embed two fragments in Acivity A, when running on a tablet-sized device. However, on a handset-sized screen, there's not enough room for both fragments, so Activity A includes only the fragment for the list of articles, and when the user selects an article, it starts Activity B, which includes the second fragment to read the article.
Fragment Life Cycle
Android fragments have their own life cycle very similar to an android activity. This section briefs different stages of its life cycle.
Phase I: When a fragment gets created, it goes through the following states:
onAttach()
onCreate()
onCreateView()
onActivityCreated()
Phase II: When the fragment becomes visible, it goes through these states:
onStart()
onResume()
Phase III: When the fragment goes into the background mode, it goes through these states:
onPaused()
onStop()
Phase IV: When the fragment is destroyed, it goes through the following states:
onPaused()
onStop()
onDestroyView()
onDestroy()
onDetach()
How to use Fragments?
This involves number of simple steps to create Fragments.
First of all decide how many fragments you want to use in an activity. Fors example let's we want to use two fragments to handle landscape and portrait modes of the device.
Next based on number of fragments, create classes which will extend the Fragment class. The Fragment class has above mentioned callback functions. You can override any of the functions based on your requirements.
Corresponding to each fragment, you will need to create layout files in XML file. These files will have layout for the defined fragments.
Finally modify activity file to define the actual logic of replacing fragments based on your requirement.
Here is the list of important methods which you can to override in your fragment class:
onCreate() The system calls this when creating the fragment. You should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
onCreateView() The system calls this callback when it's time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View component from this method that is the root of your fragment's layout. You can return null if the fragment does not provide a UI.
onPause() The system calls this method as the first indication that the user is leaving the fragment. This is usually where you should commit any changes that should be persisted beyond the current user session.
Example
This example will explain you how to create your ownFragments. Here we will create two fragments and one of them will be used when device is in landscape mode and another fragment will be used in case of portrait mode. So let's follow the following steps to similar to what we followed while creating Hello World Example:
Step
Description
1
You will use Eclipse IDE to create an Android application and name it as MyFragments under a package com.example.myfragments, with blank Activity.
2
Modify main activity file MainActivity.java as shown below in the code. Here we will check orientation of the device and accordingly we will switch between different fragments.
3
Create a two java files PM_Fragment.java andLM_Fragement.java under the packagecom.example.myfragments to define your fragments and associated methods.
4
Create layouts files res/layout/lm_fragment.xmland res/layout/pm_fragment.xml and define your layouts for both the fragments.<
5
Modify the detault content of res/layout/activity_main.xml file to include both the fragments.
6
Define required constants in res/values/strings.xml file
7
Run the application to launch Android emulator and verify the result of the changes done in theaplication.
Following is the content of the modified main activity file src/com.example.mycontentprovider/MainActivity.java:
package com.example.myfragments;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.res.Configuration;
import android.view.WindowManager;
public class MainActivity extends Activity {
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
Configuration config =getResources().getConfiguration();
FragmentManager fragmentManager =getFragmentManager();
FragmentTransactionfragmentTransaction =
fragmentManager.beginTransaction();
/**
* Check the device orientation and act accordingly
*/
if (config.orientation ==Configuration.ORIENTATION_LANDSCAPE) {
/**
* Landscape mode of the device
*/
LM_Fragment ls_fragment = newLM_Fragment();
fragmentTransaction.replace(android.R.id.content,ls_fragment);
}else{
/**
* Portrait mode of the device
*/
PM_Fragment pm_fragment = newPM_Fragment();
fragmentTransaction.replace(android.R.id.content,pm_fragment);
}
fragmentTransaction.commit();
}
}
Create two fragment files LM_Fragement.java andPM_Fragment.java undercom.example.mycontentprovider package.
Following is the content of LM_Fragement.java file:
package com.example.myfragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class LM_Fragment extends Fragment{
@Override
public View onCreateView(LayoutInflaterinflater,
ViewGroup container, BundlesavedInstanceState) {
/**
* Inflate the layout for this fragment
*/
return inflater.inflate(
R.layout.lm_fragment, container, false);
}
}
Following is the content of PM_Fragement.java file:
package com.example.myfragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PM_Fragment extends Fragment{
@Override
public View onCreateView(LayoutInflaterinflater,
ViewGroup container, BundlesavedInstanceState) {
/**
* Inflate the layout for this fragment
*/
return inflater.inflate(
R.layout.pm_fragment, container, false);
}
}
Create two layout files lm_fragement.xml andpm_fragment.xml under res/layout directory.
Following is the content of lm_fragement.xml file:
<?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"
android:background="#7bae16">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/landscape_message"
android:textColor="#000000"
android:textSize="20px" />
<!-- More GUI components go here -->
</LinearLayout>
Following is the content of pm_fragment.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#666666">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/portrait_message"
android:textColor="#000000"
android:textSize="20px" />
<!-- More GUI components go here -->
</LinearLayout>
Following will be the content of res/layout/activity_main.xml file which includes your fragments:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<fragment
android:name="com.example.fragments"
android:id="@+id/lm_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment
android:name="com.example.fragments"
android:id="@+id/pm_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
Make sure you have following content of res/values/strings.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyFragments</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="landscape_message">Thisis Landscape mode fragment
</string>
<string name="portrait_message">This is Portrait mode fragment
</string>
</resources>
Let's try to run our modified MyFragments application we just created. I assume you had created your AVDwhile doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display Emulator window where you will click on Menu button to see the following window. Be patience because it may takesometime based on your computer speed:
To change the mode of the emulator screen, let's do the following
fn+control+F11 on Mac to change the landscape to portrait and vice versa.
ctrl+F11 on Windows.
ctrl+F11 on Linux.
Once you changed the mode, you will be able to see the GUI which you have implemented for landscape mode as below:
This way you can use same activity but different GUIs through different fragments. You can use different type of GUI components for different GUIs based on your requirements.
Android Intents and Filters
An Android Intent is an object carrying an intent ie.message from one component to another component with-in the application or outside the application. The intents can communicate messages among any of the three core components of an application - activities, services, and broadcast receivers.
The intent itself, an Intent object, is a passive data structure holding an abstract description of an operation to be performed.
For example, let's assume that you have an Activity that needs to launch an email client and sends an email using your Android device. For this purpose, your Activity would send an ACTION_SEND along with appropriate chooser, to the Android Intent Resolver. The specified chooser gives the proper interface for the user to pick how to send your email data.
For example, assume that you have an Activity that needs to open URL in a web browser on your Android device. For this purpose, your Activity will send ACTION_WEB_SEARCH Intent to the Android Intent Resolver to open given URL in the web browser. The Intent Resolver parses through a list of Activities and chooses the one that would best match your Intent, in this case, the Web Browser Activity. The Intent Resolver then passes your web page to the web browser and starts the Web Browser Activity.
There are separate mechanisms for delivering intents to each type of component - activities, services, and broadcast receivers.
S.N.
Method & Description
1
Context.startActivity()
The Intent object is passed to this method to launch a new activity or get an existing activity to do something new.
2
Context.startService()
The Intent object is passed to this method to initiate a service or deliver new instructions to an ongoing service.
3
Context.sendBroadcast()
The Intent object is passed to this method to deliver the message to all interested broadcast receivers.
Intent Objects
An Intent object is a bundle of information which is used by the component that receives the intent plus information used by the Android system.
An Intent object can contain the following components based on what it is communicating or going to perform:
Action
This is mandatory part of the Intent object and is a string naming the action to be performed — or, in the case of broadcast intents, the action that took place and is being reported. The action largely determines how the rest of the intent object is structured . The Intent class defines a number of action constants corresponding to different intents. Here is a list of Android Intent Standard Actions
The action in an Intent object can be set by thesetAction() method and read by getAction().
Data
The URI of the data to be acted on and the MIME type of that data. For example, if the action field is ACTION_EDIT, the data field would contain the URI of the document to be displayed for editing.
The setData() method specifies data only as a URI,setType() specifies it only as a MIME type, andsetDataAndType() specifies it as both a URI and a MIME type. The URI is read by getData() and the type bygetType().
Some examples of action/data pairs are:
S.N.
Action/Data Pair & Description
1
ACTION_VIEW content://contacts/people/1
Display information about the person whose identifier is "1".
2
ACTION_DIAL content://contacts/people/1
Display the phone dialer with the person filled in.
3
ACTION_VIEW tel:123
Display the phone dialer with the given number filled in.
4
ACTION_DIAL tel:123
Display the phone dialer with the given number filled in.
5
ACTION_EDIT content://contacts/people/1
Edit information about the person whose identifier is "1".
6
ACTION_VIEW content://contacts/people/
Display a list of people, which the user can browse through.
Category
The category is an optional part of Intent object and it's a string containing additional information about the kind of component that should handle the intent. TheaddCategory() method places a category in an Intent object, removeCategory() deletes a category previously added, and getCategories() gets the set of all categories currently in the object. Here is a list of Android Intent Standard Categories.
You can check detail on Intent Filters in below section to understand how do we use categories to choose appropriate acivity coressponding to an Intent.
Extras
This will be in key-value pairs for additional information that should be delivered to the component handling the intent. The extras can be set and read using the putExtras() and getExtras() methods respectively. Here is a list of Android Intent Standard Extra Data
Flags
These flags are optional part of Intent object and instruct the Android system how to launch an activity, and how to treat it after it's launched etc.
Component Name
This optional field is an android ComponentNameobject representing either Activity, Service orBroadcastReceiver class. If it is set, the Intent object is delivered to an instance of the designated class otherwise Android uses other information in the Intent object to locate a suitable target.
The component name is set by setComponent(),setClass(), or setClassName() and read bygetComponent().
Types of Intents
There are following two types of intents supported by Android till version 4.1
Explicit Intents
These intents designate the target component by its name and they are typically used for application-internal messages - such as an activity starting a subordinate service or launching a sister activity. For example:
// Explicit Intent by specifying its class name
Intent i = new Intent(this,TargetActivity.class);
i.putExtra("Key1", "ABC");
i.putExtra("Key2", "123");
// Starts TargetActivity
startActivity(i);
Implicit Intents
These intents do not name a target and the field for the component name is left blank. Implicit intents are often used to activate components in other applications. For example:
// Implicit Intent by specifying a URI
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));
// Starts Implicit Activity
startActivity(i);
The target component which receives the intent can use the getExtras() method to get the extra data sent by the source component. For example:
// Get bundle object at appropriate place in your code
Bundle extras = getIntent().getExtras();
// Extract data using passed keys
String value1 = extras.getString("Key1");
String value2 = extras.getString("Key2");
Example
Following example shows the functionality of aAndroid Intent to launch various Android built-in applications.
Step
Description
1
You will use Eclipse IDE to create an Android application and name it as IntentDemo under a package com.example.intentdemo. While creating this project, make sure you Target SDK andCompile With at the latest version of Android SDK to use higher levels of APIs.
2
Modify src/MainActivity.java file and add the code to define two listeners corresponding two buttons ie. Start Browser and Start Phone.
3
Modify layout XML file res/layout/activity_main.xml to add three buttons in linear layout.
4
Modify res/values/strings.xml to define required constant values
5
Run the application to launch Android emulator and verify the result of the changes done in theaplication.
Following is the content of the modified main activity file src/com.example.intentdemo/MainActivity.java.
package com.example.intentdemo;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startBrowser = (Button)findViewById(R.id.start_browser);
startBrowser.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));
startActivity(i);
}
});
Button startPhone = (Button)findViewById(R.id.start_phone);
startPhone.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent(android.content.Intent.ACTION_VIEW,
Uri.parse("tel:9510300000"));
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action
// bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Following will be the content of res/layout/activity_main.xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="@+id/start_browser"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser"/>
<Button android:id="@+id/start_phone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_phone" />
</LinearLayout>
Following will be the content of res/values/strings.xml to define two new constants:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">IntentDemo</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="start_browser">Start Browser</string>
<string name="start_phone">Start Phone</string>
</resources>
Following is the default content ofAndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.intentdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Let's try to run your IntentDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:
Now click on Start Browser button which will start a browser configured and display http://www.example.com as shown below:
Similar way Ou can launch phone interface using Start Phone button, which will allow you to dial already given phone number.
Intent Filters
You have seen how an Intent has been used to call an another activity. Android OS uses filters to pinpoint the set of Activities, Services, and Broadcast receivers that can handle the Intent with help of specified set of action, categories, data scheme associated with an Intent. You will use <intent-filter> element in the manifest file to list down actions, categories and data types associated with any activity, service, or broadcast receiver.
Following is an example of a part ofAndroidManifest.xml file to specify an activitycom.example.intentdemo.CustomActivity which can be invoked by either of the two mentioned actions, one category, and one data:
<activity android:name=".CustomActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.VIEW" />
<actionandroid:name="com.example.intentdemo.LAUNCH" />
<categoryandroid:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
Once this activity is defined along with above mentioned filters, other activities will be able to invoke this activity using either theandroid.intent.action.VIEW, or using thecom.example.intentdemo.LAUNCH action provided their category is android.intent.category.DEFAULT.
The <data> element specifies the data type expected by the activity to be called and for above example our custom activity expects the data to start with the "http://"
There may be a situation that an intent can pass through the filters of more than one activity or service, the user may be asked which component to activate. An exception is raised if no target can be found.
There are following test Android checks before invoking an activity:
A filter <intent-filter> may list more than one action as shown above but this list cannot be empty; a filter must contain at least one <action> element, otherwise it will block all intents. If more than one actions are mentioned then Android tries to match one of the mentioned actions before invoking the activity.
A filter <intent-filter> may list zero, one or more than one categories. if there is no category mentioned then Android always pass this test but if more than one categories are mentioned then for an intent to pass the category test, every category in the Intent object must match a category in the filter.
Each <data> element can specify a URI and a data type (MIME media type). There are separate attributes like scheme, host, port, and path for each part of the URI. An Intent object that contains both a URI and a data type passes the data type part of the test only if its type matches a type listed in the filter.
Example
Following example is a modification of the above example. Here we will see how Android resolves conflict if one intent is invoking two activities defined in, next how to invoke a custom activity using a filter and third one is an exception case if Android does not file appropriate activity defined for an intent.
Step
Description
1
You will use Eclipse IDE to create an Android application and name it as IntentDemo under a package com.example.intentdemo. While creating this project, make sure you Target SDK andCompile With at the latest version of Android SDK to use higher levels of APIs.
2
Modify src/MainActivity.java file and add the code to define three listeners corresponding to three buttons defined in layout file.
3
Add a new src/CustomActivity.java file to have one custom activity which will be invoked by different intents.
4
Modify layout XML file res/layout/activity_main.xml to add three buttons in linear layout.
5
Add one layout XML file res/layout/custom_view.xml to add a simple <TextView> to show the passed data through intent.
6
Modify res/values/strings.xml to define required constant values
7
Modify AndroidManifest.xml to add <intent-filter> to define rules for your intent to invoke custom activity.
8
Run the application to launch Android emulator and verify the result of the changes done in theaplication.
Following is the content of the modified main activity file src/com.example.intentdemo/MainActivity.java.
package com.example.intentdemo;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// First intent to use ACTION_VIEW action with correct data
Button startBrowser_a = (Button)findViewById(R.id.start_browser_a);
startBrowser_a.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));
startActivity(i);
}
});
// Second intent to use LAUNCH action with correct data
Button startBrowser_b = (Button)findViewById(R.id.start_browser_b);
startBrowser_b.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent("com.example.intentdemo.LAUNCH",
Uri.parse("http://www.example.com"));
startActivity(i);
}
});
// Third intent to use LAUNCH action with incorrect data
Button startBrowser_c = (Button)findViewById(R.id.start_browser_c);
startBrowser_c.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent("com.example.intentdemo.LAUNCH",
Uri.parse("https://www.example.com"));
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the
// action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Following is the content of the modified main activity file src/com.example.intentdemo/CustomActivity.java.
package com.example.intentdemo;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;
public class CustomActivity extends Activity {
@Override
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_view);
TextView label = (TextView)findViewById(R.id.show_data);
Uri url = getIntent().getData();
label.setText(url.toString());
}
}
Following will be the content of res/layout/activity_main.xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="@+id/start_browser_a"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser_a"/>
<Button android:id="@+id/start_browser_b"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser_b"/>
<Button android:id="@+id/start_browser_c"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser_c"/>
</LinearLayout>
Following will be the content of res/layout/custom_view.xml file:
<?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/show_data"
android:layout_width="fill_parent"
android:layout_height="400dp"/>
</LinearLayout>
Following will be the content of res/values/strings.xml to define two new constants:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">IntentDemo</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="start_browser_a">Start Browser with VIEW action</string>
<string name="start_browser_b">Start Browser with LAUNCH action</string>
<string name="start_browser_c">Exception Condition</string>
</resources>
Following is the default content ofAndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.intentdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activityandroid:name="com.example.intentdemo.CustomActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.VIEW" />
<actionandroid:name="com.example.intentdemo.LAUNCH" />
<categoryandroid:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
</application>
</manifest>
Let's try to run your IntentDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:
Now let's start with first button "Stat Browser with VIEW Action". Here we have defined our custom activity with a filter "android.intent.action.VIEW", and there is already one default activity against VIEW action defined by Android which is launching web browser, so android displays following two options to select the activity you want to launch.
Now if yu select Browser, then Android will launch web browser and open example.com website but if you select IndentDemo option then Android will launchCustomActivity which does nothing but just capture passed data and displays in a text view as follows:
Now go back using back button and click on "Start Browser with LAUNCH Action" button, here Android applies filter to choose define activity and it simply launch your custom activity and again it displays following screen:
Again, go back using back button and click on "Exception Condition" button, here Android tries to find out a alid filter for the given intent but it does not find a valid activity defined because this time we have used data as https instead of http though we are giving a correct action, so Android raises an exception and shows following screen:
Android Intents and Filters
An Android Intent is an object carrying an intent ie.message from one component to another component with-in the application or outside the application. The intents can communicate messages among any of the three core components of an application - activities, services, and broadcast receivers.
The intent itself, an Intent object, is a passive data structure holding an abstract description of an operation to be performed.
For example, let's assume that you have an Activity that needs to launch an email client and sends an email using your Android device. For this purpose, your Activity would send an ACTION_SEND along with appropriate chooser, to the Android Intent Resolver. The specified chooser gives the proper interface for the user to pick how to send your email data.
For example, assume that you have an Activity that needs to open URL in a web browser on your Android device. For this purpose, your Activity will send ACTION_WEB_SEARCH Intent to the Android Intent Resolver to open given URL in the web browser. The Intent Resolver parses through a list of Activities and chooses the one that would best match your Intent, in this case, the Web Browser Activity. The Intent Resolver then passes your web page to the web browser and starts the Web Browser Activity.
There are separate mechanisms for delivering intents to each type of component - activities, services, and broadcast receivers.
S.N.
Method & Description
1
Context.startActivity()
The Intent object is passed to this method to launch a new activity or get an existing activity to do something new.
2
Context.startService()
The Intent object is passed to this method to initiate a service or deliver new instructions to an ongoing service.
3
Context.sendBroadcast()
The Intent object is passed to this method to deliver the message to all interested broadcast receivers.
Intent Objects
An Intent object is a bundle of information which is used by the component that receives the intent plus information used by the Android system.
An Intent object can contain the following components based on what it is communicating or going to perform:
Action
This is mandatory part of the Intent object and is a string naming the action to be performed — or, in the case of broadcast intents, the action that took place and is being reported. The action largely determines how the rest of the intent object is structured . The Intent class defines a number of action constants corresponding to different intents. Here is a list of Android Intent Standard Actions
The action in an Intent object can be set by thesetAction() method and read by getAction().
Data
The URI of the data to be acted on and the MIME type of that data. For example, if the action field is ACTION_EDIT, the data field would contain the URI of the document to be displayed for editing.
The setData() method specifies data only as a URI,setType() specifies it only as a MIME type, andsetDataAndType() specifies it as both a URI and a MIME type. The URI is read by getData() and the type bygetType().
Some examples of action/data pairs are:
S.N.
Action/Data Pair & Description
1
ACTION_VIEW content://contacts/people/1
Display information about the person whose identifier is "1".
2
ACTION_DIAL content://contacts/people/1
Display the phone dialer with the person filled in.
3
ACTION_VIEW tel:123
Display the phone dialer with the given number filled in.
4
ACTION_DIAL tel:123
Display the phone dialer with the given number filled in.
5
ACTION_EDIT content://contacts/people/1
Edit information about the person whose identifier is "1".
6
ACTION_VIEW content://contacts/people/
Display a list of people, which the user can browse through.
Category
The category is an optional part of Intent object and it's a string containing additional information about the kind of component that should handle the intent. TheaddCategory() method places a category in an Intent object, removeCategory() deletes a category previously added, and getCategories() gets the set of all categories currently in the object. Here is a list of Android Intent Standard Categories.
You can check detail on Intent Filters in below section to understand how do we use categories to choose appropriate acivity coressponding to an Intent.
Extras
This will be in key-value pairs for additional information that should be delivered to the component handling the intent. The extras can be set and read using the putExtras() and getExtras() methods respectively. Here is a list of Android Intent Standard Extra Data
Flags
These flags are optional part of Intent object and instruct the Android system how to launch an activity, and how to treat it after it's launched etc.
Component Name
This optional field is an android ComponentNameobject representing either Activity, Service orBroadcastReceiver class. If it is set, the Intent object is delivered to an instance of the designated class otherwise Android uses other information in the Intent object to locate a suitable target.
The component name is set by setComponent(),setClass(), or setClassName() and read bygetComponent().
Types of Intents
There are following two types of intents supported by Android till version 4.1
Explicit Intents
These intents designate the target component by its name and they are typically used for application-internal messages - such as an activity starting a subordinate service or launching a sister activity. For example:
// Explicit Intent by specifying its class name
Intent i = new Intent(this,TargetActivity.class);
i.putExtra("Key1", "ABC");
i.putExtra("Key2", "123");
// Starts TargetActivity
startActivity(i);
Implicit Intents
These intents do not name a target and the field for the component name is left blank. Implicit intents are often used to activate components in other applications. For example:
// Implicit Intent by specifying a URI
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));
// Starts Implicit Activity
startActivity(i);
The target component which receives the intent can use the getExtras() method to get the extra data sent by the source component. For example:
// Get bundle object at appropriate place in your code
Bundle extras = getIntent().getExtras();
// Extract data using passed keys
String value1 = extras.getString("Key1");
String value2 = extras.getString("Key2");
Example
Following example shows the functionality of aAndroid Intent to launch various Android built-in applications.
Step
Description
1
You will use Eclipse IDE to create an Android application and name it as IntentDemo under a package com.example.intentdemo. While creating this project, make sure you Target SDK andCompile With at the latest version of Android SDK to use higher levels of APIs.
2
Modify src/MainActivity.java file and add the code to define two listeners corresponding two buttons ie. Start Browser and Start Phone.
3
Modify layout XML file res/layout/activity_main.xml to add three buttons in linear layout.
4
Modify res/values/strings.xml to define required constant values
5
Run the application to launch Android emulator and verify the result of the changes done in theaplication.
Following is the content of the modified main activity file src/com.example.intentdemo/MainActivity.java.
package com.example.intentdemo;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startBrowser = (Button)findViewById(R.id.start_browser);
startBrowser.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));
startActivity(i);
}
});
Button startPhone = (Button)findViewById(R.id.start_phone);
startPhone.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent(android.content.Intent.ACTION_VIEW,
Uri.parse("tel:9510300000"));
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action
// bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Following will be the content of res/layout/activity_main.xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="@+id/start_browser"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser"/>
<Button android:id="@+id/start_phone"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_phone" />
</LinearLayout>
Following will be the content of res/values/strings.xml to define two new constants:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">IntentDemo</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="start_browser">Start Browser</string>
<string name="start_phone">Start Phone</string>
</resources>
Following is the default content ofAndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.intentdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Let's try to run your IntentDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:
Now click on Start Browser button which will start a browser configured and display http://www.example.com as shown below:
Similar way Ou can launch phone interface using Start Phone button, which will allow you to dial already given phone number.
Intent Filters
You have seen how an Intent has been used to call an another activity. Android OS uses filters to pinpoint the set of Activities, Services, and Broadcast receivers that can handle the Intent with help of specified set of action, categories, data scheme associated with an Intent. You will use <intent-filter> element in the manifest file to list down actions, categories and data types associated with any activity, service, or broadcast receiver.
Following is an example of a part ofAndroidManifest.xml file to specify an activitycom.example.intentdemo.CustomActivity which can be invoked by either of the two mentioned actions, one category, and one data:
<activity android:name=".CustomActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.VIEW" />
<actionandroid:name="com.example.intentdemo.LAUNCH" />
<categoryandroid:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
Once this activity is defined along with above mentioned filters, other activities will be able to invoke this activity using either theandroid.intent.action.VIEW, or using thecom.example.intentdemo.LAUNCH action provided their category is android.intent.category.DEFAULT.
The <data> element specifies the data type expected by the activity to be called and for above example our custom activity expects the data to start with the "http://"
There may be a situation that an intent can pass through the filters of more than one activity or service, the user may be asked which component to activate. An exception is raised if no target can be found.
There are following test Android checks before invoking an activity:
A filter <intent-filter> may list more than one action as shown above but this list cannot be empty; a filter must contain at least one <action> element, otherwise it will block all intents. If more than one actions are mentioned then Android tries to match one of the mentioned actions before invoking the activity.
A filter <intent-filter> may list zero, one or more than one categories. if there is no category mentioned then Android always pass this test but if more than one categories are mentioned then for an intent to pass the category test, every category in the Intent object must match a category in the filter.
Each <data> element can specify a URI and a data type (MIME media type). There are separate attributes like scheme, host, port, and path for each part of the URI. An Intent object that contains both a URI and a data type passes the data type part of the test only if its type matches a type listed in the filter.
Example
Following example is a modification of the above example. Here we will see how Android resolves conflict if one intent is invoking two activities defined in, next how to invoke a custom activity using a filter and third one is an exception case if Android does not file appropriate activity defined for an intent.
Step
Description
1
You will use Eclipse IDE to create an Android application and name it as IntentDemo under a package com.example.intentdemo. While creating this project, make sure you Target SDK andCompile With at the latest version of Android SDK to use higher levels of APIs.
2
Modify src/MainActivity.java file and add the code to define three listeners corresponding to three buttons defined in layout file.
3
Add a new src/CustomActivity.java file to have one custom activity which will be invoked by different intents.
4
Modify layout XML file res/layout/activity_main.xml to add three buttons in linear layout.
5
Add one layout XML file res/layout/custom_view.xml to add a simple <TextView> to show the passed data through intent.
6
Modify res/values/strings.xml to define required constant values
7
Modify AndroidManifest.xml to add <intent-filter> to define rules for your intent to invoke custom activity.
8
Run the application to launch Android emulator and verify the result of the changes done in theaplication.
Following is the content of the modified main activity file src/com.example.intentdemo/MainActivity.java.
package com.example.intentdemo;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// First intent to use ACTION_VIEW action with correct data
Button startBrowser_a = (Button)findViewById(R.id.start_browser_a);
startBrowser_a.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));
startActivity(i);
}
});
// Second intent to use LAUNCH action with correct data
Button startBrowser_b = (Button)findViewById(R.id.start_browser_b);
startBrowser_b.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent("com.example.intentdemo.LAUNCH",
Uri.parse("http://www.example.com"));
startActivity(i);
}
});
// Third intent to use LAUNCH action with incorrect data
Button startBrowser_c = (Button)findViewById(R.id.start_browser_c);
startBrowser_c.setOnClickListener(newView.OnClickListener() {
public void onClick(View view) {
Intent i = newIntent("com.example.intentdemo.LAUNCH",
Uri.parse("https://www.example.com"));
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the
// action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Following is the content of the modified main activity file src/com.example.intentdemo/CustomActivity.java.
package com.example.intentdemo;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;
public class CustomActivity extends Activity {
@Override
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_view);
TextView label = (TextView)findViewById(R.id.show_data);
Uri url = getIntent().getData();
label.setText(url.toString());
}
}
Following will be the content of res/layout/activity_main.xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="@+id/start_browser_a"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser_a"/>
<Button android:id="@+id/start_browser_b"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser_b"/>
<Button android:id="@+id/start_browser_c"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_browser_c"/>
</LinearLayout>
Following will be the content of res/layout/custom_view.xml file:
<?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/show_data"
android:layout_width="fill_parent"
android:layout_height="400dp"/>
</LinearLayout>
Following will be the content of res/values/strings.xml to define two new constants:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">IntentDemo</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="start_browser_a">Start Browser with VIEW action</string>
<string name="start_browser_b">Start Browser with LAUNCH action</string>
<string name="start_browser_c">Exception Condition</string>
</resources>
Following is the default content ofAndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.intentdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activityandroid:name="com.example.intentdemo.CustomActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.VIEW" />
<actionandroid:name="com.example.intentdemo.LAUNCH" />
<categoryandroid:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
</application>
</manifest>
Let's try to run your IntentDemo application. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project's activity files and click Run icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window:
Now let's start with first button "Stat Browser with VIEW Action". Here we have defined our custom activity with a filter "android.intent.action.VIEW", and there is already one default activity against VIEW action defined by Android which is launching web browser, so android displays following two options to select the activity you want to launch.
Now if yu select Browser, then Android will launch web browser and open example.com website but if you select IndentDemo option then Android will launchCustomActivity which does nothing but just capture passed data and displays in a text view as follows:
Now go back using back button and click on "Start Browser with LAUNCH Action" button, here Android applies filter to choose define activity and it simply launch your custom activity and again it displays following screen:
Again, go back using back button and click on "Exception Condition" button, here Android tries to find out a alid filter for the given intent but it does not find a valid activity defined because this time we have used data as https instead of http though we are giving a correct action, so Android raises an exception and shows following screen
Android Styles and Themes
If you already know about Cascading Style Sheet (CSS) in web design then to understand Android Style also works very similar way. There are number of attributes associated with each Android widget which you can set to change your application look and feel. A style can specify properties such as height, padding, font color, font size, background color, and much more.
You can specify these attributes in Layout file as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/text_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:capitalize="characters"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="@string/hello_world" />
</LinearLayout>
But this way we need to define style attributes for every attribute separately which is not good for source code maintenance point of view. So we work with styles by defining them in separate file as explained below.
Defining Styles
A style is defined in an XML resource that is separate from the XML that specifies the layout. This XML file resides under res/values/ directory of your project and will have <resources> as the root node which is mandatory for the style file. The name of the XML file is arbitrary, but it must use the .xml extension.
You can define multiple styles per file using <style> tag but each style will have its name that uniquely identifies the style. Android style attributes are set using <item> tag as shown below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomFontStyle">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:capitalize">characters</item>
<item name="android:typeface">monospace</item>
<item name="android:textSize">12pt</item>
<item name="android:textColor">#00FF00</item>/>
</style>
</resources>
The value for the <item> can be a keyword string, a hex color, a reference to another resource type, or other value depending on the style property.
Using Styles
Once your style is defined, you can use it in your XML Layout file using style attribute as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/text_id"
style="@style/CustomFontStyle"
android:text="@string/hello_world" />
</LinearLayout>
To understand the concept related to Android Style, you can check Style Demo Example.
Style Inheritance
Android supports style Inheritance in very much similar way as cascading style sheet in web design. You can use this to inherit properties from an existing style and then define only the properties that you want to change or add.
Its simple, to create a new style LargeFont that inherits the CustomFontStyle style defined above, but make the font size big, you can author the new style like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomFontStyle.LargeFont">
<item name="android:textSize">20ps</item>
</style>
</resources>
You can reference this new style as @style/CustomFontStyle.LargeFont in your XML Layout file. You can continue inheriting like this as many times as you'd like, by chaining names with periods. For example, you can extend FontStyle.LargeFont to be Red, with:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomFontStyle.LargeFont.Red">
<item name="android:textColor">#FF0000</item>/>
</style>
</resources>
This technique for inheritance by chaining together names only works for styles defined by your own resources. You can't inherit Android built-in styles this way. To reference an Android built-in style, such asTextAppearance, you must use the parent attribute as shown below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomFontStyle" parent="@android:style/TextAppearance">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:capitalize">characters</item>
<item name="android:typeface">monospace</item>
<item name="android:textSize">12pt</item>
<item name="android:textColor">#00FF00</item>/>
</style>
</resources>
Android Themes
Hope you understood the concept of Style, so now let's try to understand what is a Theme. A theme is nothing but an Android style applied to an entire Activity or application, rather than an individual View.
Thus, when a style is applied as a theme, every View in the Activity or application will apply each style property that it supports. For example, you can apply the same CustomFontStyle style as a theme for an Activity and then all text inside that Activity will have green monospace font.
To set a theme for all the activities of your application, open the AndroidManifest.xml file and edit the<application> tag to include the android:themeattribute with the style name. For example:
<application android:theme="@style/CustomFontStyle">
But if you want a theme applied to just one Activity in your application, then add the android:theme attribute to the <activity> tag only. For example:
<activity android:theme="@style/CustomFontStyle">
There are number of default themes defined by Android which you can use directly or inherit them using parent attribute as follows:
<style name="CustomTheme" parent="android:Theme.Light">
...
</style>
To understand the concept related to Android Theme, you can check Theme Demo Example.
Default Styles & Themes
The Android platform provides a large collection of styles and themes that you can use in your applications. You can find a reference of all available styles in the R.style class. To use the styles listed here, replace all underscores in the style name with a period. For example, you can apply the Theme_NoTitleBartheme with "@android:style/Theme.NoTitleBar". You can see the following source code for Android styles and themes:
Android Styles (styles.xml)
Android Themes (themes.xml)
Comments
Post a Comment