4

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.

Bhiefer
  • 1,613
  • 4
  • 16
  • 31
  • There is no `DocumentsContractApi19` in the Android SDK. How are you checking via `File.length()`, since you don't have filesystem access to most of removable storage? – CommonsWare Mar 04 '16 at 16:07
  • `android.support.v4.provider.DocumentsContractApi19` is part of Support library. It is used in `android.support.v4.provider.TreeDocumentFile` too. I have my own methods that converts the tree uri to file path. So I can check the file using `File` class too - it is readable. As I said, it returns the same values. – Bhiefer Mar 04 '16 at 16:18
  • Out of curiosity, do you get the correct length if you [use the official API](http://developer.android.com/guide/topics/providers/document-provider.html#metadata) to get the size? – Phillip Mar 18 '16 at 16:51
  • No, I get incorrect length, it doesn't matter. If you look at the implementation of `DocumentsContractApi19.length()` - it uses the official API. It is just a helper designed to emulate `File` behaviour. This method is used in official `DocumentFile` for obtaining [length](http://developer.android.com/reference/android/support/v4/provider/DocumentFile.html#length()) – Bhiefer Mar 19 '16 at 11:15
  • Have you tried closing the stream (`outStream.close();`) when done, does that help? – Kai Mar 20 '16 at 10:54
  • Yes, as used in my example - there is try-with-resources statement that autoclose the stream. I also tried `flush()`. But I think that there must be something that do this... – Bhiefer Mar 21 '16 at 08:47

1 Answers1

1

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
Bhiefer
  • 1,613
  • 4
  • 16
  • 31
  • Did you find the real root cause of the problem or any workaround? – PerracoLabs Apr 28 '16 at 11:27
  • I don't know the root cause. My workaround was replacing all uses of `java.io.File` with strict SAF api. I have my own implementation of file class because `DocumentFile` is not fast enough. But I am using the same methods from `android.provider.DocumentsContract`. – Bhiefer Apr 28 '16 at 13:23