Posts Tagged ‘Android’

Flex 4.6 and SplitViewNavigator in AIR : Demo application – Finnkino Movies

Adobe Flex 4.6 includes several new and updated mobile-optimized Spark components (for example SplitViewNavigator, CallOutButton, SpinnerList, DateSpinner, Text Enhancements and ToggleSwitch).

In this example I used SplitViewNavigator to show Finnkino‘s Theatres in the first view of the SplitViewNavigator. Second view shows the selected Theatre’s movies (what are running at this day) or all movies that are running in Finnkino’s Theatres.

<s:SplitViewNavigator id="splitNavigator" width="100%" height="100%" autoHideFirstViewNavigator="true">
<s:ViewNavigator id="areasView" width="200" height="100%" firstView="views.AreaCategory"/>
<s:ViewNavigator id="detailView" width="100%" height="100%" firstView="views.MoviesTileView">
<s:Button id="navigatorButton" label="Valitse Teatteri"

Movies in Landscape mode

SplitViewNavigator is working very nicely and it hide’s the first view in navigator when tablet is rotated to Portrait. You should add resize event handling to your application and use states in ActionContent in ViewNavigator.

<s:Application resize="resizeHandler(event);">
protected function resizeHandler(event:ResizeEvent):void {
currentState = aspectRatio;
<s:State name="portrait"/>
<s:State name="landscape"/>

Movies in Portrait mode

List and ItemRenderers
I have used List to show all the movie items and own made ItemRenderer to display some basic information (or just movie image when all the movies are selected from the main list).

<s:List id="moviesList"
width="100%" height="100%"
<s:TileLayout id="tileList"
paddingLeft="5" paddingRight="5" paddingTop="5" paddingBottom="5" horizontalGap="5" verticalGap="5"
// MovieAreaTile
<s:Image source="{data.Images.EventSmallImagePortrait}" />
<s:Label id="title" styleName="title" text="{data.Title}" />
<s:Label id="startTime" styleName="data" text="{data.dttmShowStart}" />
<s:Label id="length" styleName="data" text="{data.LengthInMinutes} min" />
<s:Label id="theatre" styleName="data" text="{data.TheatreAndAuditorium}" />
<s:Label id="genre" styleName="data" text="{data.Genres}" />

All the Movies in Finnkino’s Theatres

SQLite: Automatically display same Theatre which was used in previous time
In this example I store theatreID and theatreName to SQLite database every time when a new Theatre is selected. Those values are used when application is started again.

Connection to database:

private function connect(type:Number):void {
dbConn = new SQLConnection();
if (type == CREATE_DB) dbConn.addEventListener(SQLEvent.OPEN, createTable);
else dbConn.addEventListener(SQLEvent.OPEN, getTheatreData);
dbConn.addEventListener(SQLErrorEvent.ERROR, errorHandler);

Create a table:

private function createTable(event:SQLEvent):void {
var dbStatement:SQLStatement = new SQLStatement();
dbStatement.sqlConnection = dbConn;
dbStatement.addEventListener(SQLEvent.RESULT, theatreTableCreated);
dbStatement.addEventListener(SQLErrorEvent.ERROR, errorHandler);
dbStatement.text = "CREATE TABLE IF NOT EXISTS movieTable (id INTEGER PRIMARY KEY AUTOINCREMENT, theatreID TEXT, theatreName TEXT);";

Table is created a first time -> add some sample data to table

private function theatreTableCreated(event:SQLEvent):void {
var dbStatement:SQLStatement = new SQLStatement();
dbStatement.sqlConnection = dbConn;
// just set default data when table is created
theatreID = 1015;
theatreName = "Jyväskylä";
dbStatement.text = "INSERT INTO movieTable (theatreID, theatreName) VALUES(‘"+theatreID+"’,’"+theatreName+"’);";

Theatre (id and name) data is added first time, load events with HTTPService

<s:HTTPService id="finnkinoArea" showBusyCursor="true" url="{url}"

private function theatreDataAdded(event:SQLEvent):void {

private function getTheatreData(event:SQLEvent):void {
var dbStatement:SQLStatement = new SQLStatement();
dbStatement.sqlConnection = dbConn;
dbStatement.text = "SELECT theatreID, theatreName FROM movieTable where id=1";

TheatreID and name is loaded from SQLite, start loading XML data from Finnkino’s service

private function theatreResult(event:SQLEvent):void {
var dbResult:SQLResult = SQLStatement(;
theatreID =[0].theatreID;
theatreName =[0].theatreName;
// load previous used theatre
public function loadEvents(theatreID:uint):void {
// one Teatre
if (theatreID != -1) url = urlBase + theatreID;
// all events from Finnkino
else url = "";
// call HTTPService

Movie Details
Movie details are shown when user clicks MovieTile from TileView. Finnkino’s Service offers a lot of information about the movie. In this example I only display some sample data and movie trailer. Movie trailer can be played in fullscreen mode too (use this only in Landscape – there a some issues in portrait mode – in this example :-)

<s:Scroller width="100%" height="100%">
<s:VGroup width="100%">
<s:Image source="{data.Images.EventLargeImagePortrait}" />
<s:Label text="{data.Title} ({data.OriginalTitle})" styleName="title"/>
<s:Label text="{data.RatingLabel}" styleName="data" />
<s:Label id="startTime" styleName="data" text="{data.dttmShowStart}" />
<s:Label id="length" styleName="data" text="{data.LengthInMinutes} min" />
<s:Label id="genre" styleName="data" text="{data.Genres}" />
<s:Label id="showUrl" styleName="dataBlue" text="{data.ShowURL} – (osta liput)" click="showUrl_clickHandler(event)" />
<s:Label id="eventUrl" styleName="dataBlue" text="{data.EventURL} – (lisätietoa elokuvasta)" click="eventUrl_clickHandler(event)" />
<s:Label text="{movieData.Synopsis}" width="100%" styleName="synopsis" />
<s:VideoPlayer id="myVideo" source="{movieData.Videos.EventVideo.Location}" autoPlay="false" visible="{isVideo}" width="{this.width-20}"/>
<s:Button label="Takaisin" id="takaisin" click="takaisin_clickHandler(event)"/>

Movie details in Landscape mode

Movie details in Portrait mode

Movie trailer in fullscreen

Source codes

There are a few bugs in this example (too). Sometimes the date is missing from first views, and VideoPlayer is messing up if it is in fullscreen mode in Landscape and you turn the device to portrait.. but now it is working for my purposes :-) and finally I have only tested this in Samsung Galaxy Tab 10.1 not in mobile…

This example uses Finnkino’s Services

Send pictures from Android device to Windows with AIR applications

In this example I will show how you can take and send pictures from Android phone to Windows application using Adobe AIR in Android and Windows.

Create AIR for Android application (to take and send picture)

In Adobe AIR 2.5 there is Camera UI class that allows you to capture a still image or video using the default camera application on a device. First check that Camera is supported and create a new Camera UI object and register MediaEvent.COMPLETE to call onComplete function when picture is taken.

After that establish a new NetConnection for P2P in the local network (LAN). This can be done by specifying connection string as “rtmpf:” in NetConnection.

private function init():void {
if (CameraUI.isSupported){
myCam = new CameraUI();
myCam.addEventListener(MediaEvent.COMPLETE, onComplete);
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);

When connection is made netStatus function will be called. If NetConnection is ok it is time to setup own group for multicasting. You can set up your own NetGroup with GroupSpecifier. Enable local connections between peers and set your IP address and port for multicasting. You can find more details about multitasking for example here: (Tom Krcha – thanks about your excellent demos and work with Flash based Technologies).

private function netStatus(event:NetStatusEvent):void {
switch( {
case "NetConnection.Connect.Success":
var groupspec:GroupSpecifier = new GroupSpecifier("fi.ptm.imageApp/myChannel");
groupspec.postingEnabled = true;
groupspec.ipMulticastMemberUpdatesEnabled = true;
group = new NetGroup(nc,groupspec.groupspecWithAuthorizations());
group.addEventListener(NetStatusEvent.NET_STATUS, netStatus);

A new picture is taken when user presses Take Picture Button in device’s screen. Picture is taken with Android Native Camera Application (using with Camera UI class) and onComplete will be called when picture is taken.

In this example image is shown with <mx:Image id=”image”> and image URL is used when image is sent to Windows AIR application.

private function takePicture():void {
image.filters = [];
if (CameraUI.isSupported) myCam.launch(MediaType.IMAGE);

private function onComplete(evt:MediaEvent):void{
image.source =;
imageURL =;

Image is converted to ByteArray and all of those bytes is sent to Windows AIR application when user clicks send button in the devices screen.

private function sendPicture():void {
var fs:FileStream = new FileStream(); File(imageURL), FileMode.READ);
var bytes:ByteArray = new ByteArray();
if (bytes == null) {
trace("Image bytes is null!");
} else {
// create a new object with image data and image count (sent)
var message:Object = new Object();
message.bytes = bytes;
message.images = ++imagesSent;;
trace("Pictures sent:"+imagesSent);

Create AIR local client in Windows (receive images)

Windows AIR application is connected to same group and it is waiting for images from AIR for Android application. If we get a new netStatus with NetGroup.Posting.Notify message then a new image is received from Android. First new Sprite is created and all of those image bytes is loaded with Loader.

public function receivePicture(message:Object):void {
imageContainer = new Sprite();
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.allowCodeImport = false;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onPicLoaded,false,0,true);
loader.loadBytes(message.bytes, loaderContext);
// add a new sprite to hold image
imageSprite = new Sprite();

ImageSprite is a wrapped for a new image sprite to get Parallel image animation into it (scaling, positioning and sizing) for 4 seconds.

private function onPicLoaded(e:Event):void {
imageSprite.x = -imageContainer.width / 2;
imageSprite.y = -imageContainer.height / 2;
imageContainer.x += imageContainer.width / 2;
imageContainer.y += imageContainer.height / 2;
startX = imageContainer.width / 2;
startY = imageContainer.height / 2;
targetX = Math.floor(Math.random()*frame.width);
var borderSize:uint = 100;
if (targetX < borderSize) targetX = borderSize;
if (targetX > (frame.width-borderSize)) targetX = frame.width – borderSize;
targetY = Math.floor(Math.random()*frame.height);
if (targetY < borderSize) targetY = borderSize;
if (targetY > (frame.height-borderSize)) targetY = frame.height – borderSize;
startRotation = Math.floor(Math.random()*360);
if (Math.random() > .5) targetRotation = startRotation + 180;
else targetRotation = startRotation – 180;;

Here is a basic parallel animation used to make a cool sliding effect with a new images. All previous taken images will be visible there too.

<mx:Parallel id="imageAnimation" target="{imageContainer}" >
<mx:AnimateProperty property="scaleX" fromValue="1" toValue="0.2" duration="4000" />
<mx:AnimateProperty property="scaleY" fromValue="1" toValue="0.2" duration="4000" />
<mx:AnimateProperty property="x" fromValue="{startX}" toValue="{targetX}" duration="4000" />
<mx:AnimateProperty property="y" fromValue="{startY}" toValue="{targetY}" duration="4000" />
<mx:AnimateProperty property="rotation" fromValue="{startRotation}" toValue="{targetRotation}" duration="4000" />

Testing and source codes

You have to install Flex 4.1 (or newer) and AIR 2.5 SDK to try these examples (just copy/overwrite AIR SDK 2.5 to Flash Builder sdks/4.1.0 folder, or make copy from 4.1.0 to for example FlexAIR2.5 folder and overwrite there).

Update: Namedays widget for Android

It was time to update my Namedays widget for Android.  Now you can configure background and text colors in configure view. In configure view you can see how your widget will looks like and just save your settings when you are ready. Namedays supports now 14 countries. Please email me to get your country included.

Just tap namedays widget:
– header text to refresh data,
– name day text to show next name and
– footer to configure again.

You can find Namedays widget in Android Market’s Social Category or just search “Namedays”. Note: You have to remove earlier version to get new configuration view working!

Hope you like it now.