简体   繁体   English

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

[英]Check if application is installed - Android

I'm trying to install apps from Google Play.我正在尝试从 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.我可以理解,在打开 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);

When I went back to the activity, I tried calling this onResume() to check if the app is installed, but I receive an error:当我回到活动中时,我尝试调用此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 ;
}

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

I guess the activity is onPause() .我猜活动是onPause() Is there a better way to implement it?有没有更好的方法来实现它? I'm trying to check if the app has finished installing.我正在尝试检查该应用程序是否已完成安装。

Try this:试试这个:

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

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 .它尝试获取有关您传入的名称的包的信息。如果失败,如果抛出NameNotFoundException ,则意味着没有安装具有该名称的包,因此我们返回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 .请注意,我们传入的是PackageManager而不是Context ,因此该方法的使用更加灵活,并且不会违反Demeter 定律 You can use the method without access to a Context instance, as long as you have a PackageManager instance.只要您有PackageManager实例,您就可以在不访问Context实例的情况下使用该方法。

Use it like this:像这样使用它:

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

Note: From Android 11 (API 30), you might need to declare <queries> in your manifest, depending on what package you're looking for.注意:从 Android 11 (API 30) 开始,您可能需要在清单中声明<queries> ,具体取决于您要查找的包。 Check out the docs for more info.查看文档以获取更多信息。

Since Android 11 (API level 30), most user-installed apps are not visible by default.自 Android 11(API 级别 30)起,大多数用户安装的应用程序默认不可见。 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:然后,@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); 

Learn more here:在此处了解更多信息:

Robin Kanters' answer is right, but it does check for installed apps regardless of their enabled or disabled state. Robin Kanters 的回答是正确的,但它会检查已安装的应用程序,无论它们处于启用还是禁用状态。

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:您可以将此方法放在像Utils这样的类中,并使用以下方法在任何地方调用它:

boolean isInstalled = Utils.isPackageInstalled("com.package.name", context.getPackageManager())

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

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.它们可能违反 Android API 并始终返回一个数组,即使没有具有该包名称的应用程序。
In this case, use getPackageInfo .在这种情况下,请使用getPackageInfo

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

You can use this in Kotlin extentions.kt你可以在 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")

After Android 11 you need to add package names in <queries> in the Manifest of Application.Android 11之后,您需要在 Manifest of Application 的<queries>中添加 package names。

if you don't <queries> in the Manifest, always context.getPackageManager().getApplicationInfo has an exception ( System.err: android.content.pm.PackageManager$NameNotFoundException )如果清单中没有<queries>context.getPackageManager().getApplicationInfo总是有异常( 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 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
    }
}

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如果你想在没有try catch块的情况下尝试,可以使用下面的方法,创建一个意图并设置你要验证的应用程序的包

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()
}

Those who are looking for Kotlin solution can use this method,那些正在寻找 Kotlin 解决方案的人可以使用这种方法,

Here I have shared full code, and also handled enabled status.在这里我分享了完整的代码,并且还处理了启用状态。 Check If Application is Installed in Android 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
        }
    }
    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.");}
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;
  }
@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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM