在 android 11 中使用 intent.resolveActivity 时调用此方法时,请考虑在清单中添加查询声明

Posted

技术标签:

【中文标题】在 android 11 中使用 intent.resolveActivity 时调用此方法时,请考虑在清单中添加查询声明【英文标题】:Consider adding a queries declaration to your manifest when calling this method when using intent.resolveActivity in android 11 【发布时间】:2021-03-04 19:47:54 【问题描述】:

我有一个扩展功能,用于为我的活动打开意图:

fun Activity.openIntent(action: String?, type: String?, uri: Uri?) 
    Intent()
        .apply 
            action?.let  this.action = it 
            uri?.let  this.data = it 
            type?.let  this.type = it 
        
        .also  intent ->
            packageManager?.let 
                if (intent.resolveActivity(it) != null)
                    startActivity(intent)
                else
                    showToast(R.string.application_not_found)
            
        

我的targetSdkVersion30。它在intent.resolveActivity(it) 中给了我一个警告:

考虑在调用此方法时向您的清单添加查询声明。

那么我应该怎么做才能解决这个警告呢?

【问题讨论】:

【参考方案1】:

最简单的解决方案是去掉resolveActivity()。替换:

            packageManager?.let 
                if (intent.resolveActivity(it) != null)
                    startActivity(intent)
                else
                    showToast(R.string.application_not_found)
            

与:

            try 
                startActivity(intent)
             catch (ex: ActivityNotFoundException) 
                showToast(R.string.application_not_found)
            

这会为您提供相同的结果,但性能会更好一些,并且会消除警告。

另一种选择是添加QUERY_ALL_PACKAGES 权限。这可能会让你被 Play 商店禁止。

否则,您需要:

为您的应用可能进行的每个可能的openIntent() 调用建立一个列表

Add a <queries> element to your manifest 列出了您希望能够与resolveActivity() 一起使用的所有可能的Intent 结构

定期重复此过程,以防您为 openIntent() 添加新场景

【讨论】:

The application could not be installed: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED。如果我将查询元素添加到清单中,我会收到此错误。 gist.github.com/sudhirkhanger/fbb613b38f25c44ad0342a237a2d06e6 @SudhirSinghKhanger:none 不是有效的 MIME 类型,因此该元素没有帮助。尝试删除它。【参考方案2】:

因此,从 android 11 开始(即,如果您的应用以 Android 11 为目标平台)并非所有应用都对您的应用可见。有些应用程序是visible by default,但为了通过您的应用程序访问其他应用程序,您必须在清单中声明queries,否则您的应用程序将无法访问它们。你可以阅读here。

因此,如果您的应用程序以 Android 11 为目标并且要访问默认情况下可能不可见的应用程序,您需要在清单文件中为它们添加 queries

在您的情况下,此警告不适用,因为我相信您正在使用隐式意图打开其他应用程序。使用隐式意图,无论应用程序可见性如何,都可以访问其他应用程序。如果您的应用面向 Android 10 或更低版本,您可以隐藏警告,因为默认情况下所有应用都可见。

要抑制 lint 警告,您可以:

    添加抑制注释,如下所示:
@SuppressLint("QueryPermissionsNeeded")
fun Activity.openIntent(action: String?, type: String?, uri: Uri?): Activity 
    将以下内容添加到应用模块构建 gradle 文件中的 android 块中:
lintOptions 
    ignore "QueryPermissionsNeeded"

【讨论】:

似乎只有 lintOptions 块可以完成这项工作。谢谢! 两者都能胜任。您可以使用两者中的任何一个。 “此警告不适用,因为我认为您正在使用隐式意图打开其他应用程序”- 警告来自 resolveActivity() 调用,它需要 <queries> 元素才能工作。 是的,这就是我写的。尽管只有在官方 android 文档中指定的针对 API 30 的显式意图和应用程序才会出现这种情况。我在我的回答中提供了相同的恰当参考 假设您制作了一个针对 Android 11 的应用程序,并且您想明确打开 WhatsApp 应用程序,但您没有在 Manifest 中为其添加 query。如果我们将startActivity 调用包装在try-catch 块中,那么即使设备安装了WhatsApp 应用程序,控件也将始终落在Android 11 设备上的catch 块上。【参考方案3】:

替换

if (intent.resolveActivity(it) != null)

if (it.resolveActivity(intent, 0) != null)

警告就会消失。

【讨论】:

it是什么对象? itPackageManager

以上是关于在 android 11 中使用 intent.resolveActivity 时调用此方法时,请考虑在清单中添加查询声明的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Android 11 在 Bash 中解决此错误

Android 相机意图在 Android 11 中没有响应

Android入门第11天-Android中RadioButton的使用

在 android 11 中使用 intent.resolveActivity 时调用此方法时,请考虑在清单中添加查询声明

在 android 11 中接收专辑封面

在 Kivy 的 API 30 (Android 11) 中读取和写入文件