For desktop applications, you often need the ability to detect the status of network connectivity and monitor its changes. Some applications require a constant Internet connection, while others, called occasionally connected applications, can work offline as well as online by caching the offline content. Adobe AIR can detect network connectivity changes, thereby enabling you to plan the behavior of the application based on its status.
You want to use the service monitor framework with JavaScript to detect the status of network connectivity.
Import the service monitor framework into the AIR application.
The service monitor framework is a separate framework from the standard AIR framework. To be able to use the service monitor framework, you need to import the servicemonitor.swf file into your HTML and JavaScript application. You can find this file in the AIR SDK’s frameworks folder. Copy servicemonitor.swf into the directory of your AIR project.
To import the file, use the script
tag. The tag’s type
attribute specifies the scripting
language of the element’s contents and overrides the default scripting
language. Set the type
attribute to
the application/x-shockwave-flash
value, as shown here:
<script type="application/x-shockwave-flash" src="frameworks/servicemonitor.swf"></script>
In the previous line of code, the servicemonitor.swf file resides in the frameworks folder of the AIR project root. The following is a simple example of a complete HTML page that contains this import:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="application/x-shockwave-flash" src="frameworks/servicemonitor.swf"></script> </head> <body></body> </html>
Now the AIR application is ready to use the service monitor framework to monitor the status of network connectivity.
It is also good practice to import the AIRAliases.js file from the frameworks folder of the AIR SDK into the
project directory of any AIR applications developed with HTML and
JavaScript. Once you’ve imported it into the HTML page, you can access
the AIR APIs without using the fully qualified package name of the
class, saving you some typing. In fact, the AIRAliases.js file includes aliases for
commonly used package-level functions. If you open the AIRAliases.js file, you will find the
definitions of the aliases for all the AIR APIs. For example, for the
File
class, you’ll find the following
definitions:
air.File = window.runtime.flash.filesystem.File; air.FileStream = window.runtime.flash.filesystem.FileStream; air.FileMode = window.runtime.flash.filesystem.FileMode;
Therefore, instead of accessing the File
class by going through the runtime
property on the HTML window
object, like so:
var myFile = new runtime.flash.filesystem.File("app:/myFile.txt");
these aliases allow you to access the File
class with the shortest syntax that
doesn’t use the fully qualified package name, like so:
var myFile = new air.File("app:/myFile.txt");
The app:/
prefix refers to the
application directory of the application and is an alternative to using
the static
property on the File
class.
AIR defines the runtime
property on the HTML window
object;
runtime
provides access to the AIR
classes using the fully qualified package name of the class.
You can import AIRAliases.js
into the HTML page using the script
tag:
<script type="text/javascript" src="frameworks/AIRAliases.js"> </script>
The HTML page, complete with the importation of the service monitor framework and AIR aliases, therefore becomes the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="application/x-shockwave-flash" src="frameworks/servicemonitor.swf"></script> <script type="text/javascript" src="frameworks/AIRAliases.js"> </script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>AIR Cookbook: Including the Service Monitor Framework in an Application (JavaScript)</title> </head> <body> </body> </html>
Two objects let you check the network connection status:
the networkChangeEvent
event and
the ServiceMonitor
class.
The networkChangeEvent
event is one of the events of the NativeApplication
class, which is a
singleton object that dispatches application-level events.
A singleton object is a design pattern that is used to restrict the instantiation of a class to one object. It is useful when exactly one object is needed to coordinate actions across the system.
The AIR application dispatches the networkChangeEvent
event when a new network
connection becomes available or an existing network connection is
lost. This event informs you only that the status of the connection
has changed; it does not provide information about the cause. With all
the different types of connections available nowadays (Internet, VPN,
wireless connection, UMTS, and so on), the networkChangeEvent
event is limited in its
scope. It is almost impossible to be sure that you have access to a
certain resource by using this event only.
This is where the service monitor framework, based on the
ServiceMonitor
class, comes into play. You can use the ServiceMonitor
class to control and monitor
whether the AIR application can actually reach a specific
service.
AIR’s service monitor framework provides the classes and methods to execute controls on the status of network connectivity.
The ServiceMonitor
class is a dynamic class that acts as a base class for all
the other service monitor objects; it resides in the air.net
package and dispatches the following
events related to network connectivity:
activate
(an inherited event from the EventDispatcher
class): This event is
dispatched when the AIR application gains operating system focus
and becomes active.
deactivate
(an inherited event from the EventDispatcher
class): This event is
dispatched when the AIR application loses operating system focus
and is becoming inactive.
status
: This event is dispatched when the service status
has changed.
This class is a base class for another two subclasses: URLMonitor
and SocketMonitor
. These are the two classes,
with their related methods, that you will use most of the time to
detect the status of the service.
The URLMonitor
class, which is part of the air.net
package, controls the availability
of HTTP (or HTTPS) services, such as Representational State Transfer
(REST) services.
REST describes an interface that transmits domain-specific data over HTTP without using an additional messaging layer such as SOAP (which is used by web services).
The SocketMonitor
class, on the other hand, controls the availability of the
connection against a TCP socket, such as a mail or FTP server.
You want to use the service monitor framework with Adobe Flash to detect the status of network connectivity.
Import the ServiceMonitorShim
library to detect the status of network connectivity.
The service monitor framework is a separate framework from the
standard AIR framework. To use the ServiceMonitor
classes, you have to import the
ServiceMonitorShim.swc file into
your AIR application first. The ServiceMonitorShim
component is installed in
the environment of Adobe Flash
CS4 Professional when you install the Adobe AIR update for the
software. With the Adobe AIR update installed, Adobe Flash CS4 Professional adds
the necessary features to develop, compile, and distribute Adobe AIR
applications with Flash. You can download the Adobe AIR update for Adobe
Flash CS4 Professional
in the Downloads section of the Adobe Flash Support Center (http://www.adobe.com/support/flash/downloads.html).
Before installing the Adobe AIR update, you need to have installed the Adobe Flash Player update for Flash CS3 Professional (9.0.2). You can find this update to download in the same Downloads section.
Launch Flash CS4 Professional, and then choose Window→Components
Panel to open the Components panel. Alternatively, you can press Ctrl+F7
(Windows) or Command+7 (Mac OS). You will notice a new category among
the standard list of Flash components: AIR Service Monitor. Expand this
category to find the ServiceMonitorShim
component. To use the service monitor framework, you only have to
drag this component from the Components panel into the Library. If you
prefer, you can drag it directly on the Stage outside the visible area,
and it will automatically be added to the Library (Figure 15-1).
With the ServiceMonitorShim
component in your Flash project’s Library, you can use the classes in
the air.net
package in Flash to add
the import
statement to your
ActionScript 3 code:
import air.net.*;
For example, now you can to monitor the connection to a URL using
the URLMonitor
class (see Monitoring the Connection to a URL), which is one of the
classes in the air.net
package:
import air.net.URLMonitor;
Use the URLMonitor
class to get the status of and monitor changes on the HTTP (or
HTTPS) requests that can be made to a certain address.
To be sure that a remote service can be reached, you can call that
service to determine the status. The class you need for the job is
URLMonitor
, which is a subclass of
ServiceMonitor
.
The constructor of the class accepts two parameters: urlRequest
, which is an instance of the
URLRequest
class that specifies the
service or the URL to call, and acceptableStatusCodes
, which is typed as an
Array
and specifies the numeric
status codes of the result. The acceptableStatusCodes
parameter isn’t
compulsory, and if it isn’t specified, the following values will be
recognized as status codes:
200 (OK)
202 (Accepted)
204 (No content
205 (Reset content)
206 (Partial content in response to request with a Range
header)
To create a URLMonitor
object
that determines the status of an HTTP (or HTTPS) service, it is
sufficient to pass its constructor a URLRequest
object with the URL to connect to.
In ActionScript, you have to import the class from the air.net
package and write the
following:
import air.net.URLMonitor; private var urlRequest : URLRequest = new URLRequest( "http://www.comtaste.com" ); private var HTTPMonitor : URLMonitor = new URLMonitor( urlRequest );
With JavaScript, you have to import the servicemonitor.swf file to use the service monitor framework (see Including the Service Monitor Framework in an Application (JavaScript)) and then write the following:
<script src="servicemonitor.swf" type="application/x-shockwave-flash"> </script> <script type="text/javascript"> function init() { var urlRequest = new air.URLRequest( "http://www.comtaste.com" ); var httpMonitor = new air.URLMonitor(urlRequest); } </script>
In both cases, this code specifies only the HTTP (or HTTPS)
service to which the call must be directed to test its availability. No
test is carried out until the start
method of the URLMonitor
class has
been executed. You can also create an event listener for the StatusEvent.STATUS
event and intercept the
code
property in the event
object. The code property of the
STATUS
event contains the description
of the object’s status:
httpMonitor .addEventListener( StatusEvent.STATUS, onStatusEvent ); httpMonitor .start();
Once the start
method has
launched the URLMonitor
instance,
this object keeps monitoring every change in the network. You can set
the pollInterval
property of the
ServiceMonitor
to check connectivity
at a specified interval in milliseconds.
When this change happens, you can also use the URLMonitor.available
property, which returns
true
or false
according to the availability of the
network. The initial value is false
until something changes in the network activity that sets the property
to true
:
httpMonitor.available
You can create an ActionScript class that verifies the
availability of an HTTP service and keeps monitoring changes in the
network. The following code creates a class named CheckURL
and saves it in the com.oreilly.aircookbook.ch15
package:
package com.oreilly.aircookbook.ch15 { import air.net.URLMonitor; import flash.events.StatusEvent; import flash.net.URLRequest; import mx.controls.Alert; public class CheckURL { private var urlMonitor:URLMonitor; private var _isConnected : String; public function CheckURL(urlRequest:URLRequest, acceptableStatusCodes:Array=null) { urlMonitor = new URLMonitor(urlRequest); urlMonitor.start(); urlMonitor.addEventListener( StatusEvent.STATUS, onStatusEvent ); } private function onStatusEvent( event:StatusEvent ) : void { // it returns a Boolean isConnected = urlMonitor.available.toString(); // it returns Service.available // isConnected = event.code; // If you're using the Flex SDK Alert.show( isConnected ); // If you're using the Flash IDE trace( isConnected ); } public function get isConnected():String { return _isConnected; } [Bindable] public function set isConnected(_isConnected:String):void { this._isConnected = _isConnected; } } }
In the previous example, you declared the private property
_isConnected
in the class, and you
specified the setter/getter methods for it. This is the property that
will contain the status of network connectivity.
In the constructor class in the previous code, you created an
instance of the URLMonitor
class, which has
the urlRequest
and acceptableStatusCodes
parameters set. The
URLMonitor
instance uses these two
parameters, of which only the first is compulsory, to carry out the
tests on the HTTP (or HTTPS) service. To launch the checking process,
you executed the start
method and
created an event listener for the StatusEvent.STATUS
event,
which is registered in the onStatusEvent
event handler.
The onStatusEvent
event
handler sets the isConnected
property to the value contained in the urlMonitor.available
property. This event
handler is invoked every time the StatusEvent.STATUS
event is triggered or
every time the network connectivity changes.
If you re-create the example using the Adobe Flash IDE, remember
to insert the ServiceMonitorShim
component in the Library (see Monitoring the Connection to a URL). If, on the other
hand, you are using Flex Builder, the service monitor framework is
automatically added as a library to the Flex project.
Furthermore, make sure the StatusEvent.STATUS
event is dispatched even
if, for example, only the access to the new connection is made.
In JavaScript, using the URLMonitor
class is only slightly different.
You first have to import servicemonitor.swf into the page (see Including the Service Monitor Framework in an Application
(Flash)).
The following example creates an AIR application that uses the
URLMonitor
class to verify that the
image at http://www.comtaste.com/img/logoComtaste.gif is
reachable. If the available
property returns as true
and
therefore the service can be reached, you will load the remote image
in a div
placeholder and load the
entire http://www.comtaste.com home page in the
application. Here is the complete code for this example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <!-- Include service monitor framework --> <script src="frameworks/servicemonitor.swf" type="application/x-shockwave- flash"></script> <script type="text/javascript" src="frameworks/AIRAliases.js"></script> <script type="text/javascript" src="frameworks/AIRIntrospector.js"></script> <script type="text/javascript"> var HTTPMonitor = null; function checkConn() { var req = new air.URLRequest("http://blog.comtaste.com/atom.xml"); HTTPMonitor = new air.URLMonitor( req ); HTTPMonitor.addEventListener(air.StatusEvent.STATUS, announceStatus); HTTPMonitor.start(); } function announceStatus(e) { if (HTTPMonitor.available) { document.getElementById("resultDiv").innerText = HTTPMonitor.available; loadImage(); } else { document.getElementById("resultDiv").innerText = "Can't connect to the URL. The connection is unavailable"; } } function loadImage() { myImg = document.createElement('img'), myImg.src = "http://www.comtaste.com/img/logoComtaste.gif" document.getElementById("placeholder").appendChild(myImg); document.getElementById("htmlFrame").src = "http://www.comtaste.com/"; document.getElementById("htmlFrame").onload = sizeFrame; } function sizeFrame(evt) { document.getElementById("resultDiv").innerText = "The url: " +evt.currentTarget.src + " has been loaded !"; } </script> <meta http-equiv="Content-Type" content="text/html" /> <title>AIR Cookbook: Including the Service Monitor Framework in an Application (JavaScript)</title> </head> <body onload="checkConn()"> <div id="resultDiv">Checking .... </div> <div id="placeholder" > </div> <iframe id="htmlFrame" frameborder="0" width="600" height="450"/> </body> </html>
The JavaScript example invokes the checkConn
method when the application starts
up upon the onload
event of the
body
. The checkConn
method creates the instance of the
URLMonitor
class and verifies
whether the image at http://www.comtaste.com/img/logoComtaste.gif is
reachable. An event listener is created for the STATUS
event and registered to the announceStatus
event handler. Finally, the
HTTPMonitor
object is executed by
launching the start
method.
The result of the HTTP (or HTTPS) service is returned by the
URLMonitor.available
property when
the STATUS
event is triggered. The
announceStatus
event handler tells
the application to invoke the loadImage
function or to alert the user with
an error message.
The error message is written in the div
element of the application with an
ID
equal to resultDiv
. By using the getElementById
method, you point to this
node of the document, and by using the innerText
property, you write the following
error message: “Can’t connect to the URL. The connection is
unavailable.”
If, on the other hand, the available
property returns true
, a call to the loadImage
function is invoked. This function
loads the remote image in an img
dynamically created and loads the http://www.comtaste.com home page into an iframe
tag.
Use method
, which is a public
property of the URLRequest
class
(part of the flash.net
package), to
check only the HTTP header for an HTTP service.
Sometimes you may have to manage several instances of the URLMonitor
or SocketMonitor
class to test
whether the application can access different services. A good rule to
follow is to test and verify the availability of a network service
before using it. You must be careful, however, to use the connection
tests wisely so as to not waste bandwidth. By taking advantage of the
method
property of the URLRequest
object, you can optimize the data
requests to the server.
Monitoring the Connection to a URL used the URLMonitor
class to check the availability of an HTTP service. This class accepts
two parameters to pass to the constructor: a URLRequest
object and an Array
:
URLMonitor(urlRequest:URLRequest, acceptableStatusCodes:Array = null)
In the first parameter, you specify a URL, creating an instance
of the URLRequest
class:
var checkConn:URLMonitor; checkConn = new URLMonitor(new URLRequest('http://www.comtaste.com/index.php'));
With this code, the URLMonitor
object checks the availability of
the access to the index.php page on the
http://comtaste.com domain, downloading the
entire contents of the PHP page. For an application that has to verify
more than one HTTP service, the operation could be
bandwidth-intensive.
As an alternative, you can specify the method
property of the URLRequest
object to the URLMonitor
object so that it downloads only
the HTTP header information. This check is, in fact, sufficient to
check the connection to that service.
Before passing the entire URL to check onto the constructor of
the URLMonitor
class, create a data
type variable as URLRequest
, and
set the method value to the public constants available in the URLRequestMethod
class:
var urlCheck:URLRequest = new URLRequest("http://www.comtaste.com/index.php"); urlCheck.method = URLRequestMethod.HEAD; var checkConn:URLMonitor = new URLMonitor(urlCheck);
The URLRequestMethod
class, when used in web applications in Flash Player,
provides values that specify whether the URLRequest
object should use the POST
method or the GET
method. This class, however, also shows
the public static constant HEAD
.
HTTP headers contain all the information of an HTTP request and are very important in an HTTP response. This is an example of an HTTP response header for the http://www.comtaste.com URL request:
HTTP Status Code: HTTP/1.1 200 OK |
Server: Microsoft-IIS/5.0 |
Date: Sat, 07 Jun 2008 13:15:21 GMT |
X-Powered-By: ASP.NET |
Connection: close |
X-Powered-By: PHP/5.1.6 |
Content-type: text/html |
You can find the URLRequest
class in the air.URLRequest
package, and you can access
it with the following:
request.method = air.URLRequestMethod.HEAD;
Otherwise, using the method
property of the URLRequest
property
is similar to the ActionScript approach.
Here’s the complete example that uses the static HEAD
constant:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="application/x-shockwave-flash" src="frameworks/servicemonitor.swf"></script> <script type="text/javascript" src="frameworks/AIRAliases.js"></script> <script type="text/javascript"> var checkURL = null; function init() { var request = new air.URLRequest( 'http://www.comtaste.com/' ); request.method = air.URLRequestMethod.HEAD; checkURL = new air.URLMonitor( request ); checkURL.addEventListener(air.StatusEvent.STATUS, announceStatus); checkURL.start(); } function announceStatus(e) { if (HTTPMonitor.available) { document.getElementById("resultDiv").innerText = HTTPMonitor.available; } else { document.getElementById("resultDiv").innerText = "Can't connect to the url. The connection is unavailable"; } } </script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>AIR Cookbook:Reading only the HEAD of a URL (JavaScript)</title> </head> <body onload='init()'> <div id="resultDiv">Checking .... </div> </body> </html>
The init
function is called
upon the onload
event of the
application body
. In this function,
a URLRequest
object is created, and
its method
property is set to the
static constant air.URLRequestMethod.HEAD
.
Use SocketMonitor
, which is a
subclass of the ServiceMonitor
class,
to check and monitor the connections to a specific port on a
server.
Checking that you have the necessary authorizations to connect to a specific port on a server is crucial because firewalls or default network routers often restrict access to ports to guarantee network safety. That authorization is especially important for desktop applications that need to connect to a specific port of a server. For example, an application might have to send an email using the Simple Mail Transfer Protocol (SMTP), which initiates a TCP connection to the server’s port 25.
Adobe AIR supports the SocketMonitor
class in the service monitor framework, which allows the
developer to check and monitor a specified TCP endpoint. This class is
similar to the URLMonitor
class (see
Reading Only the Head of a URL), and its constructor
has the following syntax:
SocketMonitor(host:String, port:int)
Set as type String
, the
host
parameter specifies the host
being monitored. The value assigned to host
can be a domain name (such as http://www.comtaste.com) or an IP address
(194.242.61.188). Set as type int
,
the port
parameter specifies the port
being monitored.
This example establishes a connection to a specific
port. To check, monitor, and establish a connection to a specific
port, create an instance of the SocketMonitor
class, and specify the port to
detect in the second parameter:
import air.net.SocketMonitor; private var monitor:SocketMonitor; private var conn:Socket; private var isConnected:String; public function checkPort(); void { // Create the istance of the Socket class conn = new Socket(); // Create the istance of the SocketMonitor class // to monitor port 25 on localhost server monitor = new SocketMonitor( " www.comtaste.com", 25 ); conn.addEventListener(Event.CONNECT, onConnect); monitor.addEventListener(StatusEvent.STATUS, onSocketStatus); // To start the SocketMonitor class monitor.start(); }
If you are using the Adobe Flash IDE to create an AIR application, you need to import the ServiceMonitorShim.swc file into the Library of the Flash project in your AIR application package (see Including the Service Monitor Framework in an Application (Flash)).
The checkPort
method checks
the availability of the connection to the http://www.comtaste.com site over port 25, and if the
connection has been successful, it connects to the server.
Then create two event listeners on the events of Event.CONNECT
for the Socket
class and on the events of StatusEvent.STATUS
for the SocketMonitor
class. In the event handler of
the STATUS
event, the available
property is checked, and it
returns a Boolean according to the result obtained by the connection
test:
private function onConnect(event:Event):void { trace( "Connection to port 25 established !" ); // You are now ready to send and receive data } private function onSocketStatus(e:StatusEvent):void { // it returns a Boolean isConnected = monitor.available.toString(); // it returns Service.available // isConnected = event.code; if (monitor.available) { conn.connect("www.comtaste.com", 25 ); } else { // If you're using the Flex SDK //Alert.show( "Connection to port 25 NOT established !" ); // If you're using the Flash IDE trace( "Connection to port 25 NOT established !" ); } }
In JavaScript, the operations to check and monitor the
connection against a specific port are similar to those for
ActionScript. The class you use is the same: the SocketMonitor
that can be instanced only
after having imported the service monitor framework.
To import the service framework, you need to import the
servicemonitor.swf file with a
script
tag in the page:
<!-- Include service monitor framework --> <script src="frameworks/servicemonitor.swf" type="application/x-shockwave-flash" />
The example uses this component and its methods to detect connectivity changes to a URL connection on port 25:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <!-- Include service monitor framework --> <script src="frameworks/servicemonitor.swf" type="application/x-shockwave- flash"></script> <script type="text/javascript" src="frameworks/AIRAliases.js"></script> <script type="text/javascript" src="frameworks/AIRIntrospector.js"></script> <script type="text/javascript"> var checkSocket = null; var host = 'www.comtaste.com'; var port = 25; function checkConn() { checkSocket = new air.SocketMonitor( host, port ); checkSocket.addEventListener(air.StatusEvent.STATUS, announceStatus); checkSocket.start(); } function announceStatus(e) { if (checkSocket.available) { document.getElementById("resultDiv").innerText = checkSocket.available; } else { document.getElementById("resultDiv").innerText = "Can't connect to port 25. The connection is unavailable"; } } </script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>AIR Cookbook: Monitoring the Connection to a Specific Port on a Server (JavaScript)</title> </head> <body onload="checkConn()"> <div id="resultDiv">Checking .... </div> </body> </html>
The SocketMonitor
class
accepts two parameters in the constructor: host
and port
. These two parameters are declared in
the global variables in the script
block and then used in the checkConn
function and invoked on the
onload
event of the body
.
In addition to monitoring the connection to a server, AIR
gives JavaScript developers the ability to communicate with a server
on a specific port with the Socket
and
XMLSocket
classes.