I post this question here for educational purposes, since I couldn't find answers anywhere and eventually found the root cause the old way, i.e. by myself.
Here's the problematic code :
// initially getting the intent from polling the PackageManager about activities resolving Search intent.
ComponentName componentName = intent.resolveActivity(pm);
if (componentName != null) {
context.startActivity(intent);
}
despite the check i get an ActivityNotFound exception.
EDIT: apparently the point wasn't obvious to everyone so : how come there's an activity resolving the intent, yet trying to launch it throws an ActivityNotFound exception - two facts apparently contradictory ?
From what i could see, intent.resolveActivity() will return true if there is ANY activity resolving this intent. Even if this activity is not exported (which makes it unusable for all practical purposes in case it's not from your package).
Android's API doesn't care to mention that, so you have to figure it out by yourself, and make sure that the activity you're trying to launch is indeed exported.
ActivityInfo activityInfo = intent.resolveActivityInfo(pm, intent.getFlags());
if (activityInfo.exported) {
doSomething();
}
EDIT: the point of this question is that ResolveActivity will return a componentName even if activityInfo.exported==false AND it's not from your own package - which makes it unlaunchable, and surprised me cause the intent was resolved and yet unlaunchable.
ActivityNotFound exception is thrown when a call to startActivity(Intent) or one of its variants fails because an Activity can not be found to execute the given Intent. For example, if you’re trying to send an email, but there is no app on your device that could process ACTION_SEND intent action, ActivityNotFound will be thrown.
A way to avoid the exception is to do the following:
final ComponentName componentName = intent.resolveActivity(pm);
if (componentName != null) {
try {
context.startActivity(intent);
} catch (ActivityNotFoundException ex) {
// Notify the user?
}
}
Related
My use case is to switch from App1 to App2 . In App1, I use the packageManager.getPackageInfo() API to check whether the App2 is present or not.
When it returns true, I set the intent with intent.setPackage(App2) and trigger the context.startActivity(intent) API.
But there are times when context.startActivity(intent) API throws ActivityNotFoundException: App2 is present in the device. The intent has been set in App2 and android:exported is also set to true.
This issue is happening from Android 12. Any inputs be would be highly appreciated!
There is an official documentation on how to prepare an Activity to be launched from outside of the app:
https://developer.android.com/training/basics/intents/filters
Furthermore there are multiple examples on how to launch an external activity, maybe check out these two examples (Source for the examples):
1.
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
startActivity(intent);
2.
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
if (launchIntent != null) {
startActivity(launchIntent);//null pointer check in case package name was not found
}
The Android#startActivity(Intent) is specified to throw android.content.ActivityNotFoundException if there was no Activity found to run the given Intent.
I therefore have code like
try {
// Try to start activity provided by external app:
startActivity(intent);
} catch (ActivityNotFoundException e) {
// [...] Inform user about external app needed
// for this functionality to work.
}
which catches ActivityNotFoundException to handle the case where the external app is not installed.
However, from the Crashes & ANRs section of the Google Play Developer Console I'm starting to get crashes as IllegalArgumentException: Unknown component com.example.package/com.example.package.Activity. Should code invoking startActivity() be ready to handle that exception as well? Is this a framework bug (or documentation error)?
This exception generally arises when you haven't declared it in your manifest file. So, try doing it
Somewhere inside your application tag do this
<activity
android:name="Your_Activity_Name"
android:theme="Whatever your theme is"
</activity>
If its any other issue please let me know.
You can use this code to check it. This is the better approach then handling exception
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0)
{
// start your activity
}
I am trying to open the Google Voice Search Application
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage("com.google.android.voicesearch");
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
}
This does not launch the voice search application,
however if I use com.google.android.apps.maps as the package name then the Google Maps app is opened.
I don't understand why Voice Search is not opening, even though the package name is correct.
Solution
Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
startActivity(intent);
Please see
Launch Preinstalled App from activity (Google Voice Search) Android for more information on the solution.
Thank you.
As you can read here, getLaunchIntentForPackage (String packageName)
Return a "good" intent to launch a front-door activity in a package [...]
The current implementation will look first
for a main activity in the category CATEGORY_INFO, next for a main
activity in the category CATEGORY_LAUNCHER, or return null if neither
are found.
so, in the intent, the category will already be set. If you manually change it, probably you are breaking the intent, since the category could not be the correct one that the manager found.
so, just remove the line
i.addCategory(Intent.CATEGORY_LAUNCHER);
In my app i want to use galaxy s4 S-translator.So is it possible to use it? And normally can i call another app from my app.I am very new to android.So I don't know it is possible or not.So if possible plz tell me.I think by using intent with giving proper action we can do it.
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage("app package name");
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
}
thanx
Yes, by using intents.
For example:
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.setClassName("com.example.theotherapp", "com.example.theotherapp.MainActivity");
startActivity(intent);
This is called an explicit intent, because you're explicitly stating which component should respond to it. You can also use implicit intents, in which you specify what kind of component you expect and the OS and/or the user selects the most appropriate one.
If you can choose, implicit intents are preferred.
This might Help You.
hi Its been 2 days looking for this simple problem. I want to launch Android own launcher from my application EVEN if its not set as default.
final PackageManager packageManager=getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage("com.android.launcher");
this return null for Android own launcher but if I try custom launcher is give me successfully
Found the solution, after investigating source code of getLaunchIntentForPackage. As per documentation,
The current implementation will look first for a main activity in the
category CATEGORY_INFO, next for a main activity in the category
CATEGORY_LAUNCHER, or return null if neither are found.
So, the function don't look for CATEGORY_HOME, i rewrote it in following way, it worked perfectly.
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(Intent.CATEGORY_HOME);
intentToResolve.setPackage("com.android.launcher");
ResolveInfo ri = getPackageManager().resolveActivity(intentToResolve, 0);
if (ri != null)
{
Intent intent = new Intent(intentToResolve);
intent.setClassName(ri.activityInfo.applicationInfo.packageName, ri.activityInfo.name);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
}
Are you sure the default Google Android Launcher being installed on your device? If not, then it's truly NULL.