Как получить ориентацию файла изображения, который был взят из класса FileProvider?

Фон

Целевой API 24 или выше, вместо простой команды "Uri.fromFile", разработчики должны использовать FileProvider (или их собственный ContentProvider), чтобы другие приложения могли получать доступ к файлам приложения.

Эта проблема

Я пытаюсь открыть приложение камеры, чтобы позволить ему сохранить файл в личном хранилище моего приложения, используя этот код:

    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.

Дело в том, что мне нужен ContentProvider этого URI, чтобы предоставить приложению камеры разрешение на доступ к этому файлу...

Вопрос

Как получить ориентацию, используя приведенный выше код (или даже лучший код), используя новый FileProvider Uri? Может быть, я могу заставить ContentResolver использовать ранее ContentProvider для получения данных нужного столбца курсора?

Мне действительно нужно создавать свой собственный ContentProvider здесь?

1 ответ

Решение

Uri это не файл Ты звонишь getPath() на Uri и рассматриваем его как путь к файлу. Это работает только если схема в Uri является file, В вашем случае это не так.

У вас уже есть File объект, указывающий на файл. Это называется photoFile, Держите это в поле вашей деятельности и сохраните в сохраненном состоянии экземпляра. Bundle (поскольку ваш процесс может быть прерван, пока приложение камеры находится на переднем плане). Затем используйте photoFile, Не используйте встроенный ExifInterface хотя, поскольку у него есть недостатки безопасности.

Как получить ориентацию, используя приведенный выше код (или даже лучший код), используя новый FileProvider Uri?

Вы не использование photoFile,

Может быть, я могу заставить ContentResolver использовать ранее ContentProvider для получения данных нужного столбца курсора?

Я понятия не имею, почему вы ожидаете getOrientation() это занимает Uri работать. Вы запрашиваете MediaStore для данных о Uri это не исходит от MediaStore,

Мне действительно нужно создавать свой собственный ContentProvider здесь?

Нет потому что FileProvider это не твоя проблема. Вы бы имели такой же недостаток getOrientation() методы с вашим собственным ContentProvider,

Другие вопросы по тегам