【发布时间】:2012-12-09 08:50:34
【问题描述】:
我有一个可以执行此操作的 Android 应用:
PackageManager pm = getApplicationContext().getPackageManager();
Intent browserIntent = new Intent();
browserIntent.setAction(Intent.ACTION_VIEW);
browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
browserIntent.setData(Uri.parse("http://www.google.com"));
ResolveInfo resolveInfo = pm.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
try {
String browserType = nutent.activityInfo.packageName;
} catch (NullPointerException npe) {
npe.printStackTrace();
}
我已经在 4 种不同的手机和许多不同的模拟器配置上对此进行了测试。他们都工作正常。但是由于resolveInfo有时为空,我从野外部署的应用程序中收到了抛出NPE的崩溃报告。
直接的解决方法是在我的应用程序崩溃之前捕获 NPE 并处理它(如上所述)。但我已经尝试了好几天自己重现这个并且不能。在安装了单个默认浏览器的模拟器上,它解析为 com.android.browser.BrowserActivity:
ResolveInfo{411ef228 com.android.browser.BrowserActivity p=0 o=0 m=0x208000}
同样,在安装了多个浏览器的手机上,它的解析方式略有不同...到 com.android.internal.app.ResolverActivity:
ResolveInfo{415c13b8 com.android.internal.app.ResolverActivity p=0 o=0 m=0x0}
resolveActivity() 文档here 状态:
返回一个 ResolveInfo,其中包含被确定为最佳操作的最终活动意图。如果未找到匹配的活动,则返回 null。如果找到多个匹配的活动并且没有默认设置,则返回包含其他内容的 ResolveInfo,例如活动解析器。
所以我已经介绍了第一个场景,即被确定为最佳操作的活动意图。也是最后一个场景,多个匹配的活动没有默认操作,返回 ResolverActivity。
我真的很想重现 resolveActivity() 在请求 URL 的活动时给我一个 null 的场景。有没有人知道如何在不生根设备的情况下做到这一点?
【问题讨论】:
-
顺便说一句,像你那样“吃”异常是不好的做法。抛出异常是有充分理由的,当您访问外部资源时,它可能会失败的原因有多种,您的代码应该处理它们。
-
这实际上只是一个“虚拟”意图,仅用于获取浏览器类型和版本(如果可用),它从不用于检索任何网页或执行任何其他操作。我相信,在这种情况下,吃掉异常并将我的浏览器类型和版本字符串设置为“未知”就足够了。对于这个例外,我没有其他想做的事情。
-
好问题。我也不确定,但我的猜测是,即使您认为有,您可能还没有涵盖最后一个场景“没有默认操作的多个匹配活动”,因为您指定了 MATCH_DEFAULT_ONLY。我还没有破解PackageManager的源码(下一步好),但是我想知道如果你告诉它匹配默认值它会做什么,并且没有默认值,返回null?您是否在具有多个浏览器且未设置默认值的设备或模拟器上进行了测试? (如果您单击链接等,请确保出现选择器。)
-
好主意,今晚我会研究这些,看看效果如何。
-
也许这些崩溃报告来自没有浏览器的手机?当您启动手机时,您甚至可以删除系统应用程序,因此您甚至可以删除内置的 android 浏览器。这也可能是因为自定义固件。你知道,有数百款中国手机在安卓上运行,预装了定制固件。通常,此手机上的某些 android 应用程序会被自定义替换。因此,也许有些自定义浏览器无法满足您的意图。
标签: java android android-intent android-browser resolver