繁体   English   中英

如何获取从FileProvider类获取的图像文件的方向?

[英]How to get orientation of image file, which was taken from FileProvider class?

背景

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

问题

我尝试使用以下代码打开相机应用程序,使其将文件保存到应用程序的私有存储中:

    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>

清单文件

    <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不是文件。 您正在Uri上调用getPath()并将其视为文件路径来对待。 仅当Uri的方案为file此方法才有效。 就您而言,事实并非如此。

您已经有一个指向该文件的File对象。 它称为photoFile 在活动的某个字段中保留该内容,然后将其保存在已保存的实例状态Bundle (因为当照相机应用程序处于前台时,您的过程可能会终止)。 然后,使用photoFile 但是不要使用内置的ExifInterface ,因为它存在安全漏洞

如何使用新的FileProvider Uri使用以上代码(甚至更好的代码)获得方向?

你不知道 使用photoFile

也许我可以强制ContentResolver使用以前的ContentProvider来获取光标所需的列数据?

我不知道为什么您会期望使用UrigetOrientation() 要查询的MediaStore有关数据Uri不来自MediaStore

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

否,因为FileProvider不是您的问题。 您将拥有与自己的ContentProvider相同的有缺陷的getOrientation()方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM