getExternalStoragePublicDirectory устарела в Android Q

Поскольку getExternalStoragePublicDirectory устарела в Android Q, и рекомендуется использовать другие средства. тогда как мы можем указать, что мы хотим сохранить сгенерированные фотографии из приложения камеры в папку DCIM или пользовательскую подпапку в папке DCIM?

В документации говорится, что следующие 3 варианта являются новыми предпочтительными альтернативами:

  1. Контекст # getExternalFilesDir (String)
  2. MediaStore
  3. Намерение # ACTION_OPEN_DOCUMENT

Вариант 1 исключен, поскольку это означает, что фотографии будут удалены, если приложение будет удалено.

Вариант 3 также не является выбором, так как он потребует от пользователя выбора местоположения через проводник SAF файла.

Мы остались с вариантом 2, MediaStore; но нет документации о том, как использовать его в качестве замены для getExternalStoragePublicDirectory в Android Q.

Ответ 1

Исходя из документов, используйте DCIM/... для RELATIVE_PATH, где ... - это то, чем будет ваш пользовательский подкаталог. Итак, вы могли бы получить что-то вроде этого:

      val resolver = context.contentResolver
      val contentValues = ContentValues().apply {
        put(MediaStore.MediaColumns.DISPLAY_NAME, "CuteKitten001")
        put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
        put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/PerracoLabs")
      }

      val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

      resolver.openOutputStream(uri).use {
        // TODO something with the stream
      }

Обратите внимание, что поскольку RELATIVE_PATH является новым для API уровня 29, вам потребуется использовать этот подход на более новых устройствах и использовать getExternalStoragePublicDirectory() на старых.

Ответ 2

Ответ @CommonsWare удивителен. Но для тех, кто хочет это на Java, вам нужно попробовать это:

ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, clearName(name));
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, getMimeType(name));
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);

Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);

Я только что проверил этот код, поэтому не стесняйтесь исправлять меня.