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