Choosing photo using new Google Photos app is broken

AndroidAndroid IntentAndroid GalleryGoogle Photos

Android Problem Overview


My app has ability to select photo from library. Exactly I want file path from this selection.

This is the code to create intent for selecting photo:

    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK,
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    photoPickerIntent.setType("image/*");
    startActivityForResult(photoPickerIntent, INTENT_REQUEST_CODE_SELECT_PHOTO);

This is the code that gets file path from URI:

    Cursor cursor = null;
    String path = null;
    try {
        String[] projection = { MediaStore.Images.Media.DATA };
        cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
        int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
        cursor.moveToFirst();
        path = cursor.getString(columnIndex);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
    return path;

Before yesterday's update of Google Photos app everything worked perfectly fine. Now path is null after parsing URI.

URI is similar to this: content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F75209/ACTUAL

I also tried to create intent with Intent.ACTION_GET_CONTENT action - no luck.

Android Solutions


Solution 1 - Android

Below code is working for me to get content URI on latest Google Photos as well. What i have tried is writing to temp file and return temp image URI, if it has authority in content URI.

You can try same:

private static String getImageUrlWithAuthority(Context context, Uri uri)
{
    InputStream is = null;

    if (uri.getAuthority() != null)
    {
        try
        {
            is = context.getContentResolver().openInputStream(uri);
            Bitmap bmp = BitmapFactory.decodeStream(is);
            return writeToTempImageAndGetPathUri(context, bmp).toString();
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (is != null)
                {
                    is.close();
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    return null;
}

private static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage)
{
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}

Solution 2 - Android

This is most certainly a workaround, but you could extract the real content URI which has apparently become embedded for some reason: content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F75209

I was able to create a new URI with authority=media and path=external/images/media/xxx, and content resolver returned a real URL.

Example code:

String unusablePath = contentUri.getPath();
int startIndex = unusablePath.indexOf("external/");
int endIndex = unusablePath.indexOf("/ACTUAL");
String embeddedPath = unusablePath.substring(startIndex, endIndex);

Uri.Builder builder = contentUri.buildUpon();
builder.path(embeddedPath);
builder.authority("media");
Uri newUri = builder.build();

Solution 3 - Android

I know this question is bit old, still I did the following to get the image from gallery and use it. Below is the extension function for the same.

fun Uri.toBitmap(context: Context?): Bitmap {
    return MediaStore.Images.Media.getBitmap(context?.contentResolver, this)
}

It takes context as parameter to get contentResolver and Uri received from onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?).

To use, just do the following:

intent?.data.toBitmap(context)

where intent?.data is the Uri received from onActivityResult().

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDen DrobiazkoView Question on Stackoverflow
Solution 1 - AndroidAkhilView Answer on Stackoverflow
Solution 2 - AndroidJon RogstadView Answer on Stackoverflow
Solution 3 - Androidarungiri_10View Answer on Stackoverflow