Сохранение изображения после получения папки из пользовательского интерфейса Storage Access Framework

1

Я задал предпочтение пользователям выбирать папку сохранения для моего приложения, используя Storage Access Framework. После получения uri onActivityResult я сохраняю его в SharedPreferences как String и сохраняю изображение, когда оно будет сохранено.

Я использую этот метод для успешного сохранения изображения.

public void saveImageWithDocumentFile(String uriString, String mimeType, String name) {
    isImageSaved = false;
    try {
        Uri uri = Uri.parse(uriString);
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, uri);
        DocumentFile file = pickedDir.createFile(mimeType, name);
        OutputStream out = getContentResolver().openOutputStream(file.getUri());
        isImageSaved = mBitmap.compress(CompressFormat.JPEG, 100, out);
        out.close();

    } catch (IOException e) {
        throw new RuntimeException("Something went wrong : " + e.getMessage(), e);
    }
    Toast.makeText(MainActivity.this, "Image saved  " + isImageSaved, Toast.LENGTH_SHORT).show();
}

Если пользователь удаляет папку, выбранную с помощью SAF, iget null DocumentFile file и сбой приложения. Мой первый вопрос: как я могу проверить, существует ли папка, не открывая снова SAF ui.

Я также хочу использовать ParcelFileDescriptor для сохранения того же изображения с помощью этого метода.

public void saveImageWithParcelFileDescriptor(String folder, String name) {
    if (mBitmap == null) {
        Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();
        return;
    }
    String image = folder + File.separator + name + ".jpg";
    Toast.makeText(MainActivity.this, "image " + image, Toast.LENGTH_LONG).show();

    Uri uri = Uri.parse(image);
    ParcelFileDescriptor pfd = null;
    FileOutputStream fileOutputStream = null;
    try {
        pfd = getContentResolver().openFileDescriptor(uri, "w");
        fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
        mBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (pfd != null) {
            try {
                pfd.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (fileOutputStream != null) {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    Toast.makeText(MainActivity.this, "Image saved  " + isImageSaved, Toast.LENGTH_SHORT).show();

}

я получаю java.lang.IllegalArgumentException: Invalid URI: content://com.android.externalstorage.documents/tree/612E-B7BF%3Aname/imagePFD.jpg on line pfd = getContentResolver().openFileDescriptor(uri, "w");

Вот как я называю этот метод, currentFolder - это папка, которую я получаю с использованием намерения и той же папки при первом методе.

saveImageWithParcelFileDescriptor(currentFolder, "imagePFD");

Как я могу это исправить, и какой метод является более предпочтительным и почему?

Теги:
storage-access-framework

1 ответ

1
Лучший ответ

как я могу проверить, существует ли папка

DocumentFile имеет метод exists(). Теоретически pickedDir.exists() должен сказать вам, существует ли он. На практике это зависит от поставщика хранилища.

Я также хочу использовать ParcelFileDescriptor для сохранения того же изображения с помощью этого метода.

У этого кода есть ошибки:

  • Вы не можете предоставлять свои права, используя grantUriPermission()

  • Вы не можете изобретать произвольные значения Uri через конкатенацию, особенно для поставщика, который не принадлежит вам

Как я могу исправить это

Удалите его.

какой метод является более предпочтительным

Первый.

и почему?

Первый будет работать, возможно, с незначительной корректировкой. У второго нет шансов на работу.

  • 0
    Да, первый работает, пока существует сохраненная папка. Я проверю, существует ли папка с documentFile.exist (). Нет ли способа сохранить изображение с пользовательским именем и ParcelFileDescriptor?
  • 1
    @FatihOzcan: вы можете заменить OutputStream out = getContentResolver().openOutputStream(file.getUri()) из вашего первого фрагмента кода на getContentResolver().openFileDescriptor(file.getUri(), "w") и использовать ParcelFileDescriptor туда. Я не знаю, каково будет преимущество, результат будет намного длиннее, чем ваш первый фрагмент кода, и результат не будет сильно напоминать ваш второй фрагмент кода. Ключ использует createFile() , поэтому провайдер хранилища - это тот, кто подходит к Uri который вы пишете.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню