Android Logo MathCS.org - Android

Starting Activities through System-Wide Intents

java -> android -> system-wide intents ...

In the previous section we saw how one activity can start other child activities by creating a specific intent that includes the name of the intended class to start. Instead we could describe an "intent" to do X with data Y and let the operating system decide who can fulfill our request. For that to work, every activity needs to register the type of operations it can perform with the OS during installation, and there needs to be an event that can encapsulate the idea of "do X with data Y". Both is done via the Intent class.

The Intent class

An Intent is an object that represents an ”intention” to do something. For example, if your application wants to display a web page, it can express its “intent” to view the URI by creating an Intent instance and handing it off to the system. The system locates some other piece of code (in this case, the Browser) that knows how to handle the intent and runs it. The primary pieces of information in an intent are:

Some examples of action/data pairs are:

Example: In the previous section we created a class with a "Start Activity" button to start a specific child activity that we also created. Now let's modify that class to

Both activities are already available. After all, that's exactly what happens when we select the "contacts" application. So all we need to figure out is how to get the respective activity to run, and how to pass data into and out of it.

Note: there is one more thing to do before we start coding! We need to add a request for permission to read the contact information to our project's manifest via a uses-permission entry:

     <uses-permission android:name="android.permission.READ_CONTACTS">
    </uses-permission>

The previous project contained the class FirstMultiApp. We use that class and change the handleButtonClick method to broadcast an intent to select a name from the contact list. Thus, we create the intent:

    private void handleButtonClick()
    {
	// creating our intent
	Intent selectContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts/people"));

	// now we broadcast this intent and hope some activity will kick in:
        startActivityForResult(selectContactIntent, INPUT_REQUEST);

    }

That will bring up the standard scrollable list of contacts as if you clicked the Contacts application. Two things can happen next: the user could tap a contact, or the user can cancel the selection process. But since we called startActivityForResult we know that, either way, our activity will be informed via its onActvityResult method, which we could implement as follows:

	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == Activity.RESULT_CANCELED)
			Toast.makeText(this, "activity canceled", Toast.LENGTH_SHORT).show();
		else if (resultCode == Activity.RESULT_OK)
			Toast.makeText(this, "contact selected: " + data, Toast.LENGTH_SHORT).show();
	}

This will work perfectly, but we can do even better. The data returned when the user picks a name is again an intent. It includes, in particular, a data Uri to a specific name. We can use that to create another intent, this time to view that contact info, and post it via another startActivity or startActivityForResult call. Here is the modified method:

	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == INPUT_REQUEST)
		{
			if (resultCode == Activity.RESULT_CANCELED)
				Toast.makeText(this, "activity canceled", Toast.LENGTH_SHORT).show();
			else if (resultCode == Activity.RESULT_OK)
			{
				Toast.makeText(this, "contact selected: " + data, Toast.LENGTH_SHORT).show();
				startActivity(new Intent(Intent.ACTION_VIEW, data.getData()));
			}
		}
	}

To summarize: we have an activity with a button. If the button is clicked a list of names will appear and we can pick one. If we pick a name, the full info for that contact is displayed! Pretty nifty for that little coding, but even better: if the contact application is improved - say as a result of an OS upgrade - our application automatically benefits!

Exercise: Usually when we long-click on a name in the list of contacts, we can select to edit it. Does that work for our app? If not, how would you enable it? Instead of viewing a contact info, change the program to dial the selected contact's number (you may need to add another set of permissions in addition to changing the code (and doing some additional reading)).

The next step to get familiar with intents is to learn how to create activities that can serve as intent handlers for data. Every basic activity is registered to handle ACTION_MAIN via the following entry in the manifest file:

<intent-filter>
	<action android:name="android.intent.action.MAIN" />
	<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>  

If the launcher posts an ACTION_MAIN intent with data being the activity class name, it calls the onCreate method and thus starts the activity. We will pick up more details later, but now we have all the ingredients to write an actually useful activity in the next segment.