The Space For App Developers

Beyond Plain Old HTML Objects

Archive for the ‘Mobile’ tag

Creating SkinnableContainer skins for Flex mobile apps

with 3 comments

Recently I was looking for an example on how to create a skin that would work with the SkinnableContainer component class in a Flex mobile application. It turned out I couldn’t find any examples available in the wild so I had to dig it out myself. So below is the approach I took, which can also work for others.

The first thing I found out is that there is a SkinnableContainerSkin class in the spark.skins.mobile package that extends MobileSkin class. This is a basic implementation that works out-of-the-box when you use SkinnableContainer in mobile projects. Its only behavior is setting a contentGroup property with a new instance of the Group class and drawing a background rectangle filled with color based on the backgroundColor style.

Now my goal, instead of drawing the background with AS3, was to use a custom FXG file with some rounded corners, simple stroke and gradient. The screenshot below demonstrates what I was looking for:

In order to achieve the example above I extended SkinnableContainerSkin as in the following snippet:

package
{
	import spark.core.SpriteVisualElement;
	import spark.skins.mobile.SkinnableContainerSkin;
 
	public class MySkinnableContainerSkin extends SkinnableContainerSkin
	{
		protected var backgroundClass:Class;
 
		protected var background:SpriteVisualElement;
 
		public function MySkinnableContainerSkin()
		{
			super();
 
			// Here could be a DPI dependent logic, for demo purposes it is not necessary
			backgroundClass = MySkinnableContainerBackground;
		}
 
		override protected function createChildren():void
		{
			// Adding container background
			background = new backgroundClass;
			addChild(background);
 
			// Creating content group instance
			super.createChildren();
		}
 
		override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.layoutContents(unscaledWidth, unscaledHeight);
 
			// Setting size of background container
			setElementSize(background, unscaledWidth, unscaledHeight);
		}
 
		override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
		{
			// By default SkinnableContainerSkin draws Rect with backgroundColor but this is not
			// required in this case since background is constructed of MySkinnableContainerBackground fxg
		}
	}
}

My FXG file content looked like this:

<?xml version='1.0' encoding='UTF-8'?>
<Graphic xmlns:fc="http://ns.adobe.com/flashcatalyst/2009" xmlns:d="http://ns.adobe.com/fxg/2008/dt" 
		 xmlns="http://ns.adobe.com/fxg/2008" version="2.0"
		 scaleGridLeft="10" scaleGridTop="10" scaleGridRight="90" scaleGridBottom="90">
 
	<Rect radiusX="10" width="100" height="100">
		<fill>
			<LinearGradient rotation="90">
				<GradientEntry alpha="1.0" color="#CCCCCC" ratio="0"/>
				<GradientEntry alpha="1.0" color="#666666" ratio="1"/>
			</LinearGradient>
		</fill>
		<stroke>
			<SolidColorStroke color="#FF0000" weight="2"/>
		</stroke>
	</Rect>
 
</Graphic>

And the way I can use it now in my Flex mobile projects is as follows:

<s:SkinnableContainer left="10" top="10" right="10" bottom="10" skinClass="MySkinnableContainerSkin">
	<s:Label left="10" top="10" right="10" bottom="10">
		<s:text>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eget arcu et nibh vehicula pulvinar sit amet sit amet ligula. Duis a orci at nisi faucibus luctus. Quisque congue vulputate porttitor. Curabitur ac turpis nulla, a malesuada diam. Sed ullamcorper massa ac libero tincidunt vel ultrices odio cursus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce pharetra varius tortor id rutrum. Duis tempor, nisl sit amet scelerisque dignissim, lorem nisl vehicula leo, in auctor dolor turpis at nisl. Quisque bibendum faucibus turpis vitae pulvinar. Sed mollis risus eget turpis molestie laoreet. Aenean metus nulla, vestibulum at egestas quis, aliquet tempus lectus.</s:text>
	</s:Label>
</s:SkinnableContainer>

Written by Piotr Walczyszyn

July 14th, 2011 at 4:03 pm

Posted in Articles,Examples

Tagged with ,

Running LCDS/BlazeDS in the cloud with AWS Elastic Beanstalk

without comments

Very recently I was looking for a simple and affordable solution to host Java-based services for the mobile version of my LCDS Samples application. Unfortunately, with the Java development, life is not as easy as with PHP where you can get affordable hosting that is managed and secured by your hosting provider. The reality is that with Java you usually end up having a VPS or an instance of a dedicated Linux server (of course Windows would work also). This is certainly a very good solution that gives you a lot of flexibility but you have to remember that the tasks of administering and securing your box are usually on your shoulders. Although I have some knowledge of Unix-type systems, to be honest I wouldn’t feel comfortable doing the whole administration on my own.

So after some research and trying out different options I ended up with an AWS Elastic Beanstalk service provided by Amazon (you can see it in action running here). I’m really excited about this service because it provides an instance of Tomcat (both 6.x and 7.x versions are available) hosted and managed on Amazon’s cloud infrastructure. On top of that and out-of-the-box, it provides a load balancer that will automatically launch additional instances if your application encounters the increased load. Also you have full access to your Tomcat logs and you can receive email notifications with the status and health of your running services.  Another important thing is that it is extremely easy to use, especially when you install the AWS Eclipse plugin that can also work well with Eclipse/Flash Builder.

The good thing is that the cost of all this is not really high, the entry level service is just about $35.27 a month, more details about pricing are available here.

Getting started

Follow these steps to get up and running:

  1. Get an account (if  you don’t already have one) with AWS (Amazon Web Services). Once you get an account you can sign up for Elastic Beanstalk via the “Manage Your Account” section.
  2. Configure your IDE environment. By default Flash Builder comes with a standard version of Eclipse that has only the JDT available. I suggest downloading the Eclipse IDE for Java EE Developers and to configure FB with this environment. It will give you additional tools to handle Tomcat instances and Java Web Projects, which you can use when developing for Elastic Beanstalk. Configuring FB with a custom installation of Eclipse is really straightforward. Once you download Eclipse from here and you extract it somewhere to your hard drive, you can go to the folder where you have FB installed and find the Adobe Flash Builder 4.5 Plug-in Utility application located in the utilities folder. In my case it is here “/Applications/Adobe Flash Builder 4.5/utilities/Adobe Flash Builder 4.5 Plug-in Utility.app” but it all depends where you have your FB installation and also on what OS you are on. Run this application and it will guide you with a few simple steps through the whole Flash Builder – Eclipse integration process.
  3. Install the AWS Eclipse plugin. This can be done directly from Eclipse. Just go to the Help -> Install New Software menu and enter the following update site URL: http://aws.amazon.com/eclipse
  4. Create a new AWS Java Web Project. After a successful install of the AWS plugin you will have an option to create new AWS projects. Use the wizard available from the top bar of Eclipse (with an AWS icon on it) to create a New AWS Java Web Project. First you will need to enter a project name, and credentials like Access Key ID and Secret Access Key. These values are generated when you sign up for an AWS account and you can copy them from the Security Credentials section of your AWS account.
    You can select the Basic Java Web Application option (see the screenshot above), this will be enough for the LCDS/BlazeDS scenario. More info about other options is available through this site, with an in-depth video tutorial.
  5. Configure the LCDS/BlazeDS  environment. In order to do that you need to, copy all necessary jars into the WebContent/WEB-INF/lib folder of the newly created project. In my case I used a turnkey installation of LCDS and I just copied jars from the lcds-samples application and also jars from tomcat/lib/activemq4.1.1, tomcat/lib/jotm2.0.10 and tomcat/lib/lcds (this wouldn’t be necessary for BlazeDS but for LCDS it was required to make the DataServices and Messaging work properly). Next you will also need to copy all configuration files from the WEB-INF/flex folder and the web.xml that has all necessary LCDS/BlazeDS servlets/listeners configured. The important thing to note here is that by default the AWS Elastic Beanstalk service enables only port 80 and HTTP channels; in order to enable other ports that could be required for RTMP channels you can modify the AWS EC2 Security group settings (but that is a topic for another blog post and I will not cover it here). Another solution you have is to stick to the default settings and to configure LCDS services to use only HTTP channels; this is actually what I did for my lcds.riaspace.comservice.    One last thing I had to do to make the LCDS function properly was to create a WebContent/META-INF/context.xml file in which I defined the transaction configuration as in the following snippet:
    <?xml version="1.0" encoding="UTF-8"?>
    <Context reloadable="true">
      <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
    </Context>
  6. Deploy your application to the cloud. Once you have the configuration completed and all the services built you can deploy your application directly from Eclipse. Just right-click on the project and select the Amazon Web Services -> Deploy to AWS Elastic Beanstalk… option. Another wizard will pop up that will ask you to specify names for your application and environment.Next you will need to select the server type, which would be AWS Elastic Beanstalk for Tomcat 6 (you also have the option to deploy to Tomcat 7 instances).
    At last you will be able to specify the CNAME of your server (you can assign your own domain name in the DNS configuration, that is actually what I used to get the default lcds-samples.elasticbeanstalk.com configured as lcds.riaspace.com). Another valuable option here is to enter your email address, which will receive notifications of any changes to the service’s state and health.

    Now you are ready to click the Finish button and it will start uploading and configuring your application in the cloud. Be aware that this process may take several minutes the first time. Once it is done you will be able to access your services via the following URL: http://yourcname.elasticbeanstalk.com. To redeploy any changes made to your services you just need to follow this last step all over again.

Written by Piotr Walczyszyn

July 11th, 2011 at 2:47 pm

Posted in Articles,Examples

Tagged with , , , , , ,

LCDS Messaging on tablet devices

with 4 comments

Recently I wanted to try the LiveCycle Data Services (LCDS) messaging feature on tablet devices. LCDS is a platform that lets you easily integrate Flash/Flex/AIR RIAs with JEE back ends, giving your applications full real-time capabilities on the web.

In order to run my tests I ported one of the LCDS demo apps that is included in the package to Flex 4.5 and published it to Motorola XOOM (running Android 3.1), BlackBerry PlayBook and the iPad. You can watch the results in the video below.



Written by Piotr Walczyszyn

May 17th, 2011 at 3:10 pm

Posted in Examples,Recording

Tagged with , , ,

as3viewnavigator – ViewNavigator for as3/flash projects

with 43 comments

I’m currently working on an application for the BlackBerry PlayBook tablet. The API that comes with the PlayBook SDK is based on pure AS3. Of course I could use Flex Hero for the job but I wanted to try out the “native” stuff that it comes with. My impression so far is really positive and the only thing that I’ve found missing so far was the concept of Views and ViewNavigator that comes with Flex Hero for mobile devices.

That is why I took a bit of time today to create library heavily inspired by ViewNavigator from Flex Hero that I could use for my pure as3/flash projects. The library is available for download here. Also checkout the video below for the details on how to use it.

Just for the reference, to tween the view transitions I used Tweener library that is also used internally by PlayBook API.

Below is the snippet of code that implements the example from the video above, you can also download the project source from here.

package
{
	import com.riaspace.as3viewnavigator.ViewNavigator;
 
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.MouseEvent;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
 
	import qnx.ui.buttons.LabelButton;
	import qnx.ui.core.Container;
	import qnx.ui.core.ContainerAlign;
	import qnx.ui.core.ContainerFlow;
	import qnx.ui.core.SizeMode;
	import qnx.ui.core.Spacer;
	import qnx.ui.text.Label;
 
	[SWF(width="600", height="1024", backgroundColor="#FFFFFF", frameRate="30")]
	public class Main extends Sprite
	{
		private var navigator:ViewNavigator;
 
		private var viewNumber:int = 0;
 
		public function Main()
		{
			initializeUI();
		}
 
		private function initializeUI():void
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			// Creating instance of ViewNavigator
			navigator = new ViewNavigator(this);
			// Pushing first view to the navigator
			navigator.pushView(createView());
		}
 
		private function createView():Container
		{
			var view:Container = new Container;
			view.flow = ContainerFlow.VERTICAL;
			view.align = ContainerAlign.MID;
 
			// Incrementing view number
			viewNumber++;
 
			// 20% spacer from the top
			view.addChild(new Spacer(20));
 
			// Adding label with view number
			var numLabel:Label = new Label;
			numLabel.text = viewNumber.toString();
			var format:TextFormat = new TextFormat;
			format.size = 70;
			format.bold = true;
			format.align = TextFormatAlign.CENTER;
			numLabel.format = format;
			numLabel.size = 100;
			numLabel.sizeMode = SizeMode.BOTH;
			view.addChild(numLabel);
 
			// 15% spacer between label above and buttons
			view.addChild(new Spacer(15));
 
			// Adding "push view" button
			var btn:LabelButton = new LabelButton;
			btn.label = "push view";
			btn.addEventListener(MouseEvent.CLICK,
				function(event:MouseEvent):void
				{
					navigator.pushView(createView());
				});
			view.addChild(btn);
 
			// Adding "pop view" button
			btn = new LabelButton;
			btn.label = "pop view";
			btn.addEventListener(MouseEvent.CLICK,
				function(event:MouseEvent):void
				{
					navigator.popView();
				});
			view.addChild(btn);
 
			// Adding "pop all" button
			btn = new LabelButton;
			btn.label = "pop all";
			btn.addEventListener(MouseEvent.CLICK,
				function(event:MouseEvent):void
				{
					navigator.popAll();
				});
			view.addChild(btn);
 
			// Adding "pop to first button" button
			btn = new LabelButton;
			btn.label = "pop to first";
			btn.addEventListener(MouseEvent.CLICK,
				function(event:MouseEvent):void
				{
					navigator.popToFirstView();
				});
			view.addChild(btn);
 
			// Adding "replace" button
			btn = new LabelButton;
			btn.label = "replace";
			btn.addEventListener(MouseEvent.CLICK,
				function(event:MouseEvent):void
				{
					navigator.replaceView(createView());
				});
			view.addChild(btn);
 
			return view;
		}
	}
}

Written by Piotr Walczyszyn

February 2nd, 2011 at 9:11 pm

Paged list loaded from sqlite in Adobe AIR

with 2 comments

During my recent work on the Adobe Evangelists Blogroll application I wanted to implement a lazy-loaded/paginated List component with data coming from a local SQLite database. The reason for this was, of course, a memory usage consideration. Adobe Evangelists Blogroll is a mobile application so I didn’t want to load all available Post objects for each selected blog at once. I wanted it to be loaded dynamically as the user scrolls through the list. It turned out this wasn’t really difficult but there were few gotchas that I wanted to share:

  1. You have to implement your own IList component that throws ItemPendingError whenever the item requested with getItemAt function is not available yet. Unfortunately the Flex SDK doesn’t come with one built-in, but the good news is that you can use PagedArrayList class I created; its source code is available here :)
  2. Implement a createPendingItemFunction for the AsyncListView component. This function gets called when ItemPendingError is thrown and in our case serves two purposes. One is to trigger fetching the next page of rows from the database. It also returns a String with text that will be displayed temporarily in missing rows of the List. When that data gets fetched from the database those missing rows will be replaced with the loaded ones.
  3. One gotcha for the previous point is that if you are using SQLConnection in synchronous mode you will have to start fetching rows in the next frame after the call to the createPendingItemFunction function. That is why in my example I’m using callLater to execute the fetchRows function. This problem doesn’t arise with an asynchronous database connection.
  4. The last gotcha is most likely a bug in the Flex SDK. It occurs when the AsyncListView.list property is set before its list object is initialized and its length value is set. In that case invalidIndex error is thrown inside of LinearLayoutVector. The workaround I came up with is that right after setting the length property, PagedArrayList dispatches FlexEvent.INITIALIZE event; the application logic should handle it and programmatically set the AsyncListView.list property to the PagedArrayList instance. For reference I filed a bug in Flex SDK Jira.

Below you can find the source code that resolves the gotchas above. Also the whole Flash Builder project with paged list implementation is available here.

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   xmlns:helpers="com.riaspace.helpers.*"
					   preinitialize="windowedApplication_preinitializeHandler(event)"
					   creationComplete="windowedApplication_creationCompleteHandler(event)">
 
	<fx:Script>
		<![CDATA[
			import mx.collections.errors.ItemPendingError;
			import mx.events.FlexEvent;
 
			protected var conn:SQLConnection;
 
			protected const PAGE_SIZE:int = 50;
 
			protected function windowedApplication_preinitializeHandler(event:FlexEvent):void
			{
				// Creating inmemory database
				conn = new SQLConnection;
				conn.open();
 
				// Creating data_tab table
				var createStmt:SQLStatement = new SQLStatement;
				createStmt.sqlConnection = conn;
				createStmt.text = "CREATE TABLE data_tab (value_col TEXT)";
				createStmt.execute();
 
				// Inserting 1000 records to the table
				var insertStmt:SQLStatement = new SQLStatement;
				insertStmt.sqlConnection = conn;
				insertStmt.text = "INSERT INTO data_tab VALUES (?)";
 
				for (var i:int = 1; i <= 1000; i++)
				{
					insertStmt.clearParameters();
					insertStmt.parameters[0] = "value " + i;
					insertStmt.execute();
				}
			}
 
			protected function windowedApplication_creationCompleteHandler(event:FlexEvent):void
			{
				// STEP 1 - query rows count
				var stmt:SQLStatement = new SQLStatement;
				stmt.sqlConnection = conn;
				stmt.text = "SELECT count(*) as rowsCount FROM data_tab";
				stmt.execute();
 
				var result:SQLResult = stmt.getResult();
 
				// STEP 2 - set PagedArrayList.length equal queried rows count 
				pagedArrayList.length = result.data[0].rowsCount;
 
				// STEP 3 - fetch actual data starting from 0 offset (1st row)
				fetchRows(0);
			}
 
			protected function fetchRows(offset:int):void
			{
				// Fetch data rows with specified limit which is our requested page size
				// and offset passed as parameter
				var stmt:SQLStatement = new SQLStatement;
				stmt.sqlConnection = conn;
				stmt.text = "SELECT * FROM data_tab LIMIT :limit OFFSET :offset";
				stmt.parameters[":limit"] = PAGE_SIZE;
				stmt.parameters[":offset"] = offset;
				stmt.execute();
 
				var result:SQLResult = stmt.getResult();
				if (result && result.data)
				{
					for(var i:int = 0; i < result.data.length; i++)
					{
						// Setting return row at offset + i position
						pagedArrayList.setItemAt(result.data[i], offset + i);
					}
				}
			}
 
			private function createPendingItemFunctionHandler(index:int, ipe:ItemPendingError):Object
			{
				// In case synchronous database mode is used fetchRows function should be called
				// after return from this function. With asynchronous mode fetchRows function can
				// be called directly.
				callLater(fetchRows, [index]);
 
				// Returning a message to display
				return "List items are being fetched from database...";
			}
 
			protected function pagedArrayList_initializeHandler(event:FlexEvent):void
			{
				// NOTICE: this is a workaround for a Flex bug that causes invalidIndex error
				// in LinearLayoutVector. It all works well when asyncListView.list property
				// is set after pagedArrayList is initialized and its length property is set.
				asyncListView.list = pagedArrayList;
			}
 
		]]>
	</fx:Script>
 
	<fx:Declarations>
		<helpers:PagedArrayList id="pagedArrayList" initialize="pagedArrayList_initializeHandler(event)" />
	</fx:Declarations>
 
	<s:List width="100%" height="100%" labelField="value_col">
		<s:AsyncListView id="asyncListView" createPendingItemFunction="createPendingItemFunctionHandler" />
	</s:List>
 
</s:WindowedApplication>

Written by Piotr Walczyszyn

December 24th, 2010 at 11:21 am

Posted in Examples

Tagged with , ,

Adobe Evangelists Blogroll preview

with 10 comments

Today I’m officially announcing my new mobile application called Adobe Evangelists Blogroll. This is a simple RSS reader type of application that aggregates blog feeds from my fellow Adobe Evangelists. I’ve developed it with a preview release of Flex Hero SDK and it works on all Android devices that can handle AIR runtime. The app is available in Android Market if you look for “Adobe Evangelists Blogroll“.

What I’m also really excited about is that I managed to repackage it into a bar file and run it on BlackBerry PlayBook emulator without doing even single change to the codebase. In the video below you can see it in action running on different devices and also on PlayBook emulator.

As I already mentioned it was built with preview release of Flex SDK and also the app itself is in beta so it may have some quirks here and there. If you have any suggestions, comments or found some bugs you can contact me through this form.

Few screens of the application (running in landscape & portrait orientation and on playbook):

Written by Piotr Walczyszyn

December 20th, 2010 at 2:55 pm

Posted in News,Releases

Tagged with , , , ,

Real-Time Mobile Connectivity

with 16 comments

In the video below I present my new demo of real-time connectivity between applications running on different devices like Apple phone, Nexus One and my Mac. Apple phone runs AIR application built with Flash (source code available here), on the desktop is also an AIR app but built with Flex (source code available here) and on Nexus One is also Flex app (keep in mind that this is not yet Flex Mobile version, source code available here) running in the browser. All of these connect through Java backend with LiveCycle Data Services ES2 (source code available here).

Written by Piotr Walczyszyn

March 16th, 2010 at 9:09 am

Posted in Uncategorized

Tagged with , ,