Perhaps I'm misunderstanding how Intents and intent-filters work, but it seems to me that this should be a straight-forward case. However, it's not working.
Here is the Intent I'm sending:
Intent i = new Intent(Intent.ACTION_VIEW);
i.setType("vnd.android.cursor.item/vnd.connectsy.event");
startActivity(i);
And here is the intent-filter:
<activity android:name=".events.EventView">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="vnd.android.cursor.item/vnd.connectsy.event" />
</intent-filter>
</activity>
And finally, the error I'm recieving:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW typ=vnd.android.cursor.item/vnd.connectsy.event }
Here's the answer:
Android treats all implicit intents
passed to startActivity() as if they
contained at least one category:
"android.intent.category.DEFAULT" (the
CATEGORY_DEFAULT constant). Therefore,
activities that are willing to receive
implicit intents must include
"android.intent.category.DEFAULT" in
their intent filters.
Add
<category android:name="android.intent.category.DEFAULT" />
to your intent filter in AndroidManifest.xml
Related
I'm experimenting, specifying my own action for use in an implicit intent. In a single package, I define two activities. ActivityTwo is to be called from onClick() in ActivityOne, using an implicit intent with an action "course.labs.activitylab.MY_ACTION". But I haven't been able to make it work.
In strings.xml:
<string name="myfunnystring">course.labs.activitylab.MY_ACTION</string>
In AndroidManifest.xml:
<activity
android:name=".ActivityTwo"
android:label="#string/title_activity_activity_two" >
<intent-filter>
<action android:name="#string/myfunnystring" />
</intent-filter>
</activity>
In onClick() in the OnClickListener() in onCreate() in ActivityOne.java:
Intent intent = new Intent();
intent.setAction(getString(R.string.myfunnystring));
intent.setFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
startActivity(intent);
The program crashes in the emulator, and I find this in the logcat window:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=course.labs.activitylab.MY_ACTION flg=0x8 }
What am I doing wrong?
Add the default category to your intent filter.
<intent-filter>
<action android:name="course.labs.activitylab.MY_ACTION" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
Read the documentation but unclear as to the purpose of the DEAFAULT category in the manifest. Is it possible to have more than 1 intent-filter with the DEFAULT category attribute in the same manifest?
Yes it is possible to have more than one. From the documentation here is why you would need the default category:
*Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare this category in your intent filter, no implicit intents will resolve to your activity.* - http://developer.android.com/guide/components/intents-filters.html
Example of having more than one intent filter with default category:
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="myscheme"/>
</intent-filter>
Is it possible to have more than 1 intent-filter with the DEFAULT category attribute in the same manifest?
Sure. Most activities that have an <intent-filter> will support the DEFAULT category, as that category is automatically added to an Intent used with startActivity() if there is no other category on the Intent already.
For example, in the manifest for the AOSP Music app, you can see a variety of <activity> elements, with and without <intent-filter> elements. Those that have <intent-filter> may or may not use DEFAULT.
Two activities are installed having the following manifest files on device respectively:
The First app's activity has in its manifest:-
where,
package="com.example.tictactoe"
<intent-filter>
<action android:name="com.example.tictactoe.YOYO" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
The second app's activity has in its manifest:-
where,
package="com.example.project"
<intent-filter>
<action android:name="com.example.project.YOYO" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
Now, i want to start one of these activity from third application using the following code:
i=new Intent();
i.setAction("YOYO");
i.putExtra("KEY","HII..i am from third app");
startActivity(i);
But execution shows an error:-
03-11 08:12:30.496: E/AndroidRuntime(1744): FATAL EXCEPTION: main
03-11 08:12:30.496: E/AndroidRuntime(1744): android.content.ActivityNotFoundException:
No Activity found to handle Intent { act=ACTION_SEND (has extras) }
You need to supply the full action name; supply the mimeType you used in manifest by calling setType() in your intent.
Manifest :
<intent-filter>
<action android:name="com.example.tictactoe.YOYO" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
Java :
Intent i=new Intent();
i.setAction("com.example.tictactoe.YOYO");
i.setType("text/plain");
i.putExtra("KEY","HI..i am from third app");
startActivity(i);
You need to supply the full action:
i=new Intent();
i.setAction("com.example.tictactoe.YOYO");
i.putExtra("KEY","HII..i am from third app");
startActivity(i);
Or (depending which project you want to launch):
i.setAction("com.example.project.YOYO");
You can do it also via: (supply action directly in constructor)
i=new Intent("com.example.tictactoe.YOYO");
i.putExtra("KEY","HII..i am from third app");
startActivity(i);
Also loose the data mimeType or read up on how to use it. Because via putExtra is not going to work.
First of all you need to ensure that the name of the intent is the fully qualified name with the package name is the same in the intent filter and the activity firing the intent. In this case: "YOYO" should be "com.example.tictactoe.YOYO". You should also remove the mime type since you are not including data in the setData(), you are in this case using a bundle. So you should have for the activity firing the intent:
ACTIVITY FIRING INTENT
i=new Intent();
i.setAction("com.example.tictactoe.YOYO");
i.putExtra("KEY","HII..i am from third app");
startActivity(i);
and for the receiving activity's entry in the manifest: You need to ensure you set the category as DEFAULT and remove the data type tag.
ACTIVITY RECEIVING INTENT
<intent-filter>
<action android:name="com.example.tictactoe.YOYO" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
I don't get the Android Intent matching concept! I must be missing something, but I read and re-read the docs and don't get it. Maybe some kind soul can shed some light on this?
I am able to start an Activity if I specify a Category filter android.intent.category.DEFAULT in the manifest:
...
<activity
android:name="mmmo.android.test.ItemDetails"
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
...
and if I then don't add any Category to the Intent object:
...
Intent intent = new Intent(Intent.ACTION_INSERT);
startActivity(intent);
...
That works. However, as soon as I define any other category than android.intent.category.DEFAULT I am only getting ActivityNotFoundExceptions. E.g. if I specify:
...
<activity
android:name="mmmo.android.test.ItemDetails"
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="foo.bar" />
</intent-filter>
</activity>
...
and then try to start that Activity using:
...
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.addCategory("foo.bar");
startActivity(intent);
...
this does not work. The doc reads "... every category in the Intent object must match a category in the filter. ...". The category name I add to the Intent matches the category I specified in the filter. So why does this not match up and just throws an exception???
Michael
You must also add
<category android:name="android.intent.category.DEFAULT"></category>
to the intent filter for the intent to be resolved.
See Intent:
Activities will very often need to support the CATEGORY_DEFAULT so that they can be found by Context.startActivity().
From the documentation:
In principle, therefore, an Intent object with no categories should
always pass this test, regardless of what's in the filter. That's
mostly true. However, with one exception, Android treats all implicit
intents passed to startActivity() as if they contained at least one
category: "android.intent.category.DEFAULT" (the CATEGORY_DEFAULT
constant). Therefore, activities that are willing to receive implicit
intents must include "android.intent.category.DEFAULT" in their intent
filters
A "bug" is present if the observable behaviour does not match its documented one. This one does not a bug make.
I am trying to launch an activity by specifying only its action(custom) defined in its intent filter from an activity in other application. The activity to be launched is the main activity of its application thus have android.intent.action.MAIN & android.intent.category.LAUNCHER set as action and category in its intent filter. Now according to android doc on Intent and Intent Filter, i do not need to specify DEFAULT category at all in this case. But doing the same i am i am unable to launch the activity.
LogCat says, Activity could not be found...
Am i misinterpreting the text or is there something else missing...?
Code, used for calling the activity
Intent i=new Intent();
i.setAction("android.AddressBookV4.firstActivity");
startActivity(i);
Definition of Activity being called in the manifest file
<activity android:name=".AddressBook"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.AddressBookV4.firstActivity" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
You need to add the LAUNCHER category to your Intent, since the <intent-filter> says that it matches the following Intents (in pseudocode):
((action IS "android.AddressBookV4.firstActivity")
OR (action IS "android.intent.action.MAIN"))
AND (category IS "android.intent.category.LAUNCHER")