Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
325 views
in Technique[技术] by (71.8m points)

java - Copy exif info from one Uri to the other with the new Android Scoped Storage?

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 wich 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?
Any help would be appreciated!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...