Monday, March 03, 2008

Android: Playing with Intents

Android: Playing with Intents



Android Intent Playground 2.0 is described in this post:
Diego Torres Milano's blog: Android Intent Playground 2.0

This document is published at http://docs.google.com/Doc?id=ddwc44gs_31gjdwgxfh

WARNING: Blogspot engine change the link, so you have to cut and paste.

Intents

From Google documentation: “An Intent is a simple message object that represents an ”intention” to do something. For example, if your application wants to display a web page, it expresses 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 that Intent, and runs it. Intents can also be used to broadcast interesting events (such as a notification) system-wide.”

An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested IntentReceiver components, and startService(Intent, Bundle) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.

Intents are one of the most distinctive components of the Android platform. They, among other things, provide the transition between Activities in a similar model as the browser model, where the user navigates from on page to the other and can also go back.

Intent attributes

Intent
primary attributes
action The general action to be performed, such as VIEW_ACTION, EDIT_ACTION, MAIN_ACTION, etc.
data The data to operate on, such as a person record in the contacts database, expressed as a Uri.
secondary attributes
category Gives additional information about the action to execute. For example, LAUNCHER_CATEGORY means it should appear in the Launcher as a top-level application, while ALTERNATIVE_CATEGORY means it should be included in a list of alternative actions the user can perform on a piece of data.
type Specifies an explicit type (a MIME type) of the intent data. Normally the type is inferred from the data itself. By setting this attribute, you disable that evaluation and force an explicit type.
component Specifies an explicit name of a component class to use for the intent. Normally this is determined by looking at the other information in the intent (the action, data/type, and categories) and matching that with a component that can handle it. If this attribute is set then none of the evaluation is performed, and this component is used exactly as is. By specifying this attribute, all of the other Intent attributes become optional.
extras - This is a Bundle of any additional information. This can be used to provide extended information to the component. For example, if we have a action to send an e-mail message, we could also include extra pieces of data here to supply a subject, body, etc.

The best way to explore all of this somewhat complex model is to try it out.

Official Google documentation has some mistakes that turn your exploration a bit more difficult.

For example in http://code.google.com/android/reference/android/content/Intent.html there are some mistakes.

Some examples of action/data pairs are: * VIEW_ACTION content://contacts/1 – Display information about the person whose identifier is “1”. * EDIT_ACTION content://contacts/1 – Edit information about the person whose identifier is “1”. * VIEW_ACTION content://contacts/ – Display a list of people, which the user can browse through. This example is a typical top-level entry into the Contacts application, showing you the list of people. Selecting a particular person to view would result in a new intent { VIEW_ACTION content://contacts/N } being used to start an activity to display that person. * PICK_ACTION content://contacts/ – Display the list of people, allowing the user to browse through them and pick one and return it to the parent activity. This could be used, for example, if an e-mail application wanted to allow the user to pick a person

Should say

  • VIEW_ACTION content://contacts/people/1 – Display information about the person whose identifier is “1”.
  • EDIT_ACTION content://contacts/people/1 – Edit information about the person whose identifier is “1”.
  • VIEW_ACTION content://contacts/people/ – Display a list of people, which the user can browse through. This example is a typical top-level entry into the Contacts application, showing you the list of people. Selecting a particular person to view would result in a new intent { VIEW_ACTION content://contacts/people/N } being used to start an activity to display that person.
  • PICK_ACTION content://contacts/people/ – Display the list of people, allowing the user to browse through them and pick one and return it to the parent activity. This could be used, for example, if an e-mail application wanted to allow the user to pick a person

Intent Playground

To explore these relationships, I've made a simple application that allows you to play with Intents and see the results.

This application completes the intent attributes with the information provided and sometimes with other information obtained from it and then invokes the corresponding method.



AndroidIntentPlayground source and binaries can be downloaded from AndroidIntentPlayground.zip.





action

It's an AutoCompleteTextView to select an action from the list (try entering the first letter as a or c. You can also enter the desired action if it's not in the list.

See Intent attributes.

data uri

The data Uri to act on.

See Intent attributes.

type

The MIME type.

See Intent attributes.

intent

Select the kind of method to invoke

  • broadcast: use broadcastIntent(intet)
  • activity: use startActivity(intent)
  • service: use startService(intent, null)
  • resolve: use Intent.resolveActivity()

activity

When the activity is resolved the class name is showed here.

button

Press the button to send the Intent.

Examples

broadcast

Our first example is an intent broadcast. If there's an IntentReceiver which has an Intent that matches our attributes then its onReceiveIntent() method will be invoked. I've explained how to create an IntentReceiver only application in a previous post. If you have installed the SampleIntentReceiver.APK, we can try this example.

Set action to com.codtech.android.training.intent.SAMPLE_ACTION, leave the other fields blank and the intent to broadcast. Press the button and you'll see


Explanation

If we try to resolve the Intent we will receive an error, but broadcasting the intent it reaches our SampleIntentReceiver and the dialog is displayed.

This intent filter in our SampleIntentReceiver AndroidManifest.xml matches

        <receiver android:name=".SampleIntentReceiver">
<intent-filter>
<action android:name="com.codtech.android.training.intent.SAMPLE_ACTION"/>
</intent-filter>
</receiver>

start activity

Set action to android.intent.action.VIEW and data uri to content://contacts/people/1, set intent to activity and the press the button.


Explanation

After pressing the button we will see our first contact displayed.

We hit a bug. It's not possible to obtain the screenshot using DDMS, instead of the contact the previuos activity is displayed.

The intent was resolved to com.google.android.contacts.ViewContactActivity and this activity is invoked by startActivity(intent).

service

You need ApiDemos installed for this to work.

Set action to com.google.android.samples.app.REMOTE_SERVICE, leave the other fields blank, and set intent to service. Press the button.

And the RemoteService will be started.

The triangle in the upper left corner indicates that the service is running.

However, if we try to stop the service, opening the sliding top panel and clicking on SampleRemoteService instead of getting this service activity we'll get LocalServiceController and we cannot stop it. Another bug ?

Workaround: Go to Home, ApiDemosAppServiceRemote Service Controller and the Stop Service.

Explanation

The intent is used as a parameter of startService(intent, null) and the requested service is started if needed.

resolve

Se action to android.intent.action.WEB_SEARCH, enter some strings into data uri, for example cult thinclient. Set intent to resolve and the press the button. We can see that the action is resolved to com.google.android.browser.BrowserActivity. If we further change intent to activity and press the button again, we will see the browser starting and doing the Google search.

Explanation

The activity is resolved to the corresponding class, and if we use this information to start the activity we will see the web browser presenting the search.

Conclusion

This application, Intent Playground, has helped me a lot to discover some interactions between the Android components.

However, I was not able to intercept the intent used by the contacts application when you try to edit its photo. Could it be using an intent instantiated used an explicit class com.google.android.fallback.Fallback ?

Do you have any clue ?

16 comments:

Diego Torres Milano said...

The documentation error issue was reported to Google as http://code.google.com/p/android/issues/detail?id=400

Manu said...

Diego, runs applications with flash?, I have a universe in Netbives and will not run on the android browser.
Saludos.
Manuel

IntelliBitz Technologies said...

Diego,

Did you add write permission?
"android.permission.WRITE_CONTACTS"

Diego Torres Milano said...

No, AFAIK only android.permission.READ_CONTACTS should be added.
Test intent: android.intent.action.EDIT and data uri: content://contacts/people/1 and then start activity. Should work.

Unknown said...

Your tool looks quite useful :-)

If you want to further explore this, we have implemented VIEW, PICK, and GET_CONTENT intents for media content in our media browser and media player:
http://www.openintents.org/en/node/15

Peli

Unknown said...

Let's see if I can make the link clickable:
OpenIntents media player
:-)

Peli

Unknown said...
This comment has been removed by the author.
Unknown said...

Hello, in the last lines of your post regarding the android intents, you said "However, I was not able to intercept the intent used by the contacts application when you try to edit its photo."

Have you been able to intercept the intent used to launch the contact application ? Since I would like to replace the default contact application by mine, I tried to intercept those kind of intent. There is no document on how to do such a thing on google android... that's a shame.

Thanks

Diego Torres Milano said...

Things have changed a bit in latest release of the SDK (1.0r1) and now you can edit the photos, which was the intention of this post.
However, I don't think this is what you want, really.
Do you want to replace the contacts application completely ?

Diego Torres Milano said...

Well, it's not clear from previous post, but this is the post about editing contact's photo: http://dtmilano.blogspot.com/2008/02/android-contact-photos-you-may-wonder.html

Unknown said...

Hi Diego, thank for the quick answer.

Since you were talking about intercepting intents used for the contacts, I though I could try to ask the the question.

So what I would like to do is to replace the android contact app by mine. eg: when I click on the contact icon from G1 (or emulator) it launches my contact application instead of the default one.

What I've read from some android post is that it is not possible to replace physically the default android application but instead I could use the intents mechanism to intercept them and launch my own application.

I don't want to replace the default application completely( not possible) but allow user to set my application to the default one. So that next time user will click on the contact icon, it would launch my app.


One of the big feature announced by google was the possibility to do what we are talking about, and I think it's a shame that they don't document it.

I hope I was not too confusing...
Thanks

max said...

thank u very much for pointing out the error on the google documentation..

jer said...

Hey Diego,

Thanks for the example code, it was very helpful. I was wondering if you ever solved the issue of intercepting system intents? Like the commenter above I would like to intercept requests to the default contacts app and respond using my custom contacts application.

cheers,
jer

J said...

Diego, the link to download the source of your Android Playground is broken. Can you please provide a new link? Thanks.

Unknown said...

I have to i appreciate you for the efforts you get in writing this article. so you to promote your blog by using some internet marketing strategy, because it can easily to reach the peoples.

Android app developer

Siti Mashitah said...

Hello,

I noticed you put a link to download the IntentPlayground.zip but I don't think the link is working. I wonder if you actually got the folder off from the codetech website?