将图像添加到 MediaStore 后写入 EXIF 数据
Write EXIF data after have added image to MediaStore
我只需要将一些 Exif 元数据添加到保存到 MediaStore 的 Jpeg(使用内容解析器)
保存图片的方法如下:
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,它已被弃用)。不过不管怎样,也没用。
有人知道我怎样才能摆脱这个吗?
谢谢
P.S。图片保存正确,只是writeExif()部分失败
我解决了。
问题是文件没有在磁盘上同步。
所以,这是保存图像的工作原理:
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();
}
}
我只需要将一些 Exif 元数据添加到保存到 MediaStore 的 Jpeg(使用内容解析器)
保存图片的方法如下:
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,它已被弃用)。不过不管怎样,也没用。
有人知道我怎样才能摆脱这个吗?
谢谢
P.S。图片保存正确,只是writeExif()部分失败
我解决了。 问题是文件没有在磁盘上同步。
所以,这是保存图像的工作原理:
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();
}
}