Запись данных EXIF ​​после добавления изображения в MediaStore

Мне просто нужно добавить некоторые метаданные Exif в Jpeg, сохраненный в MediaStore (с помощью Content Resolver)

Вот как я сохраняю изображение:

    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    values.put(MediaStore.MediaColumns.DATE_ADDED, now);
    values.put(MediaStore.MediaColumns.DATE_MODIFIED, now);

    ContentResolver resolver = context.getContentResolver();
    Uri uri = resolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values );

    try( OutputStream stream = resolver.openOutputStream(uri) )
    {
        // Perform operations on "stream".
        bitmap.compress( Bitmap.CompressFormat.JPEG, 90, stream );
        stream.flush();
    } catch( IOException e )
    {
        e.printStackTrace();
    }

Вот как я пытаюсь добавить метаданные Exif:

    private void writeExif( Uri uri, List<String> exifStr )
    {
        try
        {
            // THIS fails on file opening ( Read Failed: EBADF (Bad File Descriptor)
//            uri = MediaStore.setRequireOriginal(uri);       // UNUSEFULL
            ParcelFileDescriptor imageFd = getContentResolver().openFileDescriptor(uri, "w");
            ExifInterface exif = new ExifInterface( imageFd.getFileDescriptor() );

            // THIS fails on file opening ( open failed: EACCES (Permission denied) )
//            String filename = getRealPathFromURI( uri );      // Extract full pathname from (deprecataed) MediaStore.Images.Media.DATA column
//            ExifInterface exif = new ExifInterface( filename );

            // THIS fails on saveAttributes ( write failed: EBADF (Bad file descriptor) )
//            ExifInterface exif = new ExifInterface( getContentResolver().openInputStream(uri) );

            for( int i = 0; i < ExifAttributes.length; i++ )
            {
                String value = exifStr.get(i);
                if( value != null )
                    exif.setAttribute(ExifAttributes[i], value);
            }
            
            exif.saveAttributes();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
    }

В любом случае, я пытаюсь это сделать (проверьте закомментированные строки), я получаю некоторую ошибку (плохой дескриптор файла или доступ запрещен)

Использование пути из "MediaStore.Images.Media.DATA" - это просто тест и НЕ ДОЛЖНО использоваться в решении (я нацелен на API 29, и он устарел). Но все равно не работает.

Кто-нибудь знает, как я могу от этого избавиться?

благодаря

PS Образ правильно сохранен, просто не работает часть writeExif().

1 ответ

Решение

Я решил. Проблема заключалась в том, что файл не был синхронизирован на диске.

Итак, вот как это работает для сохранения изображения:

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATE_ADDED, now);
values.put(MediaStore.MediaColumns.DATE_MODIFIED, now);

ContentResolver resolver = context.getContentResolver();
Uri uri = resolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values );

try( ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri,"w") )
{
    FileDescriptor fd = pfd.getFileDescriptor();

    try( OutputStream stream = new FileOutputStream(fd) )
    {
        // Perform operations on "stream".
        mBitmap.compress( Bitmap.CompressFormat.JPEG, 90, stream );
    }

    // Synch data with disk. It's mandatory to be able later to call writeExif
    fd.sync();    // <---- HERE THE SOLUTION

} catch( IOException e )
{
    e.printStackTrace();
}

И как я добавляю метаданные Exif:

private void writeExif( Uri uri, List<String> exifStr )
{
    try( ParcelFileDescriptor imagePfd = getContentResolver().openFileDescriptor(uri, "rw") )
    {
        ExifInterface exif = new ExifInterface( imagePfd.getFileDescriptor() );

        for( int i = 0; i < ExifAttributes.length; i++ )
        {
            String value = exifStr.get(i);
            if( value != null )
                exif.setAttribute(ExifAttributes[i], value);
        }
        
        exif.saveAttributes();
    }
    catch( Exception e )
    {
        e.printStackTrace();
    }
}
Другие вопросы по тегам