选择照片时使用新的Google相册应用程序出现问题

50

我的应用程序可以从库中选择照片。我需要从此选择中获取文件路径。

以下是创建选择照片意图的代码:

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

这是从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;

在昨天的Google Photos应用更新之前,一切都运行得非常好。 现在,在解析URI后path为null。

URI类似于这个:content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F75209/ACTUAL

我也尝试使用Intent.ACTION_GET_CONTENT操作创建意图-没有好运。

3个回答

48

以下代码对我在最新的Google相册中获取内容URI有效。我的尝试是将其写入临时文件并返回临时图像URI,如果它在内容URI中具有权限。

你也可以尝试同样的方法:

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

2
我已经接受了这个答案,尽管对于我们的流程来说这有点像是一个变通方法。但它可以让应用程序回到完全工作状态,所以这很重要。需要注意的一点是:我没有从InputStream中进行位图解码 - 我将其复制到某个File tempFile = new File("path_to_my_temp_directory");中,然后将最后一个用于所有操作。 - Den Drobiazko
@Akhil 谢谢你! - Petro
is = context.getContentResolver().openInputStream(uri); 返回 null。我似乎找不到从 Google 相册应用程序选择图像的解决方案。如果有人有可行的解决方案,请分享。 - ArJ
我在另一个类似的问题中提供了一个答案,但是使用了输入和输出流而不是位图:https://dev59.com/llcP5IYBdhLWcg3w_u8U - adalpari
但是如何从Google照片下载视频文件呢? - Lovekush Vishwakarma

6
这绝对是一种解决方法,但你可以提取实际的内容URI,因为它显然已经嵌入了某些原因:content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F75209

我能够使用authority=media and path=external/images/media/xxx创建一个新的URI,然后内容解析器返回一个真实的URL。

示例代码:

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();

请问您能分享一下这个解决方案的源代码吗?我已经卡在这个问题上好几天了! - Vishy
@JonRogstad,你的例子非常好用!但这只是暂时的解决方法。我认为应该有一种本地的方式来处理自定义/应用程序特定的URI。 - sud007
这在三星Galaxy S5,Android 5.0上崩溃。 - Maragues
仅作警告:这并不适用于所有设备和所有照片。例如,我的URI看起来像这样... content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F31769/ORIGINAL/NONE/##########,其中#表示数字(0-9)。 - Joshua King

1

我知道这个问题有点旧,但是我做了以下操作来从相册获取并使用图像。下面是相同的扩展函数。

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

它需要上下文作为参数,以获取从onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?)接收到的contentResolver和Uri。

使用方法如下:

intent?.data.toBitmap(context)

intent?.data 是从 onActivityResult() 接收到的 Uri。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接