Intent object is a messaging object(instance of the android.content.Intent class) which is used to signal/activate other components such as activities, services, and broadcast receivers. E.g., an activity B can register with intent A’s intent so that the bound activity B will be notified and activated when the event fires.
Intent is capable to include multiple components to perform certain tasks.
An Intent is sent to the Android OS system and the Android system will decide which target (for implicit intent) can do the job best. An Intent can also contain data. This data can be used by the receiving component.
An explicit intent tells Android system to run specific component such as ActivityB
Intent intent = new Intent(ActivityA.this, ActivityB.class);
startActivity(intent);
An implicit intent tells Android system to run an activity(ActivityB in this case) that can do these things that are specified in the intent filter in a manifest .
Intent intent = new Intent();
intent.addAction("thisAction");
intent.addCategory("thisCategory");
startActivity(intent);
the Android manifest file:
<activity android:name="ActivityB">
<intent-filter>
<action android:name="thisAction"/>
<category android:name="thisCategory"/>
</intent-filter>
</activity>
Android system will locate a best matched component such as ActivityB based on action and category requirement. Implicit intent also leaves a security vulnerability hole.
Here is a simple intent demo app.
Activity A has a button with a caption of "Invoke B" and activity B will display "Hello Activity A". A don't display any and B does not have button.
Copy and Paste following code into specific files.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.intent"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity
android:name=".Activityb"
android:theme="@android:style/Theme.NoTitleBar" />
<activity android:name=".IntentActivity"
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>
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"
>
<Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Invoke B"></Button>
</LinearLayout>
activityb.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="@+id/textView1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Hello Activity A"></TextView>
</LinearLayout>
intentActivity.java
package android.intent;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class IntentActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
final Context context = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button invoke=(Button)findViewById(R.id.button1);
invoke.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(context, Activityb.class);
startActivity(intent);
}
});
}
}
Activityb.java
package android.intent;
import android.app.Activity;
import android.os.Bundle;
public class Activityb extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityb);
}
}
Demo
Then save and run this app.
The first activity only has a button named Invoke B. Click it.
Then the Activity B with text "Hello Activity A" is presented.
There is another example shows more about the usage of implicit intent.
In implicit intents, we do not name a specific component, but instead declare a general action to perform, which allows a component from another app to handle it. For example, if you want to show the user a location on a map, you can use an implicit intent to request that another capable app to show a specified location on a map.
When using an implicit intent, it is the Andriod system that will find the appropriate component to start by comparing the contents of the intent to the intent-filters declared in the manifest file of the other apps on the device. If the intent matches an intent filter, the system starts that component and delivers it the Intent object. If multiple intent filters are compatible, the system displays a dialog so the user can pick which app to use. One of the example can be showed as below:
We have a video that we want to share with others, we may have multiple choice:
Caution: It's possible that a user won't have any apps that handle the implicit intent you send to startActivity(). If that happens, the call will fail and your app will crash. To verify that an activity will receive the intent, call resolveActivity() on your Intent object. If the result is non-null, then there is at least one app that can handle the intent and it's safe to call startActivity(). If the result is null, you should not use the intent and, if possible, you should disable the feature that issues the intent.
For practice and simplicity, in our lab, we have only one application and multiple activities to show how the intent-filter can be matched.
The following activity is the one that would be displayed in the screen when the app is started.
ImplicitIntentActivity.java
package android.implicitintent;
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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class ImplicitIntentActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnA=(Button) findViewById(R.id.button1);
btnA.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//set implicit intent to match activity A
Intent intent=new Intent();
//set action
intent.setAction("com.wyou.action");
//set category
intent.addCategory("com.wyou.category");
//set data
intent.setData(Uri.parse("wyou://www.wyou.com/wyou"));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
else{
Toast toast=Toast.makeText(getApplicationContext(), "No Activity is matched!", Toast.LENGTH_SHORT);
toast.show();
}
}});
Button btnB=(Button) findViewById(R.id.button2);
btnB.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//set implicit intent to match activity B
Intent intent=new Intent();
//set action
intent.setAction("com.wyou.actionB");
//set category
intent.addCategory("com.wyou.categoryB");
//set data
intent.setData(Uri.parse("wyou://www.wyou.com/wyou"));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
else{
Toast toast=Toast.makeText(getApplicationContext(), "No Activity is matched!", Toast.LENGTH_SHORT);
toast.show();
}
}});
Button btnC=(Button) findViewById(R.id.button3);
btnC.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//set implicit intent to match activity C
Intent intent=new Intent();
//set action
intent.setAction("com.wyou.action");
//set category
intent.addCategory("com.wyou.category");
//set data to match "text/*", so this intent will invoke ActivityC
intent.setDataAndType(Uri.parse("wyou://www.wyou.com/wyou"), "text/plain");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
else{
Toast toast=Toast.makeText(getApplicationContext(), "No Activity is matched!", Toast.LENGTH_SHORT);
toast.show();
}
}});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.implicit_intent, menu);
return true;
}
}
main.xml
<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=".ImplicitIntentActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textSize="25sp"
/>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginTop="64dp"
android:text="@string/matchA" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_centerVertical="true"
android:text="@string/matchB" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button2"
android:layout_below="@+id/button2"
android:layout_marginTop="49dp"
android:text="@string/matchC" />
</RelativeLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ImplicitIntent</string>
<string name="action_settings">Settings</string>
<string name="title">Implicit Intent Demo</string>
<string name="matchA">Single Activity Matched</string>
<string name="matchB">Multiple Activities Matched</string>
<string name="matchC">No Activity Matched</string>
<string name="a">Hi, I am activity A.</string>
<string name="b">Hi, I am actibity B.</string>
<string name="c">Hi, I am actibity C.</string>
<string name="back">Back</string>
</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.implicitintent"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="android.implicitintent.ImplicitIntentActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- ActivityA -->
<activity
android:name="android.implicitintent.ActivityA"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.wyou.action" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.wyou.category" />
<data
android:host="www.wyou.com"
android:scheme="wyou" />
</intent-filter>
</activity>
<!-- ActivityB -->
<activity
android:name="android.implicitintent.ActivityB"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.wyou.actionB" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.wyou.categoryB" />
<data
android:host="www.wyou.com"
android:scheme="wyou" />
</intent-filter>
</activity>
<!-- ActivityC -->
<activity
android:name="android.implicitintent.ActivityC"
android:label="@string/app_name" >
<intent-filter>
<action android:name="com.wyou.actionB" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.wyou.categoryB" />
<data
android:host="www.wyou.com"
android:scheme="wyou" />
</intent-filter>
</activity>
</application>
</manifest>
Each intent filter is defined by an <intent-filter> element in the app's manifest file, nested in the corresponding app component (such as an <activity> element). Inside the <intent-filter>, you can specify the type of intents to accept using one or more of these three elements:
<action>
Declares the intent action accepted, in the name attribute. The value must be the literal string value of an action, not the class constant.
<data>
Declares the type of data accepted, using one or more attributes that specify various aspects of the data URI (scheme, host, port, path, etc.) and MIME type.
<category>
Declares the intent category accepted, in the name attribute. The value must be the literal string value of an action, not the class constant.
Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. If you do not declare this category in your intent filter, no implicit intents will resolve to your activity.
ActivityA.java
package android.implicitintent;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityA extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
Button btn=(Button) findViewById(R.id.back);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
finish();//finish itself and return to main activity
}});
}
}
activity_a.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="63dp"
android:layout_marginTop="39dp"
android:text="@string/title"
android:textSize="25sp"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="44dp"
android:text="@string/a"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView2"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:text="@string/back" />
</RelativeLayout>
ActivityB.java
package android.implicitintent;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityB extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
Button btn=(Button) findViewById(R.id.back);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
finish();//finish itself and return to main activity
}});
}
}
activity_b.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="63dp"
android:layout_marginTop="39dp"
android:text="@string/title"
android:textSize="25sp"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="44dp"
android:text="@string/b"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView2"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:text="@string/back" />
</RelativeLayout>
ActivityC.java
package android.implicitintent;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ActivityC extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_c);
Button btn=(Button) findViewById(R.id.back);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
finish();//finish itself and return to main activity
}});
}
}
activity_c.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="63dp"
android:layout_marginTop="39dp"
android:text="@string/title"
android:textSize="25sp"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="44dp"
android:text="@string/c"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView2"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:text="@string/back" />
</RelativeLayout>
Demo
Save and run this app.
In the first screen, there are three buttons.
When clicking the first button, only one activities is matched. In our lab, only ActivityA matches this intent.
When clicking the second button, both Activity B and C are matched. So, the Android system would show a dialog for user to choose one of the activity to start.
In the screenshot above, we can see there are two Apps showed in the dialog. Both of them named as ImplicitIntent (the name of our project), it is because the activities that match this intent are in the same app.
If we choose the first one, it will start ActivityB.
There is no activity that is matched with any intent.
Resources:
http://developer.android.com/guide/components/intents-filters.html