1

I'm trying to use Meteor 1.4 with Cordova (mobile support) to read files on my android phone.

I've got a small Meteor app running on my phone (via meteor run android-device). I have also created a small text file in the app's private storage using adb shell and run-as.

I can read the file if I call getFile('a'), but I can't find any way to use cordova.file.dataDirectory (even with WebAppLocalServer.localFileSystemUrl) as recommended in the Meteor guide. I get FileError {code: 5} (ENCODING_ERR).

Here's the JS console output from the Chrome inspector when I click the button in my app:

meteor app in chrome inspector throwing FileError code 5

  • This repros on both Android 5 and 6.
  • My dev environment is 64-bit Ubuntu 14.04 LTS.
  • App Info for my app reports it has these permissions:
    • modify or delete the contents of your SD card
    • read the contents of your SD card
  • The app uses the cordova file plugin version 4.2.0.
  • Dup? How to read/write a file in Meteor-Cordova?
  • This does work in the chrome://inspect console via USB debugging: HTTP.call('GET', 'http://localhost:12640/local-filesystem/data/user/0/com.adammonsen.app/files/a', {}, function (e,r) {console.error(e); console.log(r)});
    • output is Object {statusCode: 200, content: "in external dir↵", headers: Object, data: null}
Adam Monsen
  • 9,054
  • 6
  • 53
  • 82

1 Answers1

1

Got it. The trick is to use window.resolveLocalFileSystemURL() to get at the filesystem. Here's how to get at a file on external storage. My original question was about app-private storage. If you're looking for that, just use the cordova.file.dataDirectory instead of cordova.file.externalDataDirectory.

function reportError(err) {
  console.error(err);
}

function readFile(file) {
  var reader = new FileReader();
  reader.onloadend = function() {
    console.log('read file! contents: ' + this.result);
  };
  reader.readAsText(file);
}

function processFileEntry(fileEntry) {
  fileEntry.file(file => {
    readFile(file);
  }, reportError);
}

Template.hello.events({
  'click button'(event, instance) {
    // increment the counter when button is clicked
    instance.counter.set(instance.counter.get() + 1);

    if (Meteor.isCordova) {
      // aaaaaand do some other stuff
      const path = cordova.file.externalDataDirectory + 'a';
      window.resolveLocalFileSystemURL(path, fileEntry => {
        console.log('fileEntry: ', fileEntry);
        processFileEntry(fileEntry);
      }, reportError);
    }
  },
});

See https://github.com/meonkeys/cordova-file-test/tree/solution for a full working example and instructions.

Make sure AndroidExtraFilesystems includes files-external. I used this line in my mobile-config.js:

App.setPreference('AndroidExtraFilesystems', 'files,files-external');

I'd love to understand the difference between the APIs, but for now I'm just happy I found something that works reliably.

Adam Monsen
  • 9,054
  • 6
  • 53
  • 82