Sunday, December 29, 2013

9. Flex Build scripts

Let's imagine you wrote an application and then you wanted to test it on your iPhone or Android tablet.  For this reason, it is necessary to know what device you want to support before starting. 

When you start a new project, the first task is to define the output. For example, is your application going to run in browsers, iOS, Android, or Blackberry devices or all four? This would be your output device list.

A build script or "build scripts" can define your output device list. 

Apache ANT is a cross platform open source build script manager and free to download. It allows us to define repeatable steps which results in less mistakes for each release. It is available at ant.apache.org/. MAC computers with OSX already have ANT pre-installed on their computer. 

Note: You need to install ANT extensions for FTP or email support.

Start by building three main deployment "build scripts" for:
  1. Internal deployment - testing server deployment.
  2. Beta Release - public server deployment testing.
  3. Release Build - public release.
An Ant "build script" file is simply an xml file with elements to compile, copy files, ftp, email, etc.

Inside ANT, The build tasks (called targets) are defined by the project (top element).

Example:   <target name="BuildAndPackage1"   >

The default target (or, the entire goal of the project) is defined inside the project as the default attribute.

<project name="Build Internal" default="BuildAndPackage10" >

The default target is usually the last target. Since each target has a dependency, the tasks (targets) run in order, backwards until the final (default) is ran.

The end result is all 10 targets running in order from 1 to 10.

Each of the 10 targets have a simple task.  

In this example, I update, compile and deploy a web, iPhone and Android version of the app using the internal server for data. 
  1. Delete temp folder used in previous build then create directories for building into. 
  2. Copy default values used inside application to use internal server(s) for data.
  3. Compile Model data file into an .swc. This will be explained later. 
  4. Update Version files.
  5. Compile css files into .swc files. These contain the style libraries.
  6. Compile the Main application into SWF file.
  7. Package iPhone app file.
  8. Package Android app file.
  9. FTP files to server.
  10. Send out email with version deployed. 
From within Flash Builder, i can right click on the .xml files and select Run As \ Ant Build to start the build script.
 
Here is the source for the internal build:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Build Internal" default="BuildAndPackage10" >
    <target name="BuildAndPackage1"   >
        <ant antfile="Build_MakeDirectories.xml" target="BuildDirectories" inheritall="false" />
    </target>
    <target name="BuildAndPackage2" depends="BuildAndPackage1"   >
        <!-- USE TESTING SERVER DATABASE FOR INTERNAL BUILDS -->
        <ant antfile="
Build_InternalBuildApplicationConfig.xml" target="CopyTesingServerForBuild" inheritall="false" />
    </target>
    <target name="BuildAndPackage3" depends="BuildAndPackage2"   >
        <ant antfile="
Build_ModelSWC.xml" target="CompileModel" inheritall="false" />
    </target>
    <target name="BuildAndPackage4" depends="BuildAndPackage3"  >
        <ant antfile="
Build_UpdateVersion.xml" target="UpdateVersionBeta" inheritall="false" />
    </target>
    <target name="BuildAndPackage5" depends="BuildAndPackage4" >
        <ant antfile="
Build_CSSFiles.xml" target="CompileCSS" inheritall="false" />
    </target>
    <target name="BuildAndPackage6"   depends="BuildAndPackage5" >
        <ant antfile="Build_CompileSWF.xml" target="CompileSWF" inheritall="false" />
    </target>
    <target name="BuildAndPackage7"   depends="BuildAndPackage6" >
        <ant antfile="
Build_PackageIPA.xml" target="CompileIPA" inheritall="false" />
    </target>
    <target name="BuildAndPackage8"   depends="BuildAndPackage7" >
        <ant antfile="
Build_PackageAPK.xml" target="CompileAPK" inheritall="false" />
    </target>
    <target name="BuildAndPackage9"   depends="BuildAndPackage8" 

        <ant antfile="Build_FTPFilesToServer.xml" target="UploadInternalRelease" inheritall="false" />
    </target>
    <target name="BuildAndPackage10"   depends="BuildAndPackage9" >
        <ant antfile="
Build_EmailComplete.xml" target="EmailCompleteInternal" inheritall="false" />
        <echo>Internal built and uploaded.. version ${Version.MajorNumber}.${Version.BetaNumber}.${build.number} </echo>
    </target>
</project>


Here is the source for the beta build:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Build beta" default="BuildAndPackage10" >
    <target name="BuildAndPackage1"   >
        <ant antfile="Build_MakeDirectories.xml" target="BuildDirectories" inheritall="false" />
    </target>
    <target name="BuildAndPackage2" depends="BuildAndPackage1"   >
        <!-- USE RELEASE SERVER DATABASE FOR BETA -->
        <ant antfile="
Build_InternalBuildApplicationConfig.xml" target="CopyReleaseServerForBuild" inheritall="false" />
    </target>
    <target name="BuildAndPackage3" depends="BuildAndPackage2"   >
        <ant antfile="
Build_ModelSWC.xml" target="CompileModel" inheritall="false" />
    </target>
    <target name="BuildAndPackage4" depends="BuildAndPackage3"  >
        <ant antfile="
Build_UpdateVersion.xml" target="UpdateVersionBeta" inheritall="false" />
    </target>
    <target name="BuildAndPackage5" depends="BuildAndPackage4" >
        <ant antfile="
Build_CSSFiles.xml" target="CompileCSS" inheritall="false" />
    </target>
    <target name="BuildAndPackage6"   depends="BuildAndPackage5" >
        <ant antfile="Build_CompileSWF.xml" target="CompileSWF" inheritall="false" />
    </target>
    <target name="BuildAndPackage7"   depends="BuildAndPackage6" >
        <ant antfile="
Build_PackageIPA.xml" target="CompileIPA" inheritall="false" />
    </target>
    <target name="BuildAndPackage8"   depends="BuildAndPackage7" >
        <ant antfile="
Build_PackageAPK.xml" target="CompileAPK" inheritall="false" />
    </target>
    <target name="BuildAndPackage9"   depends="BuildAndPackage8" 

        <ant antfile="Build_FTPFilesToServer.xml" target="UploadInternalRelease" inheritall="false" />
    </target>
    <target name="BuildAndPackage10"   depends="BuildAndPackage9" >
        <ant antfile="
Build_EmailComplete.xml" target="EmailCompleteInternal" inheritall="false" />
        <echo>Internal built and uploaded.. version ${Version.MajorNumber}.${Version.BetaNumber}.${build.number} </echo>
    </target>
</project>


Here is the source for the release build:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Build release" default="BuildAndPackage10" >
    <target name="BuildAndPackage1"   >
        <ant antfile="Build_MakeDirectories.xml" target="BuildDirectories" inheritall="false" />
    </target>
    <target name="BuildAndPackage2" depends="BuildAndPackage1"   >
        <!-- USE RELEASE SERVER DATABASE FOR RELEASE -->
        <ant antfile="
Build_InternalBuildApplicationConfig.xml" target="CopyReleaseServerForBuild" inheritall="false" />
    </target>
    <target name="BuildAndPackage3" depends="BuildAndPackage2"   >
        <ant antfile="
Build_ModelSWC.xml" target="CompileModel" inheritall="false" />
    </target>
    <target name="BuildAndPackage4" depends="BuildAndPackage3"  >
        <ant antfile="
Build_UpdateVersion.xml" target="UpdateVersionBeta" inheritall="false" />
    </target>
    <target name="BuildAndPackage5" depends="BuildAndPackage4" >
        <ant antfile="
Build_CSSFiles.xml" target="CompileCSS" inheritall="false" />
    </target>
    <target name="BuildAndPackage6"   depends="BuildAndPackage5" >
        <ant antfile="Build_CompileSWF.xml" target="CompileSWF" inheritall="false" />
    </target>
    <target name="BuildAndPackage7"   depends="BuildAndPackage6" >
        <ant antfile="
Build_PackageIPA.xml" target="CompileIPA" inheritall="false" />
    </target>
    <target name="BuildAndPackage8"   depends="BuildAndPackage7" >
        <ant antfile="
Build_PackageAPK.xml" target="CompileAPK" inheritall="false" />
    </target>
    <target name="BuildAndPackage9"   depends="BuildAndPackage8" 

        <ant antfile="Build_FTPFilesToServer.xml" target="UploadInternalRelease" inheritall="false" />
    </target>
    <target name="BuildAndPackage10"   depends="BuildAndPackage9" >
        <ant antfile="
Build_EmailComplete.xml" target="EmailCompleteInternal" inheritall="false" />
        <echo>Internal built and uploaded.. version ${Version.MajorNumber}.${Version.BetaNumber}.${build.number} </echo>
    </target>
</project>

  
Here is the source for the make directories:
 <project name="BuildDirectories" default="BuildDirectories" >
<!-- 0. Setup properties   -->
    <property file="build.properties_version" />
    <property file="MASTER_build.properties" />   
    <property name="temp_dir" location="${app_root_dir}/build/temp" />
    <property name="build_dir" location="${app_root_dir}/build" />
    <property name="debug_dir" location="${app_root_dir}/build/internal" />
    <property name="publish_dir" location="${app_root_dir}/build/public" />
    <property name="assets_dir" location="${class_path}/${assets_dir_name}" />
    <property name="output_loc" location="${publish_dir}/${swf_file}" />
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/>    
<!-- 1.0 Clean and create directories.  -->
    <!-- Clean existing directories   -->
    <target name="CleanupDirectories" description="clean up">
        <delete dir="${temp_dir}" />
    </target>
    <!-- Create required directories   -->
    <target name="BuildDirectories" depends="CleanupDirectories">
        <mkdir dir="${build_dir}" /> 
        <mkdir dir="${temp_dir}" /> 
        <mkdir dir="${debug_dir}" />

        <mkdir dir="${publish_dir}" /> 
    </target>
</project>


Here is the source for the build.properties:
Replace items identified by [], for example [project]. So, in my case,
[developer name] would be replaced with John Molinari.

 ######################################
## Project information
######################################
author=
[developer name]
project.owner=[company]
project.owner.url=http\://www.[website].com
project.name=
[project]
project.fullname=[project]
application.name=[project]
app_name=[project] 
app_type=mxml
# Where flex is installed:
FLEX_HOME=C\:/Program Files/Adobe/Adobe Flash Builder 4.7 (64 Bit)/sdks/4.6.0
LOCALE=en_US
######################################
## tools
######################################
### FlexTask
FLEX_TASKS=${FLEX_HOME}/ant/lib/flexTasks.jar
ADT=${FLEX_HOME}/lib/adt.jar
PFI=${FLEX_HOME}/lib/pfi.jar
ADL=${FLEX_HOME}/bin/adl
AIR_GLOBAL=${FLEX_HOME}/frameworks/libs/air/airglobal.swc
######################################
## Properties
######################################
app_root_dir=.
app_descriptor=${class_path}/${app_name}-app.xml
MOBILE_DIR=W\:/[productname]/htdocs/
[project]
MODEL_DIR=W\:/[productname]/htdocs/[project]
MODEL_PLUGINS_DIR=C\:/Program Files/Adobe/Adobe Flash Builder 4.7 (64 Bit)/eclipse/plugins/com.adobe.flexbuilder.project_4.7.0.349722
SOFTWARE_FOLDER=W\:/[website].com/public_html/software
class_path=${MOBILE_DIR}/src
lib_path=${MOBILE_DIR}/libs
view_path=${MOBILE_DIR}/src/com/
[project] /view
enum_path=${MODEL_DIR}/src/com/
[project] /model/enum
### File names
swf_file=${app_name}.swf
air_file=${app_name}.air
ipa_file=${app_name}.ipa
apk_file=${app_name}.apk
### iOS Configuration
ios_provisioning=${cert_loc}/Provisional.mobileprovision
ios_pass=[enter password here]

android_keystore=${cert_loc}/[name] Android.p12
ios_keystore=${cert_loc}/
[name].p12
cert_loc=W\:/Certificates
assets_dir_name=${class_path}/icons
main_class=${class_path}/${app_name}.${app_type}
splash_path=${class_path}/Default.png
### FTP   
[enter ftp address] 
ftp-server=  [enter ftp address] 
ftp-userid=  [enter ftp login name] 
ftp-password=[enter ftp password] 
ftp-remotedir=public_html/software

Here is the source for the CopyApplicationConfig:
<project name="CopyApplicationConfig" default="CopyTesingServerForBuild" >
<!-- 0. Setup properties - DONE  -->
    <property file="build.properties_NEW" />
    <property file="MASTER_build.properties" />
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/>    
    <target name="CopyReleaseServerForBuild" >
        <copy file="${enum_path}/ApplicationValues_LiveServer.as" tofile="${enum_path}/ApplicationValues.as" overwrite="true" />
    <replaceregexp file="${enum_path}/ApplicationValues.as"
                           match="ApplicationValues_LiveServer"
                           replace="ApplicationValues"
                               byline="true"
            />   
    </target>
    <target name="CopyTesingServerForBuild" >
        <copy file="${enum_path}/ApplicationValues_TestingServer.as" tofile="${enum_path}/ApplicationValues.as" overwrite="true" />
            <replaceregexp file="${enum_path}/ApplicationValues.as"
                                       match="ApplicationValues_TestingServer"
                                       replace="ApplicationValues"
                                           byline="true"
                        />
        </target>   
</project>


Here is the source for the UpdateVersion:
 <project name="UpdateVersion" default="UpdateVersionInternal" >
<!-- 0. Setup properties - DONE  -->
    <property file="build.properties_NEW" />
    <property file="build.properties_Versions" />
    <property file="MASTER_build.properties" />
    <property name="temp_dir" location="${app_root_dir}/build/temp" />
    <!-- Use the Flex ANT tasks for easier compilation - DONE -->
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/>     
<!-- build.number will increment each time it is ran.. use it to add to end of file using wildcard..  --> 
    <target name="UpdateVersionInternal" depends="UpdateProperties"  >
      
        <!--    store into new file via wildcard.         -->
        <!--    increment Build number         -->
        <buildnumber file="build.properties_NEW" />
        <echo>Build Number: ${build.number} </echo>
        <echo>Major Version ${Version.MajorNumber} </echo>
        <echo>Beta Version ${Version.BetaNumber} </echo>
        <replaceregexp file="${temp_dir}/eMEApp-app_ForBuilds.xml"
                       match="%%versionNumber%%"
                       replace="${Version.MajorNumber}.${Version.BetaNumber}.${build.number}"
                       byline="true"
        />
        <echo>Internal Version: ${Version.MajorNumber}.${Version.BetaNumber}.${build.number} </echo>
        <echo>Build: ${build.number}</echo>
    </target>
    <target name="UpdateVersionPublic"    >
        <!--    increment first, set middle and last number to 0       -->
        <!--    store into new file via wildcard.         -->
        <!--    increment Build number         -->
            <buildnumber file="build.properties_NEW" />
            <echo>Build Number: ${build.number} </echo>
        <!--   CHANG PROPERTIES FILE VALUES  -->
            <propertyfile  file="build.properties_Versions" >
                      <entry  key="Version.MajorNumber" operation="+" type="int" value="1" />
            </propertyfile>
            <echo>Major Version ${Version.MajorNumber} </echo>
            <echo>Beta Version ${Version.BetaNumber} </echo>
            <replaceregexp file="${temp_dir}/eMEApp-app_ForBuilds.xml"
                           match="%%versionNumber%%"
                           replace="${Version.MajorNumber}.0.0"
                           byline="true"
            />
            <echo>Public Version: ${Version.MajorNumber}.0.0 </echo>
            <echo>Build: ${build.number}</echo>
    </target>
    <target name="UpdateVersionBeta"   >
        <!--    increment middle number, set last to 0        -->
        <!--    store into new file via wildcard.         -->
        <!--    increment Build number         -->
                    <buildnumber file="build.properties_NEW" />
                    <echo>Build Number: ${build.number} </echo>
                  
                    <propertyfile  file="build.properties_Versions" >
                              <entry  key="Version.BetaNumber" operation="+" type="int" value="1" />
                    </propertyfile>
                  
                    <echo>Major Version ${Version.MajorNumber} </echo>
                    <echo>Beta Version ${Version.BetaNumber} </echo>
                    <replaceregexp file="${temp_dir}/eMEApp-app_ForBuilds.xml"
                                   match="%%versionNumber%%"
                                   replace="${Version.MajorNumber}.${Version.BetaNumber}.0"
                                   byline="true"
                    />
            <echo>Beta Version: ${Version.MajorNumber}.${Version.BetaNumber}.0 </echo>
            <echo>Build: ${build.number}</echo>
    </target>  

</project>

Here is the source for the CompileCSS:
<project name="CompileCSS" default="CompileCSS" >
<!--0. Setup properties - DONE  -->
     <property file="build.properties_NEW" />
    <property file="MASTER_build.properties" />
    <property name="temp_dir" location="${app_root_dir}/build/temp" />
    <property name="build_dir" location="${app_root_dir}/build" />
    <property name="debug_dir" location="${app_root_dir}/build/internal" />
    <property name="publish_dir" location="${app_root_dir}/build/public" />
    <property name="assets_dir" location="${class_path}/${assets_dir_name}" />
    <property name="output_loc" location="${publish_dir}/${swf_file}" />
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/>
   
<!-- 2.0 Compile css files into swc files. (libraries) -  -->  
    <target name="CompileCSS"  >
        <compc output="${temp_dir}/AppNameTheme.swc"   defaults-css-url="./default_components.css" >
            <include-file name="default_components.css" path="./default_components.css" />
            <include-file name="default_fonts.css" path="./default_fonts.css" />
            <include-file name="default_colors.css" path="./default_colors.css" />
            </compc>
    </target>
 </project>


 Here is the source for the CompileSWF:
<project name="CompileSWF" default="CompileSWF" >
<!-- 0. Setup properties - DONE  -->
    <property file="build.properties_NEW" />
    <property file="MASTER_build.properties" />   
    <property name="temp_dir" location="${app_root_dir}/build/temp" />
    <property name="build_dir" location="${app_root_dir}/build" />
    <property name="debug_dir" location="${app_root_dir}/build/internal" />
    <property name="publish_dir" location="${app_root_dir}/build/public" />
    <property name="assets_dir" location="${class_path}/${assets_dir_name}" />
    <property name="output_loc" location="${temp_dir}/${swf_file}" />
    <!-- Use the Flex ANT tasks for easier compilation - DONE -->
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/> 

<!-- 2.0 Compile css files into swc files. (libraries) -  -->  
    <target name="CompileSWF"  >
            <mxmlc
                file="${main_class}"
                output="${output_loc}"
                locale="${LOCALE}"
                static-rsls="false"
                accessible="false"
                configname="airmobile"
                debug="${debug_mode}"
                failonerror="true"
                fork="true"
                maxmemory="1024m">
                <source-path path-element="${class_path}"/>
                <compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
                    <include name="libs/*" />
                </compiler.library-path>               
                <theme  dir="${temp_dir}" append="true"  >
                        <include name="AppnameTheme.swc" />
                </theme>                               
                <!-- <defaults-css-files >
                    <include filename="default_fonts.css" />
                </defaults-css-files>
                <library-path dir="${MOBILE_DIR}/src" includes="*" append="true" /> -->
                <library-path dir="${temp_dir}" includes="AppName_Model.swc" append="true" />
                <library-path file="${FLEX_HOME}/frameworks/locale/${LOCALE}" append="true"/>
                <library-path dir="${lib_path}" includes="*.swc" append="true"/>
                <external-library-path file="${AIR_GLOBAL}" append="true"/>
            </mxmlc>
    </target>
</project>



 Here is the source for the CompileIPA:
<project name="CompileIPA" default="MoveToPublic" >
<!-- 0. Setup properties - DONE  -->
    <property file="build.properties_NEW" />
    <property file="MASTER_build.properties" />   
    <property name="temp_dir" location="${app_root_dir}/build/temp" />
    <property name="build_dir" location="${app_root_dir}/build" />
    <property name="debug_dir" location="${app_root_dir}/build/internal" />
    <property name="publish_dir" location="${app_root_dir}/build/public" />
    <property name="assets_dir" location="${class_path}/${assets_dir_name}" />
    <property name="output_loc" location="${publish_dir}/${swf_file}" />
    <!-- Use the Flex ANT tasks for easier compilation - DONE -->
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/>
    <property name="app_descriptor_forbuilding" location="${temp_dir}/${app_name}-app_ForBuilds.xml"/>
    <target name="MoveToPublic"  depends="CompileIPA">
          <move file="${temp_dir}/${ipa_file}" tofile="${publish_dir}/${ipa_file}"/>
    </target>
<!-- Package the application to an ipa file & save it in the publish directory -->
    <target name="CompileIPA" >
        <echo>IPA Start    -    BE PATIENT!!!!   - THIS CAN TAKE 10 TO 15 MINUTES TO GENERATE IPA (IPHONE APP)</echo>
            <java jar="${ADT}" fork="true" failonerror="true">
                <arg value="-package"/>
                <arg value="-target"/>
                <arg value="ipa-test"/>
                <arg value="-provisioning-profile"/>
                <arg value="${ios_provisioning}"/>                
                <arg value="-storetype"/>
                <arg value="pkcs12"/>
                <arg value="-keystore"/>
                <arg value="${ios_keystore}"/>
                <arg value="-storepass"/>
                <arg value="${ios_pass}"/>                
                <arg value="${temp_dir}/${ipa_file}"/>
                <arg value="${app_descriptor_forbuilding}"/>                             
                <arg value="-C" />
                <arg value="${temp_dir}"/>
                <arg value="${swf_file}"/>               
                <!--    Include    icons        --> 
                <arg value="-C" />
                <arg value="${class_path}"/>
                <arg value="/icons" /> 
            </java>
        <echo>IPA Built</echo>
    </target>   
</project>


 Here is the source for the CompileAPK:
<project name="CompileAPK" default="CompileAPK" >
<!-- 0. Setup properties - DONE  -->
    <property file="build.properties_NEW" />
    <property file="MASTER_build.properties" />   
    <property name="temp_dir" location="${app_root_dir}/build/temp" />
    <property name="build_dir" location="${app_root_dir}/build" />
    <property name="debug_dir" location="${app_root_dir}/build/internal" />
    <property name="publish_dir" location="${app_root_dir}/build/public" />
    <property name="assets_dir" location="${class_path}/${assets_dir_name}" />
    <property name="output_loc" location="${publish_dir}/${swf_file}" />
    <!-- Use the Flex ANT tasks for easier compilation - DONE -->
    <taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
    <taskdef name="compc" classname="flex.ant.CompcTask" classpath="${FLEX_TASKS}"/>

<property name="app_descriptor_forbuilding" location="${temp_dir}/${app_name}-app_ForBuilds.xml"/>   
<!-- Package the application to an ipa file & save it in the publish directory -->
    <target name="CompileAPK" >
        <echo>APK Start</echo>
            <java jar="${ADT}" fork="true" failonerror="true">
                <arg value="-package"/>
                <arg value="-target"/>
                <arg value="apk"/>                
                <arg value="-storetype"/>
                <arg value="pkcs12"/>
                <arg value="-keystore"/>
                <arg value="${android_keystore}"/>
                <arg value="-storepass"/>
                <arg value="${ios_pass}"/>                
                <arg value="${temp_dir}/${apk_file}"/>
                <arg value="${app_descriptor_forbuilding}"/>

                <arg value="-C" />
                <arg value="${temp_dir}"/>
                <arg value="${swf_file}"/>
                <!--    Include    icons        --> 
                <arg value="-C" />
                <arg value="${class_path}"/>
                <arg value="/icons" /> 
            </java>
        <echo>APK END</echo>
    </target>   
</project>



In future blogs I will go over the details of writing Actionscript and MXML. I will also explain the details of a Model, View, Controller (MVC) system and how you should use it in your development.


PREVIOUS POST

Saturday, December 28, 2013

8. Start with an idea, then build it. It's that simple, right?


There are three popular reasons to build a product:

1. To automate an internal business process.
2. To provide eCommerce for products or services.
3. To sell new functionality to a new or existing market; build a new product

This post is about number 3... Building a new product.

It is impossible to build a successful product without a good idea. With thousands of products in the market, the process to clarify and validate your idea is more important than ever.

Does the product already exist? Does the solution the product solves already solved by another product? Is your idea original or does it look very similar to another product?

I am not a big fan of software patents. Mainly because it causes innovation to be dictated and controlled by lawyers instead of innovators. If you have a unique idea that can clearly give you an unfair advantage, then a patent might be necessary, from a business stand point.


Trademarks are another story, they protects your identity in the market. It takes a lot of work to successfully build a product, and that work is protected by it's identity in the market though its trademark. 

Long story short, It is best to file to trademark for a new product the day it is released. This is due to it's classification, which can be defined as "a product in use". If you want to reserve your trademark for later release, it is going to cost you a lot more money.
"The Software process is an iteration!"
I will repeat this many times in the future to emphasize my point! You will constantly be changing your mind about the product, its features and even its name. This is another reason to not spend money on a trademark at the beginning.

Patents do give you an unfair advantage, especially to your lawyers. But, it is your product identity, its features and functionality in your market you are reaching that can ultimately be the difference between success and failure.

Know your customer

The more you can articulate about your customer, the better you will be at coming up with the functionality they want. If you can build something that someone wants, you have the potential to sell it to them.


Analyze how your customer uses other products that are similar to your idea. 

Consumer vs. Business

Consumers are very different from businesses and there needs are very different. Businesses will pay to save time or money. Consumers usually pay based on emotion or for basic needs like education, transportation and communication. 

Here are some ideas for finding functionality for a business product.

Analyze your customers daily routine. What is the most important thing in their daily routine that they would like to automate.
 
Define how the product will be used in specific circumstances, also known as "Use Cases". Create a "Use Case" by writing a list of things they do now and how it can be sped up with a software product. 

How will the customer benefit from the software? What is the most important benefit the new product has to offer? How much will the customer pay for this benefit? A benefit is usually speed, quality or savings.

Consumer products

To build a consumer software product, you first need to ask yourself the following question; Are you going to copy another idea or find a new market? Another way of saying this is: do you want to duplicate or innovate? Dell was very successful by duplicating HP and putting it online. So, if you duplicated another product and add something new, you might be able sell your product to a market that already is buying similar products. But, if you want to innovate, be prepared to spend years developing your product (unless you have deep pockets).

Market Positioning

Focus the functionality on the features that the competition does not have. Inspire your ideas by looking at products that do what you want; Then come up with advantages and benefits that the other products do not offer to their customers. 


Once you have identified the customer and the product you wand to build, create a list of minimum requirements that you need to build to sell the product. 

Describe how the product could be used in steps, called use cases.

Build a small prototype or large platform environment
From a requirements list and use case descriptions, you can usually get a bid on building a  prototype from any platform engineer. If you have enough resources or time, you can build a multi-platform application environment as I will describe in detail in this blog. If you need help, you can contact me at john@sonomadatasolutions.com and I would be happy to assist you.

READ PREVIOUS POST  -  CONTINUE TO NEXT POST






Wednesday, October 2, 2013

7. Build, Deploy and Run

What type of app do you want to build?

A social app? An internal app to automate business processes? A game? A communication app? A new utility or device? Each idea would require a different approach to accomplishing their tasks; and so you would create a different development environment for each type of app.

Now imagine if your code and its functionality was in the form of movable objects that you could plug in and remove to configure a new development environment, like Lego's. What ever your ideas, it is nice to have a bunch of components already built that you can simply plug together and configure. It's like designing a new car based on specs of the new vehicle but using many of the same components that the other cars use (bolts, wires, battery, etc).
 

This is the power of using an "MVC" development environment.
"MVC" stands for Model, View and Controller and it has many advantages that I will explain in future blogs.
I use PureMVCa FREE Model-View-Controller Framework for Apache Flex applications.
 

Build, Deploy and Run


Besides the development environment, the way the app is physically built, deployed and ran is also determined by the type of app you want to build. Just like a car, if you built a formula 1 hot rod car, it would be custom built, only deployed at big races and only run on specially prepared raceways. If you manufactured a consumer sports car it would be built using many standard components, deployed through car dealers and ran on highways and paved roads (It's not an off road vehicle).

The same is true for applications. If you were building a game, you might build your app as an iOS app, deploy your app though iTunes and design you app to run on iPhones and iPads.

If you were building a communication app, then the app might be built using standard social components, deployed via multiple App Stores and run on multiple devices (iOS, Android, etc).

Using Apache Flex and PureMVC, you can custom build, deploy and run your application on multiple devices using standard object components.

Build - Client / Server two-way data-flow


There are many components to an application. When an application is run, it usually will need to get information from outside the application. So, it sends data to and from your computer server and/or other third party servers.

On your server, you can use any server database; I use MYSQL because it is FREE and usually already installed on all low cost web hosting packages. I also use PHP as my server language because it also FREE and installed on all low cost hosting packages. MYSQL also has a very powerful and easy way to scale your system up as you grow. MYSQL is owned by Oracle and they have a proven knowledge of managing very large sets of data.


Here is an example of an application sending and getting data that is stored on your server.


The Client app requests data through "PHP Services" (automatically managed by something called the "Zend Framework"). 

Deploy - One Solution, Many platforms


My solution for running on multiple platforms involves creating four projects. One to manage all of your data called the "Model". A second project to automate tests against the Model. And two more to manage the logic and display for both the web and mobile devices (cell phones and tablets).

This is an
application Folder structure example for an application called "services". After you create your four projects, your folder structure will look like the following image.


  • A mobile project to create all apps for mobile and tablet devices.
  • A model file to manage the data (services_model) and generate the library file which the other three projects will use.
  • A model test project to test the library.
  • A swf project to create a swf for HTML display. (optional, if you want your app to run in a browser) 

Using this structure, you can build multiple different file types from many of the same components.

Run - Create "runtime" for specific usage


Your application will either run directly in an operating system or through a browser. When you build your application in Apache Flex, it will automatically configure itself to do this.

Here are three example applications. The first one is a swf running on top of flash player which is on top of a browser. The last two run within Adobe Air.

 
As you can see by the image above; when you run an iPhone app, it is run on top of Adobe Air, which runs on top of Apple iOS.  The iPhone app would be created in the form that iOS expects (an .ipa file).

If you ran the app on a PC or MAC, it would run through the Flash Player (97% of all PC's and MAC's has Adobe Flash Player already installed).
The time period in which the app is running is known as the "runtime".
In future Blogs I will review Market Positioning, Security, Legality, and of course coding!
 
PREVIOUS POST - NEXT POST

Tuesday, September 24, 2013

6. Backups

No matter how big or small your project, you need to backup your data! Why not do it for FREE!
Most people do not know how backup your data properly. If you are building an HTML site or any size application, you need to backup your data. I will explain how to do that correctly and for FREE. 

Online repositories

High end applications can have more than one person working on it. There can be one person per project file or multiple people working on the same project file. The system that stores all of the files in a large application is called a data repository. If the data is on the internet, it is referred to as an online repository. If the data is on your computer, it is called a local repository.

If you backup your data, you can retrieve the backup after you accidentally delete, modify or corrupt any file. But, not only are you limited to whatever you backed up, you also can only retrieve the one backup you made. If you have multiple backups you can get older files but it is usually not easy. Of course if your computer is stolen or gets a virus, without a backup, you are screwed!

If you use an online repository, you have all of your data safe online. You get a free online "folder" that manages every version of every file you use for each project. Anyone can download the entire repository and get every version of every file you have made in your project. It also has tight security and can be configured to transfer all of your files securely.

There are many free online repositories. SourceForge, GitHub and Bitbucket are the most popular. All three allow unlimited space and free hosting for source code. I use Bitbucket because you can setup 5 repositories with 5 users each, all for FREE! It also includes an issue tracker.



Version Control Application

In addition to an online repository, you also need version control software installed on your computer. I will explain how to use TortoiseHg, a version control software for PC's. If you are running a MAC, you can use SourceTree.

People usually think of a backup system as being capable of doing the following tasks.
  • Backup my data.
  • Retrieve a file from my data.
That sounds easy. But, in order to take advantage of the power of a Version Control Application and be ready to scale up any project, you will need to learn how to do the following tasks which I explain below.
  1. Create a local Repository.
  2. Manage local Repositories. 
  3. Commit a change to local Repository.
  4. Upload to online repository.
  5. Download from online repository.
They are very similar to the two steps above (backup and retrieve). But, there are a few other steps because you have the entire backup on your machine and on the online repository (e.g. Bitbucket). 

In order to backup, you first commit a change to your local repository. Then, you upload it to the server (bitbucket). 

To retrieve a file you simply view the history of files and then retrieve any version you previously committed. If your computer gets corrupted, you have the entire repository safe, on the server.
One of the advantages of using a Version control software, is your do not have to save any document as version 1, version 2, etc. Just name every file exactly what it should be called, then backup every version (or "commit" every change, as I will explain below).
1. Create an local Repository

Have you ever bought a new DVD disk or flash drive to backup some data? First it costs money, and second it is not as easy as creating a new repository on your computer to store backups. With the use of a version control system, you will never have to buy another backup disk again, and it's always FREE!

When you start building a new application, one of the first things to do is create a repository to store your files for each project file that you will be building for the application.

Here is how to create a new repository on your computer using Bitbucket (installed).

Open up Windows File Explorer and navigate to the folder where you store your project files. If you have multiple projects for you application you will need to repeat this for each one. 

Right-Click with your mouse in the center of the File Explorer, inside the folder. You will see the following menu. Choose Create Repository Here. When the dialog comes up, leave everything alone and click on Create and you are done.

































This does not backup any data, it simply creates a new local repository for you to store you data. 

When you create a local repository, it creates a folder called .hg. Do not delete, edit, move or modify this file. This is your physical repository, which is actually a compressed package of all of your files. 

2. Manage local Repositories.


Now that you have a repositry, you want to open it up in the TortoiseHg interface to view your backups. From within the TortoiseHg workbench interface, choose File \ Open Repository. Choose the folder you created and open it. Once open, double click the repository listed on the right, you can see the files as displayed in the image below.
























3. Commit to local Repository.

Every time you want to save a backup, usually every night or when you complete something, follow these steps to commit changes to your local repository:

The top item will be called Working Directory, click on it to see what you have recently edited (files are listed below). Of course, you have to have changes to commit or this will not work!

Click on the button above the files to make sure you have selected all files to be added or removed.
















Type in something to describe your modification into to the box then click Commit. Keep in mind, the files must not be open when you click on commit or it will not work. 











Before you can upload to an online repository you need to setup an account with an online repository. If you have not done already, go to bitbucket.org and create a new account and repository. Once you do you can choose the repository. Name the repository the same name as your Flash Builder or Flash Develop project file name. Make sure you have chosen local repository you want to synchronize and working directory has been selected. 

After you commit your files, the file icons in your project, viewed from Windows Explorer will have a green check mark next to them. When you modify files, the green check changes to a red one.

4. Upload to online Repository

After you commit changes to your local repository, you can upload it to the online repository anytime you want. If you are working alone, you might update your online repository around every week or so. But, if you are working with other team members, you will need to update the online repository daily so that other team members can get your changes.

  • Log into Bitbucket and select your repository. 
  • Choose HTTPS from status dialog pull down, as shown in image below. 




















  • Copy the address displayed into your clipboard. 
  • Enter TortoiseHg and select your project.
  • Select Working Directory.
  • Click on Push Changes button as shown on the image below.










An error will appear, click OK.
  • Paste the address into the box provided, as shown in the image below.










  • Click on Push Changes again.
  • Supply your Bitbucket password to start the upload. 
In a future blog, I will explain advanced version control techniques like branches, pull requests, forking and merging code. I will also explain setting up secure connection with your online repository through "configured files" so that the process does not include copying and pasting anything.

5. Download from online repository.

Now that you have an online repository with all of your data, you can have other team members download it. Or, simply access it to replace corrupt files on your computer. 

When they download the repository, they are downloading every version of every file that everyone has ever made for that project.

Bitbucket makes this real easy; you can view the entire folder structure with the Source button. To download the source code, click on Download, on the bottom of the Bitbucket status area, as seen in the image below.



















 

About Sonoma Data Solutions LLC

My company, Sonoma Data Solutions is located in Sonoma County, in northern California. I started my company with the goal of building high end applications. I have worked for HP, Agilent, and on applications for EA Sports and Disney.

We provide full services to conceptualize, design, build, test and deploy your application online. We also provide financial options to make your application a reality.
Do not wait to build your application, define and grow your brand, and monetize your ideas.
Check out my website or contact me if you have any questions.

Thank you, 
John Molinari

Sonoma Data Solutions LLC
john@sonomadatasolutions.com


PREVIOUS POST  - NEXT POST