Source Code and Comments

There is a couple of ways to display web pages in your AIR mobile app: the navigateToURL method and the AS3 StageWebView class. We discuss both, but focus on StageWebView as it displays web content without leaving your app. We explain finer points of using the class, e.g. disabling and enabling zooming in StageWebView instance. If you want to see the app in action, open the Android Market on your phone, search for flashandmath, and locate AIR StageWebView on our apps list. You can then download and install the app. Below are screen shots.

Download

  • Download all source files corresponding to this app (Flash CS5 and CS5.5 formats): swvcode.zip

The package contains SWVDemo.fla and and navtourl.fla in CS5.5 and CS5 formats. The latter is included to illustate the simple navigateToURL method and it is unrelated to StageWebView app.

Working with the Source Files

In Flash CS5.5, you simply open each of the fla files. Under AIR for Android Publish settings, under General select Portrait mode, under Deployment enter the location or create your p12 certificate and choose deployment settings that you want, under Permissions check INTERNET. If you have your Android phone all set up for development and connected to your computer, click Publish and the app will be installed on your phone.

You can use CS5 versions of the files if you have AIR for Android Extension for Flash CS5 installed.

Code and Comments

Below is complete Timeline source code in SWVDemo.fla punctuated by comments. The code begins with several class import statements. Let's highlight importing the class StageWebView in the flash.media package:

............................

import flash.media.StageWebView;

...........................

(If you use the Timeline code, most of the classes will be imported automatically. If you place your code in an AS3 class, Flash will prompt you to import all the needed classes.)

stage.align = StageAlign.TOP_LEFT;

stage.scaleMode = StageScaleMode.NO_SCALE;

We set up several global variables. The first, of data type StageWebView, will hold our instance of StageWebView. The window in which web content will be displayed is defined by a rectangle that we will assign later to the property "viewPort" of StageWebView instance. We calculate the height and y position of this rectangle based on the size of the UI elements that we placed on the stage (buttons, control panels etc.).

var webView:StageWebView;

var swvRect:Rectangle;

var swvHeight:Number;

var uiElemsTop:Number=140;

var swvY:Number=140;

var uiElemsBot:Number=40+20+75+20;

var uiElemsHeight:Number=uiElemsTop+uiElemsBot;

infoBox, mainPanel (of buttons), webBtnsPanel, and a clip mcStart were all created on the stage. The app opens with mcStart covering the screen. The clip describes the app. After the user clicks on it, we initialize the app. We attach listeners to buttons in "mainPanel" that create an instance of StageWebView, stored in "webView" variable, delete the instance, and exit the app. To "webBtnsPanel" buttons we attach listeners that will create back, forward, reload, stop loading navigation in our webView viewPort after an instance of StageWebView is created.

infoBox.text="";

infoBox.visible=false;

mainPanel.visible=false;

webBtnsPanel.visible=false;

mcStart.addEventListener(MouseEvent.CLICK,init);

 

function init(e:MouseEvent):void {

mcStart.removeEventListener(MouseEvent.CLICK,init);

mcStart.visible=false;

mainPanel.btnExit.addEventListener(MouseEvent.CLICK, exitApp);

mainPanel.btnCloseSwv.addEventListener(MouseEvent.CLICK,closeSwv);

mainPanel.btnOpenSwv.addEventListener(MouseEvent.CLICK, openSwv);

infoBox.text="Click open stage web view to begin";

webBtnsPanel.btnNext.addEventListener(MouseEvent.CLICK, nextPage);

webBtnsPanel.btnPrev.addEventListener(MouseEvent.CLICK, prevPage);

webBtnsPanel.btnReload.addEventListener(MouseEvent.CLICK, reloadPage);

webBtnsPanel.btnStop.addEventListener(MouseEvent.CLICK, stopPage);

swvHeight=stage.stageHeight-uiElemsHeight;

infoBox.x=stage.stageWidth/2-infoBox.width/2;

infoBox.y=stage.stageHeight-40;

mainPanel.x=stage.stageWidth/2-mainPanel.width/2;

webBtnsPanel.x=stage.stageWidth/2-webBtnsPanel.width/2;

webBtnsPanel.y=140+swvHeight+20;

mainPanel.visible=true;

infoBox.visible=true;

}

The handler "openSwv" that runs when the button mainPanel.btnOpenSwv is clicked creates an instance, "webView", of the StageWebView class. We see how it is done within "openSwv" function. An instance of StageWebView is not a DisplayObject and it is not added as a child of anything. Instead, it is assigned to the stage via: webView.stage=this.stage. The instance "webView" of StageWebView will always appear on top of all other content. The size and the position of the window in which web content will be displayed is defined by a Rectangle assigned to the viewPort property of the webView instance. The viewPort serves as a "window" in which the native device's browser is shown. The navigation bar, address window etc. of the native browser will not be visible; the only part that is displayed in viewPort is the web content.

Before calling the "loadURL" method of the StageWebView class, we assign listeners to "webView" that will be (possibly) fired during loading. LOCATION_CHANGING fires just before a new URL begins to load. We use it to display a message "Loading..." in the infoBox. Other events are self-explanatory.

function openSwv(event:MouseEvent):void {

if(webView!=null){

return;

}

webBtnsPanel.visible=true;

infoBox.text="";

webView=new StageWebView();

webView.stage=this.stage;

webView.viewPort=new Rectangle(0,swvY,stage.stageWidth,swvHeight);

webView.addEventListener(ErrorEvent.ERROR,onError);

webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING,onChanging);

webView.addEventListener(Event.COMPLETE,onComplete);

webView.loadURL("http://www.math.uri.edu/~bkaskosz/webview/index.html");

}

 

function onError(e:ErrorEvent):void {

infoBox.text="Page is not available. Try reloading.";

}

 

function onChanging(e:LocationChangeEvent):void {

infoBox.text="Loading...";

}

 

function onComplete(e:Event):void {

infoBox.text="";

}

The next several handlers run when navigation buttons in webBtnsPanel are clicked. They use the properties and the methods of the StageWebView class that mimic browser navigation. When the user clicks on the links within pages displayed in viewPort, isHistoryBackEnabled and isHistoryForwardEnabled properties become true. The methods webView.historyForward() and webView.historyBack() load then the next or the previous page logged in the history. The methods webView.reload() and webView.stop() reload a current page or stop loading it.

function nextPage(e:MouseEvent):void {

if(webView==null){

return;

}

if(!webView.isHistoryForwardEnabled){

return;

}

webView.historyForward();

}

 

function prevPage(e:MouseEvent):void {

if(webView==null){

return;

}

if(!webView.isHistoryBackEnabled){

return;

}

webView.historyBack();

}

 

function reloadPage(e:MouseEvent):void {

if(webView==null){

return;

}

webView.reload();

}

 

function stopPage(e:MouseEvent):void {

if(webView==null){

return;

}

webView.stop();

}

Since an instance of StageWebView is not a DisplayObject, it is not removed by "removeChild". Instead, the method webView.dispose() is used as shown in the function below.

function closeSwv(event:MouseEvent):void {

if(webView==null){

return;

}

webView.removeEventListener(ErrorEvent.ERROR,onError);

webView.removeEventListener(LocationChangeEvent.LOCATION_CHANGING,onChanging);

webView.removeEventListener(Event.COMPLETE,onComplete);

webView.viewPort=null;

webView.dispose();

webView=null;

webBtnsPanel.visible=false;

infoBox.text="Click open stage web view to begin";

}

 

function exitApp(event:MouseEvent):void {

NativeApplication.nativeApplication.exit(0);

}

Note:   In our app we didn't use another important event dispatched by the instance webView of StageWebView: LocationChangeEvent.LOCATION_CHANGE that signals that the URL displayed in viewPort has changed. The event, say "e", dispatched at that time has the String property e.location that contains the URL currently displayed in viewPort. (So does the event dispatched at LOCATION_CHANGING.)

StageWebView versus navigateToURL

When you use StageWebView, you display web content WITHOUT leaving your app. This is the crucial advantage of the class. Your app remains in the foreground with all its controls. It is easy enough to open the native browser from your app using the navigateToURL method. However, when you use navigateToURL, your app goes into the background. The native browser is in the foreground. Clicking the back button on the phone will eventually bring the user back to your app, but only after going through all the pages viewed while using the browser.

Here are the main lines of code from navtourl.fla that open the native browser:

mcPanel.btnNav.addEventListener(MouseEvent.CLICK,navToUrl);

function navToUrl(event:MouseEvent):void {

navigateToURL(new URLRequest("http://www.math.uri.edu/~bkaskosz/webview/index.html"));

}

StageWebView and Zooming

Curiously, zooming being enabled in your instance's of StageWebView viewPort, say webView.viewPort, depends on the HTML code of the page you are loading and not on the settings of your instance of StageWebView. This topic deserves a separate tutorial (coming soon). In a nutsheell, if the browser believes that the page loaded is designed for mobile, it will not scale it down and change its layout. Zooming can be turned off, too. All it takes is a meta tag in the head of your HTML page:

<meta name="viewport" content="width=device-width; initial-scale=1.0;
                maximum-scale=1.0; user-scalable=0;" />

"viewport" in the meta tag is not directly related to the viewPort instance property of the StageWebView class. More about HTML for mobile soon.

This tutorial was written by Barbara Kaskosz of flashandmath.

Back to AIR for Android              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.