Understanding StageWebView and the viewport tag

My current solution for displaying dynamic interactive maps in my Android applications is to display a HTML-based Google Map within an instance of StageWebView. For the most part this has worked well, except for the long start up process. This often gives the appearance of the application being frozen. So, I sought a solution to try to improve the user experience.

The first step was to find a way to hide the StageWebView until it had finished its initialization and contacted the server. Since this component is of the ‘Stage’ type, this means that the normal display manipulation will not work. Instead, I created the viewport of the StageWebView offscreen. Now, I just need to know when it has contacted the server and the first page has been loaded. For this, you can listen for the Location Changed event. (Note, there appears to be a bug in AIR for Android 3.0, where this event is only fired upon the first URL that is accessed. This is important later).

Once the page has been loaded into our StageWebView, I reset the viewport to be on-screen. Since I have a loading spinner animating on the stage, this delay is now neatly masked.

Loading Indicator

Loading spinner

However, my screen still shows a white StageWebView. Then the map tiles are displayed, followed by the map controls. So how can I improve this portion of the process?

StageWebView initializing

The white StageWebView

In exploring the Google Map forums, I came across the notion of first serving a static Google Map, then waiting for the “tiles_loaded” event to be fired to swap the static map with the dynamic one. This was as simple as adding an <img> tag for the static map, and an event listener. In my web browser, this solution worked flawlessly.

Since there is a Location_Changing event that StageWebView is supposed to fire when the URL is changing, I thought I could tie into this by changing the page’s URL with an # attribute. But I then learned that this event does not currently properly fire on Android devices. I had planned to keep the StageWebView off-screen until the dynamic version of the map was ready before changing its viewport location.

Instead, I was forced to display the static map, then allow the loading of tiles and the map controls to occur visibly to the user. I soon ran into another problem. I had defined the width of the static map to be 480 pixels wide (I would have custom versions of the html page per device width), but once the html file was loaded into the StageWebView, I was able to scroll the image horizontally. What was going on!? Everything was working fine in my desktop browsers.

Map with scroll bars

Note the scroll bars

So, I began looking into the various attributes of the viewport meta tag, to see if there was something I could do to adjust the viewport. If you are not familiar with this tag, the Android documentation has a great reference on it. If you read through their documentation, you will learn that web pages on high-density devices (which is required to run AIR for Android) are automatically scaled by 150%. Eureka! Now I had confirmed why the static image became scrollable, now to find the solution. Reading further, there is another interesting attribute that can be set: target-densitydpi. To quote the documentation, “You can change the target screen density for your web page using the target-densitydpi viewport property.” This property has five values; device-dpi, high-dpi, medium-dpi, low-dpi, or a value. The one of interest for us is the device-dpi. If the target-densitydpi is set to device-dpi, the page will use the device’s native dpi as the target dpi and default scaling never occurs. And with this one addition to our viewport tag, our html file will now renders correctly on-device. Here is a sample apk and the source files.

7 comments

  1. Okay, here’s what works (at least, in Air 3): instead of a LocationChange event, simply use an Event.Complete event. This will move the viewport after it’s already begun to load the content, and it gets rid of the white flash. Woohoo! Thanks for the idea 🙂

    1. Hello Tina,

      I have been struggling with this problem in reference the white loading box being viewed before stage view context has loaded. I understand that you stated to simply use Event.Complete event, but i place it in the example source file provide above and in my own app and its still not working out. If possible could provide an example of code in text or Flash source file format. Thanks for any help you can offer.

  2. Trying to figure out how to implement your solution with the Facebook login screen but somehow Facebook is storing a cookie on my debugger app through the StageWebView that is keeping me logged in between runs so I can’t even see the login screen anymore! I’ve cleaned out the #SharedObjects folder for the AIR app and it’s not that

    Have you come across how you reset these cookies?

  3. To log out properly, pass the application URL from your Facebook application settings into the logout command:

    FacebookMobile.logout(callbackFunction, “http://yourapp.com/facebook”);

    Something that was missed in the tutorial, annoyingly.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.