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
}
}
Related
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).
I have added some buttons to my app in order to create intents for calendar events. But I think it would be better to check if the user has or not any calendar app. How could I do this?
Calendar intents look like:
Intent calIntent = new Intent(Intent.ACTION_INSERT);
calIntent.setType("vnd.android.cursor.item/event");
calIntent.putExtra(Events.TITLE, "My House Party");
calIntent.putExtra(Events.EVENT_LOCATION, "My Beach House");
calIntent.putExtra(Events.DESCRIPTION, "A Pig Roast on the Beach");
GregorianCalendar calDate = new GregorianCalendar(2012, 7, 15);
calIntent.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, true);
calIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME,
calDate.getTimeInMillis());
calIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME,
calDate.getTimeInMillis());
startActivity(calIntent);
In section 3.2.3.1 of the Android Compatibility Definition Document, it says
The Android upstream project defines a number of core applications, such as contacts, calendar, photo gallery, music player, and
so on. Device implementers MAY replace these applications with alternative versions.
However, any such alternative versions MUST honor the same Intent patterns provided by the upstream project. For example, if a
device contains an alternative music player, it must still honor the Intent pattern issued by third-party applications to pick a song.
The document goes on to list all core applications:
Desk Clock
Browser
Calendar
Contacts
Gallery
GlobalSearch
Launcher
Music
Settings
This basically means that all devices with the Google Play Store will have a calendar app (as well as all the apps listed above) installed that honour the standard intent patterns. Therefore, you don't need to check at all.
As MusicMaster said, all Android devices should have a Calendar application. However if you're making an intent that you're not sure will be honored by any activities, you can query the package manager using your intent to see if there are any activities able to respond to it. Like this:
PackageManager pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(yourIntent, 0);
If the size of activities is greater than zero, the user has an app that can respond to your Intent.
How to check if an app is installed in android?
This is my method:
public static boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (NameNotFoundException e) {
return false;
}
}
for example, if the app exists then start an intent:
if(isPackageInstalled("com.android.calendar", getApplicationContext())){
Intent i = new Intent();
PackageManager manager = getPackageManager();
i = manager.getLaunchIntentForPackage(packageName);
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
}else{
Log.i("myApp", "Application NOT Installed! :( ");
}
In my widget, when the widget is opened, I want it to open up a new page that shows links to the users already installed applications. The users must be able to add and delete the links as needed and the links would be updated if that application was deleted from the users device. I have already created the ability in my widget to open a new class but I don't know on how to go about linking to user applications. How can I do this?
You have to get the Activity of the app and link it with URI.
For example:
Uri.parse("market://details?id=" + facebookpackagename);
will load the Facebook app from within your app.
Try this code:
PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for(ApplicationInfo packageInfo:packages){
if( pm.getLaunchIntentForPackage(packageInfo.packageName) != null ){
String currAppName = pm.getApplicationLabel(packageInfo).toString();
//This app is a non-system app
}
else{
//System App
}
}
I want to identify list of apps that are installed on phone memory & movable to sdcard.
I am using following function to get list of installed apps.
I have checked Android Source code for InstalledAppDetails but unable to get solution.
Advance thanks
private List<App> loadInstalledApps(boolean includeSysApps)
{
List<App> apps = new ArrayList<App>();
// the package manager contains the information about all installed apps
PackageManager packageManager = getPackageManager();
List<PackageInfo> packs = packageManager.getInstalledPackages(0); //PackageManager.GET_META_DATA
for(int i = 0; i < packs.size(); i++)
{
PackageInfo p = packs.get(i);
ApplicationInfo a = p.applicationInfo;
// skip system apps if they shall not be included
if ((!includeSysApps) && ((a.flags & ApplicationInfo.FLAG_SYSTEM) == 1))
{
continue;
}
App app = new App();
app.setTitle(p.applicationInfo.loadLabel(packageManager).toString());
app.setPackageName(p.packageName);
app.setVersionName(p.versionName);
app.setVersionCode(p.versionCode);
app.setInstallDir(p.applicationInfo.sourceDir);
app.setInstallSize(calculateSize(app.getInstallDir()));
CharSequence description = p.applicationInfo.loadDescription(packageManager);
app.setDescription(description != null ? description.toString() : "");
if(app.getInstallDir().contains("/mnt"))
{
//app on sdcard
apps.add(app);
}
else
{
//app on phone memory
apps.add(app);
}
}
return apps;
}
The App Install Location is specified on the AndroidManifest.xml of your app. Take a look here for more info. In short:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="preferExternal"
... >
or
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
... >
Where auto means that the app may be installed on external device but you don't have a preference; and preferExternal means that the app will be installed on external device when possible
Remember that...
If you do not declare this attribute, your application will be
installed on the internal storage only and it cannot be moved to the
external storage.
So, the question is now how to get the androidManifest.xml file from the app. Well, you can take it from the APK (if not deleted after installed). For that issue, take a look at this post: How to parse the AndroidManifest.xml file inside an .apk package
Finally, a great topic about parsing the xml is found on this post, too. Accessing android:installLocation manifest attribute
Cheers,
Aldo
How could I write a code which can tell me that android market is installed on your android phone?
There are two ways. You can use the already mentioned getPackageManager() and getApplicationInfo() (if the package is not found, a PacketManager.NameNotFoundException will be thrown - see here). Android Market's package name is com.android.vending.
However, you can also create a dummy intent for searching the market and check how it is handled. If the resulting list has at least one entry, you can be sure that Android Market is installed:
Intent market = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=dummy"));
PackageManager manager = getPackageManager();
List<ResolveInfo> list = manager.queryIntentActivities(mmarket, 0);
Here's what I did (assumes browser exists):
Intent market = new Intent(Intent.ACTION_VIEW).setData(Uri
.parse("market://details?id=com.example.app"));
Intent website = new Intent(Intent.ACTION_VIEW).setData(Uri
.parse("http://play.google.com/store/apps/details?id=com.example.app"));
try {
startActivity(market);
} catch (ActivityNotFoundException e) {
startActivity(website);
}