How To Store Adobe AIR Application Preferences Using JavaScript

Share this article

In my previous article I was quite excited about starting my first AIR application, called Harpoon, using only HTML, CSS, and JavaScript. One of the features I ran out of time to discuss was the way you can use an XML file to store and retrieve application preferences.

If you downloaded and installed Harpoon you may have noticed the Preferences panel with the select list.

The Harpoon Preferences panel

Here’s the HTML for that field and its label:

<label>Refresh every (minutes)</label> 
<select id="pref_refresh" name="pref_refresh">
 <option value="1">1</option>
 <option value="2">2</option>
 <option value="3">3</option>
 <option value="4">4</option>
 ...
 <option value="10">10</option>
</select>

If you recall, Harpoon is destined to be an auction watching application for the Flippa site. Eventually this will control how often Flippa is checked for new auctions matching your query. Of course you’d want Harpoon to remember this setting, so we’ll store the selected value in an XML file.

Our task is this:

  • When Harpoon is opened we check to see if the preferences file is available.
  • If unavailable Harpoon should create the file and write the default value.
  • If available Harpoon should read it and set the field value.
  • Whenever the field value is changed Harpoon should write the new value to the preferences file.

This sounds way more complicated than it really is. Let’s dive in so I can show you.

First some adjustments to our Harpoon object. (If you need to prod your memory, take a detour and refer back to my previous article.) We want to store the refresh value, and a couple of other important values within the Harpoon object:

var Harpoon = { 
 ...
 prefsFile : null,
 storePath : null,
 prefs : {
   refresh : 10
 }
}

I’ll address prefsFile and storePath in a moment, but you can also see the prefs object that has one property called refresh. This is where we’ll store the refresh value, and it’ll be accessible within our application from Harpoon.prefs.refresh.

Now we come back to the prefsFile and storePath properties. For security reasons each AIR application is given its own storage directory from which it can read and write files. This is where our preferences file will reside. These two properties will store the path to the application storage directory and the path to the preferences file.

If you remember from the previous article Harpoon has an init function for initialisation, where we placed that call to the setupWindow function. We’ll add a few lines of code to that:

init : function() { 
 Harpoon.setupWindow();
 Harpoon.storePath = air.File.applicationStorageDirectory;
 Harpoon.prefsFile = Harpoon.storePath.resolvePath("prefs.xml");
 Harpoon.getPrefs();
 ...
},

We use the air.File.applicationStorageDirectory to obtain Harpoon’s storage directory. Then we use the resolvePath method to retrieve the path to the preferences file prefs.xml and store it as a File object. The next line, Harpoon.getPrefs(), is a call to a new function we shall write.

The getPrefs function will retrieve the application preferences from the file if it exists, otherwise it will create a new one. The default preferences file will look like this:

<?xml version="1.0" encoding="utf-8"?> 
<preferences>
 <refresh>10</refresh>
</preferences>

Here’s the getPrefs function:

getPrefs : function() { 
 if (Harpoon.prefsFile.exists) {
   ...
 } else {
   ...
 }
},

First we check to see if the preferences file exists, using the conveniently named exists property of the File object we stored back in our init function. If it does exist, then we read the contents using a custom function you’ll see in a moment called readXML — basically it takes a file path and returns an XML document:

  if (Harpoon.prefsFile.exists) { 
   var xml = Harpoon.readXML(Harpoon.prefsFile);

We next find the first refresh element in our XML document using some jQuery selector magic and store its text value as an integer in our Harpoon object:

    Harpoon.prefs.refresh = parseInt($(xml).find('refresh:eq(0)').text());

In jQuery :eq(index) is a selector filter that matches the element by its index. In the above code refresh:eq(0) will match the first refresh element.

The final step in this branch is to set the select field’s value, again using jQuery:

    $('#pref_refresh option[value=' + Harpoon.prefs.refresh + ']').attr("selected","selected");

On the other hand, if there’s no preferences file then we want to create one:

  } else { 
   Harpoon.savePrefs();
 }

The savePrefs function is another one of our custom functions:

savePrefs : function() { 
 var cr = air.File.lineEnding;
 var prefsXML =   '<?xml version="1.0" encoding="utf-8"?>' + cr
     + '<preferences>' + cr  
     + '  <refresh>' + Harpoon.prefs.refresh + "</refresh>" + cr
     + '</preferences>';
 Harpoon.writeXML(Harpoon.prefsFile, prefsXML);
},

It’s a simple function that builds a string representing the XML tags, and saves it to the preferences file using the as yet unseen writeXML function. The current value of Harpoon.prefs.refresh is concatenated into the XML string. You may notice the use of air.File.lineEnding in the above function; it’s a property that represents the platform line-ending character which is different on Mac OS X, Windows, and Linux.

Now to those previously named readXML and writeXML functions. In Adobe AIR, if you want to read and write files in JavaScript you need to use a FileStream object. First, the readXML file creates a new FileStream object and opens the preference file from the File object we pass into it, in read mode. The FileStream is read as a string, stored in the xml variable, and closed:

readXML : function(path) { 
 var stream = new air.FileStream();
 stream.open(path, air.FileMode.READ);
 var xml = stream.readUTFBytes(stream.bytesAvailable);
 stream.close();


Next we use a DOMParser object to convert the string into an XML document and return it:
  var domParser = new DOMParser(); 
 xml = domParser.parseFromString(xml, "text/xml");
 return xml;
},

The writeXML function also uses a FileStream object, but opens it in write mode. This function takes a File object and the XML source string, and writes the string to the file:

writeXML : function(path, xml) {   
 var stream = new air.FileStream();
 stream.open(path, air.FileMode.WRITE);
 stream.writeUTFBytes(xml);
 stream.close();
},

Have we forgotten anything? There’s still one more task. When the user changes the preference value in the interface we want Harpoon to save that preference. All it takes is a simple event listener:

$('#pref_refresh').change(function(){ 
 Harpoon.prefs.refresh = this.options[this.selectedIndex].value;
 Harpoon.savePrefs();
});

The above code binds a function to be executed every time the select list value is changed. The function stores the new preference value and calls the savePrefs function. We add this to the setupWindow function we created in the first article.

And there we have it. Reading and writing preferences to an XML file using JavaScript in an Adobe AIR application: easy! The source code can be downloaded as well as the packaged application. Hopefully this has provided enough code for you to go and implement preferences in your own AIR application.

Andrew TetlawAndrew Tetlaw
View Author

iOS Developer, sometimes web developer and Technical Editor.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week