PageRenderTime 27ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/EladLibAIR/src/com/elad/framework/utils/ContextAwarenessManager.as

http://github.com/EladElrom/eladlib
ActionScript | 371 lines | 172 code | 41 blank | 158 comment | 4 complexity | 1dd616a696698a857637042ecb566c9b MD5 | raw file
  1. /*
  2. Copyright (c) 2009 Elad Elrom. Elrom LLC. All rights reserved.
  3. Permission is hereby granted, free of charge, to any person
  4. obtaining a copy of this software and associated documentation
  5. files (the "Software"), to deal in the Software without
  6. restriction, including without limitation the rights to use,
  7. copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the
  9. Software is furnished to do so, subject to the following
  10. conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. OTHER DEALINGS IN THE SOFTWARE.
  21. @author Elad Elrom
  22. @contact elad.ny at gmail.com
  23. */
  24. package com.elad.framework.utils
  25. {
  26. import air.net.*;
  27. import com.elad.framework.vo.ContextVO;
  28. import flash.desktop.NativeApplication;
  29. import flash.display.NativeWindow;
  30. import flash.events.Event;
  31. import flash.events.EventDispatcher;
  32. import flash.events.NativeWindowBoundsEvent;
  33. import flash.events.StatusEvent;
  34. import flash.filesystem.File;
  35. import flash.net.URLRequest;
  36. import mx.core.Application;
  37. import mx.core.FlexGlobals;
  38. /**
  39. * Context Awareness Manager is the platform to gather and track information
  40. * regarding the system physical information as well as track changes in the
  41. * system.
  42. *
  43. * The Context Awareness manager than can translate the information dispatch events
  44. * and allow our application to react accordingly.
  45. *
  46. * @author Elad Elrom
  47. *
  48. */
  49. public class ContextAwarenessManager extends EventDispatcher implements IContextAwarenessManager
  50. {
  51. // VO holds all the information
  52. public var contextVO:ContextVO;
  53. // Singleton instance.
  54. protected static var instance:ContextAwarenessManager;
  55. protected var nativeApp:NativeApplication;
  56. protected var monitor:URLMonitor;
  57. protected var socketMonitor:SocketMonitor;
  58. // events strings
  59. public static const USER_IDLE:String = "userIdle";
  60. public static const USER_PRESENT:String = "userPresent";
  61. public static const NETWORK_CHANGE:String = "networkChange";
  62. public static const HTTP_CONNECTIVITY_TRUE:String = "HTTPConnectivityTrue";
  63. public static const HTTP_CONNECTIVITY_FALSE:String = "HTTPConnectivityFalse";
  64. public static const SOCKET_CONNECTIVITY_TRUE:String = "socketConnectivityTrue";
  65. public static const SOCKET_CONNECTIVITY_FALSE:String = "socketConnectivityFalse";
  66. public static const NATIVE_WINDOW_MOVED:String = "nativeWindowMoved";
  67. // settings properties
  68. public var siteToTrack:String;
  69. public var idleThresholdTime:int;
  70. public var portToCheck:int;
  71. public var siteSocketMonitor:String;
  72. /**
  73. * Method needs to enforce that class is only created once
  74. *
  75. * @param enforcer
  76. *
  77. */
  78. public function ContextAwarenessManager(enforcer:AccessRestriction)
  79. {
  80. if (enforcer == null)
  81. throw new Error("Error enforcer input param is undefined" );
  82. initializeContextAwareness();
  83. }
  84. /**
  85. * Default constructor
  86. *
  87. */
  88. public function initializeContextAwareness():void
  89. {
  90. siteToTrack = "http://www.google.com";
  91. siteSocketMonitor = "www.adobe.com";
  92. idleThresholdTime = 5;
  93. portToCheck = 6667;
  94. contextVO = new ContextVO();
  95. nativeApp = NativeApplication.nativeApplication;
  96. }
  97. /**
  98. * Setting properties and start tracking changes
  99. *
  100. */
  101. public function start():void
  102. {
  103. detectUserPresence();
  104. detectNetworkChanges();
  105. detectHTTPConnectivity();
  106. detectSocketConnectivity();
  107. setRuntimeInformation();
  108. setSystemSupportCapability();
  109. detectLocalDrivers();
  110. detectWindowedApplicationMovment();
  111. }
  112. /**
  113. * Stopping tracking events
  114. *
  115. */
  116. public function stop():void
  117. {
  118. nativeApp.removeEventListener(Event.USER_IDLE, onUserIdleHandler);
  119. nativeApp.removeEventListener(Event.USER_PRESENT, onUserPresentHandler);
  120. nativeApp.removeEventListener(Event.NETWORK_CHANGE, onNetworkStatusChange);
  121. monitor.removeEventListener(StatusEvent.STATUS, onHTTPConnectivityChange);
  122. socketMonitor.removeEventListener(StatusEvent.STATUS, onSocketStatusChange);
  123. monitor.stop();
  124. socketMonitor.stop();
  125. }
  126. /**
  127. * AIR application can detect when a user is actively using the device.
  128. * There are two states: userPresent and idleThreshold.
  129. * Once user used their keyboard, mouse or touch-screen AIR NativeApplication
  130. * API will dispatch a userPresent event. In the event the user is not using the input devices
  131. * an idleThreshold will be dispatch and we can find out how long since the user used
  132. * his input devices using timeSinceLastUserInput property.
  133. *
  134. * @see NativeApplication.nativeApplication.idleThreshold
  135. * @see flash.events.Event
  136. *
  137. */
  138. private function detectUserPresence():void
  139. {
  140. nativeApp.idleThreshold = idleThresholdTime;
  141. nativeApp.addEventListener(Event.USER_IDLE, onUserIdleHandler);
  142. nativeApp.addEventListener(Event.USER_PRESENT, onUserPresentHandler);
  143. }
  144. /**
  145. * AIR application can run in environments with uncertain and changing network connectivity.
  146. * To help an application manage connections to online resources,
  147. * Adobe AIR sends a network change event whenever a network connection becomes available
  148. * or unavailable. The application’s NativeApplication object dispatches the network change event.
  149. *
  150. * @see flash.events.Event
  151. *
  152. */
  153. private function detectNetworkChanges():void
  154. {
  155. nativeApp.addEventListener(Event.NETWORK_CHANGE, onNetworkStatusChange);
  156. }
  157. /**
  158. * The URLMonitor class determines if HTTP requests can be made to a specified address at port 80
  159. * (the typical port for HTTP communication). The following code uses an instance of the URLMonitor
  160. * class to detect connectivity changes.
  161. *
  162. * @see flash.net.URLRequest
  163. * @see air.net.URLMonitor
  164. *
  165. */
  166. private function detectHTTPConnectivity():void
  167. {
  168. monitor = new URLMonitor(new URLRequest(siteToTrack));
  169. monitor.addEventListener(StatusEvent.STATUS, onHTTPConnectivityChange);
  170. monitor.start();
  171. }
  172. /**
  173. * Applications can also use socket connections for push-model connectivity.
  174. * Firewalls and network routers typically restrict network communication on
  175. * unauthorized ports for security reasons.
  176. * For this reason, developers must consider that users may not have the
  177. * capability of making socket connections.
  178. *
  179. * @see air.net.SocketMonitor
  180. *
  181. */
  182. private function detectSocketConnectivity():void
  183. {
  184. socketMonitor = new SocketMonitor(siteSocketMonitor,portToCheck);
  185. socketMonitor.addEventListener(StatusEvent.STATUS, onSocketStatusChange);
  186. socketMonitor.start();
  187. }
  188. /**
  189. * the version of the runtime in which the application is running (a string, such as "1.0.5").
  190. * The NativeApplication object also has a runtimePatchLevel property, which is the patch level
  191. * of the runtime (a number, such as 2960).
  192. *
  193. * @see NativeApplication.nativeApplication.runtimeVersion
  194. * @see NativeApplication.nativeApplication.runtimePatchLevel
  195. *
  196. */
  197. private function setRuntimeInformation():void
  198. {
  199. contextVO.getRuntimeVersion = nativeApp.runtimeVersion;
  200. contextVO.getRuntimePatchLevel = nativeApp.runtimePatchLevel;
  201. }
  202. /**
  203. * Setting additional Capabilities
  204. *
  205. * @see NativeApplication.supportsDockIcon
  206. * @see NativeApplication.supportsMenu
  207. * @see NativeApplication.supportsSystemTrayIcon
  208. * @see NativeWindow.supportsMenu
  209. * @see NativeWindow.supportsNotification
  210. * @see NativeWindow.supportsTransparency
  211. * @see NativeWindow.systemMaxSize
  212. * @see NativeWindow.systemMinSize
  213. *
  214. */
  215. private function setSystemSupportCapability():void
  216. {
  217. contextVO.supportsDockIcon = NativeApplication.supportsDockIcon;
  218. contextVO.supportsMenu = NativeApplication.supportsMenu;
  219. contextVO.supportsSystemTrayIcon = NativeApplication.supportsSystemTrayIcon;
  220. contextVO.supportsMenu = NativeWindow.supportsMenu;
  221. contextVO.supportsNotification = NativeWindow.supportsNotification;
  222. contextVO.supportsTransparency = NativeWindow.supportsTransparency;
  223. contextVO.systemMaxSize = NativeWindow.systemMaxSize;
  224. contextVO.systemMinSize = NativeWindow.systemMinSize;
  225. }
  226. /**
  227. * Adobe AIR File function getDirectoryListing for Mac or getRootDirectories for PC
  228. * allow detecting local drives.
  229. *
  230. * @see flash.filesystem.File.getDirectoryListing
  231. * @see flash.filesystem.File.getRootDirectories
  232. *
  233. */
  234. private function detectLocalDrivers():void
  235. {
  236. contextVO.currentAvaliableDrives = (contextVO.osName=="mac") ?
  237. new File('/Volumes/').getDirectoryListing() : File.getRootDirectories() ;
  238. }
  239. /**
  240. * Allow access to manual refresh of local drives
  241. *
  242. */
  243. public function refreshLocalDrives():void
  244. {
  245. detectLocalDrivers();
  246. }
  247. /**
  248. * Detecting WindowedApplication movement
  249. *
  250. * information placed in <code>contextVO</code>, under the properties;
  251. * <ul>
  252. * <ui><code>windowPositionAfterBounds</code></ui>
  253. * <ui><code>windowPositionBeforeBounds</code></ui>
  254. * </ul>
  255. *
  256. * @see flash.events.NativeWindowBoundsEvent
  257. *
  258. */
  259. private function detectWindowedApplicationMovment():void
  260. {
  261. FlexGlobals.topLevelApplication.addEventListener(NativeWindowBoundsEvent.MOVING, onWindowedApplicationMovment);
  262. }
  263. /* ----------------------------------------------
  264. | EVENT HANDLERS |
  265. ----------------------------------------------
  266. */
  267. private function onUserIdleHandler(evt:Event):void
  268. {
  269. var lastUserInput:Number = NativeApplication.nativeApplication.timeSinceLastUserInput;
  270. var event:Event = new Event(USER_IDLE, true);
  271. contextVO.isUserPresent = false;
  272. contextVO.lastUserInput = lastUserInput;
  273. this.dispatchEvent(event);
  274. }
  275. private function onUserPresentHandler(evt:Event):void
  276. {
  277. var event:Event = new Event(USER_PRESENT, true);
  278. contextVO.isUserPresent = true;
  279. this.dispatchEvent(event);
  280. }
  281. private function onNetworkStatusChange(evt:Event):void
  282. {
  283. var event:Event = new Event(NETWORK_CHANGE, true);
  284. contextVO.isNetworkChanged = true;
  285. this.dispatchEvent(event);
  286. }
  287. private function onHTTPConnectivityChange(evt:StatusEvent):void
  288. {
  289. var event:Event;
  290. contextVO.isHTTPAvaliable = monitor.available;
  291. event = (monitor.available) ? new Event(HTTP_CONNECTIVITY_TRUE, true) :
  292. new Event(HTTP_CONNECTIVITY_FALSE, true);
  293. this.dispatchEvent(event);
  294. }
  295. private function onSocketStatusChange(evt:StatusEvent):void
  296. {
  297. var event:Event;
  298. contextVO.isSocketMonitorAvailable = socketMonitor.available;
  299. event = (socketMonitor.available) ? new Event(SOCKET_CONNECTIVITY_TRUE, true) :
  300. new Event(SOCKET_CONNECTIVITY_FALSE, true);
  301. this.dispatchEvent(event);
  302. }
  303. private function onWindowedApplicationMovment(evt:*):void
  304. {
  305. var event:Event = new Event(NATIVE_WINDOW_MOVED, true);
  306. contextVO.windowPositionAfterBounds = evt.afterBounds;
  307. contextVO.windowPositionBeforeBounds = evt.beforeBounds;
  308. this.dispatchEvent(event);
  309. }
  310. /**
  311. * Method function to retrieve instance of the class
  312. *
  313. * @return The same instance of the class
  314. *
  315. */
  316. public static function getInstance():ContextAwarenessManager
  317. {
  318. if( instance == null )
  319. instance = new ContextAwarenessManager(new AccessRestriction());
  320. return instance;
  321. }
  322. }
  323. }
  324. class AccessRestriction {}