Mobile (3G) vs. WIFI Network Detection with Adobe AIR

Did you know that you can determine whether your mobile device is on wifi or your mobile data connection when using Adobe AIR for mobile? To be honest, I wasn’t aware of it either until yesterday when my friend and former colleague Brian O’Connor pointed me towards a recent tweet from @adobe_cookbook that showed an example how to do it.

These networking APIs have been around since AIR 2.0, but I’ve seldom had the need to dig into them for the desktop. Now that AIR for mobile is widely available, this can be critically important for your applications. For example, what if you want to minimize network usage while on the mobile network? This may even prevent you being chastised for eating up expensive mobile bandwidth.

Using the NetworkInfo class’ findInterfaces() method, you can retrieve a list of all network interfaces on your computer/device. If you iterate through these, you can see which are active, what their IP and MAC addresses are, and even which IP protocol version they are using. Here’s a quick example (code below the video):

Network Detection on AIR Mobile

I know that video is a little hard to see, so here are some screen captures. First, a capture showing the mobile network connection active:

Mobile Network Active

Next, a capture showing the WIFI network active:

WIFI Network Active

Basically, I just have a list that shows all of the network interfaces. When the app loads, or whenever the network connection changes, the content of that list is updated to reflect the current state of the network interfaces. If you want to determine whether you are on wifi, you can compare the name of the active network interface to see if it contains the string “wifi”, as shown in the Adobe Cookbook.

[as3]<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="Network Detection"
creationComplete="view1_creationCompleteHandler(event)">

<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;

[Bindable]
private var interfaces : ArrayCollection = new ArrayCollection();

protected function view1_creationCompleteHandler(event:FlexEvent):void
{
NativeApplication.nativeApplication.addEventListener(Event.NETWORK_CHANGE, onNetworkChange);
updateInterfaceDataProvider();
}

protected function onNetworkChange(event : Event) : void
{
updateInterfaceDataProvider();
}

//this is used b/c you can’t bind directly to a Vector
protected function updateInterfaceDataProvider() : void
{
interfaces.disableAutoUpdate();
interfaces.removeAll();

for each ( var ni : NetworkInterface in NetworkInfo.networkInfo.findInterfaces() )
{
interfaces.addItem( ni );
}
interfaces.enableAutoUpdate();
}
]]>
</fx:Script>

<s:List dataProvider="{ interfaces }"
width="100%" height="100%"
itemRenderer="NetworkInterfaceDetailsRenderer"/>
</s:View>[/as3]

In the list renderer, I’m simply setting an iconFunction and messageFunction to reflect the details on each individual NetworkInterface.

[as3]<?xml version="1.0" encoding="utf-8"?>
<s:IconItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
labelField="name"
messageFunction="networkInterfaceDetail"
iconFunction="networkInterfaceIcon"
iconWidth="64" iconHeight="64" >

<fx:Script>
<![CDATA[

[Embed(source="assets/active.png")]
public static var activeImageClass:Class;

[Embed(source="assets/inactive.png")]
public static var inactiveImageClass:Class;

private function networkInterfaceDetail(item:Object):String
{
var ni : NetworkInterface = this.data as NetworkInterface;
if ( ni )
{
var result : String = "mac: " + ni.hardwareAddress;
for each ( var ia : InterfaceAddress in ni.addresses )
{
result += "\nip: " + ia.address + " " + ia.ipVersion;
}
result += "\nmtu: " + ni.mtu.toString();
return result;
}

return "Error: Unable to identify network interface.";
}

private function networkInterfaceIcon(item:Object):Object
{
var ni : NetworkInterface = this.data as NetworkInterface;
if ( ni && ni.active )
return activeImageClass;
return inactiveImageClass;
}
]]>
</fx:Script>
</s:IconItemRenderer>
[/as3]

One thing not to forget: You must make sure that your application has been provisioned to allow access to network interfaces! You’ll just need to uncomment the Android permissions in your app.xml for network state:

[xml]
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>[/xml]

13 replies on “Mobile (3G) vs. WIFI Network Detection with Adobe AIR”