【问题标题】:Can't open camera intent. queryIntentActivities returns an empty list on api level 30 but finds results in level 29. What changed?无法打开相机意图。 queryIntentActivities 在 api 级别 30 返回一个空列表,但在级别 29 中找到结果。发生了什么变化?
【发布时间】:2021-01-23 06:45:24
【问题描述】:

我正在使用 queryIntentActivities 查询活动,它在 api 级别 29 中运行良好,但一旦我升级到级别 30,结果总是为空。

这是意图:

val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra("android.intent.extras.CAMERA_FACING", typeCamera)
uri?.grantWriteForIntent(activity, intent)
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
if (intent.isIntentSafe(activity)) {
    activity.__waitResult__ = true
    activity.startActivityForResult(intent, requestCode)
}

然后是isIntentSafe函数:

fun Intent?.isIntentSafe(context: Context) =
    if (this == null)
        false
    else
        context.packageManager.queryIntentActivities(this, PackageManager.MATCH_DEFAULT_ONLY).size > 0

这就是queryIntentActivites 在第 30 级为空而在第 29 级有内容的地方。有谁知道这些级别之间发生了什么变化会产生这种效果?

我应该补充一点,如果我在两个 api 级别中跳过isIntentSafe 检查,那么无论如何活动都可以正常启动。但我想知道为什么 isIntentSafe 在较新的 api 中停止工作。

编辑:我已经尝试改变前置摄像头的意图,就像在这个答案 How to launch front camera with intent? 中一样,这并没有什么不同。

【问题讨论】:

    标签: android


    【解决方案1】:

    我再次经历了Android 11的变化,发现"Media intent actions require default system camera"

    所以我搜索了一下,找到了solution from CommonsGuy。稍微修改一下代码,打开前置摄像头,马上就生效了!

    fun enhanceCameraIntent(context: Context, baseIntent: Intent, title: String): Intent {
        val pm = context.packageManager
    
        val cameraIntents =
            CAMERA_CANDIDATES.map { Intent(baseIntent).setPackage(it) }
                .filter { pm.queryIntentActivities(it, 0).isNotEmpty() }
                .toTypedArray()
    
        return if (cameraIntents.isEmpty()) {
            baseIntent
        } else {
            Intent
                .createChooser(baseIntent, title)
                .putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents)
        }
    }
    
    fun openFrontFacingCamera(activity: BaseActivity, uri: Uri?, requestCode: Int) {
        try {
            val baseIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    
            uri?.grantWriteForIntent(activity, baseIntent)
            baseIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
            baseIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            baseIntent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true)
    
            activity.startActivityForResult(
                enhanceCameraIntent(activity, baseIntent, MediaStore.ACTION_IMAGE_CAPTURE),
                requestCode
            )
        } catch (ex: ActivityNotFoundException) {
            Log.d("No default camera", "Activity not found!")
        }
    }
    

    和以前一样,向 CommonsGuy 致敬!

    【讨论】:

      【解决方案2】:

      在 Android 11 中,有新的rules 用于与设备上安装的应用进行交互。

      因此,如果您的应用面向 Android 11 或更高版本,您可能需要在应用的清单文件中添加 <queries> 元素:

      <queries>
        <intent>
          <action android:name="android.media.action.IMAGE_CAPTURE" />
        </intent>
      </queries>
      

      您还可以在此guide 中找到更多详细信息。

      【讨论】:

      • Android Studio 会抱怨我直接在清单中添加了一个 标签,并在上面加上芥末背景,并说“这里不允许使用这个标签”。
      猜你喜欢
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      • 2022-08-10
      • 2021-08-21
      • 2020-11-09
      • 2022-06-21
      • 1970-01-01
      相关资源
      最近更新 更多