Friday, July 13, 2012

AS3 : Toggle Fullscreen

The other day, friends were asking me how to do full screen popup for flash. So here I am with a simple demo for creating a full screen swf popup. (Note: the full screen popup can only be trigger by a generic mouse click only.)

Time for some coding... The main as file for the swf - Main.as
package com.zcs 
{ 
 import flash.events.Event;
 import flash.display.MovieClip;
 import flash.events.MouseEvent;
 import flash.display.StageDisplayState;

 public class Main extends InterfaceSetup implements IInterfaceSetup
 {
  private var _top_mc:MovieClip;
  private var _bottom_mc:MovieClip;
  private var _left_mc:MovieClip;
  private var _right_mc:MovieClip;
  
  private var _cover_mc:MovieClip;
  
  public function Main():void 
  {
   // constructor code
  }
  
  //Override the stage variables
  override public function setupStageEvent(event:Event):void
  {
   super.setupStageEvent(event);
   stageWidthF = 600;
   stageHeightF = 400;
   
   _top_mc = this.getChildByName("top_mc") as MovieClip;
   _bottom_mc = this.getChildByName("bottom_mc") as MovieClip;
   _left_mc = this.getChildByName("left_mc") as MovieClip;
   _right_mc = this.getChildByName("right_mc") as MovieClip;
   
   _cover_mc = this.getChildByName("cover_mc") as MovieClip;
   _cover_mc.buttonMode = true;
   _cover_mc.addEventListener(MouseEvent.CLICK, clickEvent);
   
   resizeEvent();
  }
  
  //Upon Screen Resize....
  override public function resizeEvent(event:Event = null):void
  {
   //Scale and position the MovieClip accordingly
   resizeSubFunc(_top_mc, "50%", "l", "0", "t", 1);
   resizeSubFunc(_bottom_mc, "50%", "l", "0", "b", 1);
   resizeSubFunc(_left_mc, "0", "l", "50%", "t", 1);
   resizeSubFunc(_right_mc, "0", "r", "50%", "t", 1);
   resizeSubFunc(_cover_mc, "0", "l", "0", "t", 1);
  }
  
  private function clickEvent(event:Event):void
  {
   toggleFullScreen();
  }
  
  private function toggleFullScreen():void
  {
   //if normal size, go to fullscreen, else go to normal size
   if(stage.displayState==StageDisplayState.NORMAL){
    stage.displayState=StageDisplayState.FULL_SCREEN;
   }else{
    stage.displayState=StageDisplayState.NORMAL;
   }
  }  
 }
}
This is an simple as file that I have been using for reusing some screen resize functions - InterfaceSetup.as
package com.zcs
{
 import flash.display.MovieClip;
 import flash.events.*;
 import flash.system.*;
 import flash.external.*;
 
 public class InterfaceSetup extends MovieClip implements IInterfaceSetup
 {
  public var stageWidthF;
  public var stageHeightF;
  
  public function InterfaceSetup():void
  {
   this.addEventListener(Event.ADDED_TO_STAGE, setupStageEvent);
  }
  
  //setup the stage after this is added to stage and listen for resize of flash file
  public function setupStageEvent(event:Event):void
  {
   this.removeEventListener(Event.ADDED_TO_STAGE, setupStageEvent);
   stageWidthF = 1024;
   stageHeightF = 768;
   
   stage.addEventListener(Event.RESIZE, resizeEvent);
  }
  
  //resize event
  public function resizeEvent(event:Event = null):void
  {
   
  }
  
  //sub resize function that requires the following variables
  //tempMC = the movieclip lo :P
  //tempPosX, the x position (ex: 0 || 50%)
  //Hdir, from l (left) or r (right)
  //tempPosY, the y position (ex: 0 || 50%)
  //Vdir, from t (top) or b (bottom)
  public function resizeSubFunc(tempMC,tempPosX,Hdir,tempPosY,Vdir,scaleByScreen = 0):void
  {
   var strArray;
   
   if(scaleByScreen == 1){
    tempMC.scaleX = (stage.stageWidth/stageWidthF) * 1;
    tempMC.scaleY = (stage.stageHeight/stageHeightF) * 1;
   }else if(scaleByScreen == -1){
    tempMC.scaleX = (stage.stageHeight/stageHeightF) * 1;
    tempMC.scaleY = (stage.stageWidth/stageWidthF) * 1;
   }
   
   if(Hdir == "l"){
    tempMC.x = -1 * ((stage.stageWidth - stageWidthF) / 2);
    if(String(tempPosX).indexOf("%") != -1)
    {
     strArray = String(tempPosX).split("%");
     tempMC.x += (int(strArray[0])/100) * stage.stageWidth;
    }else{
     tempMC.x += Number(tempPosX);
    }
   }else{
    tempMC.x = stageWidthF + ((stage.stageWidth - stageWidthF) / 2);
    if(String(tempPosX).indexOf("%") != -1)
    {
     strArray = String(tempPosX).split("%");
     tempMC.x -= (int(strArray[0])/100) * stage.stageWidth;
    }else{
     tempMC.x -= Number(tempPosX);
    }
   }
   
   if(Vdir == "t"){
    tempMC.y = -1 * ((stage.stageHeight - stageHeightF) / 2);
    if(String(tempPosY).indexOf("%") != -1)
    {
     strArray = String(tempPosY).split("%");
     tempMC.y += (int(strArray[0])/100) * stage.stageHeight;
    }else{
     tempMC.y += Number(tempPosY);
    }
   }else{
    tempMC.y = stageHeightF + ((stage.stageHeight - stageHeightF) / 2);
    if(String(tempPosY).indexOf("%") != -1)
    {
     strArray = String(tempPosY).split("%");
     tempMC.y -= (int(strArray[0])/100) * stage.stageHeight;
    }else{
     tempMC.y -= Number(tempPosY);
    }
   } 
   tempMC.x = Math.ceil(tempMC.x);
   tempMC.y = Math.ceil(tempMC.y);
  }
 }
}
A simple Interface file - IInterfaceSetup.as
package com.zcs
{
 import flash.events.Event;

 public interface IInterfaceSetup 
 {
  // Interface methods:
  function setupStageEvent(event:Event):void;
  function resizeEvent(event:Event = null):void;
 }
}
Main HTML file - main.html
<html>
 <head>
<style type="text/css">
<!--
html{height:100%}
body {
 margin-left: 0px;
 margin-top: 0px;
 margin-right: 0px;
 margin-bottom: 0px;
 background-color: #000;
}
#flashContent {width:100%;height:100%;}
-->
</style>
    
   <!-- Include support librarys first -->  
  <script type="text/javascript" src="jsScript/swfobject.js"></script>
  <script type="text/javascript" src="jsScript/swfforcesize.js"></script>      
  <script type="text/javascript" src="jsScript/swfaddress.js?tracker=null"></script>    


    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <table cellpadding="0" cellspacing="0" border="0" width="100%" height="100%">
    <tr><td align="center">
    <div id="flashContent">
         <h1>You need at least Flash Player 10.0 to view this page.</h1>
                <p><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>
    </div>
  <script type="text/javascript">
   function createSWF(){
    var now=new Date();
    now = Date.UTC(now.getYear(),now.getMonth(),now.getDate(),now.getHours(),now.getMinutes(),now.getSeconds());
    var swfURL = "swf/main.swf?date=" + now;
    var flashvars = {};
    var params = {bgcolor:"#FFFFFF"};
    //Need to set allowfullscreen to "true"
    params.allowfullscreen = "true";
    //By changing scale to "exactFit" will make the swf
    //fill up all the spaces in the browser window
    params.scale = "exactFit";

    var attributes = {};
    attributes.name = "flashContent";
    swfobject.embedSWF(swfURL, "flashContent", "100%", "100%", "10.0.2", null, flashvars, params, attributes);   
   }
   createSWF();
  </script>    
     </td></tr></table>  
</body>
</html>
* Click here for the demo.
(Click on any part of the flash file to show the full screen popup.)
^ Click here for the source files of the demo.

Wednesday, July 4, 2012

AS3: Mesmerizing Stars

Someone has asked me how to create a 'mesmerizing galaxy' in Flash. Well, there's definitely more than one way of doing it and one of them will be tweening the whole animation... which is kind of crazy. Well here's an easier way of doing it. :P

Main.as (The .as file of the fla file)
package com.massStar
{
 import flash.display.MovieClip;
 import flash.events.Event;
 
 public class Main extends MovieClip 
 {
  public function Main() 
  {
   //Upon adding the flash file to the stage
   this.addEventListener(Event.ADDED_TO_STAGE, stageEvent);
  }
  
  //Create a grid of animated stars
  private function stageEvent(event:Event):void
  {
   var tempStar:Star_mc;
   for(var i:int = 0; i <= 400; i += 40)
   {
    for(var j:int = 0; j <= 320; j += 40)
    {
     tempStar = new Star_mc();
     tempStar.x = i;
     tempStar.y = j;
     this.addChild(tempStar);
    }
   }
  }
 } 
}
Star.as (The .as file of the star animation)
package com.massStar
{
 import flash.display.MovieClip;
 import flash.events.Event;
 
 public class Star extends MovieClip 
 {
  public function Star() {
   //Upon adding the animated star on stage...
   this.addEventListener(Event.ADDED_TO_STAGE, stageEvent);
  }
  
  private function stageEvent(event:Event)
  {
   //we will select a random frame and start playing the
   //animation sequence from that random frame
   var tempFrame:int = this.totalFrames;
   this.gotoAndPlay(Math.floor(Math.random() * tempFrame));
  }
 }
}
* Click here for the demo.
^ Click here for the source files of the demo.

Thursday, June 28, 2012

PHP: Playing with a simple form

I was trying to come up with a solution to minimise the number of php files needed to manipulate and submit the form data and this is the solution that I have come up with. :D (Though it can be done using 3 php files but too many files lah...)

form.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<?
 $hasPostData = "false";
 $name = "";
 $address = "";
 $info = "";
 //Check if this php file has receive any form data
 //through POST method.
 if(isset($_POST["form_name"]))
 {
  $hasPostData = "true";
  $name = $_POST["form_name"];
  $address = $_POST["form_address"];
  $info = $name.$address;
 }
?>
</head>
<body>
<form action="" method="post" name="loginForm">
Name: <input type="text" name="form_name" size="32"/><br />
Address: <input type="text" name="form_address" size="32"/><br />
<input type="submit"/>
</form>
<?
 //If you have submitted some data thru the form, 
 //we need to send the data to the next php file.
 if($hasPostData === "true")
 {
  echo "<form action='nextPage.php' method='post' name='mainLoginForm'>";
  echo "<input type='hidden' name='name' value='". $name ."'/>";
  echo "<input type='hidden' name='address' value='". $address ."'/>";
  echo "<input type='hidden' name='info' value='". $info ."'/>";
  echo "</form>";
  echo "<script type='text/javascript'>";
  echo "function sendFormData(){document.mainLoginForm.submit();}";
  echo "sendFormData();";
        echo "</script>";
 }
?>
</body>
</html>
nextPage.php
<?
 if(isset($_POST["info"]))
 {
  echo $_POST["info"];
 }
?>
* Click here for the demo.
^ Click here for the source files of the demo.

Saturday, June 23, 2012

Android: Playing with a Singleton

A few weeks ago, I have shown you the steps of creating a Singleton object for Flex applications. As for this week, I am going to show you how to create a Singleton for a Android Application.


Image of Demo Android App.
The App that I am showing in this post will be using the Singleton
object to store the number of clicks.

Main application file - zcs/simpleSingleton/SimpleSingletonActivity.java
package zcs.simpleSingleton;

import android.app.Activity;
import android.os.Bundle;

public class SimpleSingletonActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

A reusable Custom Component File - zcs/simpleSingleton/CustomComponent.java
package zcs.simpleSingleton;

import zcs.singleton.MainSingleton;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class CustomComponent extends LinearLayout 
{
 private TextView txt = null;
 
 public CustomComponent(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub      
  LayoutInflater.from(context).
   inflate(R.layout.layout_custom_component, this, true);
  
  Button btn = (Button) this.findViewById(R.id.btn);
  btn.setOnClickListener(clickListener);
  
  txt = (TextView) this.findViewById(R.id.txt);
 }
 
 // Create a clickListener of type OnClickListener
 // Which will be added to the Button
 private OnClickListener clickListener = new OnClickListener() 
 {
  @Override
  public void onClick(View arg0) {
   //Create an instance of MainSingleton
   MainSingleton tempObj;
   tempObj = MainSingleton.getInstance();
   //Get the current value for Counter and
   //increase it by 1
   int tempCount = tempObj.getCounter() + 1;
   //Set it back to the MainSingleton
   tempObj.setCounter(tempCount);
   
   //Update the text of the label
   txt.setText("Number of Counts:" + tempCount);
  }
 };

}

Main Singleton File - zcs/singleton/MainSingleton.java
package zcs.singleton;

public class MainSingleton 
{
 private static MainSingleton instance;
 
 public static MainSingleton getInstance()
 {
  //If the Singleton is not found, create
  //an instance of it and init / reset the
  //values.
  if(instance == null)
  {
   instance = new MainSingleton();
   instance.reset();
  }
  return instance;
 }
 
 //function to reset data
 public void reset()
 {
  _counter = 0;
 }
 
 //Variable storing the number of counter
 private int _counter = 0;

 public int getCounter() {
  return _counter;
 }

 public void setCounter(int _counter) {
  this._counter = _counter;
 }
 
}
Main Application XML Layout file - layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <zcs.simpleSingleton.CustomComponent
        android:layout_width="wrap_content"
     android:layout_height="wrap_content"/>
    <TableLayout 
        android:layout_width="fill_parent"
     android:layout_height="fill_parent">
        <LinearLayout 
            android:layout_width="fill_parent"
      android:layout_height="wrap_content">
         <zcs.simpleSingleton.CustomComponent
          android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
     </LinearLayout>
        <LinearLayout 
            android:layout_width="fill_parent"
      android:layout_height="wrap_content">
         <zcs.simpleSingleton.CustomComponent
          android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
     </LinearLayout>
     <TableLayout 
         android:layout_width="fill_parent"
      android:layout_height="fill_parent">
         <LinearLayout 
             android:layout_width="fill_parent"
       android:layout_height="wrap_content">
          <zcs.simpleSingleton.CustomComponent
           android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
      </LinearLayout>
         <LinearLayout 
             android:layout_width="fill_parent"
       android:layout_height="wrap_content">
          <zcs.simpleSingleton.CustomComponent
           android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
      </LinearLayout>
     </TableLayout>
    </TableLayout>
</LinearLayout>
Custom Component Layout File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <Button android:id="@+id/btn"         
         android:text="@string/btn_name"
         android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
    <TextView android:id="@+id/txt"    
         android:text="@string/txt_name"     
         android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>
</LinearLayout>
* Click here to download the source files of this Android Demo.

Thursday, June 14, 2012

Flex: Pasting a serial number

In the past if you want to detect pasting of a text into a normal text field, you probably can try checking for Ctrl+V but what about the paste option on a mouse right click menu? Well, you can always start looking out for the change of the text in the text field, but that will become more and more complicated... :( As for today, I 'm going to show you a easier way to do it...

Here's the source code of my main application.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx"
      width="100%" height="100%">
 <fx:Script>
  <![CDATA[
   import flashx.textLayout.operations.PasteOperation;
   
   import spark.events.TextOperationEvent;
   
   //Max number of char that we allow in each text field.
   public static var numOfMaxChar:int = 4;
   //Number of text field that we have
   public static var numOfBox:int = 4;
   //Delimiter or seperator 
   public static var delimiter:String = "-";
   
   //Upon changing the text in each text field...
   protected function changeHandler(event:TextOperationEvent):void
   {
    var tempTxtField:TextInput;
    var currentStr:String = "";
    var id:String;
    //Check whether this is a paste action
    if (event.operation is PasteOperation) 
    {
     //Get the numerical num of the current text field
     //if the user paste something in the 2nd field, 
     //paste action should work from 2 onwards
     id = String(event.target.id).split("Txt")[1];
     //Grab the text in this text field
     currentStr = event.target.text;
     //Pass it into the function populateTextBox
     populateTextBox(currentStr,id);
    }
    
    //If the user tries to edit this textfield,
    //we need to ensure that the text in the textfield
    //is shorter than the Max number of char that we 
    //allow in each text field.
    if(String(event.target.text).length > numOfMaxChar)
    {
     event.target.text = String(event.target.text)
      .substr(0,numOfMaxChar);
    }
    
    //Now we will combine all the text in the editable
    //text field and populate them in the next field
    serialTxt.text = "";
    for(var i:int = 0; i < numOfBox; i ++)
    {
     tempTxtField = (this["serialTxt" + String(i)]) as TextInput;
     if(i != 0)
     {
      serialTxt.text += delimiter;
     }
     serialTxt.text += tempTxtField.text;
    }
   }
   
   //This function will handle all the populating of
   //the text into its neighbours.
   private function populateTextBox(tempStr:String, 
            tempID:String = "0"):void
   {
    var textArray:Array;
    var id:String = tempID;
    var count:int = 0;
    var tempTxtField:TextInput;
    //If the copied text contains the delimiter
    if(String(tempStr).indexOf(delimiter) != -1)
    {
     //Split them based on the delimiter
     textArray = String(tempStr).split(delimiter);
     for(var i:int = Number(id); i < textArray.length; i ++)
     {
      tempTxtField = (this["serialTxt" + String(i)]) as TextInput;
      tempTxtField.text = textArray[count]
       .substr(0,numOfMaxChar);
      count ++;
     }
    }else{
     //Otherwise just split them accordingly
     for(i = Number(id); i < numOfBox; i ++)
     {
      tempTxtField = (this["serialTxt" + String(i)]) as TextInput;
      tempTxtField.text = String(tempStr)
       .substr(count * numOfMaxChar, numOfMaxChar);
      count ++;
     }
    }
   }
  ]]>
 </fx:Script>
 <s:BorderContainer width="100%" height="100%">
  <s:layout>
   <s:VerticalLayout verticalAlign="middle" 
         horizontalAlign="center"
         gap="0"/>
  </s:layout>
  <s:FormItem label="Serial Number:">
   <s:layout>
    <s:HorizontalLayout gap="0" verticalAlign="middle"/>
   </s:layout>
   <s:TextInput id="serialTxt0" width="60" 
       change="changeHandler(event)"/>
   <s:Label text="-"/>
   <s:TextInput id="serialTxt1" width="60" 
       change="changeHandler(event)"/>
   <s:Label text="-"/>
   <s:TextInput id="serialTxt2" width="60" 
       change="changeHandler(event)"/>
   <s:Label text="-"/>
   <s:TextInput id="serialTxt3" width="60" 
       change="changeHandler(event)"/>
  </s:FormItem>
  <s:TextInput id="serialTxt" text="" width="250"
      editable="false" selectable="false"/>
 </s:BorderContainer>
</s:Application>
* Click here for the demo.
  (Try pasting text like ABCD-2934-ADSG-4890 or 1234HJGF9898DDNN into the demo. :))
^ Click here for the source files of the demo.

Friday, June 8, 2012

Flex: I am the only 1....?

There are numerous situation that requires you to have a singleton object so that you prompt the user to enter a value (like a nickname) and you can easily slot them into the numerous places that you need to reflect the value. Therefore I'm making this demo to show you how to create a singleton object in flex.

This would be the main file of the project - SingleSingleton.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" width="100%" height="100%" 
    xmlns:local="*">
 <mx:VBox width="100%" height="100%" 
    verticalGap="0" verticalAlign="middle">
  <mx:Spacer height="100%"/>
  <mx:HBox width="100%"
     horizontalGap="0" horizontalAlign="center">
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox/>
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox2/>
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox/>
   <mx:Spacer width="100%"/>
  </mx:HBox>
  <mx:Spacer height="100%"/>
  <mx:HBox width="100%"
     horizontalGap="0" horizontalAlign="center">
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox2/>
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox/>
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox2/>  
   <mx:Spacer width="100%"/> 
  </mx:HBox>
  <mx:Spacer height="100%"/>
  <mx:HBox width="100%"
     horizontalGap="0" horizontalAlign="center">
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox/>
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox2/>
   <mx:Spacer width="100%"/>
   <local:SimpleInputBox/>
   <mx:Spacer width="100%"/>
  </mx:HBox>
  <mx:Spacer height="100%"/>
 </mx:VBox>
</mx:Application>

This would be the one of file of the project - SimpleInputBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
   horizontalGap="0"
   creationComplete="creationCompleteEvent(event)">
 <mx:Script>
  <![CDATA[
   import com.zcs.SingletonObject;
   
   import mx.events.FlexEvent;
   import mx.binding.utils.BindingUtils;
   
   private var tempObj:SingletonObject;
   
   [Bindable]
   private var lblText:String = "Changing the value here " +
    "<br>will affect the others:";
   
   protected function changeEvent(event:Event):void
   {
    //Upon changing the text in SingletonObject,
    //Update the value of _txt in the SingletonObject
    tempObj.txt = txtInput.text;
   }
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    //Create an instance of SingletonObject
    tempObj = SingletonObject.getInstance();
    //Bind the text of the TextInput field to
    //the _txt variable in the SingletonObject 
    BindingUtils.bindProperty(txtInput, "text", tempObj, "txt");
   }
   
  ]]>
 </mx:Script>
 <mx:TextArea htmlText="{lblText}"
     borderStyle="none" backgroundAlpha="0"/>
 <mx:TextInput id="txtInput"
      change="changeEvent(event)"/>
</mx:HBox>

This would be the one of file of the project - SimpleInputBox2.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
   horizontalGap="0"
   creationComplete="creationCompleteEvent(event)">
 <mx:Script>
  <![CDATA[
   import com.zcs.SingletonObject;
   
   import mx.events.FlexEvent;
   import mx.binding.utils.BindingUtils;
   
   private var tempObj:SingletonObject;
   
   [Bindable]
   private var lblText:String = "Changing the value here " +
    "<br><font color='#FF0000'>doesn't</font> affect the others:";
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    //Create an instance of SingletonObject
    tempObj = SingletonObject.getInstance();
    //Bind the text of the TextInput field to
    //the _txt variable in the SingletonObject 
    BindingUtils.bindProperty(txtInput, "text", tempObj, "txt");
   }
   
  ]]>
 </mx:Script>
 <mx:TextArea htmlText="{lblText}"
       borderStyle="none" backgroundAlpha="0">
 </mx:TextArea>
 <mx:TextInput id="txtInput"/>
</mx:HBox>

This would be the Singleton Object of the project - SingletonObject.as
package com.zcs
{
 public class SingletonObject
 {
  private static var _instance:SingletonObject=null;
  
  //You need the following functions to create a 
  //singleton Object. SingletonObject(e:SingletonEnforcer)
  //and getInstance():SingletonObject
  //Rather than using new SingletonObject to create a new
  //object of the class, you need to use
  //SingletonObject.getInstance() to point to the Singleton
  //class.
  public function SingletonObject(e:SingletonEnforcer){
   trace("new singleton object created");
  }
  
  public static function getInstance():SingletonObject{
   if(_instance==null){
    _instance=new SingletonObject(new SingletonEnforcer);
   }
   return _instance;
  }
  
  //Created a variable _txt that will be used
  //in storing text.
  private var _txt:String = "Nothing here";

  [Bindable]
  public function get txt():String
  {
   return _txt;
  }

  public function set txt(value:String):void
  {
   _txt = value;
  }

  
 }
}

//This class is needed in creating a singleton class.
class SingletonEnforcer{
 
}

* Click here for the demo.
^ Click here for the source files.

Sunday, June 3, 2012

Android: Copying an asset from your App into your Phone.

I was playing some Android Mobile Game the other day and I was wondering how do I create a file from my Android App into the phone itself. If I'm not wrong, I think I have done it before... Hence the journey of code searching starts again.


My Main Android Application file - CopyAssetToPhoneActivity.java
package zcs.copyAsset;

import java.io.IOException;
import java.io.InputStream;

import zcs.utility.io.FileIO;
import zcs.utility.io.FileIOResult;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.text.Html;
import android.widget.TextView;

public class CopyAssetToPhoneActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        FileIOResult myFile;
        //Create file food.jpg
        myFile = FileIO.createFile("zcs/copy from assets/food.jpg");
        //Grab the Text View on the layout
     TextView tempTxtView = (TextView)this.findViewById(R.id.txtOutput);
     String strOutput;
     
        if(myFile.get_exist() == 1)
        {
         //If file exist, get contents of file and display it
         strOutput = this.getString(R.string.str_exist);
        }else if(myFile.get_exist() == 0){
         //If file doesn't exist, show a different msg
         strOutput = this.getString(R.string.str_create);
   try {
    //Create a InputStream Instance
          InputStream is;
          //Open the file that is located in the assets
          //folder of your Application as a InputStream
    is = getAssets().open("food.jpg");
    //Write the data into myFile 
    FileIO.writeStreamIntoFile(myFile.get_file(), is);
    //Closes the InputStream
    is.close();
    //Broadcast a Command telling your phone that
    //the sdcard has been mounted again so that it will
    //scan the sdcard for images
    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
      Uri.parse("file://"+ 
      Environment.getExternalStorageDirectory())));
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
        }else{
         //Error occurred
         strOutput = this.getString(R.string.str_error);
        }
        //Show the text base on the condition of the file.
        tempTxtView.setText(Html.fromHtml(strOutput));
    }
}

One of my class file used for file I/O - FileIO.java
package zcs.utility.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.os.Environment;

public class FileIO {
 
 /**
  * Function that will create the specified file
  * name.
  * @param tempPath - path of the file you are 
  *       trying to access
  * @return FileIOResult Object
  *
  */ 
 public static FileIOResult createFile(String tempPath)
 {
  FileIOResult tempResult = new FileIOResult();
  //Check if the App has access to the External 
  //Storage first.
  boolean mExternalStorageWriteable = false;
  String state = Environment.getExternalStorageState();

  if (Environment.MEDIA_MOUNTED.equals(state)) {
      // We can read and write the media
      mExternalStorageWriteable = true;
  } else {
      // Something else is wrong. 
   // It may be one of many other states, but all we need
      // to know is we can neither read nor write
      mExternalStorageWriteable = false;
  }  
  //If we have access to the storage
  if(mExternalStorageWriteable)
  {
   String tempFilePath = tempPath;
   if(!tempFilePath.startsWith("/"))
   {
    tempFilePath = "/" + tempFilePath;
   }
         File root = Environment.getExternalStorageDirectory();
         File tempFile = new File(root + tempPath);
         //Check if file exist         
         if(!tempFile.exists())
         {
          //split the string and grab all the folders first 
          String[] strPathArray = tempFilePath.split("/");
          //Create all the folders first
          String strFolder = "";
          for(int i = 0; i < (strPathArray.length - 1); i ++)
       {
           strFolder = strFolder + "/" + strPathArray[i];
       }
       File sdDir = new File(root + strFolder);
          if(!sdDir.exists()){
           sdDir.mkdirs();
          }
          //Create File Path
    tempFile = new File(root + strFolder, 
         strPathArray[strPathArray.length - 1]);
         }
         try {
          //Check for file existence.
          if(tempFile.exists())
          {
           tempResult.set_exist(1);
          }else{
           tempResult.set_exist(0);
          }
          //If file doesn't exist, let's make one. 
          if(!tempFile.exists())
          {
           tempFile.createNewFile();
          }
   } catch (IOException e) {
    e.printStackTrace();
   }
         tempResult.set_file(tempFile);
  }else{
      tempResult.set_exist(2);
  }
  return tempResult;
 }

 /**
  *
  * Writing contents to the specified file.
  * Note: Use createFile(String) to gain access to the
  * file first. 
  * @param tempFile - File you are accessing
  * @return contents as a string
  */ 
 public static String readContentFromFile(File tempFile)
 {
  FileInputStream fis = null;    
  int ch;
     StringBuffer strContent = new StringBuffer("");
  try 
  {
   fis = new FileInputStream(tempFile);
      while((ch = fis.read()) != -1)
      {
       strContent.append((char)ch);
      }
  } catch (Exception e) 
  {
   e.printStackTrace();
  } finally
  {
            try
            {
             fis.close();
             fis = null;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
  }
  return strContent.toString();
 }

 /**
  * Writing contents to the specified file.
  * Note: Use createFile(String) to gain access to the
  * file first. 
  * @param tempFile - File you are accessing
  * @param value - value you are going to write
  *       in the file
  */ 
 public static void writeContentIntoFile(File tempFile, String value)
 {
  FileOutputStream fos = null;
  try 
  {
   fos = new FileOutputStream(tempFile);

   fos.write(value.getBytes(),0,value.getBytes().length);
   fos.flush();
  } catch (Exception e) 
  {
   e.printStackTrace();
  } finally
  {
            try
            {
                fos.close();
                fos = null;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
  }
 }

 /**
  * Writing data to the specified file.
  * Note: Use createFile(String) to gain access to the
  * file first. 
  * @param tempFile - File you are accessing
  * @param in - data you are going to write
  *       in the file
  */ 
 public static void writeStreamIntoFile(File tempFile, InputStream in) throws IOException { 
  OutputStream out = new FileOutputStream(tempFile); 
  // Transfer bytes from in to out 
        int size = in.available();
        
  byte[] buf = new byte[size]; 
  int len; 
  while ((len = in.read(buf)) > 0) { 
   out.write(buf, 0, len); 
  } 
  out.close(); 
 } 
}

One of my class file used for file I/O - FileIOResult.java
package zcs.utility.io;

import java.io.File;

public class FileIOResult { 
 private int _exist = 0;
 private File _file = null;

 /**
  * Used to check for the existance of the file.  
  * @return one of the below integer (0-2)
  *  
0 - file does not exist and it will * be created *
1 - file exist *
2 - Error */ public int get_exist() { return _exist; } public void set_exist(int _exist) { this._exist = _exist; } public File get_file() { return _file; } public void set_file(File _file) { this._file = _file; } public FileIOResult() { } }

My App Manifest file - AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="zcs.copyAsset"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="7" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".CopyAssetToPhoneActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Once you have run the application once, go to gallery and it
will be showing you a new folder that contains a new image.

* Click here to download the source file of the App that I have shown here.