Android 11 (R) 在查询 ACTION_IMAGE_CAPTURE 的意图时返回空列表

Posted

技术标签:

【中文标题】Android 11 (R) 在查询 ACTION_IMAGE_CAPTURE 的意图时返回空列表【英文标题】:Android 11 (R) return empty list when querying intent for ACTION_IMAGE_CAPTURE 【发布时间】:2020-11-24 12:34:22 【问题描述】:

设备:模拟器像素 3a - android 11

代码:

    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    final List<ResolveInfo> listCam = 
    context.getPackageManager().queryIntentActivities(captureIntent, 0);

使用时:

targetSdkVersion 30
compileSdkVersion 30

listCam 大小为 0

当更改为:

compileSdkVersion 29

listCam 大小为 1 - 应该是。

使用以下代码:

    val captureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    baseActivity.startActivity(captureIntent)

工作正常并显示相机应用程序。

知道为什么 queryIntentActivities 没有返回相机意图吗?

谢谢!

【问题讨论】:

developer.android.com/preview/privacy/package-visibility 【参考方案1】:

Android 11 改变了应用查询和与其他应用交互的方式。

来自docs:

返回有关其他应用程序的结果的 PackageManager 方法, 如queryIntentActivities(),根据调用过滤 应用的&lt;queries&gt; 声明。

所以你需要在你的AndroidManifest.xml 中声明&lt;queries&gt;

<manifest package="com.example">
    <queries>
        <intent>
            <action android:name="android.media.action.IMAGE_CAPTURE" />
        </intent>
    </queries>
    ...
</manifest>

【讨论】:

是的,但是:从 Android 11 开始,只有预装的系统相机应用可以响应以下意图操作:android.media.action.VIDEO_CAPTURE android.media.action.IMAGE_CAPTURE android.media。 action.IMAGE_CAPTURE_SECURE 所以即使我们声明了 标签 - queryIntentActivities 函数也总是只返回一个系统相机应用程序 ADB 有解决方法吗?即使通过 ADB,这些意图也已停止在 Android 11 上运行。 这也正是我的解决方案!我不得不将这些查询元素放在清单中。我只想提一下,为了让它工作,我必须升级 gradle。我有一个非常旧的代码库和一个非常旧的 gradle 版本。我的工作是从 API 级别 22 升级到 30,这是我必须解决的一个问题。关于元素的 gradle 支持 看看this 什么是包名“com.example”,这是您应用的包名还是您定位的应用? @Madhan 这是你应用的包名【参考方案2】:

我的 Android 11 解决方案,用于获取 ResolveInfo 列表。

当我们仅通过 MediaStore.ACTION_IMAGE_CAPTURE 过滤器进行扫描时,我们只会得到一个!应用记录 - 系统默认相机应用。 为了使用其他相机应用,我们需要通过包名称指定每个应用,并通过 setPackage() 调用为其提供 - 然后 queryIntentActivities 可以正常工作,即使在 Android R 中也是如此

完整的解决方案如下:

/**
 * Return all camera possible apps
 * @param context
 * @return
 */
public static List<ResolveInfo> getCameraAppsResolveInfo(Context context)
    List<ResolveInfo> resolveInfo = new ArrayList<>();
    if (Utils.isNull(context))
        return resolveInfo;
    
    final Intent capturePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    PackageManager pm = context.getPackageManager();
    resolveInfo = pm.queryIntentActivities(capturePhoto, 0);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
        // For Android 11 we need to add specific camera apps
        // due them are not added during ACTION_IMAGE_CAPTURE scanning...
        resolveInfo.addAll(getCameraSpecificAppsInfo(context));
    
    return resolveInfo;


/**
 * For Android 11
 * Return camera possible apps
 */
static final String[] CAMERA_SPECIFIC_APPS =  new String[]
        "best.camera",
        "net.sourceforge.opencamera",
        "com.google.android.GoogleCamera",
        "tools.photo.hd.camera",
;
private static List<ResolveInfo> getCameraSpecificAppsInfo(Context context)
    List<ResolveInfo> resolveInfo = new ArrayList<>();
    if (Utils.isNull(context))
        return resolveInfo;
    
    PackageManager pm = context.getPackageManager();
    for (String packageName : CAMERA_SPECIFIC_APPS) 
        resolveInfo.addAll(getCameraSpecificAppInfo(packageName, pm));
    
    return resolveInfo;

private static List<ResolveInfo> getCameraSpecificAppInfo(String packageName, PackageManager pm)
    Intent specificCameraApp = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    specificCameraApp.setPackage(packageName);
    return pm.queryIntentActivities(specificCameraApp, 0);

当然,我们应该在清单文件中添加这些行(如接受的答案中所述)

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

【讨论】:

你能给亚行提供一个解决方法吗?这 - adb -d shell am start -a android.media.action.IMAGE_CAPTURE 在 android 11 上没有任何作用【参考方案3】: 如果您的应用在 targetSdkVersion 30 上运行,

packageManager.queryIntentActivities(intent, 0) 将返回一个 EMPTY 列表

要解决此问题,您必须在清单中使用 &lt;queries&gt;,因为 queryIntentActivities() 会根据调用应用的声明进行过滤。

修复图像捕获 + 图像上传以使用 Android“范围存储”

该问题可能与新包的可见性有关 (https://developer.android.com/about/versions/11/privacy/package-visibility)。 在所有更新(至少是 Android Studio 4.1)之后,尝试在您的清单中添加显示您的应用需要执行哪些操作。

在我的情况下,当我添加时问题消失了 IMAGE_CAPTURE 用于 CAMERA,GET_CONTENT 用于 GALLERY(获取文件,如果需要视频,请更改 mimeType),PICK 用于 GALLERY(如果需要,应更改 mimetype视频) CHOOSER 用于 GALLERY(如果有人有其他图像浏览器)

您还可以在 logcat 中检查您必须添加哪些查询(应该包含“BLOCKED”或“no permission”。 错误是因为ImagePickerModule 当您没有使用resolveActivity 的Intent 权限时返回null(您可以评论它以检查startActivityForResult 中更好的错误)

AndroidManifest.xml中添加&lt;query&gt;

<manifest>
.....
.....
<queries>
    <!-- Browser -->
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="http" />
    </intent>
    <!-- Camera -->
    <intent>
        <action android:name="android.media.action.IMAGE_CAPTURE" />
    </intent>
    <!-- Gallery -->
    <intent>
        <action android:name="android.intent.action.GET_CONTENT" />
        <data android:mimeType="image/*" />
    </intent>
    <intent>
        <action android:name="android.intent.action.PICK" />
        <data android:mimeType="image/*" />
    </intent>
    <intent>
        <action android:name="android.intent.action.CHOOSER" />
     </intent>
</queries>
.....
.....
</manifest>

【讨论】:

完美,感谢分享!【参考方案4】:

@saurabh-thorat 关于查询是正确的。但我发现,即使你想要全部,你仍然需要添加一个数据标签以使其适用于所有 mime 类型(或者至少在我的 react-native 应用程序中是这样)。所以对于 mime 类型的操作应该如下所示(例如:查看/发送/打开):

<manifest package="com.example">
    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data android:mimeType="*/*" />
        </intent>
    </queries>
    ...
</manifest>

【讨论】:

以上是关于Android 11 (R) 在查询 ACTION_IMAGE_CAPTURE 的意图时返回空列表的主要内容,如果未能解决你的问题,请参考以下文章

我的Android进阶之旅使用PackageManager.queryIntentServices方法来查询指定action的Service是否存在

我的Android进阶之旅使用PackageManager.queryIntentServices方法来查询指定action的Service是否存在

没有找到处理 Intent 的活动:android.intent.action.EDIT

(Android UI)Action Bar

Android: Action Bar的使用

R in action -- 2.1 数据结构