Tagged: actionscript Toggle Comment Threads | Keyboard Shortcuts

  • pit 11:58 pm on February 9, 2010 Permalink | Reply
    Tags: actionscript, , , , , ,   

    How to use Nokia API Bridge in Flash Lite with FDT 

    API Bridge is a Symbian engine that exposes a set of native functionalities to Web Runtime, Flash Lite and Java ME applications. Nokia has recently released an ActionScript library that allows to easily integrate APIBridge functionalities in a Flash Lite application.

    In this article I’ll try to explain how to setup and develop a Flash Lite application that uses APIBridge, by using FDT.

    If you want to know how to configure FDT (and Eclipse) to properly develop Flash Lite application, you should read this article: Web Runtime and Flash Lite integrated development on Eclipse.

    Setup the project in FDT

    First of all, you need to download the API Bridge FlashLite library from Forum Nokia: API Bridge Flash Lite Library and Sample Code. The package also contains useful sample code that will definitely help.

    Now, create a new Flash Lite project within Eclipse.

    Then, open up the API Bridge package downloaded from Forum Nokia, and copy the “si/” folder to the “src/” folder of your Flash Lite project.

    Once copied, you should notice some errors in your FDT project, as shown in the picture below.

    These errors are due to the “mx.*” package, that is not included in the ActionScript classes shipped with FDT. To solve this error, you have to tell FDT where to find these classes.

    First, let’s copy these classes from the Flash IDE to a dedicated folder:

    1. Create a folder called “mx_package/” somewhere on your machine
    2. Go into “<FLASH_IDE_PATH>\en\First Run\Classes\” folder
    3. Copy the “mx/” folder inside the “mx_package/” folder created above

    Now, configure FDT:

    1. Go into “Window” -> “Preferences” -> “FDT” -> “Core Libraries”, open the “Path variables” panel and select “New…”
    2. Enter “MX_PACKAGE” as name, and select the “mx_package/” created above as folder
    3. Once done, your Core Libraries should look similar to the picture below

    Now, what remains to do is to add the MX library to the Flash Lite project. Go into the project’s properties and, in the “FDT Build Path” section, select “Add Linked Library…” -> “Add…” and pick “MX_PACKAGE”.

    Done this, all the errors should have gone away from the project. Hurrah! :)

    Patching the mx.utils.Delegate class

    The MTASC compiler is stricter than the compiler you can find within the Flash IDE. For this reason, the mx.utils.Delegate class needs to be slightly modified in order to make it properly compile with MTASC.

    Specifically, the ‘create()’ function needs to be adjusted as follows:

    static function create(obj:Object, func:Function):Function
    {
    	var f = function()
    	{
    		var target = arguments.callee.target;
    		var func2 = arguments.callee.func;
    		return func2.apply(target, arguments);
    	};
    	f.target = obj;
    	f.func = func;
    	return f;
    }

    Patching the si.apibridge.APIBridge class

    For the same reasons explained above, also the si.apibridge.APIBridge class needs to be patched to work with MTASC.  To do this, open APIBridge.as and replace the setPort() function with this one:

    	private function setPort(): Void
    	{
    		var portVars:LoadVars = new LoadVars();
     
    		portVars.load( portPath );
     
    		var pushErrorDelegate : Function = Delegate.create(this, pushError);
     
    		portVars.onLoad = function( success )
    		{
    			if (success)
    			{
    				var portData:String = portVars.toString();
    				portData = portData.substr(0,portData.indexOf("="));
    				trace(portData);
    				APIBridge.BridgeURL += portData; 
     
    			}
    			else
    			{
    				trace("Error loading Port");// The data didn't load
    				pushErrorDelegate("1","Error loading port, using default 9080");
    				APIBridge.BridgeURL += "9080";
    			}
     
    		}
    	}

    Once done, just create a new MTASC launch configuration and check that the project properly compiles. If it doesn’t, re-check the steps above.

    Using API Bridge Call Log service in Flash Lite

    Now, we’ll see how to use an API Bridge service, the Call Log one, in Flash Lite.

    First, let’s create the main project’s class. In this example I’ll call it ‘MainMovie’.

    import com.jappit.flashlite.apibridgetest.Logger;
    import com.jappit.flashlite.apibridgetest.CallLogRetriever;
     
    class com.jappit.flashlite.apibridgetest.MainMovie
    {
    	public static function main(container : MovieClip) : Void
    	{
    		Stage.align = "TL";
    		Stage.scaleMode = "noScale";
    		container.createTextField("tf", 1, 0, 0, 360, 500);
    		var textField : TextField = container["tf"];
    	}
    }

    The TextField instance will be used to show the events retrieved from the device logs. Now, let’s create a separate class, EventsLogRetriever, that will take care of calling APIBridge, and of managing its responses. Its constructor is defined to accept a TextField as argument, and it will use it to print out the API Bridge response.

    import mx.utils.Delegate;
    import si.apibridge.*;
     
    class com.jappit.flashlite.apibridgetest.EventsLogRetriever
    {
    	private var textField : TextField;
     
    	public function EventsLogRetriever(_textField : TextField)
    	{
    		this.textField = _textField;
    	}

    Now, it’s time to define the method that will call the API Bridge engine. Each call to an API Bridge interface must typically define two handlers: a success and a failure handler. The error handler receives a single argument, containing the data of the occurred error. About the success handler, it receives three arguments:

    1. the transaction ID, that must be used to uniquely identify the transaction that is calling the handler (useful in scenarios where multiple transactions are active concurrently)
    2. the event ID, that identify the state of the event
    3. an object containing data returned by the API Bridge call

    Said that, the EventsLogRetriever class will end up containing these 3 methods:

    public function retrieveEvents() : Void
    {
    }
    public function onApiError(outParam : Object) : Void
    {
    }
    public function onApiSuccess(transactionID:Number, eventID:String, outParam:Object)
    {
    }

    Starting with the retrieveEvents() method, it has to:

    • instantiate APIBridge, passing a reference to the error handler as argument
    • grab a reference to the Logging service
    • define which kind of log events it wants to retrieve
    • call the GetList() service method

    So, the retrieveEvents() can be implemented as follows:

    public function retrieveEvents() : Void
    {
    	var _onApiError : Function = Delegate.create(this, onApiError);
    	var _onApiSuccess : Function = Delegate.create(this, onApiSuccess);
     
    	var bridge:APIBridge = new APIBridge(_onApiError);
     
    	var logging = bridge.Service("Service.Logging", "IDataSource");
     
    	textField.text  = "Retrieving phone numbers ..." + APIBridge.BridgeURL;
     
    	var filter = {EventType:0};
    	var inParams = {Type:"Log", Filter:filter};
     
    	logging.GetList(inParams, _onApiSuccess);
    }

    Coming to the error handler, let’s just implement it to make it show the returned error data:

    public function onApiError(outParam : Object) : Void
    {
    	textField.text  = "APIBridge error " + outParam.ErrorCode + " " + outParam.ErrorMessage;
    }

    Now, the success handler. First, it has to check if the returned API Bridge data contains an error, and this can be done with the same logic used in the error handler above. If no errors are detected, the handler can retrieve the actual returned data, contained in outParam.ReturnValue, and loop all the returned log events.

    public function onApiSuccess(transactionID : Number, eventID : String, outParam : Object)
    {
    	textField.text = "Results: " + outParam.ReturnValue.length + "\n" ;
     
    	if (outParam.ErrorCode != 0)
    	{
    		textField.text = "Error: " + outParam.ErrorCode + ", " + outParam.ErrorMessage;
    		return;
    	}
    	else
    	{
    		var outList = outParam.ReturnValue;
    		var outputEntry = null;
    		do
    		{
    			outputEntry = outList.next();
     
    			if (null != outputEntry)
    			{
    				textField.text += outputEntry.Direction + ": " +
    					outputEntry.Description + ", " +
    					outputEntry.PhoneNumber;
     
    				textField.text += "\n";
    			}
    			else
    			{
    				break;
    			}
    		}
    		while (true);
    	}
    }

    Done this, the EventsLogRetriever is ready to be used, and to do this it’ll be enough to add this two lines to the static() method of the MainMovie class:

    var retriever : EventsLogRetriever = new EventsLogRetriever(textField);
     
    retriever.retrieveEvents();

    That’s all!

    Build and deploy

    Once the Flash Lite app is ready, just build it using the MTASC launch configuration created before.

    Now the tough part: to make the whole thing work, it is necessary to package the Flash Lite application with the API Bridge engine. To do this, there are various options:

    1. Build a Flash Lite launcher in Symbian C++. These Forum Nokia Wiki articles explain how this can be done:
    2. Package the Flash Lite application in a WRT widget, and then package it with the API Bridge engine. This approach is described in these articles:

    Both the approaches can equally work, so feel free to choose the one you prefer :)

    Once deployed on a device, just run it, and you should see this:

    1) The Flash Lite app starts, and the API Engine is initialized

    2) The API Bridge engine asks the user for permission to access sensitive data

    3) And here are the retrieved log events!

     
  • pit 4:24 pm on February 23, 2009 Permalink | Reply
    Tags: actionscript, , , gestures, ,   

    Handling touch gestures in Flash Lite 

    With the release of many touch-enabled devices, as the latest Nokia 5800 XpressMusic and the forthcoming Nokia N97, applications can benefit from new ways of touch-based interactions. A typical example of these new patterns is represented by gestures: simple finger/stylus actions that allow the user to perform specific task, without the need of a precise interaction (e.g.: identify and press a specific button).

    This article will explain how to implement basic touch gestures in Flash Lite. Specifically, we’ll see how to detect both horizontal (left-to-right and right-to-left) and vertical (up-to-down and down-to-up) gestures.

    In the above video it’s possible to see a simple Flash Lite photo viewer, where the user can go from a photo to the next/previous just sliding finger or stylus.

    The source code

    Step 1. Detect touch events

    First thing to do is to detect and handle touch-based events, and this can be done by implementing a MouseListener, and its onMouseDown() and onMouseUp() methods. We also define 4 Number variables to hold the x and y coordinates associated to the mouse up and down events: these will be used to detect if the touch interaction was actually a gesture or not.

    So, take a new and empty FLA, and add this code on your first frame:

    var startX:Number;
    var startY:Number;
    var endX:Number;
    var endY:Number;
     
    var gesturesListener:Object = new Object();
     
    gesturesListener.onMouseDown = function()
    {
    	startX = _root._xmouse;
    	startY = _root._ymouse;
    }
    gesturesListener.onMouseUp = function()
    {
    	endX = _root._xmouse;
    	endY = _root._ymouse;
     
    	checkGesture();
    }
    Mouse.addListener(gesturesListener);

    The onMouseDown() function just sets the starting coordinates values, while the onMouseUp() also calls the checkGesture() function, defined below, that will check if the touch interaction was actually a gesture.

    Step 2. Identify a gesture

    Before trying to identify a gesture, let’s define some variables used to identify and define specific gesture types:

    // minimum length of an horizontal gesture
    var MIN_H_GESTURE:Number = Stage.width / 3;
    // minimum length of a vertical gesture
    var MIN_V_GESTURE:Number = Stage.height / 3;
     
    // flags for each kind of gesture
    var UP_TO_DOWN:Number = 1;
    var DOWN_TO_UP:Number = 2;
    var LEFT_TO_RIGHT:Number = 4;
    var RIGHT_TO_LEFT:Number = 8;

    The MIN_H_GESTURE and MIN_V_GESTURE variables define the minimum horizontal and vertical distances that must exist between the onMouseDown() and the onMouseUp() event to have, respectively, a horizontal or a vertical gesture.

    Now, we can easily implement the checkGesture() function, by getting the horizontal and vertical length of the touch interaction, and comparing them with the minimum distances defined above.

    function checkGesture()
    {
    	var xDelta:Number = endX - startX;
    	var yDelta:Number = endY - startY;
     
    	var gesture:Number = 0;
     
    	if(xDelta > MIN_H_GESTURE)
    		gesture |= LEFT_TO_RIGHT;
    	else if(xDelta < - MIN_H_GESTURE)
    		gesture |= RIGHT_TO_LEFT;
     
    	if(yDelta > MIN_V_GESTURE)
    		gesture |= UP_TO_DOWN;
    	else if(yDelta < - MIN_V_GESTURE)
    		gesture |= DOWN_TO_UP;
     
    	if(gesture > 0)
    		handleGesture(gesture);
    }

    Step 3. Handling the detected gesture

    Once identified a gesture, we have to actually handle it in some way. To do it, we’ll implement the handleGesture() function, that will check the passed argument to find which is the specific identified gesture.

    In this example, we’ll simply trace the kind of identified gesture(s).

    function handleGesture(gestureFlags:Number)
    {
    	if(gestureFlags & LEFT_TO_RIGHT)
    		trace("left to right gesture");
    	if(gestureFlags & RIGHT_TO_LEFT)
    		trace("right to left gesture");
    	if(gestureFlags & UP_TO_DOWN)
    		trace("up to down gesture");
    	if(gestureFlags & DOWN_TO_UP)
    		trace("down to up gesture");
    }

    Further development

    A lot of improvements can be done to the code presented in this article. Just some example:

    • Detect diagonal gestures: by checking the appropriate gesture flags, it’s already possible to identify mixed diagonal gestures. So, basically you need to extend a bit the handleGesture() method
    • Define a maximum time to perform a gesture: basically, accept a gesture only if the time elapsed to perform it is below a certain limit. This could be useful in some scenarios, to avoid detecting fake gestures.

    Download source code

    You can download the full source code used in this article here:

    Rate this article!

    If you like this article, please vote it on Forum Nokia Wiki. Thanks :)

     
    • joy 5:08 am on April 7, 2009 Permalink

      this is a joss tutorial

    • Rich 3:10 pm on July 20, 2009 Permalink

      Thanks for the tutorial. It’s great!

    • Aj 3:59 pm on August 18, 2009 Permalink

      Hey,

      This is an awesome tutorial and it’s much appreciated.

      I was having some trouble assigning the gestures to soft keys.
      In this tutorial, you are displaying the gestures, However for example could you please tell me how I would be able to assign the “right to left” gesture to the right key?
      Thanks.

    • Supriya Tenany 11:18 am on December 21, 2010 Permalink

      Hi,

      A really good tutorial. I am only waiting for the practical implementation now. How can I check the touch functionalities on the device central? It provides me ‘Multitouch’ but I am unable to use it.

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel