当前位置:  开发笔记 > Android > 正文

关于如何从URI获取Exif数据的最终答案

如何解决《关于如何从URI获取Exif数据的最终答案》经验,为你挑选了3个好方法。

这里已经讨论了很多问题,主要是不同的结果,并且由于API的变化和不同类型的URI,没有明确的答案.

我自己没有答案,但让我们谈谈它.该ExifInterface有一个接受一个构造函数filePath.这本身很烦人,因为现在不鼓励依赖路径 - 你应该使用Uris和ContentResolver.好.

我们的Uri名字uri可以从意图中检索出来onActivityResult(如果您从图库中选择图片ACTION_GET_CONTENT)或者可以是Uri我们之前拥有的(如果您从相机中选择图片并打电话intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)).

API <19

我们uri可以有两种不同的模式:

来自相机的Uris大多都有file://架构.那些很容易治疗,因为他们坚持这条道路.你可以打电话new ExifInterface(uri.getPath()),你就完成了.

来自画廊或其他内容提供商的Uris通常都有一个content://界面.我个人不知道那是什么,但让我发疯.

据我所知,第二种情况应该用ContentResolver你能得到的东西来对待Context.getContentResolver().以下适用于我测试的所有应用程序,无论如何:

public static ExifInterface getPictureData(Context context, Uri uri) {
    String[] uriParts = uri.toString().split(":");
    String path = null;

    if (uriParts[0].equals("content")) {
        // we can use ContentResolver.
        // let’s query the DATA column which holds the path
        String col = MediaStore.Images.ImageColumns.DATA;
        Cursor c = context.getContentResolver().query(uri,
                new String[]{col},
                null, null, null);

        if (c != null && c.moveToFirst()) {
            path = c.getString(c.getColumnIndex(col));
            c.close();
            return new ExifInterface(path);
        }

    } else if (uriParts[0].equals("file")) {
        // it's easy to get the path
        path = uri.getEncodedPath();
        return new ExifInterface(path);
    }
    return null;
}

API19 +

我的问题来自Kitkat以及content://URI.Kitkat介绍了Storage Access Framework(见这里)以及一个新的意图ACTION_OPEN_DOCUMENT和平台选择器.但是,有人说

在Android 4.4及更高版本中,您还可以选择使用ACTION_OPEN_DOCUMENT意图,该意图显示由系统控制的选择器UI,允许用户浏览其他应用程序可用的所有文件.通过此单一UI,用户可以从任何支持的应用程序中选择文件.

ACTION_OPEN_DOCUMENT不能替代ACTION_GET_CONTENT.您应该使用的那个取决于您的应用程序的需求.

所以为了保持这个非常简单,让我们说我们对旧版本没问题ACTION_GET_CONTENT:它会触发一个选择器对话框,您可以在其中选择一个图库应用程序.

但是,内容方法不再适用.有时,它适用于奇巧,但永远不会奏效的棒棒糖,例如.我不知道究竟发生了什么变化.

我已经搜索并尝试过很多次; Kitkat采取的另一种方法是:

String wholeId = DocumentsContract.getDocumentId(uri);
String[] parts = wholeId.split(“:”);
String numberId = parts[1];

Cursor c = context.getContentResolver().query(
    // why external and not internal ?
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    new String[]{ col },
    MediaStore.Images.Media._ID + “=?”,
    new String[]{ numberId },
    null);

这有时会起作用,但有些则没有.具体来说,它可以在wholeId什么时候起作用image:2839,但是当wholeId它只是一个数字时显然会中断.

您可以使用系统选择器尝试此操作(即启动画廊ACTION_OPEN_DOCUMENT):如果您从"最近"中选择一个图像,它可以工作; 如果您从"下载"中选择图像,则会中断.

那怎么样?!

直接答案是你没有,你没有在较新版本的操作系统中找到内容uris的文件路径.可以说并非所有内容都指向图片甚至文件.

这对我来说完全没问题,起初我努力避免这种情况.但是,如果我们不应该使用路径,我们应该如何使用ExifInterface类?

我不明白现代应用程序如何做到这一点 - 找到方向和元数据是您立即面临的问题,并且ContentResolver在这个意义上不提供任何API.你有ContentResolver.openFileDescriptor()和类似的东西,但没有API来读取元数据(真正在该文件中).可能有外部库Exif从流中读取内容,但我想知道解决此问题的通用/平台方法.

我在谷歌的开源应用程序中搜索了类似的代码,但一无所获.



1> startoftext..:

使用一些示例代码扩展alex.dorokhov的答案.支持库是一个很好的方法.

的build.gradle

dependencies {
...    
compile "com.android.support:exifinterface:25.0.1"
...
}

示例代码:

import android.support.media.ExifInterface;
...
try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
      ExifInterface exif = new ExifInterface(inputStream);
      int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
    } catch (IOException e) {
      e.printStackTrace();
    }

一旦我们开始瞄准api 25(也许24 +上也有问题)但仍支持回到api 19,我必须这样做,因为在Android 7我们的应用程序会崩溃,如果我将URI传递给相机只是引用一个文件.因此我必须创建一个URI来传递给相机意图.

FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", tempFile);

问题是该文件无法将URI转换为真正的文件路径(除了保留临时文件路径).



2> alex.dorokho..:

现在,支持库中提供了从内容URI(实际上是一个InputStream)获取EXIF.请参阅:https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html



3> CommonsWare..:

以下适用于我测试的所有应用程序,无论如何:

只有Uri恰好是来自的东西才会有效MediaStore.如果Uri碰巧来自其他任何事情,它将失败.

直接答案是你没有,你没有在较新版本的操作系统中找到内容uris的文件路径.可以说并非所有内容都指向图片甚至文件.

正确.我已经多次指出这一点,比如这里.

如果我们不应该使用路径,我们应该如何使用ExifInterface类?

你没有.使用其他代码获取EXIF标头.

可能有外部库从流中读取Exif内容,但我想知道解决此问题的通用/平台方法.

使用外部库.

我在谷歌的开源应用程序中搜索了类似的代码,但一无所获.

你会在Mms应用程序中找到一些.

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有