Ionic – PhoneGap – Cordova – Read and write a profile file locally on Android and iOS

Write and read a local file using Cordova on iOS and Android is pretty much easy but I lost a lot of time trying to find a good example of this.

So here is a little snippet to call wherever you want after the deviceready event has been triggered.

You need to install the File plugin

cordova plugin add org.apache.cordova.file

It uses the $rootScope

See the complete ionic project here

$rootScope.profileFileName = "profile.json";;
$rootScope.profile = { //default profile
            firstName: "Clark",
            lastName: "Kent",
            imageURL: "img/default.png";
        };
$rootScope.fileEntry = null;
$rootScope.fileSystem = null;

window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, failToGetFileSystem);
//On iOS, LocalFileSystem.PERSISTENT is the Documents folder under the private app folder
//On Android, we are in the root folder of the sdcard...
 
function failToGetFileSystem() {
    alert("fail to get file system");
}
 
function gotFS(fs) {
    $rootScope.fileSystem = fs; //keep the file system accessible
     //Here we try to get the file. The exclusive attribute sets to true will cause the method to fail if the file already exists. So I now that I should try to read the profile instead of writting the default profile.
     fs.root.getFile($rootScope.profileFileName, { create: true, exclusive: true },
                            gotFileEntryForFirstTime, failToGetExclusiveFileEntry);
}
 
/**
  * File didn't exist and has just been created so we need to write the profile one time at least.
  */
function gotFileEntryForFirstTime(fileEntry) {
      alert("got file entry for first time");
      alert("url : " + fileEntry.toURL());
      $rootScope.fileEntry = fileEntry;
      $rootScope.saveProfile(function () { alert("profile file written"); }, function () { alert("profile file FAIL written"); });
}
 
$rootScope.saveProfile = function (successFunction, errorFunction) {
     if (!$rootScope.fileEntry) {
           alert("no file to write in");
           return;
      }
      var contentToWrite = angular.toJson($rootScope.profile); //convert profile to JSON
      $rootScope.fileEntry.createWriter(function (fileWriter) {
          fileWriter.onwriteend = successFunction;
          fileWriter.onerror = errorFunction;

          fileWriter.write(contentToWrite);
      },
       errorFunction);
}
 
function failToGetExclusiveFileEntry() {
   alert("file maybe exists ?");
   $rootScope.fileSystem.root.getFile($rootScope.profileFileName, { create: true, exclusive: false },
                   gotFileEntry, failToGetFileEntry);
}
 
function failToGetFileEntry(error) {
    alert("fail to get file entry");
}
 
/**
  * Got file entry but it already exists so we need to read it.
  */
function gotFileEntry(fileEntry) {
   alert("got file entry");
   alert(fileEntry.toURL());
   $rootScope.fileEntry = fileEntry;
   readProfile();
}
 
function readProfile() {
   if (!$rootScope.fileEntry) {
     alert("no file to read");
     return;
   }
$rootScope.fileEntry.file(function (profileFile) {
  var reader = new FileReader();
  reader.onloadend = function (evt) {
     alert("read!");
     alert(evt.target.result);
     if (typeof this.result == 'string') {
       $rootScope.profile = JSON.parse(evt.target.result);
     }
     else {
        $rootScope.profile = evt.target.result;
     }
  }
   reader.readAsText(profileFile);
  }, failToReadProfileFile);
}
 
function failToReadProfileFile(error) {
    alert("fail to readprofile file");
}

JavaScript – Stats.js

JavaScipt library that shows the Frame per Second on top of web page. Just copy-paste the following code.

function startStatsJS(){var script=document.createElement('script');script.src='http://github.com/mrdoob/stats.js/raw/master/build/stats.min.js';document.body.appendChild(script);script=document.createElement('script');script.innerHTML='var interval=setInterval(function(){if(typeof Stats==\'function\'){clearInterval(interval);var stats=new Stats();stats.domElement.style.position=\'fixed\';stats.domElement.style.left=\'0px\';stats.domElement.style.top=\'0px\';stats.domElement.style.zIndex=\'10000\';document.body.appendChild(stats.domElement);setInterval(function(){stats.update();},1000/60);}},100);';document.body.appendChild(script);};
 
startStatsJS();