如何在Android中以编程方式检查应用程序是否已安装?

177

我们已经通过编程方式安装了应用程序。

  1. 如果设备中已经安装了该应用程序,则自动打开该应用程序。
  2. 否则,安装该特定的应用程序。

指导我。我一无所知。 谢谢。


2
可能是重复的问题:Android - 检查另一个应用程序是否存在 - noelicus
17个回答

345

试试这个:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Add respective layout
        setContentView(R.layout.main_activity);

        // Use package name which we want to check
        boolean isAppInstalled = appInstalledOrNot("com.check.application");  
        
        if(isAppInstalled) {
            //This intent will help you to launch if the package is already installed
            Intent LaunchIntent = getPackageManager()
                .getLaunchIntentForPackage("com.check.application");
            startActivity(LaunchIntent);
                    
            Log.i("SampleLog", "Application is already installed.");          
        } else {
            // Do whatever we want to do if application not installed
            // For example, Redirect to play store

            Log.i("SampleLog", "Application is not currently installed.");
        }
    }

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

        return false;
    }

}

1
@Sathish:我希望这对你有所帮助。 - Aerrow
2
毫无疑问,您的帖子确实很有帮助,但我遇到了一个异常“java.lang.RuntimeException: Adding window failed”和“E/AndroidRuntime(7554): Caused by: android.os.TransactionTooLargeException 05-14 11:37:25.305: E/AndroidRuntime(7554): at android.os.BinderProxy.transact(Native Method) 05-14 11:37:25.305: E/AndroidRuntime(7554): at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:516) 05-14 11:37:25.305: E/AndroidRuntime(7554): at android.view.ViewRootImpl.setView(ViewRootImpl.java:494)”。 - DJhon
2
@BlueGreen:你好,希望这个链接能对你有所帮助,https://dev59.com/lmgu5IYBdhLWcg3wRlBh,如果你正在使用Dialog类,请检查一下。 :) - Aerrow
1
假设我正在安装时检查我的.apk是否已安装...在检查我的包com.test.installedornot时,我遇到了相同的异常。我的.apk大小超过9MB,那么在这种情况下,我该如何处理此异常? - DJhon
1
在API 23上发生了崩溃 Fatal Exception: java.lang.RuntimeException 包管理器已停止运行 - Mathi Arasan
显示剩余12条评论

77
相对于被接受的答案而言,这是一个更为简洁的解决方案(基于此问题):
public static boolean isAppInstalled(Context context, String packageName) {
    try {
        context.getPackageManager().getApplicationInfo(packageName, 0);
        return true;
    }
    catch (PackageManager.NameNotFoundException e) {
        return false;
    }
}

我选择将它放在一个帮助类中作为一个静态实用程序。使用示例:

boolean whatsappFound = AndroidUtils.isAppInstalled(context, "com.whatsapp");

这篇回答 展示了如何从 Play 商店获取应用程序(如果应用程序丢失),但在没有 Play 商店的设备上需要小心。


2
这需要特定的Android权限才能工作吗? - Bootstrapper
@Bootstrapper:不需要任何特殊权限。 - Jonik
感谢(解决方案有效) - Naveed Ahmad

31

上面的代码对我没用,以下方法有效。

使用适当的信息创建一个Intent对象,然后使用以下函数检查Intent是否可调用:

private boolean isCallable(Intent intent) {  
        List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,   
        PackageManager.MATCH_DEFAULT_ONLY);  
        return list.size() > 0;  
}

5
这样做更好,因为它不需要使用异常来控制流程! - QED
2
@QED,使用异常作为“if”语句的人数令人震惊!这绝对是正确的答案。 - ILikeTacos
1
Intent的内容是什么?带有packageName的字符串无法工作。 - Henrique de Sousa
4
Intent intent = getPackageManager().getLaunchIntentForPackage("org.package.name");Intent intent = getPackageManager().getLaunchIntentForPackage("org.package.name"); - Dominic K
如果应用程序被禁用,那么它应该是错误的。 - Hugo

18

如果您知道包的名称,那么可以不使用try-catch块或迭代一堆包就能实现:

public static boolean isPackageInstalled(Context context, String packageName) {
    final PackageManager packageManager = context.getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(packageName);
    if (intent == null) {
        return false;
    }
    List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return !list.isEmpty();
}

1
return !list.isEmpty(); 更符合 Java 风格。 - headsvk

14

Android 11更新
您必须在清单文件中指定要搜索的确切捆绑标识。

以Facebook和WhatsApp为例:

在“应用程序”上面的清单文件中(即权限所在位置)

<queries>
    <package android:name="com.whatsapp" />
    <package android:name="com.facebook.katana" />
</queries>  

这将允许您检查Facebook和WhatsApp是否已安装,否则该检查始终会返回false。
有关此主题的进一步阅读:
https://medium.com/androiddevelopers/package-visibility-in-android-11-cc857f221cd9

这节省了我的时间。 - Abhilasha

7

这段代码检查应用程序是否已安装,同时还检查是否已启用。

private boolean isAppInstalled(String packageName) {
    PackageManager pm = getPackageManager();
    try {
        pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
        return pm.getApplicationInfo(packageName, 0).enabled;
    }
    catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}

这是应用程序的包名。例如,“com.example.apps.myapp”。我已经编辑了我的答案,以显示packageName而不是uri。 - caly__pso

6

使用 Kotlin 检查 Android 应用是否已安装。

创建 Kotlin 扩展。

fun PackageManager.isAppInstalled(packageName: String): Boolean = try {
        getApplicationInfo(packageName, PackageManager.GET_META_DATA)
        true
    } catch (e: Exception) {
        false
    }

现在,可以检查应用程序是否已安装

if (packageManager.isAppInstalled("AppPackageName")) {
    // App is installed
}else{
    // App is not installed
}

4

下面的解决方案(不需要try-catch)比被接受的答案更干净,基于AndroidRate库

public static boolean isPackageExists(@NonNull final Context context, @NonNull final String targetPackage) {
    List<ApplicationInfo> packages = context.getPackageManager().getInstalledApplications(0);
    for (ApplicationInfo packageInfo : packages) {
        if (targetPackage.equals(packageInfo.packageName)) {
            return true;
        }
    }
    return false;
}

4

使用 Kotlin 实现一个更简单的方法

fun PackageManager.isAppInstalled(packageName: String): Boolean =
        getInstalledApplications(PackageManager.GET_META_DATA)
                .firstOrNull { it.packageName == packageName } != null

可以这样调用(查找 Spotify 应用):

packageManager.isAppInstalled("com.spotify.music")

从Android 11开始,此方法不再返回有关所有应用程序的信息;有关详细信息,请参见https://g.co/dev/packagevisibility。 - Mori

3

我认为使用try/catch模式的性能并不是很好。我建议使用以下方法:

public static boolean appInstalledOrNot(Context context, String uri) {
    PackageManager pm = context.getPackageManager();
    List<PackageInfo> packageInfoList = pm.getInstalledPackages(PackageManager.GET_ACTIVITIES);
    if (packageInfoList != null) {
        for (PackageInfo packageInfo : packageInfoList) {
            String packageName = packageInfo.packageName;
            if (packageName != null && packageName.equals(uri)) {
                return true;
            }
        }
    }
    return false;
}

以上是Kotlin中的代码: private fun isAppInstalled(context: Context, uri: String): Boolean { val packageInfoList = context.packageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES) return packageInfoList.asSequence().filter { it?.packageName == uri }.any() } - Kishan B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接