Intents can used in many ways to invoke another Activity. The tutorial is not very explicit on the two main kinds of Intents so the I had to discover them myself in the documentation of the Intent class.
- Explicit intent targets a particular class that has been declared intent receiver in the AndroidManifest.xml
- Implicit intent targets an intent receiver with particular characteristics (like a particular action)
I tried out three setups in the simple test program (that actually consists of two Android applications).
- Explicit intent addressing with the invoked activity internal to the application (exp/int).
- Explicit intent addressing with the invoked activity external to the application (IntentSender application invokes IntentReceiver application) (exp/ext).
- Implicit intent addressing with external activity invocation (imp/ext). The invoked activity is again in the IntentReceiver application.
The implementation of this simple application did have its adventures. :-) The tutorial uses a simple form of explicit intent creation.
Intent i = new Intent(this, NoteEdit.class);
This was not usable for me because in the exp/ext case the target activity class was not located within the application. The solution seemed to be simple and relied on the Intent class' setClassName( pkgName, className ) method. Who could have thought that the right form of parametrization requires full path in className too (after having received the package part in the pkgName parameter)? This took me something like an hour wasted and was resolved by finding out, how the tutorial version of explicit invocation works.
The critical piece of code is the following:
Intent i = new Intent();
i.setClassName( "aexp.intentreceiver", "aexp.intentreceiver.IntentReceiver" );
i.putExtra( "i1", new Integer( 4 ) );
i.putExtra( "i2", new Integer( 5 ) );
startSubActivity(i, ACTIVITY_INVOKE);
The target activity needs to be declared in the AndroidManifest.xml. IntentReceiver class in IntentReceiver application happens to be the app's main intent receiver therefore no additional declaration is necessary. The internal IntentReceiver in IntentSender needs to be declared in IntentSender's AndroidManifest.xml.
[activity class=".IntentReceiver"]
(of course, this is XML with <> characters, I just can't get it through the #&@@! blog engine).
After getting through the explicit addressing's arcane package name/class name convention, I went after the implicit addressing which seemed similarly simple. In this case, there is an extra level of indirection between the invoker and invoked activity. The intent does not carry the target class, it carries a set of information that is used by the system to identify the target activity. In my example, I used only the intent action that I set to an action string I made up myself (aexp.intentsender.add).
Invoking code is simple:
Intent i = new Intent();
i.setAction( "aexp.intentsender.add" );
i.putExtra( "i1", new Integer( 5 ) );
i.putExtra( "i2", new Integer( 6 ) );
startSubActivity(i, ACTIVITY_INVOKE);
The intent receiver is identified according to the intent filter declaration in IntentReceiver's AndroidManifest.xml.
[intent-filter]
[action android:value="aexp.intentsender.add"/]
[category android:value="android.intent.category.DEFAULT"/]
[/intent-filter]
There is one point here to note that costed me again some half an hour wasted. :-) Although I don't use any categories, Intent's constructor creates one category by default, the Intent.DEFAULT_CATEGORY whose string format is android.intent.category.DEFAULT. I did not include the category originally into the AndroidManifest.xml and that's why the intent resolution was not succesful. This problem was rectified using the fantastic adb logcat command.
Guess, what goes into the log if there is an action match whose category does not match?
W/IntentResolver( 461): resolveIntent failed: found match, but none with Intent
.DEFAULT_CATEGORY
Thanks, emulator developers, this log message was really helpful!
16 comments:
I wish to thank you for this article! I had been trying to invoke an activity across applications and for the life of me couldn't figure out what I was doing wrong! After altering my AndroidManifest.xml file to use the Default category, the cross activity calling worked! The constructor for 'Intent' states that an "empty" Intent is created, but this isn't true based on your findings which I confirmed!
Thanks for the great help!
Thanks a lot! :)
This article helped me so much understanding intent basics about Category.
Your post is a real treasure for beginners like me, Your style of making to understand Intents is wonderful .I wish a post on PendingIntent too . In an effort to understand pending Intent ,I messed up something silly , http://groups.google.com/group/android-beginners/browse_thread/thread/c2e62e2bb9b53755/ac49603fc465dd9a .
I hope you could clarify my doubts
Thanks
Thanks for your postings.
I have a question about implicit intent, could you please give solution.
My question is"I want command for intent action, and intent data" for getting battery information(which is at spareparts/device info/battery info).
Could you please give code for intent.setAction("") & intent.setData("")
THANK YOU SO MUCH.
the tutorial of android really is crappy. and all google-results are one line snippets that dont work without the others. really, really good post.
ps. did you try html-codes like < instead of < for the xml formatting?
This is very very good post.
OK, this has been driving me nuts. No where in the documentation can I find that you have to put your fully qualified package name and class as the second parameter.
Thanks to this website I can now get it so I can launch other people's activities.
Superb article
Anthony, the package name is a tricky parameter. It does not refer to the Java package name but the package name of the apk, set by the manifest. They can be completely unrelated (even though normally they have some relationship but it is up to the apk creator). In the examples, the package name is often set to the Java package name in the Java sources in the package, hence the confusion.
The Android app framework identifies an installed application package by its "package name". When sending the intent, it picks up the application package first by the package name, then it picks the Activity that handles the intent by the class name which has to be fully qualified in order to be found by the Dalvik classloader. As the apk package name is often the same as the Java package name used in the sources, one can have the impression that the "package name" has to be specified twice. In reality, they are two completely different data items.
I want to have a button launch the clock activity on any phone. I understand this will be suitable for an implicit intent.
How is this done please?
Thanks
is the code outdated now. I am trying to compile with andorid 1.6 and it shows many methods are outdated?
Good stuff!!! Thanks
i like it good work
wtf?
can't you put the codes little large??? f'off wit ur blog
Great info..thanks..you also can find more at www.androidcookers.co.cc
;) :o (y)
Post a Comment