简体   繁体   中英

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. 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. 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? 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. You can use List.contains() or List.containsAll() to accomplish the task in one line of code. 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

Bash shell expression that gets the PM list Java Runtime expression Java Pipes and buffers and streams Java NIO Java grep

So the bash expression would be :

pm list packages -f | sed 's/^package.//' | 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...

PipedBuffers

NIO/grep

Runtime/streams

Handling a NameNotFoundExcepetion should not make you feel "wrong all over" IMHO. 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.

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(). However, I don't know what steps android takes prior to returning a NameNotFoundExcepetion. 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.

  2. Calling PackageManger.getPackageInfo took between 1 and 1.5 seconds in all cases as well.

Calling getPackageInfo and catching the exception to determine if the package isn't installed is by far the faster way to check.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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