Search code examples
androidandroid-cursorandroid-contentresolver

How to obtain Cursor via ContentResolver on ANY device?


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

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;
}

However, on Galaxy S5, when we save an image to its own directory in the internal public memory (not private data/data), we get cursor==null. On other devices, we DON't get null cursor.

The flow of the app is like this:

  1. Take image with Camera

  2. Save it into file in its own directory (public directory in internal memory)

  3. Access file via ContentResolver and return Cursor

Steps 1 and 2 are properly done. Verified! I can see the image I take via Camera inside the specified directory.

I also checked if the Bitmap is accessible via

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

and I never get an exception.

However, in spite of all this, Cursor remains null on some devices. Anyone can guess why and what is the ultimate way never to get null cursor?

PS. is there any 3rd party library that handles this part properly?

PPS. We are using Retrofit to get up to 10 images saved via Camera and upload to the remote server. Using and working with Bitmap is not possible in this case as we get OOM on the 5th or 6th image. So Retrofit logic must use ContentResolver to get hold of the image(s) that need(s) to be uploaded.


Solution

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

    I strongly recommend that you delete all that code and use a Uri properly.

    The flow of the app is like this:

    Your step #3 is pointless. You know where the file is, because you put it there in step #2. And, by getting rid of step #3, you can also get rid of all of the bogus "real path" code.

    Anyone can guess why

    Perhaps MediaStore does not know about the image, because it has not been indexed yet. See MediaScannerConnection and its scanFile() method.

    Also note that you are not actually setting cursor to a value in getRealPathFromURI_API19(). I would expect that code to not compile, so I am assuming that it is a copy/paste problem in your question.

    what is the ultimate way never to get null cursor?

    Stop querying for it in the first place.