Detecting network connectivity
Back to: Apollo Documentation home page
Your Apollo application can run in environments with uncertain and changing network connectivity. To help an application manage connections to online resources, Apollo sends a network change event whenever a network connection becomes available or unavailable.
Apollo does not attempt to interpret the meaning of the network change. In general, the only way for an application to determine whether it can connect to a remote resource is to try it. A networked computer may have many real and virtual connections, so losing a connection does not necessarily mean losing a resource. On the other hand, new connections do not guarantee improved resource availability, either. Sometimes a new connection can even block access to resources previously available (for example, when connecting to a VPN).
A common strategy used by applications that have online and offline modes is to poll their online resources to determine availability. The Apollo network change event can be used to make a polling strategy more responsive to local connectivity changes. In addition to polling its resources on a regular interval, an Apollo application can check its resources whenever the network change event is dispatched.
The network change event is dispatched by the application’s flash.system.Shell object. To react to this event, add a listener:
Shell.shell.addEventListener(Event.NETWORK_CHANGE, onNetworkChange);
And define an event handler function:
function onNetworkChange(event:Event){
//Check resource availability
}
(Since Shell is a singleton object, you do not need to create an instance of Shell before using it).
Note, when interacting with remote resources, there is no substitute for the expectation of failure. All program operations that involve remote resources should expect and handle failure.
Checking Resource Availability
Once a network change event has occurred, the next step is to determine whether a remote resource is still available.
If you are in the fortunate position of having control of the API of a resource (such as a web service), then you can add a simple interrogate-response API to the server that allows your application to check availability while consuming the least possible bandwidth. This will tell you that not only that the resource reachable, but also its status. On the other hand, if you do not control the resource (perhaps it is an existing service that cannot be changed, or controlled by another organization), then you may only be able to determine whether the resource is reachable, not whether it is responding properly (at least not without incurring the full cost of a normal transaction).
To check the availability of resources accessed through the HTTP protocol, you can use an HTTP GET or HEAD request. In a HEAD request, only the request headers are returned, so the bandwidth consumed by the transaction is minimized. However, in many cases the destination server must still fully process the request in order to populate the response headers, so the optimization may be a small one.
To make a HEAD request, you load a resource as normal, but instead of using the GET method, you set the request method to HEAD. You can use the URLRequest and URLLoader classes in a SWF-based application, or an XMLHttpRequest in an HTML-based application. The following example shows how to make a HEAD request in ActionScript:
var headRequest:URLRequest = new URLRequest();
headRequest.method = "HEAD";
headRequest.url = resourceURL.text;
var response:URLLoader = new URLLoader(headRequest);
In a SWF-based application, you examine the response headers as well as listen for the complete, HTTP status and IO error events to determine whether the resource is reachable. In an HTML-based application, you can use an XMLHttpRequest to access the response headers. See the SWF-based or HTML-based network detection examples for more details.
SWF-based network detection example
This example demonstrates techniques for detecting changes in network connection and resource availability. The program listens for the NETWORK_CHANGE event. When an event is received, the program initiates a HEAD request using the URLLoader class and reports the status and whether a result was received.
<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
applicationComplete="init()" title="Network Change Event Log">
<mx:Script>
<![CDATA[
import flash.events.NetStatusEvent;
import flash.system.Shell;
import flash.net.URLRequest;
public function init():void{
Shell.shell.addEventListener(Event.NETWORK_CHANGE,onNetworkChange);
}
public function onNetworkChange(networkChangeEvent:Event):void{
var now:String = new Date().toTimeString();
logEvent("Network change event at: " + now);
ping();
}
public function ping():void{
var headRequest:URLRequest = new URLRequest();
headRequest.method = "HEAD";
headRequest.url = resourceURL.text;
logEvent("Requesting: " + headRequest.url.toString());
var response:URLLoader = new URLLoader(headRequest);
response.addEventListener(HTTPStatusEvent.HTTP_STATUS,onHTTPStatus);
response.addEventListener(Event.COMPLETE,onComplete);
response.addEventListener(IOErrorEvent.IO_ERROR,onError);
response.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);
}
public function onComplete(status:Event):void{
logEvent(" Response received.");
}
public function onHTTPStatus(status:HTTPStatusEvent):void{
logEvent(" Status: " + status.status);
}
public function onError(error:IOErrorEvent):void{
logEvent(" Request failed. " + error.text);
}
public function onSecurityError(error:SecurityErrorEvent):void{
logEvent(" Request failed. " + error.text);
}
public function logEvent(entry:String):void {
log.text += entry + "\n";
trace(entry);
}
]]>
</mx:Script>
<mx:HBox width="100%">
<mx:Button label="Ping" id="pingButton" click="ping();" width="30%"/>
<mx:TextInput id="resourceURL" text="http://www.adobe.com" width="70%"/>
</mx:HBox>
<mx:TextArea id="log" width="100%" height="100%" editable="false"
valueCommit="log.verticalScrollPosition=log.textHeight;"/>
</mx:ApolloApplication>
HTML-based network detection example
This example demonstrates techniques for detecting changes in network connection and resource availability. The program listens for the NETWORK_CHANGE event. When an event is received, the program initiates a HEAD request using an XMLHttpRequest and reports the status and response headers.
<html>
<head>
<title>Network Change Event Log</title>
<script type="text/javascript"><!--
function appLoad(){
if(window.runtime){
runtime.trace("Network Detection Log.");
runtime.flash.system.Shell.shell.addEventListener
(runtime.flash.events.Event.NETWORK_CHANGE,onNetworkChange);
}
}
function onNetworkChange(event){
logEvent("Network change event received.");
ping();
}
function ping(){
var timeoutInterval = 2000;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("HEAD", document.getElementById('resourceURL').value,true);
xmlhttp.setRequestHeader('Cache-Control','no-cache');
xmlhttp.setRequestHeader('Cache-Control','max-age=0');
xmlhttp.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" );
logEvent("Checking resource: " + document.getElementById('resourceURL').value);
var timeout = setTimeout(function(){
xmlhttp.abort();
reportTimeout();
}
,timeoutInterval);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
clearTimeout(timeout);
logEvent("Status: " + xmlhttp.status);
parseHeaders(xmlhttp.getAllResponseHeaders());
}
}
xmlhttp.send(null);
}
function parseHeaders(responseHeaders){
if(responseHeaders) {
var headerLines = responseHeaders.split("\n");
for( var line in headerLines){
logEvent(headerLines[line]);
}
}
}
function reportTimeout(){
logEvent("Request timed out.");
}
function logEvent(message){
var logger = document.getElementById('log');
var line = document.createElement('p');
line.innerHTML = message;
logger.appendChild(line);
if(window.runtime){
runtime.trace(message);
}
}
--></script>
</head>
<body onLoad="appLoad();">
<div id="UI">
<button onClick="ping();">Check Resource</button>
<input name="textfield" type="text" id="resourceURL" value="http://www.adobe.com" size="60"/>
</div>
<div id="log">
</div>
</body>
</html>
Back to: Apollo Documentation home page