Get Persistable SD Cad write Permission using SAF

2019-09-14 02:07发布

问题:

In my application, list of Image files is inflated in recyclerview. Then after application edits the metadata of Image file.

My code for writing metadata:-

DocumentFile fos = DocumentFile.fromFile(new File(fileIn));

ByteSource bytsInputStream = new ByteSourceFile(new File(fileIn));
byte[] byteArrayInputStream = bytsInputStream.getAll();

try {
    ParcelFileDescriptor pfd = context.getContentResolver().
            openFileDescriptor(fos.getUri(), "w");
    FileOutputStream fileOutputStream =
            new FileOutputStream(pfd.getFileDescriptor());

    rewriter.updateExifMetadataLossy(byteArrayInputStream,fileOutputStream,outputSet);

    fileOutputStream.close();
    pfd.close();

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

I am able to update image file stored in phone memory, but for the Sd Card Images, I get error ---->

java.io.FileNotFoundException: Permission denied

I know that from android 5 , we need to take permission using SAF. My code for taking permission:-

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(
        Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);












@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case REQUEST_CODE_OPEN_DOCUMENT_TREE:
            if (resultCode == Activity.RESULT_OK) {
                Uri treeUri = data.getData();
                int takeFlags = data.getFlags();
                takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION |
                              Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    this.getContentResolver().takePersistableUriPermission(treeUri, takeFlags);
                }
           }
    }

Now I dont know what to do with this treeUri. I want that I take SdCard Permission Once at initial startup only.

In simple terms my question relates to this question:-

This Link

回答1:

DocumentFile documentFile = DocumentFile.fromTreeUri(this, treeUri);

here treeUri is what you get from SAF permission. Means what you get in OnActivityResult().

DocumentFile fos = DocumentFile.fromFile(new File(fileIn));

In this, fileIn is your selected file. then

String[] parts = (fileIn.getPath()).split("\\/");
for (int i = 3; i < parts.length; i++) {
if (documentFile != null) {
    documentFile = documentFile.findFile(parts[i]);
}  
}

hereafter for getting byteArray you need to use this code

try {
                        InputStream iStream = getContentResolver().openInputStream(documentFile.getUri());
                        byte[] byteArrayInputStream = getBytes(iStream);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

After getting byte array you want to continue your code, and also i metion below.

try {
                        ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(fos.getUri(), "w");
                        FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
                        rewriter.updateExifMetadataLossy(byteArrayInputStream,fileOutputStream,outputSet);
                        fileOutputStream.close();
                        pfd.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }

Not: I think this will help you. If you find any mistakes please correct it. Thanks



回答2:

Saving the Uri with

takePersistableUriPermission()

is absolutely right to gain access. The permission is kept until uninstalling or clearing app data. Next step is to keep the Uri for later access (i.e. SharedPreferences).

This will help you.