Currently I have written a code to load all capable applications which can view images from the phone.
public static List<String> getAllCapableForFileViewing (Context context, String mimeType) {
List<String> packages = new ArrayList<>();
PackageManager pm = context.getPackageManager();
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_VIEW);
sendIntent.setType(mimeType);
List<ResolveInfo> resolveInfoList = context.getPackageManager()
.queryIntentActivities(sendIntent, 0);
for (ResolveInfo resolveInfo : resolveInfoList) {
packages.add(resolveInfo.activityInfo.packageName);
System.out.println(resolveInfo.activityInfo.packageName);
System.out.println(resolveInfo.activityInfo.applicationInfo.className);
System.out.println(resolveInfo.activityInfo.name);
System.out.println("");
}
return packages;
}
When I tried to list all the applications, one of them have two set listed e.g. WeChat, WeChat Moment. Obviously it have two activities which can handle the image for viewing. The problem is the name of the two are the same "WeChat".
Additionally? even though it can consume the content i passed in but they are not really application for viewing images e.g. Gallery application. Is there a way to recognise them. I know it may be impossible.
The problem is the name of the two are the same "WeChat".
Well, in the end, that is up to the developers of that app. However, look at labelRes of the ResolveInfo, as this may be a better label to use (e.g., pulled from the <intent-filter>).
Is there a way to recognise them
You are welcome to try using CATEGORY_APP_GALLERY, though this may lead to false negatives (i.e., apps that the user would expect to show up that do not).
Related
I am building an app that auto sorts installed apps and allows the user to launch those apps. I just ran into a small issue with the camera app. When I scan through the installed apps with 'queryIntentActivities' for 'ResolveInfo' I get the gallery ResolveInfo twice and both objects are identical. I am wondering if I am missing something obvious or the camera is simply not launch-able from a package name.
If the camera and the gallery share the same package would I still be able to use the package manager to pull the icons and labels for each? I want to avoid using my own drawable as different OEMs make different icons.
I am aware that I can simply launch the camera with a capture image intent but I do not care for the results and I want to launch the camera as a stand alone activity plus using this intent doesn't really solve my issue.
Update:
So the ResolveInfo's I am receiving for the camera and gallery aren't exactly the same. They share the same package name but I can pull their respective icons through the ResolveInfo.loadLabel and ResolveInfo.loadIcon (rather then what I was doing with ResolveInfo.ApplicationInfo.loadLabel ... which returned identical labels and icons). However I am still unable to find any way to launch the activities for the camera and gallery separately.
Update 2.0
Problem solved. I found the unique activity string in the ResolveInfo.ActivityInfo.name. Now rather then launching the app with the package name I just launch it with the activity that was listed in that variable.
No, the package manager for camera and gallery are different.
for camera - com.android.camera.
for gallery - com.android.gallery.
this is the way in which you would differentiate the gallery and camera.
The best way to get the package name of the camera app is pasted below. You can get the package name by refering to cameraInfo.activityInfo.packageName; returned by the function below
public static ResolveInfo getCameraPackageName(Context context, PackageManager pm) {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
ResolveInfo cameraInfo = null;
List<ResolveInfo> pkgList = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if(pkgList != null && pkgList.size() > 0) {
cameraInfo = pkgList.get(0);
}
return(cameraInfo);
}
I'm wondering if it's possible to check if an application is shipped with Android, for example: Gallery, Contacts, Downloads, Email, etc. all these kind applications are the ones I would like to exclude from a list I'm creating, but don't want to hardcode the names.
This is the code I'm using to grab application names:
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
final List pkgList = getApplicationContext().getPackageManager().queryIntentActivities(mainIntent, 0);
pkgList contains ResolveInfo objects.
Edit:
One way to check if application is part of Android OS is to check if ResolveInfo.activityInfo.applicationInfo.packageName contains "com.android" char seq., but I'm still interested in a more elegant solution.
See this answer.
Basically, this:
PackageManager pm = getPackageManager();
//Gets the info for all installed applications
List<ApplicationInfo> apps = pm.getInstalledApplications(0);
for(ApplicationInfo app : apps) {
if((app.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
//It's a pre-installed app
} else if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1) {
//It's a pre-installed app with a market update installed
}
}
I would like to start a default application: browser, contact-book, phone, email, music app, etc. I have found many q/a, like browser opening a specific URL or blank, and here the answer is even "No not possible". But I would like to just open/launch it without telling it to go to a specific URL or sending a mail to someone, etc.
However, I also saw some Home applications where this seems to be working (at least for some apps). On my colleague's device there is for example a different contact-book (no google) which is detected and opened correctly.
I have seen in the Android documentation some intent categories that point to these problems, but these are only >= API.11. So I can't use/test them on my device.
Question: Is it not somehow possible to launch a default application (having the app chooser is of course ok) without providing extra data? If no, what do you think are these Home apps doing (perhaps workarounds are somehow possible).
PS: for the phone app I think, I have a workaround using Intent.ACTION_DIAL without any other information which will open simply the dialer.
UPDATE: I modified the title. Some applications like the address book may not be the same on different devices. So in this case I would like to start the address-book app, whichever this is.
This answer is not a 100% answer, but some workarounds on some typical applications.
Still open are: music player, address book
Browser: I get a list of applications that handle "http"-data intents, and then I look if one is available in the list of preferred applications.
Intent appFilter = new Intent(Intent.ACTION_VIEW);
appFilter.setData(Uri.parse("http://www.google.com"));
List<ResolveInfo> browserInfoList = pm.queryIntentActivities(appFilter, 0);
List<IntentFilter> outFilters = new ArrayList<IntentFilter>();
List<ComponentName> outActivities = new ArrayList<ComponentName>();
pm.getPreferredActivities(outFilters, outActivities, null);
if(outActivities.size() > 0) {
for(ComponentName cn : outActivities) {
String cnClass = cn.getClassName();
String cnPkg = cn.getPackageName();
for (ResolveInfo info : browserInfoList) {
if(info.activityInfo.name.equals(cnClass) &&
info.activityInfo.packageName.equals(cnPkg)) {
return cn;
}
}
}
}
In case no default is found, I open a browser chooser dialog, see here.
Phone: as described in the question:
Intent intent = new Intent(Intent.ACTION_DIAL);
startActivity(intent);
You can start apps by the function "startActivity" if you know about the canonical app name
like "android.com.browser". Do this simple by searching for AndroidManifest.xml in the app
source code (look at Codeaurora.com or at github/Cyanogenmod) and grab the app name you want.
After you know about the App name ("Activity") implement the code as follows:
Intent intent = new Intent();
intent.setClassName(this, "com.android.browser");
intent.setCategory(Intent.ACTION_MAIN);
startActivity(intent);
THIS is only a example, sometimes you have to put intent extras or data values, this information can be found in the app's AndroidManifest.xml too.
Some Android devices don't have Android Market, like Korea, etc.
Is it possible to detect the existence of Android Market at runtime?
I know I can try to open a market uri first to see if there is any exception thrown. But I don't think this is a wise approach.
I know I can try to open a market uri
first to see if there is any exception
thrown.
Create the ACTION_VIEW Intent for the Market Uri, then use PackageManager and queryIntentActivities() to see if you get anything back. If that returns an empty list, you know nothing on the device handles Market Uri values.
A complete solution, that also reads the packagename by itself ...
Context context = this;
final PackageManager packageManager = context.getPackageManager();
String packagename = this.getPackageName();
String url = "market://details?id=" + packagename;
Intent i2 = new Intent(Intent.ACTION_VIEW);
i2.setData(Uri.parse(url));
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(i2,PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfo.size() > 0) startActivity(i2);
I want to check if my application is set as the default application for the Intents I'm handling inside my App.
As an example ff more than one application supports to open a specified file format. I need to make my application as a default application from my code. How it possible to make my application a default (from the code)? Can anyone help me?
At least I would like to check this on startup of my app and redirect the user to fill in some information if my App is not set as the default on the device.
As far as I know this is not possible. That dialogue is handled by the system - your app will only be launched if the user picks your app from the list.
Allowing such a behaviour would impact the user's ability to control their default applications, and from a technical point of view would mean a process and its memory would have to be allocated to every app in the list every time such a list appeared.
You could use this method:
public static boolean isOurAppDefault(Context context) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://google.com"));
ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(browserIntent,PackageManager.MATCH_DEFAULT_ONLY);
String defaultBrowserPkg = null;
if (resolveInfo != null) {
if (resolveInfo.activityInfo != null) {
defaultBrowserPkg = resolveInfo.activityInfo.packageName;
}
}
return TextUtils.equals(context.getPackageName(), defaultBrowserPkg);
}
It's actual for some editor or browser. In other case use different Uri data for intent.