android获取已安装列表权限,Android如何完整的获取到⽤户已
安装应⽤列表
接到产品经理的预研需求,说希望获取⽤户已安装应⽤列表。这个问题应该不难,只要是要把相关的知识点整理和验证⼀下。
对于获取⽤户已安装应⽤列表,我个⼈是很熟悉的,因为我的华为⼿机上,⼿机管家天天会在通知栏弹出”xxx应⽤尝试获取⽤户已安装应⽤列表被禁⽌”。所以,很明显,跟权限是有关系的。于是,我尝试去查到底是manifest清单中的哪⼀个use-permission引起。结果,了很久,翻了很久,并没有哪个权限对已安装的应⽤列表负责。
但奇怪的是,我的⼿机上⼏乎全部的软件都声明了这个权限。于是,尝试去求助其他组员,咨询了⼏个,不少⼈⼀脸懵逼的表⽰这是个什么玩意。在他们的⼿机上压根就没有见过这个东西。
在写demo验证的过程中,发现⾮常简单的⼀个demo,居然也声明使⽤了该权限。 ⼀开始怀疑,难道是检测到了相关代码⾃动申请了权限?发现全部注释后还是会声明。 后来,将清单⽂件中的唯⼀的访问Internet权限去掉,这样才正常。安卓intent用法
所以,得出了⼀个结论就是,国内部分⼚商⽐如华为、oppo,他们将”获取⽤户已安装应⽤列表”的权限
暴露给了⽤户,让⽤户可以⾃由决定允许或者禁⽌应⽤访问该信息。同时,这个权限类似于附加的默认权限,⼀旦app声明了任何权限,那么”获取⽤户已安装应⽤列表”的权限也会被附加进来。但这个权限也不是太敏感,所以对于⽤户是⽆感知的。这⾥的⽆感知指的是不会在应⽤中去主动让我们弹窗申请权限,⼿机管家弹出的通知不算。
好吧,说了这么多,看⼀下过程中的3种⽅案。
⽅案1
private void getAppList() {
PackageManager pm = getPackageManager();
// Return a List of all packages that are installed on the device.
List packages = pm.getInstalledPackages(0);
for (PackageInfo packageInfo : packages) {
// 判断系统/⾮系统应⽤
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) // ⾮系统应⽤
{
System.out.println("AppList, packageInfo=" + packageInfo.packageName);
} else {
// 系统应⽤
}
}
}
此⽅法在华为、oppo⼿机上,把权限禁⽌后,就不能正确获取到已安装应⽤列表了。
⽅案2
考虑到⽅案1受权限的影响,于是考虑⽤adb命令去获取已安装的应⽤列表。
命令:adb shell pm list package -3
上⾯的命令可以获取到⼿机上已安装的第3⽅应⽤列表,去掉-3这个参数可以获取到全部的应⽤列表。本来对这个⽅案抱挺⼤的期望的,但是最终发现在oppo⼿机上,如果禁⽌了获取已安装应⽤列表的权限,那么结果就会受到影响,⽆奈⼜不⾏。
⼩插曲:在代码调⽤命令⾏过程中遇到个坑,
private void runCommand() {
try {
Process process = Runtime().exec("adb shell pm list package -3");
BufferedReader bis = new BufferedReader(new InputStream()));
String line = null;
while ((line = adLine()) != null) {
System.out.println("MainActivity.runCommand, line=" + line);
}
} catch (IOException e) {
System.out.println("MainActivity.runCommand,e=" + e);
}
}
⽤代码去执⾏了 adb shell pm list package -3的命令,发现⼀直报IOException,最终耗费⼀定的时间,定位到问题。我们使⽤adb shell是因为⼿机跟pc要连接,但是在⼿机上运⾏时,其实不⽤加adb shell,直接执⾏”pm list package -3”即可。
⽅案3
采⽤getPackageManager().queryIntentActivities(intent,PackageManager.MATCH_ALL)去查询是否有符合指定意图的Activity,从⽽判断是否安装了某应⽤。
该⽅法返回的是ResolveInfo列表,⽽ResolveInfo包含的是IntentFilter信息。
以下结论都经过demo的验证:
清单⽂件的声明中必须包含IntentFilter信息,queryIntentActivities⽅法才能查到。
IntentFilter中不能包含data信息,如果有定义,则查不到信息了,连启动的Activity都不到。这⾥暂时没有去查看The Fucking Source Code。
添加 android:exported与否对于此⽅法的结果没有影响
在华为等对应⽤安装列表有权限控制的⼿机上,采⽤隐式的Intent获取不到正确的信息,就连每个应⽤的启动Activity都获取不到。
显⽰的Intent则不受权限的影响,均可以获取到。
结论
采⽤第三种⽅案,⽤显⽰的Intent(⼀般指定包名或者类名)去查询是否安装了某应⽤在各个⼚商各个系统的⼿机上是可⾏的,但是只能获取到指定的,⽽不是全部。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论