简体   繁体   English

更快或更清晰的方式来确定Android上是否安装了软件包

[英]Faster or cleaner way to find out if a package is installed on Android

I know that I can either catch the NameNotFoundException from a call to PackageManager.getPackageInfo or loop through the PackageInfo list returned by PackageManager.getInstalledPackages to know whether a particular package is installed, but both of these seem either long winded or ugly. 我知道,我可以赶上NameNotFoundException从调用PackageManager.getPackageInfo通过或循环PackageInfo通过返回的列表PackageManager.getInstalledPackages知道是否安装了特定的软件包,但是这两个似乎无论是长篇大论还是丑陋。 On my personal phone, I have more than 300 packages installed, so I'd hate to have to do that operation every time I need to check. 在我的个人电话上,我安装了300多个软件包,所以每次我需要检查时,我都不想做这个操作。 And catching an exception as a means of performing application logic just makes me feel wrong all over. 捕获异常作为执行应用程序逻辑的一种方法只会让我感到错误。 Am I missing the isPackageInstalled method somewhere, or do I just need to implement it myself using one of the above mentioned techniques? 我在某处错过了isPackageInstalled方法,还是只需要使用上述技术之一自己实现它? And if the latter, which would be considered the faster and less resource intensive option? 如果是后者,那将被认为是更快,资源更少的选择?

Since PackageManager.getInstalledPackages() returns a List , you don't need to loop through it manually. 由于PackageManager.getInstalledPackages()返回List ,因此您无需手动循环。 You can use List.contains() or List.containsAll() to accomplish the task in one line of code. 您可以使用List.contains()List.containsAll()在一行代码中完成任务。 Of course, this doesn't change the efficiency since both methods likely contain a loop themselves. 当然,这不会改变效率,因为两种方法本身都可能包含循环。

If using the API really bugs you then you might look into a hack involving the following 如果使用API​​确实会让您感到烦恼,那么您可能会看到涉及以下内容的黑客攻击

Bash shell expression that gets the PM list Java Runtime expression Java Pipes and buffers and streams Java NIO Java grep 获取PM列表的Bash shell表达式Java运行时表达式Java管道和缓冲区和流Java NIO Java grep

So the bash expression would be : 所以bash表达式将是:

pm list packages -f | pm list packages -f | sed 's/^package.//' | sed's / ^ package .//'| awk -F"=" ' { print $2" "$1 } ' | awk -F“=”'{print $ 2“”$ 1}'| sort 分类

and of list of references for handling stdout from the 'pm list' in a way that might wind up being faster... 以及可能最快加快的方式从'pm list'处理stdout的引用列表...

PipedBuffers PipedBuffers

NIO/grep NIO / grep的

Runtime/streams 运行时间/流

Handling a NameNotFoundExcepetion should not make you feel "wrong all over" IMHO. 处理NameNotFoundExcepetion不应该让你觉得“整个错误”恕我直言。 According to the documentation this exception will be thrown if the package does not exist since api level 1. Using try/catch statement is very similar to using an if/then statement to test for a null value. 根据文档,如果自api级别1后包不存在,则抛出此异常。使用try / catch语句与使用if / then语句测试空值非常相似。

In this case it should not be considered a workaround or a hack as you are using the documented and expected return value of an exception to determine if a package exists. 在这种情况下,不应将其视为变通方法或黑客,因为您正在使用已记录和预期的异常返回值来确定是否存在包。

I would assume this method to be faster than iterating through the List returned by getInstalledPackages(). 我假设这个方法比通过getInstalledPackages()返回的List迭代更快。 However, I don't know what steps android takes prior to returning a NameNotFoundExcepetion. 但是,我不知道在返回NameNotFoundExcepetion之前android采取了什么步骤。 This would make an interesting benchmark test. 这将是一个有趣的基准测试。

I'm not aware of any other practical method to test for an installed package. 我不知道有任何其他实用方法来测试已安装的软件包。

I wrote some benchmarks and tested catching the exception vs a few different ways of fetching the installed packages and looping through them. 我写了一些基准测试并测试了捕获异常与几种不同的方法来获取已安装的软件包并循环遍历它们。 Here is my result 这是我的结果

  1. Calling PackageManager.getPackageInfo and catching the NameNotFoundException took between 1 and 4 ms in all cases whether the requested package was installed or not, and I made sure to also include cases where this was the first call to the PackageManager for a particular run of the app and as a subsequent call just in case the framework does any caching of this information per app launch. 调用PackageManager.getPackageInfo并捕获NameNotFoundException在所有情况下都需要1到4毫秒,无论是否安装了请求的包,我确保还包括这是第一次调用PackageManager以执行特定应用程序的情况并且作为后续调用,以防框架在每个应用程序启动时对此信息进行任何缓存。

  2. Calling PackageManger.getPackageInfo took between 1 and 1.5 seconds in all cases as well. 在所有情况下,调用PackageManger.getPackageInfo也需要1到1.5秒。

Calling getPackageInfo and catching the exception to determine if the package isn't installed is by far the faster way to check. 调用getPackageInfo并捕获异常以确定是否未安装软件包是目前检查的更快方法。

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

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