Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronization between Context.openFileInput and Context.openFileOutput

I have an Android Service running daily which does some data synchronization. Once a day it downloads a file and caches it to disk via context.openFileOutput:

String fileName = Uri.parse(url).getLastPathSegment();
try (FileOutputStream outputStream =
     context.openFileOutput(fileName, Context.MODE_PRIVATE)) {
   outputStream.write(bytes);
   // ...
} catch (IOException e) {
   // logging ...
}

This happens on a background thread. I also have a UI which contains a WebView. The WebView uses those cached resources if they are available via context.openFileInput:

@Override
public WebResourceResponse shouldInterceptRequest(
    WebView view, WebResourceRequest request) {
  String url = request.getUrl().toString();
  if (shouldUseCache(url)) {
     try {
        return new WebResourceResponse(
             "video/webm",
             Charsets.UTF_8.name(),
             context.openFileInput(obtainFileName(url)));
     } catch (IOException e) {
       // If a cached resource fails to load, just let the WebView load it the normal way.
       // logging ...
     }
  }
  return super.shouldInterceptRequest(view, request);
}

This happens on another background thread independently from the service.

Can I rely on Context implementation and be sure that file reads and writes are safe, or do I have to take care of the synchronization myself? E.g. if the Service is currently writing data to a file and the WebView is trying to access it, will I run into a problem? If so, how should I implement the synchronization?

like image 633
Gennadii Saprykin Avatar asked Jun 18 '18 16:06

Gennadii Saprykin


1 Answers

If the Service is currently writing data to a file and the WebView is trying to access it, will I run into a problem?

In such cases you can write data to a file by appending something to file name and changing its name back once download is finished. e.g.

context.openFileOutput(fileName + ".downloading", Context.MODE_PRIVATE))

and later once download is finished rename the file to original fileName. I am sure you check for file presence in shouldUseCache(url) so it will keep working normally. This will avoid situations where a file is still downloading while you try to read it.

like image 105
M-WaJeEh Avatar answered Oct 23 '22 19:10

M-WaJeEh