147

I'm trying to install apps from Google Play. I can understand that on opening the Google Play store URL, it opens the Google Play and when I press the back button, the activity resumes.

Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(appURL));
marketIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(marketIntent);

When I went back to the activity, I tried calling this onResume() to check if the app is installed, but I receive an error:

@Override
protected void onResume() {
    super.onResume();
    boolean installed = false;
    while (!installed) {
        installed  =   appInstalledOrNot(APPPACKAGE);
        if (installed) {
             Toast.makeText(this, "App installed", Toast.LENGTH_SHORT).show();
        }
    }
}

private boolean appInstalledOrNot(String uri) {
  PackageManager pm = getPackageManager();
  boolean app_installed = false;
  try {
      pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
      app_installed = true;
  }
  catch (PackageManager.NameNotFoundException e) {
      app_installed = false;
  }
  return app_installed ;
}

The error is as follows:

E/AndroidRuntime(796): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.appinstaller/com.example.appinstaller.MainActivity}: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=market://details?id=com.package.name flg=0x40080000 }

I guess the activity is onPause(). Is there a better way to implement it? I'm trying to check if the app has finished installing.

Micho
  • 3,929
  • 13
  • 37
  • 40
Siddharthan Asokan
  • 4,321
  • 11
  • 44
  • 80
  • possible duplicate of [Detect an application is installed or not?](http://stackoverflow.com/questions/3922606/detect-an-application-is-installed-or-not) – Philipp Jahoda Sep 11 '13 at 22:23
  • @SiddharthanAsokan If I understand correctly, what you are trying to achieve here is, start your app -> go to play store-> click install -> come back to your own activity -> start the newly installed app.. is that right? – Varun Sep 11 '13 at 22:57
  • Nope go back to the app which I opened initially. I need to get to get some info about the installed app using PackageManager. This information retrieval starts after I install the app from the initial which used opened the web url. – Siddharthan Asokan Sep 11 '13 at 23:02
  • check this answer, it need for android 11 https://stackoverflow.com/a/72014352/4797289 – Rasoul Miri Apr 26 '22 at 12:58

13 Answers13

383

Try this:

private boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    try {
        packageManager.getPackageInfo(packageName, 0);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

Note!

From Android 11 (API 30), you might need to declare <queries> in your manifest, depending on what package you're looking for. Check out the docs for more info.

How it works:

It attempts to fetch information about the package whose name you passed in. Failing that, if a NameNotFoundException was thrown, it means that no package with that name is installed, so we return false.

Note that we pass in a PackageManager instead of a Context, so that the method is slightly more flexibly usable and doesn't violate the law of Demeter. You can use the method without access to a Context instance, as long as you have a PackageManager instance.

How to use:

public void someMethod() {
    // ...
    
    PackageManager pm = context.getPackageManager();
    boolean isInstalled = isPackageInstalled("com.somepackage.name", pm);
    
    // ...
}
Robin Kanters
  • 5,018
  • 2
  • 20
  • 36
93

Since Android 11 (API level 30), most user-installed apps are not visible by default. In your manifest, you must statically declare which apps you are going to get info about, as in the following:

<manifest>
    <queries>
        <!-- Explicit apps you know in advance about: -->
        <package android:name="com.example.this.app"/>
        <package android:name="com.example.this.other.app"/>
    </queries>
    
    ...
</manifest>

Then, @RobinKanters' answer works:

private boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    try {
        packageManager.getPackageInfo(packageName, 0);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

// ...
// This will return true on Android 11 if the app is installed,
// since we declared it above in the manifest.
isPackageInstalled("com.example.this.app", pm); 
// This will return false on Android 11 even if the app is installed:
isPackageInstalled("another.random.app", pm); 

Learn more here:

now
  • 4,772
  • 2
  • 24
  • 26
  • 2
    Note: According to the dedicated documentation page, you can get the applicationInfo of the app itself by default. So there should be no need to include the app itself in its own manifest. – BenjyTec Feb 27 '21 at 10:16
  • @ArpitRastogi that comes with certain restriction . You can't use it for all kind of apps . Your app must comply with policy. `Apps granted access to this permission must comply with the User Data policies, including the Prominent Disclosure and Consent requirements, and may not extend its use to undisclosed or invalid purposes.` [more information](https://support.google.com/googleplay/android-developer/answer/10158779#zippy=%2Cexceptions%2Cpermitted-uses-of-the-query-all-packages-permission) – Bhavin Patel Jul 14 '21 at 06:51
  • @bhavin that is only for apps published on Google Play store. if you aren't on Google Play you don't need to comply with that. – Adam Burley Dec 17 '21 at 12:19
48

Robin Kanters' answer is right, but it does check for installed apps regardless of their enabled or disabled state.

We all know an app can be installed but disabled by the user, therefore unusable.

This checks for installed AND enabled apps:

public static boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    try {
        return packageManager.getApplicationInfo(packageName, 0).enabled;
    }
    catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

You can put this method in a class like Utils and call it everywhere using:

boolean isInstalled = Utils.isPackageInstalled("com.package.name", context.getPackageManager())
Tammen
  • 3,924
  • 2
  • 28
  • 27
Antonio Papalillo
  • 1,262
  • 13
  • 22
11

Faster solution:

private boolean isPackageInstalled(String packagename, PackageManager packageManager) {
    try {
        packageManager.getPackageGids(packagename);
        return true;
    } catch (NameNotFoundException e) {
        return false;
    }
}

getPackageGids is less expensive from getPackageInfo, so it work faster.

Run 10000 on API 15
Exists pkg:
getPackageInfo: nanoTime = 930000000
getPackageGids: nanoTime = 350000000
Not exists pkg:
getPackageInfo: nanoTime = 420000000
getPackageGids: nanoTime = 380000000

Run 10000 on API 17
Exists pkg:
getPackageInfo: nanoTime = 2942745517
getPackageGids: nanoTime = 2443716170
Not exists pkg:
getPackageInfo: nanoTime = 2467565849
getPackageGids: nanoTime = 2479833890

Run 10000 on API 22
Exists pkg:
getPackageInfo: nanoTime = 4596551615
getPackageGids: nanoTime = 1864970154
Not exists pkg:
getPackageInfo: nanoTime = 3830033616
getPackageGids: nanoTime = 3789230769

Run 10000 on API 25
Exists pkg:
getPackageInfo: nanoTime = 3436647394
getPackageGids: nanoTime = 2876970397
Not exists pkg:
getPackageInfo: nanoTime = 3252946114
getPackageGids: nanoTime = 3117544269

Note: This will not work in some virtual spaces. They can violate the Android API and always return an array, even if there is no application with that package name.
In this case, use getPackageInfo.

Enyby
  • 4,162
  • 2
  • 33
  • 42
5

Try this:

public static boolean isAvailable(Context ctx, Intent intent) {
    final PackageManager mgr = ctx.getPackageManager();
    List<ResolveInfo> list =
        mgr.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}
fdermishin
  • 3,519
  • 3
  • 24
  • 45
Gopi Cg
  • 384
  • 3
  • 7
4

You can use this in Kotlin extentions.kt

fun Context.isPackageInstalled(packageName: String): Boolean {
    return try {
        packageManager.getPackageInfo(packageName, 0)
        true
    } catch (e: PackageManager.NameNotFoundException) {
        false
    }
}

Usage

context.isPackageInstalled("com.somepackage.name")
Radesh
  • 13,084
  • 4
  • 51
  • 64
3

After Android 11 you need to add package names in <queries> in the Manifest of Application.

if you don't <queries> in the Manifest, always context.getPackageManager().getApplicationInfo has an exception (System.err: android.content.pm.PackageManager$NameNotFoundException)

check the reference:link

Example:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <queries>
        <package android:name="com.xxx.yyy" />
    </queries>

    <application></application>

</manifest>

Java

 public boolean applicationIsInstall(Context context , String packageName){
        try {
            context.getPackageManager().getApplicationInfo(packageName, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

Koltin

fun applicationIsInstall(context: Context, packageName: String): Boolean {
    return try {
        context.packageManager.getApplicationInfo(packageName, 0)
        true
    } catch (e: PackageManager.NameNotFoundException) {
        e.printStackTrace()
        false
    }
}
Rasoul Miri
  • 11,234
  • 1
  • 68
  • 78
1

If you want to try it without the try catch block, can use the following method, Create a intent and set the package of the app which you want to verify

val intent = Intent(Intent.ACTION_VIEW)
intent.data = uri
intent.setPackage("com.example.packageofapp")

and the call the following method to check if the app is installed

fun isInstalled(intent:Intent) :Boolean{
    val list = context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
    return list.isNotEmpty()
}
ked
  • 2,426
  • 21
  • 24
0

Those who are looking for Kotlin solution can use this method,

Here I have shared full code, and also handled enabled status. Check If Application is Installed in Android Kotlin

fun isAppInstalled(packageName: String, context: Context): Boolean {
        return try {
            val packageManager = context.packageManager
            packageManager.getPackageInfo(packageName, 0)
            true
        } catch (e: PackageManager.NameNotFoundException) {
            false
        }
    }
Asad Ali Choudhry
  • 4,985
  • 4
  • 31
  • 36
0

Though the answer is already posted and will work till Android 29 or Android 10but when an app targets Android 11 (API level 30) or higher and queries for information about the other apps that are installed on a device, the system filters this information by default. This filtering behavior means that your app can’t detect all the apps installed on a device, which helps minimize the potentially sensitive information that your app can access but doesn't need to fulfill its use cases.

So to achieve this we just need to add <queries> or need to add the below permission in AndroidManifest.xml file -

<uses-permission
    android:name="android.permission.QUERY_ALL_PACKAGES" />

It's because of there are few behavior changes in Android 11 - https://developer.android.com/training/package-visibility

Bajrang Hudda
  • 3,028
  • 1
  • 36
  • 63
-1
    private boolean isAppExist() {

    PackageManager pm = getPackageManager();
    try {
        PackageInfo info = pm.getPackageInfo("com.facebook.katana", PackageManager.GET_META_DATA);
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
    return true;
}




if (isFacebookExist()) {showToast(" Facebook is  install.");}
     else {showToast(" Facebook is not install.");}
DEVSHK
  • 833
  • 11
  • 10
-1
isFakeGPSInstalled = Utils.isPackageInstalled(Utils.PACKAGE_ID_FAKE_GPS, this.getPackageManager());

//method to check package installed true/false

  public static boolean isPackageInstalled(String packageName, PackageManager packageManager) {
    boolean found = true;
    try {
      packageManager.getPackageInfo(packageName, 0);
    } catch (PackageManager.NameNotFoundException e) {
      found = false;
    }

    return found;
  }
Fakhar
  • 3,946
  • 39
  • 35
-11
@Override 
protected void onResume() {
    super.onResume();
    boolean installed = false;

    while (!installed) {
        installed = appInstalledOrNot (APPPACKAGE);
        if (installed) {
            Toast.makeText(this, "App installed", Toast.LENGTH_SHORT).show ();
        }
    }
} 

private boolean appInstalledOrNot (String uri) {
    PackageManager pm = getPackageManager();
    boolean app_installed = false;
    try {
        pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
        app_installed = true;
    } catch (PackageManager.NameNotFoundException e) {
        app_installed = false;
    }
    return app_installed;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Pertho
  • 1