Category Archives: Air

Detecting Network Connectivity With HTML AIR Apps

19 Feb 2013

Nice thing about my job is how varied it is – this time around I’m jumping into HTML AIR apps and the first thing on the list (actually this is the second, the first thing is setting up the AIR debugger… ) is to be able to detect the presence of the network. Its not too difficult, here we go…

Assumptions

First, I assume that you have Dreamweaver with the AIR extension installed. Next I assume that you know how to create the AIR runtime.

If you want to debug this then you should have the AIR SDK present on your machine – debugging is out of scope of this article but will pen some notes on how to do it at some point.

Setup

What I have done here is written an object that will do the “hard work” for you, its just copy and paste. Before we get to that you must first set up your HTML page with the necessary includes – note the script tags in the following bare-bones example:


  
    Untitled Document
    
    
  
  
  

You will notice that the first SCRIPT tag references AIRAliases.js (available in the “frameworks” folder within the AIR SDK) – this is necessary only if you are using the shortcut reference to AIR specific methods/functions, which I am. Next you will notice the second SCRIPT tag with the reference to “servicemonitor.swf” (also available in the AIR SDK). This second file is an ActionScript library that encapsulates the service monitor framework which is separate from the AIR framework.

Code

Lets now take a look at the bit of code that I’ve written which is where the network detection setup happens:

  var network = (function(){
    var monitor;
    function initNetwork(b,u,l){
      if (air){
        setNetworkDefaults(b);
        startNetMonitor(u,l);
      }
    }
    function startNetMonitor(u,l){
      monitor = new air.URLMonitor(new air.URLRequest(u)); 
      monitor.addEventListener(air.StatusEvent.STATUS,l); 
      monitor.start(); 
    }
    function setNetworkDefaults(b){
      air.URLRequestDefaults.manageCookies = air.URLRequestDefaults.useCache = b;
    }
    function getMonitorStatus(){
      return monitor.available;	
    }
    return{
      initNetwork:initNetwork,
      getMonitorStatus:getMonitorStatus
    }
  })();

This is designed to be left as-is, you configure it via its initNetwork method where you set your own function to be called when the network status changes. The getMonitorStatus method allows you to go get the network status whenever you want.

Lets see how to use them:

network.initNetwork(urlRequestDefaults,URLtoMonitor,CallBackFunc)

As mentioned this inits the monitor, the following table describes the required arguments.

Argument Type Description
URLtoMonitor String This is the URL to monitor. You could set it as ‘http://www.google.com’ if you are simply looking to monitor the network in general, or maybe it makes sense to use a specific URL so that you know if your web services are up or not.
CallBackFunc Function This is your custom callback function which will be called each time the network status changes. A simple boolean is returned.
urlRequestDefaults Boolean The ability to set 2 AIR network defaults to true or false as you wish – this isn’t related to network monitoring, just the network in general. This will set the values for the following two AIR network options:

  • manageCookies
  • useCache

IMO passing false here is a good idea.

An example of initing the network monitor also must involve a load listener so that it is inited after the document has been loaded:

...
window.addEventListener('load',
  function(){
    network.initNetwork(false,'http://www.cnn.com',myCallback);
  }, false
);
...

network.getMonitorStatus()

You can call this at any point to get the current network status. A little redundant yet maybe useful to some. This will return a boolean.

Lastly, if the variable “network” is reserved by your particular application then feel free to change it.

To test your code run your AIR app and make sure that it is either printing out something to the ADL console orprinting something to the screen that tells you the status of the network. Maybe something like this:

...
window.addEventListener('load',
  function(){
    network.initNetwork(false,'http://www.cnn.com',myCallback);
  }, false
);
...
function myCallBack(bool){
  var el = document.getElementsByTagName('body');
  el[0].innerHTML = bool ? 'Network is present' : 'Network is disconnected';
}
...

Now, assuming you have all the other code in place and are looking at your AIR app on your desktop, simply enable/disable your network by unplugging your Ethernet or disabling WiFi. Give it a few seconds and you will see your app telling you your network status.

Debugging AIR Apps with ADL & the AIR Introspector

12 Jan 2013

One of the very first things you will do when setting up your environment for developing AIR apps is learning to debug via the ADL – the Air Debug Launcher. This gives you rudimentary console logging within the command prompt and is a bridge to using the Flex debug tools (which I won’t cover). Beyond this is the ADL’s companion – the Air Introspector. The Introspector does some really cool things analagous to what WEINRE/Chrome does for html-based mobile app development. I’ll be talking about setting up the ADL and then will jump into the Introspector.

Learning the ADL is necessary as the Introspector will not function without it.

The AIR SDK can be downloaded from here:

Click to download the AIR SDK.

ADL – AIR Debug Launcher

Debugging works by invoking the ADL via the Command Prompt and passing your AIR application’s application.xml to it so that it knows what to launch. At that point the ADL launches your AIR app. You can log statements to the the Command Prompt via trace statements:

...
air.trace('Hello World');
...

Anything that you want to see in the Command Prompt will need to be printed to it via the above trace statement. Note that the “air” prefix is shorthand and will only work if your HTML-based AIR App contains a reference to AIRAliases.js:

...

...

AIRAliases.js comes as part of the AIR SDK (located in the “frameworks/libs/air/” directory) which you should already have in order to run the ADL.

Once you have the SDK and assuming that you know how to create AIR packages the first thing you will do is add an environment variable that points to the install of the ADL so that you can invoke it from the Command Prompt when needed.

To access your Environment Variables dialog box:

  1. Right-click your “Computer” icon on your desktop
  2. Select “Properties”
  3. Select “Advanced System Settings”
  4. Select “Environment Variables”

Next scroll down in the System Variables pane until you see the “Path” variable. Select it and then click the “Edit” button.

At the end of the “Variable value” field you will want to paste/type in the path to the bin folder within your AIR SDK folder. For the sake of convenience whenever I download SDK’s I always keep them in the root of one of my hard drives so as to keep the path really short. Also, don’t use spaces in your folder names!!! Ok, so the path to my AIR SDK bin in this example is: E:\AdobeAIRSDK\bin – your path will obviously be different.

Knowing the path to your own AIR SDK bin you will add it to the end of the pre-existing “Variable value” taking care to precede it with a semi-colon, as can be seen below:

Once you’ve entered the correct path click “Ok” and close the rest of the windows.

Now lets assume that you have an AIR project in Dreamweaver to creatte the AIR file go to “Site > Create AIR file…” or hot the CTRL+SHIFT+B key combo.

Next you’ll want to launch the Command Prompt. In Windows:

  • Click “Start”
  • In the “Start Search” field type “cmd”, then hit “enter” on your keyboard
  • The command prompt will appear

Navigate via the prompt to the root of your project. If you don’t know how to do this then do a quick google search to learn how; try searching for “Windows Command Prompt commands” – you’ll make heavy use of the cd command.

TIP You may have a really long path to your project root – if so, simply keep the complete command and path in a text file. Then when needed copy the entire string and right-click the insertion point in your command prompt and choose “paste”.

Once you are in the root of your project type the following:

ADL application.xml

Your AIR App will now launch – DO NOT close the command prompt, you’ll need it as whatever you’ve traced inside your app will appear within the prompt. Basic debugging, yes, and sadly sans line numbers however the AIR HTML Introspector is another thing entirely….

AIR HTML Inspector

This is where the really cool stuff comes in to play, following is a list of what you can do via the Introspector (verbatim from Adobe’s site):

  • It includes an introspector tool that allows you to point
    to a user interface element in the application and see its markup
    and DOM properties.
  • It includes a console for sending objects references for
    introspection, and you can adjust property values and execute JavaScript
    code. You can also serialize objects to the console, which limits
    you from editing the data. You can also copy and save text from
    the console.
  • It includes a tree view for DOM properties and functions.
  • It lets you edit the attributes and text nodes for DOM elements.
  • It lists links, CSS styles, images, and JavaScript files loaded in your application.
  • It lets you view to the initial HTML source and the current markup source for the user interface.
  • It lets you access files in the application directory. (This feature is
    only available for the AIR HTML Introspector console opened for
    application sandbox. Not available for the consoles open for non-application
    sandbox content.)
  • It includes a viewer for XMLHttpRequest objects and their properties, including responseText and responseXML properties
    (when available).
  • You can search for matching text in the source code and files.

Cool stuff, eh? Ok, lets walk through the set up.

Adding the Introspector to your project

First you must add the AIRIntrospector.js file to your page. That file is located in the “frameworks/libs/air/” directory within your AIR SDK folder.

An example of adding it to your page:

...

...
NOTE Don’t forget to remove the AIRIntrospector.js from your production code!

Displaying the Introspector

Run the ADL as you normally would. The Introspector can be revealed by hitting F12. It will also launch automatically whenever you call any one of the 5 Console methods, accessible via air.Introspector.Console, which are:

  • log()
  • warn()
  • info()
  • error()
  • dump()

If you want the Introspector to appear every time you debug the app you can do so by calling one of the above within your app. For example, if I wanted to I could call air.Introspector.Console.log(‘loaded’) within my body load listener.

As in regular HTML development with Chrome you can send an object to the Introspector console and inspect its properties by expanding a tree representation of the object.

As well, once the Inspector has launched you have access to your project’s DOM, assets, Source, XHR, etc – essentially everything you need in modern web development.

Here’s a peek at the Introspector:

One really needs to actually build something to demonstrate the Introspector properly, so…. I’ll do just that. I’ll build a small app that incorporates an AJAX call to a server, retrieves the JSON payload and updates the display. I will also add in my network detection code which you can read more about here.

AIR HTML Introspector Demo

An aspect of AIR worth pointing out is that it severely limits network communication. Attempting to load external scripts will not work – you have to package all of your scripts within the root of your AIR Project. The one thing that Adobe has seen fit to allow though is the XMLHttpRequest() method which allows us to query servers and receive responses.

Here’s my XMLHttpRequest:

...
function getData(){
  xmlhttp = new XMLHttpRequest(); 
  xmlhttp.open("GET", "http://127.0.0.1/data.json", true); 
  xmlhttp.onreadystatechange = function(){
  if (air){
    air.trace('state changed: ' + xmlhttp.readyState);
    air.Introspector.Console.log('state changed: ' + xmlhttp.readyState);
  }
  if (xmlhttp.readyState == 4) { 
      //do something with data... 
      if (air){
        air.trace(xmlhttp.responseText);
        air.Introspector.Console.log(xmlhttp.responseText);
      } else {
        console.log(xmlhttp.responseText);
      }
      var theData = JSON.parse(xmlhttp.responseText);
      if(air){
        air.trace(theData);
        air.Introspector.Console.log(theData);
      } else {
        console.log(theData);	
      }
      popDiv();
    }
  }
  xmlhttp.onerror = function(e){
    if(air){
      air.trace('some sort of error happened: ' + e);
    } else {
      console.log('some sort of error happened: ' + e);
    }
  }
  xmlhttp.send(null);
}

function popDiv(theData){
  var str =  '

' + theData.name + '

'; for (var i=0;i'; } str += '
' + theData.stats[i].value + '
'; document.getElementById('output').innerHTML = str; } ...

You can see that I’ve included some logging merely for demonstration. Also, you can see that I’m checking for the existence of the AIR framework – thats because I tested this thing in Chrome before trying it in AIR and Chrome would throw errors because AIR doesn’t exist outside of the AIR runtime. So, console.log() is for regular desktop use while air.whatever is for AIR (of course).

Ok, lets run the app and look at all the Introspector features.

Here’s the JSON file:

{"name":"eric","stats":[
  {"name":"hair","value":"short"},
  {"name":"eyes","value":"2"},
  {"name":"height","value":"6ft"}]
}

Here’s my sample AIR Application – you can see that the JSON data has been printed to the screen:

Here’s the Introspector’s console:

Note the logging statements and how the the JSON payload is treated as an object whose tree can be inspected.

Here’s the XHR tab:

Here’s a peek at the HTML tab – note how I can inpsect the DOM and that there is DOM hilighting:

The DOM tab:

Lastly, a peek at the Command Prompt while all of this has been going on, note the difference between the Inspector output and what appears here: