I have two Uri
from different files with schema "content" obtained by the Android SAF API and I need to copy exif information from one file to the other. The destination file was created by my app so I have granted write access to it.
With the ContentResolver
I can obtain an InputStream
that I can use to instantiate an ExifInterface
from which I can extract the exif from the source Uri
:
InputStream ins = context.getContentResolver().openInputStream(imageInputUri);
ExifInterface originalExif = new ExifInterface(ins);
So far so good...
The problem is to write the exif info into the destination Uri
. I can't do the same as I did with the source because an ExifInferface
created with an InputStream
is read-only and can't be used to save the exif info as stated in the docs.
How can I solve this problem and finally be able to copy those exif info from one file to another?
Since no one came with an answer but thanks to @blackapps comment I was able to find out the solution myself. I will post it here if someone else gets to this post searching for the answer for this same question.
It turns out that the ExifInterface
has a constructor that receives a FileDescriptor
as a parameter and it is possible to open a FileDescriptor
from an Uri
by using the ContentResolver
. Then the solution is easy and the only extra care one needs in order to successfully open the FileDescriptor
is to use the "rw" mode since the ExifInterface
will need to read and write info and not just only write.
Here goes a sample code:
InputStream ins = null;
ParcelFileDescriptor outFd = null;
try {
ins = context.getContentResolver().openInputStream(imageInputUri);
ExifInterface originalExif = new ExifInterface(ins);
outFd = context.getContentResolver().openFileDescriptor(imageOutputUri, "rw");
ExifInterface newExif = new ExifInterface(outFd.getFileDescriptor());
copyExifAttributes(originalExif, newExif, width, height);
} catch (IOException e) {
Log.d(TAG, e.getMessage(), e);
} finally {
if (ins != null) {
try {
ins.close();
} catch (IOException e) {
Log.d(TAG, e.getMessage(), e);
}
}
if (outFd != null) {
try {
outFd.close();
} catch (IOException e) {
Log.d(TAG, e.getMessage(), e);
}
}
}
Be warned though that this code wont work on Android versions older than Lollipop (api 21). That's an ExifInterface
limitation since it needs a seekable FileDescriptor in order to work and the ExifiInterface
uses a native call for doing this. Looking at the Android docs is possible to see that this native code is only available since Lollipop.