android - 如何获取取自 FileProvider 类的图像文件的方向?

标签 android orientation exif android-fileprovider

背景

针对 API 24 或更高版本,开发人员无需使用简单的“Uri.fromFile”命令,而是需要使用 FileProvider(或他们自己的 ContentProvider),以便让其他应用程序访问应用程序的文件。

问题

我尝试使用以下代码打开一个相机应用程序,让它将文件保存到我的应用程序的私有(private)存储中:

    final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    final File photoFile = FileHelper.generateTempCameraFile(this);
    mCameraCachedImageURI = FileProvider.getUriForFile(this, getPackageName()+ ".provider", photoFile);
    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraCachedImageURI);
    takePictureIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    startActivityForResult(takePictureIntent, REQ_CODE_PICK_IMAGE_FROM_CAMERA);

provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

list 文件
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>

这开始很好,因为相机应用程序已启动,但在返回的结果中,我无法使用以前运行良好的代码获取图像文件的方向:
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    int orientation = getOrientation(this,mCameraCachedImageURI );
    ...

public static int getOrientation(final Context context, final Uri photoUri) {
    Cursor cursor = null;
    try {
        cursor = context.getContentResolver().query(photoUri,
                new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
    } catch (final Exception ignored) {
    }
    if (cursor == null) {
        // fallback
        return getOrientation(photoUri.getPath());
    }
    int result = 0;
    if (cursor.getCount() > 0) {
        cursor.moveToFirst();
        result = cursor.getInt(0);
    }
    cursor.close();
    return result;
}

public static int getOrientation(final String filePath) {
    if (TextUtils.isEmpty(filePath))
        return 0;
    try {
        final ExifInterface exifInterface = new ExifInterface(filePath);
        final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);
        int rotate = 0;
        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;
        }
        return rotate;
    } catch (final IOException ignored) {
    }
    return 0;
}

这将崩溃,因为在运行此代码时游标没有任何列。

不仅如此,甚至后备功能(在更改代码以使用它时)也不起作用,因为它向文件路径添加了一个附加部分(在本例中为“外部”)。

我发现了什么

似乎 contentResolver 在这里使用了 FileProvider,而不是以前版本的 Android 上使用的。

问题是,我需要此 URI 的 ContentProvider 才能授予相机应用程序访问此文件的权限...

问题

如何使用上面的代码(甚至更好的代码),使用新的 FileProvider Uri 获得方向?也许我可以强制 ContentResolver 使用以前的 ContentProvider 来获取游标所需的列数据?

我真的必须在这里创建自己的 ContentProvider 吗?

最佳答案

一个 Uri不是文件。您调用getPath()Uri并将其视为文件路径。这只适用于 Uri 中的方案。是 file .在你的情况下,它不是。

您已经有一个 File指向文件的对象。它被称为 photoFile .在您的 Activity 字段中保留它,并将其保存为已保存的实例状态Bundle (因为当相机应用程序处于前台时,您的进程可能会终止)。然后,使用 photoFile .不要使用内置的 ExifInterface但是,作为 it has security flaws .

How do I get the orientation using the above code (or even a better code), using the new FileProvider Uri ?



你没有。使用photoFile .

Maybe I can force the ContentResolver to use the previously ContentProvider to get the needed column's data of the cursor?



我不知道你为什么会期待 getOrientation()这需要 Uri去工作。您正在查询 MediaStore关于 Uri 的数据不是来自MediaStore .

Do I really have to create my own ContentProvider here?



不,因为 FileProvider不是你的问题。你会有同样的缺陷getOrientation()使用您自己的方法ContentProvider .

关于android - 如何获取取自 FileProvider 类的图像文件的方向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41085950/

相关文章:

android - SQLiteOpenHelper:未在物理设备上调用 onCreate() 方法

android - 旋转设备时磁场测量的奇怪行为

iphone - 如何从照片中获取exif?

android - 为 Android > 4.0 Webkit 的焦点禁用文本输入的矩形(橙色边框)

android - 在华为设备上设置默认 Android 启动器?

Android源码编译问题

iphone - 添加到 UIWindow 的 UIView 中的方向

ios - iPhone 6 Plus 的方向不正确?

php - 使用 PHP imageCreateFromJpeg 复制图像并保留其 EXIF/IPTC 数据?

.net - 如何使用 .NET 检索在数码相机上拍摄的照片的属性?