如何在任何设备上通过 ContentResolver 获取 Cursor?

How to obtain Cursor via ContentResolver on ANY device?

到目前为止,我们已经通过对 SDK <11、11-18、>=19 使用单独的逻辑解决了通过 ContentResolver 检索时的 Cursor == null。像

public static Cursor getRealPathFromURI_API19(Context context, Uri uri) {
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
    return cursor;
}

public static Cursor getRealPathFromURI_API11to18(Context context, Uri contentUri) {
    String[] proj = {MediaStore.Images.Media.DATA};
    String result = null;

    CursorLoader cursorLoader = new CursorLoader(context, contentUri, proj, null, null, null);
    Cursor cursor = cursorLoader.loadInBackground();
    return cursor;
}

public static Cursor getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
    String[] proj = {MediaStore.Images.Media.DATA};
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    return cursor;
}

然而,在 Galaxy S5 上,当我们将图像保存到内部 public 内存(非私有 data/data)中它自己的目录时,我们得到 cursor==null。在其他设备上,我们不会得到空游标。

app的流程是这样的:

  1. 用相机拍照

  2. 保存到自己目录下的文件中(内存中的public目录)

  3. 通过ContentResolver和return访问文件Cursor

第 1 步和第 2 步已正确完成。已验证!我可以在指定目录中看到我通过相机拍摄的图像。

我还检查了 Bitmap 是否可以通过

访问
    InputStream input;
    Bitmap bmp;
    try {
        input = getContentResolver().openInputStream(uri);
        bmp = BitmapFactory.decodeStream(input);
    } catch (FileNotFoundException e1) {
        Log.e("tafg", "error");
    }

而且我从来没有例外。

然而,尽管如此,Cursor 在某些设备上仍然为空。任何人都可以猜出为什么以及永远不会获得空游标的最终方法是什么?

PS。是否有任何第三方库可以正确处理这部分?

PPS。我们正在使用 Retrofit 获取最多 10 张通过相机保存的图像并上传到远程服务器。在这种情况下,使用和处理 Bitmap 是不可能的,因为我们在第 5 或第 6 个图像上出现 OOM。所以 Retrofit 逻辑必须使用 ContentResolver 来获取需要上传的图像。

So far, we have solved Cursor == null when retrieved via ContentResolver by using separate logic for SDKs <11, 11-18, >=19.

我强烈建议您删除所有代码和 use a Uri properly

The flow of the app is like this:

您的第 3 步毫无意义。您知道文件在哪里,因为您在步骤 #2 中将它放在那里。而且,通过去掉第 3 步,您还可以去掉所有伪造的 "real path" 代码。

Anyone can guess why

可能 MediaStore 不知道图像,因为它还没有被索引。请参阅 MediaScannerConnection 及其 scanFile() 方法。

另请注意,您实际上并未将 cursor 设置为 getRealPathFromURI_API19() 中的值。我希望该代码无法编译,所以我假设这是您问题中的 copy/paste 问题。

what is the ultimate way never to get null cursor?

首先停止查询。