You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ma...@apache.org on 2014/03/16 22:52:46 UTC

git commit: [flex-sdk] [refs/heads/develop] - COMPLETE - FLEX-33949: Manage OS version in @media CSS - Now X.Y.Z version is supported is os-version media selector - Computes version for Android devices. so now the follow media query works: @media (os-

Repository: flex-sdk
Updated Branches:
  refs/heads/develop 1da2381b2 -> d67e20c04


COMPLETE - FLEX-33949: Manage OS version in @media CSS
- Now  X.Y.Z version is supported is os-version media selector
- Computes version for Android devices.
 so now the follow media query works:
 @media (os-platform: "android") AND (min-os-version: "4.1.2") {

    /* JELLY BEAN SKINS */
 }


Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/d67e20c0
Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/d67e20c0
Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/d67e20c0

Branch: refs/heads/develop
Commit: d67e20c04e6c262630e5ac91a76bdc784bb2e143
Parents: 1da2381
Author: mamsellem <ma...@systar.com>
Authored: Sun Mar 16 22:51:36 2014 +0100
Committer: mamsellem <ma...@systar.com>
Committed: Sun Mar 16 22:51:36 2014 +0100

----------------------------------------------------------------------
 .../framework/src/mx/utils/MediaQueryParser.as  | 219 +++++++++++++------
 .../projects/framework/src/mx/utils/Platform.as | 131 ++++++++---
 .../src/MobileComponentsClasses.as              |   2 +
 .../src/MobileComponentsClassesAIR2.as          |   1 +
 .../supportClasses/ViewNavigatorBase.as         |   9 +
 .../src/spark/utils/PlatformMobileHelper.as     |  74 +++++++
 6 files changed, 341 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/d67e20c0/frameworks/projects/framework/src/mx/utils/MediaQueryParser.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/framework/src/mx/utils/MediaQueryParser.as b/frameworks/projects/framework/src/mx/utils/MediaQueryParser.as
index 55dcadd..ea1e1d6 100644
--- a/frameworks/projects/framework/src/mx/utils/MediaQueryParser.as
+++ b/frameworks/projects/framework/src/mx/utils/MediaQueryParser.as
@@ -31,6 +31,12 @@ use namespace mx_internal;
  *  Parser for CSS Media Query syntax.  Not a full-fledged parser.
  *  Doesn't report syntax errors, assumes you have your attributes
  *  and identifiers spelled correctly, etc.
+ *  Media query parser now supports os-version selectors such as X, X.Y or X.Y.Z
+ *  Note that version with 3 parts must be  quoted
+Examples:
+ (os-platform: "ios") AND (min-os-version: 7)
+ (os-platform: "android") AND (min-os-version: "4.1.2")
+
  *  
  *  @langversion 3.0
  *  @playerversion Flash 10.2
@@ -103,7 +109,7 @@ public class MediaQueryParser
                 applicationDpi = moduleFactory.info()["applicationDPI"];
         }
         osPlatform = getPlatform();
-        osVersion = getOSVersion(osPlatform);
+        osVersion = getOSVersion();
     }
     
     /**
@@ -291,49 +297,52 @@ public class MediaQueryParser
             
             // break into two pieces
             var parts:Array = expr.split(":");
+            var key: String = parts[0];
             var min:Boolean = false;
             var max:Boolean = false;
             // look for min
-            if (parts[0].indexOf("min-") == 0)
+            if (key.indexOf("min-") == 0)
             {
                 min = true;
-                parts[0] = parts[0].substr(4);
+                key = key.substr(4);
             }
             // look for max
-            else if (parts[0].indexOf("max-") == 0)
+            else if (key.indexOf("max-") == 0)
             {
                 max = true;
-                parts[0] = parts[0].substr(4);
+                key = key.substr(4);
             }
             // collapse hypens into camelcase
-            if (parts[0].indexOf("-") > 0)
-                parts[0] = deHyphenate(parts[0]);
+            if (key.indexOf("-") > 0)
+                key = deHyphenate(key);
             // if only one part, then it only matters that this property exists
             if (parts.length == 1)
             {
-                if (!(parts[0] in this))
+                if (!(key in this))
                     return false;
             }
             // if two parts, then make sure the property exists and value matches
             if (parts.length == 2)
             {
                 // if property doesn't exist, then bail
-                if (!(parts[0] in this))
+                if (!(key in this))
                     return false;
+                var value: Object = normalize(parts[1], this[key]) ;
+                var cmp: int = compareValues(this[key], value) ;
                 // handle min (we don't check if min is allowed for this property)
                 if (min)
                 {
-                    if (this[parts[0]] < normalize(parts[1], typeof(this[parts[0]])))
-                        return false;
+                   if (cmp < 0)
+                       return false;
                 }
                 // handle max (we don't check if min is allowed for this property)
                 else if (max)
                 {
-                    if (this[parts[0]] > normalize(parts[1], typeof(this[parts[0]])))
+                    if (cmp > 0)
                         return false;
                 }
                 // bail if the value doesn't match
-                else if (this[parts[0]] != normalize(parts[1], typeof(this[parts[0]])))
+                else if (cmp != 0)
                 {
                     return false;
                 }
@@ -344,8 +353,9 @@ public class MediaQueryParser
         return true;
     }
     
-    // strip off metrics (maybe convert metrics some day)
-    private function normalize(s:String, type:String):Object
+    // strip off  unit if currentValue is Number or int
+    //  now supports versions (X.Y.Z) and numbers with units
+    private function normalize(s:String, currentValue: Object ):Object
     {
         var index:int;
         
@@ -356,7 +366,7 @@ public class MediaQueryParser
         // for the numbers we currently handle, we
         // might find dpi or ppi on it, that we just strip off.
         // We don't handle dpcm yet.
-        if (type == "number")
+        if (currentValue is Number)
         {
             index = s.indexOf("dpi");
             if (index != -1)
@@ -365,25 +375,51 @@ public class MediaQueryParser
             }
             return Number(s);
         }
-        else if (type == "int")
+        else if (currentValue is int)
         {
             return int(s);
         }
-        else if (type == "string")
+        // string or CSS value
+        // strip quotes of strings
+        if (s.indexOf('"') == 0) {
+            if (s.lastIndexOf('"') == s.length - 1)
+                s = s.substr(1, s.length - 2);
+            else
+                s = s.substr(1);
+        }
+        //  string , return
+         if (currentValue is String)
         {
-            // strip quotes of strings
-            if (s.indexOf('"') == 0)
-            {
-                if (s.lastIndexOf('"') == s.length - 1)
-                    s = s.substr(1, s.length - 2);
-                else
-                    s = s.substr(1);
-            }
+             return s;
+        }
+        else if (currentValue is CssOsVersion) {
+            return new CssOsVersion(s) ;
         }
-        
         return s;
     }
-    
+
+    /**  @private
+     * Compares current value with test values, using currentValue type to determine comparison function
+     *  accepts number, int, string and CssOsVersion.
+     *  Will accept LexicalUnit in the future
+     *
+     * @param currentValue
+     * @param testValue
+     * @return   -1 if currentValue < testValue, 1 if currentValue > testValue and 0 if equal
+     */
+    private function compareValues ( currentValue: Object, testValue: Object): int
+    {
+        if (currentValue is CssOsVersion)
+           return CssOsVersion(currentValue).compareTo(CssOsVersion(testValue))  ;
+        else // scalar compare operators
+           if ( currentValue == testValue)
+              return 0;
+           else if ( currentValue < testValue)
+             return -1;
+           else
+             return 1;
+    }
+
     // collapse "-" to camelCase
     private function deHyphenate(s:String):String
     {
@@ -415,45 +451,10 @@ public class MediaQueryParser
     }
 
     /** @private
-     * extract OS version information from os
-     * os is typically a non-numeric string (such as Windows,  iPhone OS, Android, etc...)  followed by a number.
-     * if no number is found, OS version is set to 0.
-     * os on ADL will return the host OS and not the device OS.
-     * That why we need to check for a specific sequence for iOS and Android
+     * returns a CssOsVersion suitable for MediaQueryParser for the current device operating system version.
      * */
-    private function getOSVersion(osPlatform:String):Number {
-        //TODO (mamsellem)  retrieve  os version for Android, reading  system/build.prop
-        var os: String = Capabilities.os;
-        var osMatch: Array;
-		
-        if (osPlatform == "ios")
-		{
-            osMatch = os.match(/iPhone OS\s([\d\.]+)/);
-        }
-        else
-		{
-            osMatch = os.match(/[A-Za-z\s]+([\d\.]+)/);
-        }
-		
-		return osMatch ? convertVersionStringToNumber(osMatch[1]) : 0.0;
-    }
-
-    /** @private  converts string version such as "X" or "X.Y" or "X.Y.Z" into a number.
-     * minor version parts are normalized to 100  so that eg. X.1 < X.10
-     * so "7.1" return 7.01 and "7.12" return 7.12
-  */
-    private function convertVersionStringToNumber(versionString: String): Number
-	{
-        var versionParts: Array = versionString.split(".");
-        var version: Number = 0;
-        var scale: Number = 1;
-		
-        for each (var part: String in versionParts) {
-            version += Number(part) * scale;
-            scale /= 100;
-        }
-		
-        return version;
+    private function getOSVersion():CssOsVersion {
+		return  new CssOsVersion(Platform.osVersion) ;
     }
 
     // the type of the media
@@ -466,8 +467,92 @@ public class MediaQueryParser
     public var osPlatform:String;
 
     // the platform os version of the media
-    public var osVersion: Number;
+    public var osVersion: CssOsVersion;
     
 }
+}
+
+/**
+ * Support class for MediaQueryParser to store and compare versions such as X.Y.Z
+ * Its mainly used in os-version  media selector.
+ */
+internal class CssOsVersion
+{
+     /* separator between version parts*/
+    private static const SEPARATOR: String = ".";
 
+    /** Contructor
+     *   Returns an CssOsVersion with the
+     * @param versionString
+     */
+    public function CssOsVersion(versionString: String = "")
+    {
+        var versionParts: Array = versionString.split(SEPARATOR);
+        var l: int = versionParts.length;
+        if (l >= 1)
+            major = Number(versionParts[0]);
+        if (l >= 2)
+            minor = Number(versionParts[1]);
+        if (l >= 3)
+            revision = Number(versionParts[2]);
+        // ignore remaining parts
+    }
+
+    /**
+     *  major figure of the version.
+     */
+    public var major: int = 0;
+    /**
+     *  minor figure  of the version.
+     */
+    public var minor: int = 0;
+    /**
+     *  revision figure  of the version.
+     */
+    public var revision: int = 0;
+
+    /**
+     * Printable string of the version, as X.Y.Z
+     * @return version as a string
+     */
+    public function toString(): String
+    {
+        return  major.toString() + SEPARATOR + minor.toString() + SEPARATOR + revision.toString();
+    }
+
+    /**
+     *  Compares to another version.
+     *
+     *  @param other Second Version.
+     *
+     *  @return 0 if both versions are equal
+     *  -1 if <code>this</code> is lower than <code>otherVersion</code>.
+     *  1 if <code>this</code> is greater than <code>otherVersion</code>.
+     *  @langversion 3.0
+     *  @productversion Flex 4.13
+     */
+    public function compareTo(otherVersion: CssOsVersion): int
+    {
+        if (major > otherVersion.major)
+            return 1;
+        else if (major < otherVersion.major)
+            return -1;
+        else //major == other.major)
+        {
+            if (minor > otherVersion.minor)
+                return 1;
+            else if (minor < otherVersion.minor)
+                return -1;
+            else //minor == other.minor)
+            {
+                if (revision > otherVersion.revision)
+                    return 1;
+                else if (revision < otherVersion.revision)
+                    return -1;
+                else
+                    return 0; // all equal
+            }
+        }
+    }
 }
+

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/d67e20c0/frameworks/projects/framework/src/mx/utils/Platform.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/framework/src/mx/utils/Platform.as b/frameworks/projects/framework/src/mx/utils/Platform.as
index 494b83c..9f3cd26 100644
--- a/frameworks/projects/framework/src/mx/utils/Platform.as
+++ b/frameworks/projects/framework/src/mx/utils/Platform.as
@@ -19,11 +19,12 @@
 
 package mx.utils
 {
-	
+
 import flash.system.Capabilities;
+import flash.utils.getDefinitionByName;
 
 /**
- *  The Platform utility class constain several static methods to check what
+ *  The Platform utility class contains several static methods to check what
  *  desktop or mobile platform the application is running on.
  *  
  *  @langversion 3.0
@@ -34,8 +35,10 @@ import flash.system.Capabilities;
 public class Platform
 {
     include "../core/Version.as";
+
+    private static var _instance: Platform;
 	
-	protected static var _initilised:Boolean;
+	protected static var _initialized:Boolean;
 	protected static var _isAndroid:Boolean;
 	protected static var _isIOS:Boolean;
 	protected static var _isIPad:Boolean;
@@ -47,9 +50,10 @@ public class Platform
 	protected static var _isDesktop:Boolean;
 	protected static var _isBrowser:Boolean;
 	protected static var _isAir:Boolean;
+    private static var _osVersion: String = null;
 	
 	/**
-	 *  Returns true if the applciation is runing on IOS.
+	 *  Returns true if the application is running on IOS.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -64,8 +68,8 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on an iPad.
-	 *  Note this returns false in the mobile device simulator.
+	 *  Returns true if the application is running on an iPad.
+	 *  Note this returns false in the AIR mobile device simulator.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -80,7 +84,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on a BlackBerry.
+	 *  Returns true if the application is running on a BlackBerry.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -95,7 +99,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on Android.
+	 *  Returns true if the application is running on Android.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -110,7 +114,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on Windows.
+	 *  Returns true if the application is running on Windows.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -125,7 +129,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on a Mac.
+	 *  Returns true if the application is running on a Mac.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -140,7 +144,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on Linux.
+	 *  Returns true if the application is running on Linux.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -155,7 +159,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on a Desktop OS.
+	 *  Returns true if the application is running on a Desktop OS.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -170,7 +174,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on a Mobile device.
+	 *  Returns true if the application is running on a Mobile device.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -185,7 +189,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing on a desktop AIR.
+	 *  Returns true if the application is running on a desktop AIR.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -200,7 +204,7 @@ public class Platform
 	}
 	
 	/**
-	 *  Returns true if the applciation is runing in a browser.
+	 *  Returns true if the application is running in a browser.
 	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10
@@ -213,27 +217,98 @@ public class Platform
 		
 		return _isBrowser;
 	}
-	
+
+    /**
+     *  Returns the version of the OS the application  is running on
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.13
+     */
+    public static function get osVersion(): String
+    {
+        //We needed to compute _osVersion later than getPlatforms, because it relies on resources that  ready later
+        if (_osVersion == null){
+            _osVersion = computeOSVersionString();
+        }
+        return _osVersion;
+    }
+
+    /* Notes on Capabilities.os for mobile apps:
+        - on ADL => returns the OS where the ADL is running ( eg. Windows 7, or Mac OS )
+         - on device => returns the OS of the device (eg.  iPhone OS ...  for iOS devices  )
+    * */
 	protected static function getPlatforms():void {
-		if (!_initilised)
+		if (!_initialized)
 		{
-			_isAndroid = Capabilities.version.indexOf("AND") > -1;
-			_isIOS = Capabilities.version.indexOf('IOS') > -1;
-			_isBlackBerry = Capabilities.version.indexOf('QNX') > -1;
+            var cap: Class = Capabilities;
+            var version:  String = Capabilities.version;
+            var os: String = Capabilities.os;
+            var playerType: String = Capabilities.playerType;
+
+			_isAndroid = version.indexOf("AND") > -1;
+			_isIOS = version.indexOf('IOS') > -1;
+			_isBlackBerry = version.indexOf('QNX') > -1;
 			_isMobile = _isAndroid || _isIOS || _isBlackBerry;
 			
-			_isMac = Capabilities.os.indexOf("Mac OS") != -1;
-			_isWindows = Capabilities.os.indexOf("Windows") != -1;
-			_isLinux = Capabilities.os.indexOf("Linux") != -1; // note that Android is also Linux
-			_isIPad = Capabilities.os.indexOf('iPad') > -1;
+			_isMac = os.indexOf("Mac OS") != -1;
+			_isWindows = os.indexOf("Windows") != -1;
+			_isLinux = os.indexOf("Linux") != -1; // note that Android is also Linux
+			_isIPad = os.indexOf('iPad') > -1;
 			_isDesktop = !_isMobile;
 			
-			_isAir = Capabilities.playerType == "Desktop";
-			_isBrowser = (Capabilities.playerType == "Plugin" || Capabilities.playerType == "ActiveX");
+			_isAir = playerType == "Desktop";
+			_isBrowser = (playerType == "Plugin" || playerType == "ActiveX");
 			
-			_initilised = true;
+			_initialized = true;
 		}
 	}
-}
 
+    /** @private
+     * extract OS version information from Capabilities.os
+     * os is typically a non-numeric string (such as Windows,  iPhone OS, Android, etc...)  followed by a number sequence.
+     * if no number is found, OS version is set to 0.
+     * os on ADL will return the host OS and not the device OS.
+     *
+     * That's why we need to check for a specific sequence for iOS and Android.
+     * On Android, os  is the Linux kernel version (such as Linux 3.4.34-1790463).
+     * So the version information must be  retrieved from an internal file.
+     * Since reading files API is only available on AIR, it's delegated to PlatformMobileHelper  in mobilecomponents.swc
+     * @see   spark.utils.PlatformMobileHelper
+     *
+     * @return version number string, or empty string if could not retrieve the version.
+     * */
+    private static function computeOSVersionString(): String
+    {
+        var os: String = Capabilities.os;
+        var osVersionMatch: Array;
+        var version: String = "";
+
+        if (isIOS) {
+            osVersionMatch = os.match(/iPhone OS\s([\d\.]+)/);
+            if (osVersionMatch && osVersionMatch.length == 2)
+                version = osVersionMatch[1];
+        }
+        else if (isAndroid) {
+            try {
+                var mobileHelperClass: Class = Class(getDefinitionByName("spark.utils::PlatformMobileHelper"));
+                if (mobileHelperClass != null) {
+                    version = mobileHelperClass["computeOSVersionForAndroid"]();
+                }
+            }
+            catch (e: Error) {
+                trace("Error: " + e.message);
+            }
+        }
+        else {
+            //on  other OS, extract version
+            osVersionMatch = os.match(/[A-Za-z\s]+([\d\.]+)/);
+            if (osVersionMatch && osVersionMatch.length == 2)
+                version = osVersionMatch[1];
+        }
+        return version;
+    }
+
+}
 }

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/d67e20c0/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as b/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
index bde526a..677324a 100644
--- a/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
+++ b/frameworks/projects/mobilecomponents/src/MobileComponentsClasses.as
@@ -31,6 +31,8 @@ internal class MobileComponentsClasses
  *  For example, Button does not have a reference to ButtonSkin,
  *  but ButtonSkin needs to be in framework.swc along with Button.
  */
+
+    import spark.utils.PlatformMobileHelper;  PlatformMobileHelper;
     import spark.preloaders.SplashScreen; SplashScreen;
     import spark.components.supportClasses.StyleableStageText; StyleableStageText;
     import spark.components.supportClasses.ScrollableStageText; ScrollableStageText;

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/d67e20c0/frameworks/projects/mobilecomponents/src/MobileComponentsClassesAIR2.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/MobileComponentsClassesAIR2.as b/frameworks/projects/mobilecomponents/src/MobileComponentsClassesAIR2.as
index d5468cd..7c0fec6 100644
--- a/frameworks/projects/mobilecomponents/src/MobileComponentsClassesAIR2.as
+++ b/frameworks/projects/mobilecomponents/src/MobileComponentsClassesAIR2.as
@@ -34,5 +34,6 @@ internal class MobileComponentsClassesAIR2
     import spark.preloaders.SplashScreen; SplashScreen;
     import spark.components.supportClasses.StyleableTextField; StyleableTextField;
     import spark.components.ActionBarDefaultButtonAppearance; ActionBarDefaultButtonAppearance;
+   import spark.utils.PlatformMobileHelper; PlatformMobileHelper;
 }
 }

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/d67e20c0/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ViewNavigatorBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ViewNavigatorBase.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ViewNavigatorBase.as
index 857f97a..4421498 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ViewNavigatorBase.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ViewNavigatorBase.as
@@ -35,6 +35,7 @@ import mx.utils.DensityUtil;
 import spark.components.SkinnableContainer;
 import spark.components.View;
 import spark.utils.MultiDPIBitmapSource;
+import spark.utils.PlatformMobileHelper;
 
 use namespace mx_internal;
 
@@ -91,6 +92,14 @@ public class ViewNavigatorBase extends SkinnableContainer
     // Variables
     // 
     //--------------------------------------------------------------------------
+
+    /**
+     * @private this is to force inclusion by dependency of PlatformMobileHelper in the final application swf ,
+     * as it's only accessed by QName from framework's mx.utils.Platform class.
+     * We use ViewNavigatorBase as the referring class because it's always  included in a mobile application.
+     * Note that including PlatformMobileHelper in MobileComponentClasses only ensures that its included in mobilecomponents.swc
+     */
+    private static const __includeClasses: Array = [ PlatformMobileHelper];
     
     /**
      *  @private

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/d67e20c0/frameworks/projects/mobilecomponents/src/spark/utils/PlatformMobileHelper.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/spark/utils/PlatformMobileHelper.as b/frameworks/projects/mobilecomponents/src/spark/utils/PlatformMobileHelper.as
new file mode 100644
index 0000000..8f99eb8
--- /dev/null
+++ b/frameworks/projects/mobilecomponents/src/spark/utils/PlatformMobileHelper.as
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.utils
+{
+import flash.filesystem.File;
+import flash.filesystem.FileMode;
+import flash.filesystem.FileStream;
+
+/** @private
+ * Helper class for computing device -dependent platform capabilities.
+ * This class should not be used directly.
+ */
+
+public class PlatformMobileHelper
+{
+    /** Function to retrieve OS version string on Android devices, in X.Y.Z format.
+     * On Android, Capabilities.os contains the Linux kernel version (such as Linux 3.4.34-1790463), not the Android version.
+     * So the version information must be  retrieved from an internal file:   <code> /system/build.prop</code>
+     * as <code>ro.build.version.release</code>  property value.
+     *
+     * @return the OS version as "X.Y.Z" string, or "" (empty string) if not found.
+     *
+     * @see mx.utils.Platform
+     *
+     *  @langversion 3.0
+     *  @playerversion AIR 2.0
+     *  @productversion Flex 4.13
+     */
+    public static function computeOSVersionForAndroid(): String
+    {
+        var version: String = "";
+
+        var file: File = new File();
+        var fs: FileStream = new FileStream();
+        file.nativePath = "/system/build.prop";
+        if (file.exists) {
+            try {
+                var osVersionMatch: Array;
+                fs.open(file, FileMode.READ);
+                var content: String = fs.readUTFBytes(file.size);
+                osVersionMatch = content.match(/ro.build.version.release=([\d\.]+)/);
+                if (osVersionMatch && osVersionMatch.length == 2)
+                    version = osVersionMatch[1];
+            }
+            catch (e: Error) {
+                // trace the error, and return empty string
+                trace("Error while reading build.prop file:" + e.message);
+            }
+            finally {
+                if (fs)
+                    fs.close();
+            }
+        }
+        return version;
+    }
+}
+}