Skip to content
This repository has been archived by the owner on Sep 26, 2022. It is now read-only.

downloadFile method not working correctly on Android #266

Open
tylerclark opened this issue Jun 17, 2022 · 0 comments
Open

downloadFile method not working correctly on Android #266

tylerclark opened this issue Jun 17, 2022 · 0 comments

Comments

@tylerclark
Copy link

Describe the bug
I have an app which downloads text files from an API endpoint, stores them on the phone, and then uploads the same files into cloud storage bucket. Everything works great on web and iOS, but on Android I was getting IO Error. I launched Android Studio and studied the logs and discovered this error:

E/Capacitor/Plugin: IO Error
    java.io.FileNotFoundException: /storage/emulated/0/Documents/logs/JF-200804i^20220614-213606-0m_0kt_0s-shutdown.jfl: open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:575)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
        at com.getcapacitor.plugin.http.HttpRequestHandler.downloadFile(HttpRequestHandler.java:438)
        at com.getcapacitor.plugin.http.Http.downloadFile(Http.java:167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:121)
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$Bridge(Bridge.java:598)
        at com.getcapacitor.-$$Lambda$Bridge$25SFHybyAQk7zS27hTVXh2p8tmw.run(Unknown Source:8)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.os.HandlerThread.run(HandlerThread.java:67)
     Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:273)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8501)
        at libcore.io.IoBridge.open(IoBridge.java:561)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236) 
        at com.getcapacitor.plugin.http.HttpRequestHandler.downloadFile(HttpRequestHandler.java:438) 
        at com.getcapacitor.plugin.http.Http.downloadFile(Http.java:167) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:121) 
        at com.getcapacitor.Bridge.lambda$callPluginMethod$0$Bridge(Bridge.java:598) 
        at com.getcapacitor.-$$Lambda$Bridge$25SFHybyAQk7zS27hTVXh2p8tmw.run(Unknown Source:8) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loopOnce(Looper.java:226) 
        at android.os.Looper.loop(Looper.java:313) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 

Now this error would seem to indicate that the log folder is not there but it is! I have it create it if it doesn't already exist long before this code runs. And it works perfect on iOS and web, just not Android. Weird. Ok so I changed my options from:

{
   url: this.localAddress + '/log/' + filename,
   method: 'GET',
   progress: true,
   filePath: '/logs/' + filename,
   directory: Directory.Data,
}

to

{
   url: this.localAddress + '/log/' + filename,
   method: 'GET',
   progress: true,
   filePath: filename,
   directory: Directory.Data,
}

All of a sudden it saves the file (kinda). I ended up having to write some custom code for Android only which is below:

if (this.isNative && this.isAndroid) {
   const tempPath = response.path.replace('storage/emulated/0/Documents/', '');
   const readFile = await Filesystem.readFile({
      path: tempPath,
      directory: Directory.Documents,
      encoding: Encoding.UTF8,
   });
   await Filesystem.writeFile({
      path: '/logs/' + this.device.name + '^' + filename,
      data: readFile.data,
      directory: Directory.Data,
      encoding: Encoding.UTF8,
   });
   await Filesystem.deleteFile({
      path: tempPath,
      directory: Directory.Documents,
   });
}

Notice how I have to reference the Directory.Documents instead of Directory.Data to actually read the file and then I'm basically creating a replica of the file in the right directory and deleting the original file.

To Reproduce

Expected behavior
I believe the Android code is not aware of folders that actually exist. Even when doing a readDir I can see the log folder there as expected. This causes a compound set of issues which results in hacky code. I think the next problem is the Directory.Documents vs Directory.Data issue. Not sure why I am having trouble accessing the file correctly.

Smartphone:

  • Device: Samsung Galaxy S20
  • OS: Android 12
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant