135

我正在尝试从 Google Play 安装应用程序。我可以理解,在打开 Google Play 商店 URL 时,它会打开 Google Play,当我按下后退按钮时,活动会继续。

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);

当我回到活动时,我尝试调用它onResume()来检查应用程序是否已安装,但我收到一个错误:

@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 ;
}

错误如下:

E/AndroidRuntime(796): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.example.appinstaller/com.example.appinstaller.MainActivity}: android.content.ActivityNotFoundException: 找不到活动来处理 Intent { act=android .intent.action.VIEW dat=market://details?id=com.package.name flg=0x40080000 }

我猜活动是onPause()。有没有更好的方法来实现它?我正在尝试检查应用程序是否已完成安装。

4

11 回答 11

362

尝试这个:

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

它尝试获取有关您传入的名称的包的信息。如果失败,如果NameNotFoundException抛出 a ,则意味着没有安装具有该名称的包,因此我们返回false

请注意,我们传入的是 aPackageManager而不是 a Context,因此该方法的使用更加灵活,并且不违反得墨忒耳定律Context只要您有实例,就可以在不访问实例的情况下使用该方法PackageManager

像这样使用它:

public void someMethod() {
    // ...
    
    PackageManager pm = context.getPackageManager();
    boolean isInstalled = isPackageInstalled("com.somepackage.name", pm);
    
    // ...
}

注意:从 Android 11 (API 30) 开始,您可能需要<queries>在清单中声明,具体取决于您要查找的包。查看文档以获取更多信息。

于 2013-09-11T22:20:16.307 回答
73

从 Android 11(API 级别 30)开始,大多数用户安装的应用程序默认不可见。在您的清单中,您必须静态声明您将获取有关哪些应用程序的信息,如下所示:

<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>

然后,@RobinKanters 的回答有效:

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); 

在此处了解更多信息:

于 2020-10-18T23:26:35.670 回答
43

Robin Kanters 的回答是正确的,但它确实会检查已安装的应用程序,无论它们处于启用还是禁用状态。

我们都知道一个应用程序可以安装但被用户禁用,因此无法使用。

这将检查已安装启用的应用程序:

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

您可以将此方法放在一个类中,Utils并使用以下方法在任何地方调用它:

boolean isInstalled = Utils.isPackageInstalled("com.package.name", context.getPackageManager())
于 2017-03-07T11:41:14.703 回答
10

更快的解决方案:

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

getPackageGids从 开始更便宜getPackageInfo,所以它工作得更快。

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

注意:这在某些虚拟空间中不起作用。它们可能违反 Android API 并始终返回一个数组,即使没有具有该包名称的应用程序也是如此。
在这种情况下,使用getPackageInfo.

于 2017-09-04T22:17:11.690 回答
5

尝试这个:

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;
}
于 2014-12-31T06:16:26.423 回答
4

你可以在 Kotlin 中使用它extentions.kt

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

用法

context.isPackageInstalled("com.somepackage.name")
于 2020-10-27T07:39:56.403 回答
0

如果您想在没有 try catch 块的情况下尝试它,可以使用以下方法,创建一个意图并设置您要验证的应用程序的包

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

并调用以下方法检查应用程序是否已安装

fun isInstalled(intent:Intent) :Boolean{
    val list = context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
    return list.isNotEmpty()
}
于 2019-12-10T12:42:02.970 回答
0

那些正在寻找 Kotlin 解决方案的人可以使用这种方法,

在这里,我分享了完整的代码,还处理了启用状态。检查应用程序是否安装在 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
        }
    }
于 2020-07-15T11:06:16.250 回答
-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.");}
于 2019-03-17T06:42:57.200 回答
-1
isFakeGPSInstalled = Utils.isPackageInstalled(Utils.PACKAGE_ID_FAKE_GPS, this.getPackageManager());

//检查安装包的方法 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;
  }
于 2019-10-07T09:11:50.987 回答
-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;
}
于 2015-06-24T02:45:09.157 回答