Skip to content

Android - Intents/Filters

An Intent in Android is a messaging object you can use to request an action from another app component. Intents facilitate inter-component communication in various ways, such as starting an activity, initiating a service, or delivering a broadcast.

The Intent itself is a passive data structure holding an abstract description of an operation to be performed or, for broadcasts, an event that has occurred.

For example, if your Activity needs to send an email, it would create an Intent with the ACTION_SENDTO action and a mailto: URI. It then passes this Intent to startActivity(). The Android system’s Intent Resolver finds an appropriate email app to handle this request and presents a chooser if multiple apps can handle it.

// Example: Sending an email
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse("mailto:")); // Only email apps should handle this
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"recipient@example.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email Subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email body content.");
if (emailIntent.resolveActivity(getPackageManager()) != null) {
startActivity(Intent.createChooser(emailIntent, "Choose an email client:"));
} else {
// Handle case where no email client is available
Toast.makeText(this, "No email client installed.", Toast.LENGTH_SHORT).show();
}

Similarly, to open a web page, you’d use ACTION_VIEW with an HTTP/HTTPS URI:

// Example: Opening a web page
Uri webpage = Uri.parse("https://www.example.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
if (webIntent.resolveActivity(getPackageManager()) != null) {
startActivity(webIntent);
} else {
// Handle case where no browser is available
Toast.makeText(this, "No web browser found.", Toast.LENGTH_SHORT).show();
}

Intents are delivered to different component types using specific methods:

No.Method & Description
1Context.startActivity(Intent intent)
Launches a new activity or gets an existing activity to do something new. The Intent describes the activity to start and carries any necessary data.
2Context.startService(Intent intent) / Context.bindService(Intent intent, …)
startService() initiates a service or delivers new instructions to an ongoing service. bindService() establishes a connection to a service for direct interaction.
3Context.sendBroadcast(Intent intent)
Delivers the Intent as a broadcast message to all interested BroadcastReceiver components.

An Intent object carries information used by the Android system to determine which component to start, plus information that the recipient component uses to perform the action. Key components of an Intent object include:

The name of the component to start (e.g., com.example.app.MyActivity). If set, the Intent is delivered directly to this component instance. This is an explicit intent. If not set, Android uses other Intent information to locate a suitable target (an implicit intent). Set using setComponent(), setClass(), or setClassName().

A string that specifies the generic action to perform (e.g., Intent.ACTION_VIEW, Intent.ACTION_SEND). For broadcast intents, this is the action that took place and is being reported (e.g., Intent.ACTION_BOOT_COMPLETED). The Intent class defines many ACTION_* constants. This is a crucial part of an implicit intent. Set by setAction().

A Uri (Uniform Resource Identifier) that references the data to be acted upon and/or the MIME type of that data. For example, if the action is ACTION_VIEW, the data field might contain the URI of a person in the contacts database or an HTTP URI for a web page. Set by setData(), setType(), or setDataAndType().

Examples of action/data pairs:

No.Action/Data Pair & Description
1ACTION_VIEW, content://contacts/people/1
Display information about the person whose identifier is “1”.
2ACTION_DIAL, tel:1234567890
Display the phone dialer with the given number filled in.
3ACTION_VIEW, geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California
Display a map showing the specified location.
4ACTION_EDIT, content://contacts/people/1
Edit information about the person whose identifier is “1”.
5ACTION_SENDTO, mailto:user@example.com
Open an email composer addressed to user@example.com.
6ACTION_SEND (with EXTRA_TEXT and setType("text/plain"))
Share plain text content.

An optional string containing additional information about the kind of component that should handle the intent. Common categories include Intent.CATEGORY_LAUNCHER (marks an activity as the initial entry point of an app) and Intent.CATEGORY_DEFAULT (allows an activity to be started by an implicit intent if it’s the default choice). Added using addCategory().

Key-value pairs that carry additional information required to accomplish the requested action. Stored in a Bundle object. For example, an ACTION_SEND intent might include Intent.EXTRA_EMAIL (a string array of email addresses) and Intent.EXTRA_SUBJECT (a string for the subject). Added using putExtra() methods.

Optional integers that modify the behavior of the intent, such as how an activity should be launched (e.g., FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TOP) or how the system should treat it after it’s launched. Added using addFlags().

No.Flag & Description
1FLAG_ACTIVITY_NEW_TASK
If set, this activity will become the start of a new task on this history stack. Typically used when launching activities from outside an existing activity context (e.g., from a Service or BroadcastReceiver).
2FLAG_ACTIVITY_CLEAR_TOP
If the activity being launched is already running in the current task, then instead of launching a new instance, all other activities on top of it are closed and this Intent is delivered to the (now on top) old activity as a new Intent via onNewIntent().
3FLAG_ACTIVITY_SINGLE_TOP
If the activity being launched is already at the top of the current task, then instead of launching a new instance, the existing instance will receive the intent in its onNewIntent() method.

There are two main types of intents:

Specify the component to start by its fully qualified class name. You typically use explicit intents to start components within your own app, because you know the class name of the activity or service you want to start.

// Explicit Intent: Start SecondActivity from FirstActivity (both in com.example.app)
Intent explicitIntent = new Intent(FirstActivity.this, SecondActivity.class);
// Optionally add data to the intent
explicitIntent.putExtra("MESSAGE_KEY", "Hello from FirstActivity!");
startActivity(explicitIntent);

In SecondActivity, you can retrieve the extra data:

// In SecondActivity.java onCreate() or onNewIntent()
Bundle extras = getIntent().getExtras();
if (extras != null) {
String message = extras.getString("MESSAGE_KEY");
// Use the message
}

Do not specify a particular component. Instead, they 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 show the specified location.

// Implicit Intent: View contacts
Intent implicitIntent = new Intent(Intent.ACTION_VIEW);
implicitIntent.setData(ContactsContract.Contacts.CONTENT_URI);
if (implicitIntent.resolveActivity(getPackageManager()) != null) {
startActivity(implicitIntent);
} else {
Toast.makeText(this, "No app can handle this action.", Toast.LENGTH_SHORT).show();
}

When you use an implicit intent, the Android system finds the appropriate component to start by comparing the contents of the intent to intent filters declared in the manifest files of other apps on the device. If multiple components match, the system may display a dialog for the user to choose which app to use (an “app chooser”).

Example: Launching System Apps with Intents

Section titled “Example: Launching System Apps with Intents”

This example shows how to use implicit intents to launch a web browser and a phone dialer.

  1. Create a new Android Studio project (e.g., com.example.intentdemo).

  2. Modify res/layout/activity_main.xml to include two buttons:

<?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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:id="@+id/button_start_browser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Web Browser" />
<Button
android:id="@+id/button_start_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Open Phone Dialer" />
</LinearLayout>
  1. Modify MainActivity.java (or .kt) to handle button clicks (using View Binding for modern practice):
// MainActivity.java
package com.example.intentdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
import com.example.intentdemo.databinding.ActivityMainBinding; // Generated ViewBinding class
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.buttonStartBrowser.setOnClickListener(v -> {
Uri webpage = Uri.parse("https://developer.android.com");
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(MainActivity.this, "No browser found", Toast.LENGTH_SHORT).show();
}
});
binding.buttonStartPhone.setOnClickListener(v -> {
Uri phoneNumber = Uri.parse("tel:1234567890"); // Example number
Intent intent = new Intent(Intent.ACTION_DIAL, phoneNumber);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(MainActivity.this, "No phone app found", Toast.LENGTH_SHORT).show();
}
});
}
}
  1. Ensure View Binding is enabled in your module’s build.gradle or build.gradle.kts file: android { buildFeatures { viewBinding = true } }

  2. Run the application. Clicking “Open Web Browser” will launch a browser to the specified URL. Clicking “Open Phone Dialer” will open the dialer app with the number pre-filled. The resolveActivity() check is important to prevent crashes if no app can handle the intent.

An intent filter is an expression in an app’s manifest file (AndroidManifest.xml) that specifies the types of intents that a component (Activity, Service, or BroadcastReceiver) can receive. When you create an implicit intent, the Android system searches for components that have an intent filter matching the intent.

An <intent-filter> element declares the capabilities of its parent component. It can contain one or more of these sub-elements:

  • <action android:name="...">: Declares an intent action it accepts. Must contain at least one action.
  • <category android:name="...">: Declares an intent category it accepts. An intent must match all categories in the filter.
  • <data ...>: Declares a data type it accepts, specified by URI aspects (scheme, host, port, path) and/or MIME type.

Example: An activity (ShareActivity) declared to handle sharing plain text:

<activity android:name=".ShareActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>

This ShareActivity can now be started by an implicit intent like:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(Intent.createChooser(sendIntent, "Share via"));
}

The CATEGORY_DEFAULT is important because it allows the activity to be found when startActivity() is called with an implicit intent. Without it, the activity can only be started with an explicit intent.

Intent Resolution Process: When an implicit intent is used, the system compares the intent’s action, data (URI and MIME type), and categories against the <intent-filter> declarations of all installed apps. If a match is found (or multiple matches), the corresponding component(s) can handle the intent. If no component can handle the intent, calling startActivity() will result in an ActivityNotFoundException. Always check with resolveActivity(getPackageManager()) != null before starting an activity with an implicit intent, or use a try-catch block.

Intents and intent filters are a cornerstone of Android’s application interoperability, allowing for powerful and flexible communication between components, both within a single app and across different apps.