androidandroid-6.0-marshmallowstorage-access-frameworkdocumentfile

Android Marshmallow: Files written by SAF are not immediatelly written


I am using SAF (Storage access framework) to write files to SD card. On Marshmallow, the files are actually written and updated with a big delay (approximately 10 seconds).

When I use e.g.:

android.support.v4.provider.DocumentFile docFile = DocumentFile.fromTreeUri(context, getUri()) // tree uri that represents some existing file on sd card
File file = getFile(getUri()); // java.io.File that points to same file as docFile

docFile.length(); // length of current file is e.g. 150B
file.length(); // length of file is also 150B
try (OutputStream outStream = context.getContentResolver().getOutputStream(docFile.getUri()))
{
   outStream.write(data, 0, 50); // overwrite with 50 B
   outStream.flush(); // didn't help
}

docFile.length(); // it still returns 150B !!
file.length(); // it still returns 150B

Thread.sleep(12000); // sleep 12 seconds

docFile.length(); // now it returns  correctly 50B
file.length(); // now it returns  correctly 50B

Btw. when I check the length by File.length() method, it returns the same values.

Is there a way how to write it immediately? Or can I set some listener? Otherwise I have to check the size regularly and I don't want to do it this way. And actually, I don't want to wait 10 seconds after file is written.


Solution

  • So I have found that the delays occurs when I use both java.io.File and SAF api. Checking the file by methods File.isDirectory(), File.exists(), File.length() causes that subsequent call of

    context.getContentResolver().getOutputStream(someUri))
    

    is delayed for 10 seconds. It delayes deletion too. I.e. when you try:

    DocumentFile docFile = DocumentFile.fromTreeUri(context, someUri);
    File file = new File("path to same file as someUri");
    if(file.exists() && !file.isDirectory()) // this cause the delay
    {
      docFile.delete();
    }
    
    boolean exists = file.exists(); // exists is INCORRECTLY true
    exists = docFile.exists(); // exists is INCORRECTLY true
    
    Thread.sleep(12000);
    
    exists = file.exists(); // exists is CORRECTLY false
    exists = docFile.exists(); // exists is CORRECTLY false
    

    I used File class for read only operations because it was faster. But I cannot use it together with SAF since Marshmallow. It has to use strictly SAF api:

    DocumentFile docFile = DocumentFile.fromTreeUri(context, someUri);
    if(docFile.exists() && !docFile.isDirectory()) // this cause the delay
    {
      docFile.delete();
    }
    
    boolean exists = docFile.exists(); // exists is CORRECTLY false