Доступ к фотографиям из внешнего хранилища в Android Q - PullRequest
2 голосов
/ 07 апреля 2020

Недавно я обновил целевую версию приложения до API 29. Из-за ограниченного объема хранилища в Android 10 я использовал MediaStore API для хранения и извлечения изображений из внешнего хранилища приложения. Ранее я использовал getExternalStoragePublicDirectory для хранения изображений, снятых с помощью камеры, теперь я использую MediaStore.Images.Media.EXTERNAL_CONTENT_URI для записи файла во внешнее хранилище.

Проблема, с которой я сейчас сталкиваюсь, связана с тем, когда я открываю свое приложение и делаю снимки , он хранится под именем папки, которую я дал «myapp», и я могу получить свои изображения с помощью курсора Mediastore и показать их в собственной галерее. И когда я удаляю мое приложение, папка «myapp» все еще существует. И когда я снова устанавливаю свое приложение и пытаюсь прочитать изображения из галереи, курсор не возвращает никакого изображения. Но если я снова сделаю снимок, я смогу загрузить их в свою галерею. Пользовательский вид галереи - это просто ряд изображений в нижней части экрана, чтобы пользователю не приходилось просматривать папку с фотографиями для загрузки изображения в приложение.

Так я храню свои изображения. в MediaStore

Значения содержимого:

String RELATIVE_PATH = Environment.DIRECTORY_PICTURES + File.separator + "myApp";
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, generateImageName(new Date()));
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, RELATIVE_PATH);

Метод создания имени:

int sameSecondCount;
protected String generateName(Date now)
    {
        String result = formatter.format(now);

        long nowMillis = now.getTime();
        if (nowMillis / 1000 == lastMillis / 1000)
        {
            sameSecondCount++;
            result += "_" + sameSecondCount;
        }
        else
            sameSecondCount = 0;

        lastMillis = nowMillis;

        return result + PICTURE_EXTENSION_JPG;
    }
@WorkerThread
    private Uri writePictureToFile(ContentValues contentValues, byte[] bitmapBytes) throws IOException
    {
        final ContentResolver resolver = getApplication().getContentResolver();

        Uri uri = null;
        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

        try
        {
            uri = resolver.insert(contentUri, contentValues);

            if (uri == null)
                throw new IOException("Failed to create new MediaStore record.");

            OutputStream stream = resolver.openOutputStream(uri);

            if (stream == null)
            {
                throw new IOException("Failed to get output stream.");
            }

            stream.write(bitmapBytes);
        }
        catch (IOException e)
        {
            // Delete the content from the media store
            if (uri != null)
                resolver.delete(uri, null, null);
            throw e;
        }
        return uri;
    } 

Чтение изображений

{
                String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + " in (?,?,?)";
                String[] args = new String[]{
                    MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg"),
                    MimeTypeMap.getSingleton().getMimeTypeFromExtension("png")};

                Cursor cursor = context.getContentResolver()
                    .query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selectionMimeType, selectionArgs,
                        orderBy + " DESC");
                if (cursor != null)
                {
                    int idColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
                    imageCursor.moveToFirst();
                    int imageCount = imageCursor.getCount();
                    for (int i = 0; i < imageCount && i < totalCount; i++)
                    {
                        final long imageId = imageCursor.getLong(idColumnIndex);
                        Uri uriImage = Uri.withAppendedPath(uriExternal, "" + imageId);
                        GalleryData galleryImageData = new GalleryImageData(imageId, uriImage); // Custom class with id and Uri
                        galleryViewModelList.add(galleryImageData);
                        imageCursor.moveToNext();
                    }
                    imageCursor.close();
                }

Почему Изображения, которые я сохранил в папке в Mediastore, не возвращаются вышеуказанным кодом при переустановке приложения. Это умышленно или я что-то упустил?

Это столбцы, которые я извлекаю,

final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.Media.MIME_TYPE };
final String orderBy = MediaStore.Images.Media.DATE_TAKEN; ```

1 Ответ

2 голосов
/ 08 апреля 2020

По непонятным причинам Android 10 рассматривает две установки приложений, разделенные по времени, как отдельные приложения, не отличающиеся от тех, которые были двумя совершенно разными приложениями.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...