Accessibility
 
Home / Developer Center / Mobile and Devices Developer Center /

Developer Center Article

Building the sample application: CD Tracker

This tutorial explains how to build a sample application called CD Tracker, which demonstrates several unique features of FlashAssist PRO. CD Tracker is a full-screen Pocket PC application that saves data to a local file in XML format. CD Tracker also accepts soft keyboard or handwriting recognition input through an extended ActionScript command that displays the soft input panel (SHOWSIP, HIDESIP). The user can show or hide the soft input panel using the Pocket PC application buttons.

To keep things simple, CD Tracker allows a user to store one CD with three tracks. After you're done with this tutorial, you may want to extend this application to make a fully-featured CD tracker.

You can download the FLA files and PC installer for the Pocket PC application on the first page of this article. Note that the resulting SWF file is designed to run inside a FlashAssist host application and will not work the same if run inside Pocket IE. (In other words, you will not be able to save data.)

The remainder of this tutorial shows you how to create a Macromedia Flash movie that uses FlashAssist PRO ActionScript and how to create the final application and installer using FlashAssist PRO. The code samples in this article do not show the additional debug code that's available to you in the FLA files included in the downloadable ZIP file.

Establishing communication with the host application
The CD Tracker movie (cdtrack.swf) will run inside a C++ host-application generated by FlashAssist PRO. The host-application performs two key functions:
  • Creates a web-browser control and opens the HTML file that displays the cdtrack.swf file
  • Creates a socket server for communicating with cdtrack.swf through an XMLSocket

The host-application socket server receives data and extended commands from cdtrack.swf, writes data to a local file data store, and executes extended commands (indicated by a leading "!" character). When the application first launches, the socket server looks for an existing file data store and forwards any found data to cdtrack.swf.

To store data and execute commands, cdtrack.swf needs to establish communication with the C++ host-app. This is accomplished by opening the port that the host-application creates. To avoid conflicts with other applications, the host-application requests an available port from the Pocket PC operating system and deposits the port number in a known file location in loadVariables format. In the first frame, cdtrack.swf uses the loadVariablesNum command to load the port number:

// port == 0 indicates no port available to write to
port = 0;
// load port number from known location
loadVariablesNum("\\Windows\\siptest_FlashXMLServer_port.txt", 0);
// used to avoid an infinite loop waiting for port number
keepTrying = 50;

Frames 2 and 3 simply loop to wait for the port number to load or for a timeout:

// wait for port to be supplied or for timeout
if (port == 0 and keepTrying-->0) {
gotoAndPlay("waitforport");
}

Frame 4 creates an XMLSocket to establish communication, using "localhost" to specify a port on the Pocket PC. Two callback routines are defined: OnXMLConnect is called after the connection attempt succeeds or fails; OnXMLReceive is called when data is received from the host-application:

if (port != 0) {
     socket = new XMLSocket();
     socket.onConnect = OnXMLConnect;
     socket.onXML = OnXMLReceive;
     if (!socket.connect("localhost", port)) {
             port = 0;
     }
}

OnXMLConnect is called after the connection attempt succeeds or fails:

// If we failed to connect, set port to zero to indicate failure
function OnXMLConnect(success) {
     if (success) {
     gotoAndPlay("main");
     } else {
             port = 0;
     }
}

Loading and saving data
OnXMLReceive is called when data is received from the host-application (at startup). OnXMLReceive transfers the data from the XML nodes to input text variables. When cdtrack.swf gets to frame 5 ("main"), it has loaded the persistent data into the input fields:

function OnXMLReceive(doc) {
     socketactivity = "data received";
     var e = doc.firstChild;
     socketactivity = "XML received";
     if (e != null && e.nodeName == "CDCollection") {
             socketactivity = "CDCollection received";
             e = e.firstChild;
     }
     if (e != null && e.nodeName == "DATAOBJECT") {
             socketactivity = "DATAOBJECT received";
             title = e.attributes.TITLE;
             artist = e.attributes.ARTIST;
             track01 = e.attributes.TRACK01;
             track02 = e.attributes.TRACK02;
             track03 = e.attributes.TRACK03;
     }
}

The SAVE button simply reverses the OnXMLReceive procedure, loading the data into an XML structure and sending the XML object to the host application via the XMLSocket:

on (release) {
     if (port != 0) {
             // format the data into a single XML node/tree for              // storage
             newStore = new XML();
             newRoot = newStore.createElement("CDCollection");
             newStore.appendChild(newRoot);
             newDataObject = newStore.createElement("DATAOBJECT");
             newRoot.appendChild(newDataObject);
             newDataObject.attributes.TITLE = title;
             newDataObject.attributes.ARTIST = artist;
             newDataObject.attributes.TRACK01 = track01;
             newDataObject.attributes.TRACK02 = track02;
             newDataObject.attributes.TRACK03 = track03;
             socket.send(newStore);
     }

By default, the host-application stores a single XML object at a time. The XML object can be a tree structure with as many nodes as needed. Note, however, that performance can be poor for very large XML objects on the Pocket PC. The C++ host-app can be extended to store multiple objects and allow for more complex saving and loading commands.

Using the SHOWSIP/HIDESIP extended commands
The CD Tracker sample application allows the user to input data using the soft input panel (SIP), which is normally hidden in full-screen mode. CD Tracker calls the extended commands SHOWSIP and HIDESIP, which are implemented in C++ by FlashAssist PRO. Extended commands are sent through the XMLSocket.send command and preceded by an exclamation mark ("!"):

socket.send("!SHOWSIP");

Frame 5's routine ensures that the soft input panel is shown when the user taps inside an input field, and that it is hidden when the user taps outside an input field:

if (Selection.getFocus() == "_level0.title") {
     lastFocus = Selection.getFocus();
     if (!sipup_title) {
             sipup_title = true;
             socket.send("!SHOWSIP");
     }
     sipup_artist = false;
     sipup_track01 = false;
     sipup_track02 = false;
     sipup_track03 = false;
} else if (Selection.getFocus() == "_level0.artist") {
     lastFocus = Selection.getFocus();
     if (!sipup_artist) {
             sipup_artist = true;
             socket.send("!SHOWSIP");
     }
     sipup_title = false;
     sipup_track01 = false;
     sipup_track02 = false;
     sipup_track03 = false;
} else if (Selection.getFocus() == "_level0.track01") {
     lastFocus = Selection.getFocus();
     if (!sipup_track01) {
             sipup_track01 = true;
             socket.send("!SHOWSIP");
     }
     sipup_title = false;
     sipup_artist = false;
     sipup_track02 = false;
     sipup_track03 = false;
} else if (Selection.getFocus() == "_level0.track02") {
     lastFocus = Selection.getFocus();
     if (!sipup_track02) {
             sipup_track02 = true;
             socket.send("!SHOWSIP");
     }
     sipup_title = false;
     sipup_artist = false;
     sipup_track01 = false;
     sipup_track03 = false;
} else if (Selection.getFocus() == "_level0.track03") {
     lastFocus = Selection.getFocus();
     if (!sipup_track03) {
             sipup_track03 = true;
             socket.send("!SHOWSIP");
     }
     sipup_artist = false;
     sipup_track01 = false;
     sipup_track02 = false;
} else {
     if (sipup_title || sipup_artist || sipup_track01 || sipup_track02 || sipup_track03) {
             socket.send("!HIDESIP");
             sipup_title = false;
             sipup_artist = false;
             sipup_track01 = false;
             sipup_track02 = false;
             sipup_track03 = false;
     }
}

The keyboard button at the bottom-right of the display also allows the user to show the soft input panel at any time:

on (release) {
     socket.send("!SHOWSIP");
     Selection.setFocus(_root.lastFocus);
     Selection.setSelection(Selection.getEndIndex(), Selection.getEndIndex());
}

Finally, the QUIT button is implemented, as with FlashAssist, via a GetURL call:

GetURL("FLASHASSIST_QUIT")

 

 

Previous Contents Next