检查是否安装了应用程序 - Android

Sid*_*kan 84 android android-intent google-play

我正在尝试从Google Play安装应用.我可以理解,在打开Goog​​le Play商店网址时,它会打开Goog​​le 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);
Run Code Online (Sandbox Code Playgroud)

当我回到活动时,我试着调用它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 ;
}
Run Code Online (Sandbox Code Playgroud)

错误如下:

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().有没有更好的方法来实现它?我正在尝试检查应用是否已完成安装.

Rob*_*ers 265

试试这个:

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

它试图获取有关其名称中通过.否则,如果一个包信息NameNotFoundException被抛出,就意味着没有包与这个名字安装,所以我们返回false.

请注意,我们传入的是a PackageManager而不是a Context,因此该方法可以更灵活地使用,并且不违反Demeter规律.Context只要您有实例,就可以使用该方法而无需访问PackageManager实例.

像这样使用它:

public void someMethod() {
    // ...

    PackageManager pm = context.getPackageManager();
    boolean isInstalled = isPackageInstalled("com.somepackage.name", pm);

    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 重点是将 `<queries>` 行添加到您的清单中! (4认同)
  • @SiddharthanAsokan您可以使用广播接收器进行package_added操作. (2认同)

now*_*now 44

自 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>
Run Code Online (Sandbox Code Playgroud)

然后,@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); 
Run Code Online (Sandbox Code Playgroud)

在此处了解更多信息:

  • 注:根据专用文档页面,默认可以获取应用本身的applicationInfo。因此,无需将应用程序本身包含在其自己的清单中。 (3认同)

And*_*Guy 24

Robin Kanters的回答是正确的,但它会检查已安装的应用程序,无论其启用或禁用状态如何.

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

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

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

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

boolean isInstalled = Utils.isPackageInstalled("com.package.name", context.getPackageManager())
Run Code Online (Sandbox Code Playgroud)


Gop*_* Cg 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;
}
Run Code Online (Sandbox Code Playgroud)


Eny*_*yby 5

更快的解决方案:

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

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
Run Code Online (Sandbox Code Playgroud)

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