While ActionScript to JavaScript communication is straightforward, JavaScript to ActionScript communication is less obvious and somewhat limited when working with the StageWebView class.

In this tutorial we’ll walk through the steps required to pass data from an HTML page to your AIR for iOS app.

Flash iOS Apps CookbookThis tutorial is a previously unreleased recipe from Flash iOS Apps Cookbook and supplements the content found in Chapter 11, Rendering Web Pages.

Flash iOS Apps Cookbook provides the recipes required to build native iOS apps using your existing knowledge of the Flash platform. Whether you want to create something new or simply convert an existing Flash project, the relevant steps and techniques are covered, helping you achieve your goal.

Getting ready

As with the majority of recipes presented in this chapter, the steps covered here are only applicable to those using AIR 2.6 and above.

From this recipe’s accompanying code bundle, open chapter11\recipe8\recipe.fla and use it as a starting point.

Included within the FLA’s AIR for iOS Settings is a folder named html, which contains the HTML page that will be used to pass data to your app. The HTML is basic and displays a form with two fields prompting the user for their forename and surname. When the user submits the form, a JavaScript function on the page will attempt to pass the value of both fields to your AIR for iOS app.

Sitting on the stage is a dynamic text field with an instance name of output. We’ll use this to display the data retrieved from the HTML page.

Before proceeding, use a text editor of your choice to familiarize yourself with the HTML and its JavaScript. It can be found at chapter11\recipe8\html\index.html.

Now let’s write some ActionScript to retrieve the data.

How to do it…

Perform the following steps:

  1. Create a new document class and name it Main.
  2. Add the following import statements:
    import flash.events.LocationChangeEvent;
    import flash.filesystem.File;
    import flash.geom.Rectangle;
    import flash.media.StageWebView;
    import flash.net.URLVariables;
  3. Declare a StageWebView member variable:
    private var webView:StageWebView;
  4. Within the constructor, load html/index.html and listen for the LOCATION_CHANGING event being dispatched from the StageWebView object:
    public function Main() {	
      var url:String = File.applicationDirectory.resolvePath(
        "html/index.html").nativePath;
    
      webView = new StageWebView();
      webView.stage = stage;
      webView.viewPort = new Rectangle(
        0, 0, stage.stageWidth, stage.stageHeight);
      webView.addEventListener(
        LocationChangeEvent.LOCATION_CHANGING, locationChanging);
      webView.loadURL(url);
    }
  5. Finally, add a handler for the LOCATION_CHANGING event, which will obtain the data passed from the HTML page and display it on screen:
    private function locationChanging(e:LocationChangeEvent):void {
      var arr:Array = e.location.split(".html?");
      var vars:URLVariables = new URLVariables(arr[1]);
      output.text = (vars.first + " " + vars.last);
      webView.stage = null;
      webView.dispose();
      e.preventDefault();
    }
  6. Save the class and when prompted, name its file Main.as.
  7. Move back to your FLA and save it too.
  8. Receiving text from an HTML page.

  9. Now publish the FLA and test it on your device. Once the HTML page loads, enter your forename and surname into the form’s fields, then tap the Submit button. The HTML page will disappear from view and the value of both fields will be written to the output text field.

How it works…

It’s possible to pass data from an HTML page to an AIR for iOS app by making use of the StageWebView class’ location property and the LOCATION_CHANGING event. This is achieved by having JavaScript change the page’s location to a URL that contains encoded data. The changed URL can then be obtained from the LOCATION_CHANGING event’s handler and the data extracted from it.

Here’s the JavaScript function from index.html:

<script type="text/javascript">
  function passData() {
    document.location = (
      "?first=" + encodeURIComponent(field1.value) + 
      "&last="  + encodeURIComponent(field2.value));
  }
</script>

This function is called when the user presses the Submit button on the page. Notice that it sets document.location to an encoded string of name-value pairs. The two fields within the HTML page’s form have IDs of field1 and field2 respectively, and the value of each is used to create the string.

For example, if the user was to enter Christopher into the first field and Caleb into the second, then the JavaScript function would set document.location to the following:

?first=Christopher&last=Caleb

In addition, the absolute path to the current HTML document is also prefixed resulting in the location actually resembling the following:

///var/mobile/Applications/4D7985D8-029A-4E03-85CC-E77ECD38C987/recipe8.app/html/index.html?first=Christopher&last=Caleb

When the JavaScript changes the document’s location, the StageWebView object will dispatch a LOCATION_CHANGING event, which will be captured by the locationChanging() handler. The data can then be retrieved by querying the event’s location property. Since name-value pairs are used to represent the data, we can use Flash’s URLVariables class to easily extract the value of each:

private function locationChanging(e:LocationChangeEvent):void {
  var arr:Array = e.location.split(".html?");
  var vars:URLVariables = new URLVariables(arr[1]);
  output.text = (vars.first + " " + vars.last);
  webView.stage = null;
  webView.dispose();
  e.preventDefault();
}

In the code snippet above, the split() method is used to extract the name-value pairs from the location’s string. The name-value pairs are then passed to the URLVariable class’ constructor.

Although the JavaScript function changed the page’s location property, we have no desire to actually move to a new page – we simply needed a mechanism for passing data. A call is therefore made to the event object’s preventDefault() method, stopping the new URL from actually loading. This is convenient as the new URL simply contains data and would result in a load error if the operation was to commence.

Also, this recipe used name-value pairs, but you can just as easily use some other data format such as JSON.

For more information regarding the URLVariables class, perform a search within Adobe Community Help.

There’s more

You may find bi-directional ActionScript/JavaScript communication cumbersome when using the StageWebView class. There is however, a third-party library available that removes much of the pain.

StageWebView Bridge

StageWebViewBridge is an extended version of the StageWebView class. It makes working with HTML content easier by providing an API that lets you do the following:

  • Call JavaScript functions from ActionScript
  • Call ActionScript functions from JavaScript
  • Load local files and resources

Although these things can already be done using StageWebView, the StageWebViewBridge class provides a layer of abstraction that helps remove much of the effort involved.

You can obtain the latest version of StageWebViewBridge from its Google Code Project page at code.google.com/p/stagewebviewbridge.

See also

  1. Good article! I used webviewBridge in the past but ran an into a lot of weird bugs and essentially running local HTML/js… The stagewebview may seem really limited but ends up providing the most reliable solution for cross platform solutions.

  2. Good trick!…ill test it and saving into sqlite database!……..I’ve tried webviewbridge but i couldnt make it work on mobile

    Ramcerva
  3. Well I´ve tested and works good, but with a little modification in: webView.addEventListener(LocationChangeEvent.LOCATION_CHANGE, locationChanging);
    webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, locationChanging);

    Ramcerva
  4. Thanks for the update Ramcerva!

    Christopher (Author)
  5. Thank you Ramcerva, that was a very helpfull addition that solved my problem.

    Sebastian Salzgeber
  6. Don’t use StageWebView Bridge. Its quite old now, it has a lot of strange bugs (especially on iOS), and the creator has no intention of updating the library.

    For a save cross-platform solution, use the the code described in this post.

    Carlos Bernal