Professional Documents
Culture Documents
Lars Vogel
Version 3.5
28.04.2014
Table of Contents
1. Intents and intent filter
1.1. Task
1.2. What are intents?
1.3. Starting activities
1.4. Sub-activities
1.5. Starting services
2. Intents types
2.1. Different types of intents
2.2. Explicit Intents
2.3. Implicit Intents
3. Data transfer between activities
3.1. Data transfer to the target component
3.2. Example: Using the share intent
3.3. Retrieving result data from a sub-activity
4. Defining intent filters
4.1. Intent filter
4.2. Defining intent filter
4.3. Example: Register an activity as browser
4.4. Example: Register an activity for the share intent
5. Intents as event triggers
6. Determine valid intent receivers
7. Prerequisites for this tutorial
8. Exercise: Starting activities
8.1. Target of this exercise
8.2. Create project and main layout
8.3. Create new layout file
8.4. Create additional activity
8.5. Start sub-activity
8.6. Send data to ResultActivity
8.7. Get intent data in the ResultActivity
9. Exercise: Receiving data from sub-activities
9.1. Target of this exercise
9.2. Return data from ResultActivity
9.3. Evaluate the return data in MainActivity
10. Solution: Using intents
10.1. How to use this chapter
10.2. Activity code
11. Exercise: Register an activity as Browser
11.1. Target
11.2. Create project
11.3. Register activity as browser
11.4. Validating
11.5. Optional: Make it a real browser
12. Exercise: picking an image via an intent
12.1. Target
12.2. Create project
12.3. Validating
13. Exercise: Using different implicit intents
13.1. Target
13.2. Create project
13.3. Validating
14. About this website
15. Links and Literature
15.1. Android Resources
15.2. vogella GmbH training and consulting support
1. Intents and intent filter
1.1. Task
Intents are objects of the android.content.Intent type. Your code can send them
to the Android system defining the components you are targeting. For example, via
the startActivity() method you can define that the intent should be used to start
an activity.
An intent can contain data via a Bundle . This data can be used by the receiving
component.
1.4. Sub-activities
Activities which are started by other Android activities are called sub-activities. This
wording makes it easier to describe which activity is meant.
You can also start services via intents. Use the startService(Intent) method call
for that.
2. Intents types
2.1. Different types of intents
An application can define the target component directly in the intent (explicit intent) or
ask the Android system to evaluate registered components based on the intent data
(implicit intents).
Explicit intents explicitly define the component which should be called by the Android
system, by using the Java class as identifier.
The following shows how to create an explicit intent and send it to the Android system. If
the class specified in the intent represents an activity, the Android system starts it.
Explicit intents are typically used within on application as the classes in an application
are controlled by the application developer.
Implicit intents specify the action which should be performed and optionally data which
provides content for the action.
For example, the following tells the Android system to view a webpage. All installed web
browsers should be registered to the corresponding intent data via an intent filter.
If an implicit intent is sent to the Android system, it searches for all components which
are registered for the specific action and the fitting data type.
If only one component is found, Android starts this component directly. If several
components are identified by the Android system, the user will get a selection dialog
and can decide which component should be used for the intent.
A component can register itself for actions. See Section 4.1, “Intent filter” for details.
An intent contains certain header data, e.g., the desired action, the type, etc. Optionally
an intent can also contain additional data based on an instance of the Bundle class
which can be retrieved from the intent via the getExtras() method.
You can also add data directly to the Bundle via the
overloaded putExtra() methods of the Intent objects. Extras are key/value pairs.
The key is always of type String . As value you can use the primitive data types
( int , float , ...) plus objects of
type String , Bundle , Parceable and Serializable .
Lots of Android applications allow you to share some data with other people, e.g., the
Facebook, G+, Gmail and Twitter application. You can send data to one of these
components. The following code snippet demonstrates the usage of such an intent
within your application.
An activity can be closed via the back button on the phone. In this case
the finish() method is performed. If the activity was started with
the startActivity(Intent) method call, the caller requires no result or feedback
from the activity which now is closed.
If you start the activity with the startActivityForResult() method call, you expect
feedback from the sub-activity. Once the sub-activity ends,
the onActivityResult() method on the sub-activity is called and you can perform
actions based on the result.
If you use the startActivityForResult() method, then the started activity is called
a sub-activity.
If the sub-activity is finished, it can send data back to its caller via an Intent. This is done
in the finish() method.
@Override
public void finish() {
// Prepare data intent
Intent data = new Intent();
data.putExtra("returnKey1", "Swinging on a star. ");
data.putExtra("returnKey2", "You could be better then you are. ");
// Activity finished ok, return the data
setResult(RESULT_OK, data);
super.finish();
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
if (data.hasExtra("returnKey1")) {
Toast.makeText(this, data.getExtras().getString("returnKey1"),
Toast.LENGTH_SHORT).show();
}
}
}
Intents are used to signal to the Android system that a certain event has occurred.
Intents often describe the action which should be performed and provide data upon
which such an action should be done. For example, your application can start a browser
component for a certain URL via an intent. This is demonstrated by the following
example.
But how does the Android system identify the components which can react to a certain
intent?
A component can register itself via an intent filter for a specific action and specific data.
An intent filter specifies the types of intents to which an activity, service, or broadcast
receiver can respond to by declaring the capabilities of a component.
If an intent is sent to the Android system, the Android platform runs a receiver
determination. It uses the data included in the intent. If several components have
registered for the same intent filter, the user can decide which component should be
started.
If you send such an intent to your system, the Android system determines all registered
Android components for this intent. If several components have registered for this intent,
the user can select which one should be used.
The following code will register an Activity for the Intent which is triggered when
someone wants to open a webpage.
<activity android:name=".BrowserActivitiy"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
The following example registers an activity for the ACTION_SEND intent. It declares itself
only relevant for thetext/plain mime type.
<activity
android:name=".ActivityTest"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
</intent-filter>
</activity>
If a component does not define an intent filter, it can only be called by explicit intents.
Your application can register to system events, e.g., a new email has arrived, system
boot is complete or a phone call is received and react accordingly.
The following example code checks if a component has registered for a certain intent.
Construct your intent as you are desired to trigger it and pass it to the following method.
Based on the result you can adjust your application. For example, you could disable or
hide certain menu items.
The following exercise demonstrates how to use an explicit intent to start a sub-activity
and how to send data to it.
This is the first part of an exercise continued in ???. The final solution can be found
in ???.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<EditText
android:id="@+id/inputforintent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="60dip"
android:text="First Activity"
android:textSize="20sp" >
</EditText>
<Button
android:id="@+id/startintent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/inputforintent"
android:layout_below="@+id/inputforintent"
android:onClick="onClick"
android:text="Calling an intent" />
</RelativeLayout>
Create a new layout called activity_result.xml. In the next step you create a new
activity which will use this layout file.
Enter activity_result.xml as file name and press the Finish button. Change your
layout so that it is similar to the following XML file.
<TextView
android:id="@+id/displayintentextra"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Input"
/>
<EditText
android:id="@+id/returnValue"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<requestFocus />
</EditText>
</LinearLayout>
Create a new class called ResultActivity based on the following example code.
package com.vogella.android.intent.explicit;
import android.app.Activity;
import android.os.Bundle;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_result);
}
}
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".MainActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:label="Result Activity"
android:name=".ResultActivity" >
</activity>
</application>
</manifest>
Note
This new activity will be started via the MainActivity , hence it is called a sub-activity.
Start the sub-activity via a button click from the MainActivity class. The following
code gives some pointers on how to solve this. Solve the TODO's in the source code so
that the ResultActivity activity is started from the onClick() method.
package com.vogella.android.intent.explicit;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Once you finished this part of the exercise, start your application and ensure that you
can start the second activity.
The MainActivity class should pass the value of the EditText view to the sub-
activity. For this use the putExtra("yourKey", string) on the Intent object.
In your ResultActivity sub-activity get the Bundle with the intent data via
the getIntent().getExtras() ) method call.
Get the value of the passed extra with the extras.getString("yourkey") method
on the bundle object which you got with the getExtras() call.
This value should be placed in the TextView with the displayintentextra ID.
This is the second part of an exercise which started in ???. An example solution for the
activity can be found in ???.
In the following exercise you transfer data back from your second sub-activity to
the MainActivity once the user selects the Back button.
@Override
public void finish() {
super.finish();
}
package com.vogella.android.intent.explicit;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
After finishing the exercise in ???, your activity coding should look similar to the
following classes.
You can use this chapter to compare your solution with the proposed solution.
package com.vogella.android.intent.explicit;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.TextView;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_result);
Bundle extras = getIntent().getExtras();
String inputString = extras.getString("yourkey");
TextView view = (TextView)
findViewById(R.id.displayintentextra);
view.setText(inputString);
}
@Override
public void finish() {
Intent intent = new Intent();
EditText editText= (EditText) findViewById(R.id.returnValue);
String string = editText.getText().toString();
intent.putExtra("returnkey", string);
setResult(RESULT_OK, intent);
super.finish();
}
}
package com.vogella.android.intent.explicit;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
if (data.hasExtra("returnkey")) {
String result = data.getExtras().getString("returnkey");
if (result != null && result.length() > 0) {
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
}
}
}
}
}
In the following exercise you register an activity as browser. This means, if an intent is
triggered when someone wants to view an URL starting with http, your activity will be
available to process this intent.
The example activity downloads the HTML source of this page and displays it in
a TextView .
Register your activity to the Intent.Action_VIEW action and the scheme "http" via
the following changes in your AndroidManifest.xml file Ensure that your manifest
also declares the permission to access the Internet.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.vogella.android.intent.browserfilter"
android:versionCode="1"
android:versionName="1.0" >
<application
android:icon="@drawable/icon"
android:label="@string/app_name" >
<activity
android:name=".BrowserActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category
android:name="android.intent.category.DEFAULT" />
</manifest>
package de.vogella.android.intent.browserfilter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.widget.TextView;
setContentView(R.layout.main);
Intent intent = getIntent();
TextView text = (TextView) findViewById(R.id.textView);
// To get the action of the intent use
String action = intent.getAction();
if (!action.equals(Intent.ACTION_VIEW)) {
throw new RuntimeException("Should not happen");
}
// To get the data use
Uri data = intent.getData();
URL url;
try {
url = new URL(data.getScheme(), data.getHost(),
data.getPath());
BufferedReader rd = new BufferedReader(new
InputStreamReader(url.openStream()));
String line = "";
while ((line = rd.readLine()) != null) {
text.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
11.4. Validating
Install your application. If you trigger an intent to open a URL, the user should be able to
select your custom browser implementation. Trigger for this purpose the following intent
from one of your Android applications by adding for example an additional button to the
application which can trigger the code.
intent = new
Intent(Intent.ACTION_VIEW,Uri.parse("http://www.vogella.com"));
startActivity(intent);
If you select your component, the HTML code is loaded and displayed into
your TextView .
11.5. Optional: Make it a real browser
Tip
Replace your TextView with a WebView to create a "real" browser. The WebView does
the loading of the HTTP request for you. Simply assign the URL via the loadUrl method to
it.
The following example shows how to pick an image from any registered photo
application on Android via anintent.
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="pickImage"
android:text="Button" >
</Button>
<ImageView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/icon" >
</ImageView>
</LinearLayout>
package de.vogella.android.imagepick;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView = (ImageView) findViewById(R.id.result);
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
InputStream stream = null;
if (requestCode == REQUEST_CODE && resultCode ==
Activity.RESULT_OK)
try {
// recyle unused bitmaps
if (bitmap != null) {
bitmap.recycle();
}
stream =
getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(stream);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (stream != null)
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
12.3. Validating
If you run this application, you can select an image from your image library on your
Android phone and assign it to your ImageView .
The following exercise demonstrates the usage of implicit intents to trigger activities in
your Android system.
<resources>
<string-array name="intents">
<item>Open Browser</item>
<item>Call Someone</item>
<item>Dial</item>
<item>Show Map</item>
<item>Search on Map</item>
<item>Take picture</item>
<item>Show contacts</item>
<item>Edit first contact</item>
</string-array>
</resources>
<Spinner
android:id="@+id/spinner"
android:layout_gravity="fill_horizontal"
android:drawSelectorOnTop="true"
>
</Spinner>
<Button
android:id="@+id/trigger"
android:onClick="onClick"
android:text="Trigger Intent">
</Button>
</GridLayout>
To be able to use certain intents, you need to register for the required permission in
yourAndroidManifest.xml file. Ensure that your AndroidManifest.xml contains the
permissions from the following listing.
<uses-permission
android:name="android.permission.CALL_PRIVILEGED" >
</uses-permission>
<uses-permission android:name="android.permission.CALL_PHONE" >
</uses-permission>
<uses-permission android:name="android.permission.CAMERA" >
</uses-permission>
<uses-permission android:name="android.permission.READ_CONTACTS"
>
</uses-permission>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:icon="@drawable/icon"
android:label="@string/app_name" >
<activity
android:name=".CallIntentsActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package de.vogella.android.intent.implicit;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this,
R.array.intents, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_drop
down_item);
spinner.setAdapter(adapter);
}
}
if (intent != null) {
startActivity(intent);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == 0) {
String result = data.toURI();
Toast.makeText(this, result, Toast.LENGTH_LONG);
}
}
13.3. Validating
If you start your application, you see a list of buttons and if you press one of the buttons,
your defined activities are started.
Note
Note that you didn't specify any receiving application, only the action that should be done.
This allows you to define loosely coupled tasks which use components of different
applications.
Android Homepage