├── .project ├── Android_air_build.xml ├── Controller-App.xml ├── README.md ├── assets ├── icons │ ├── AIRApp_128.png │ ├── AIRApp_16.png │ ├── AIRApp_32.png │ └── AIRApp_48.png └── settings │ └── exampleCert.pfx ├── build └── Controller.swf ├── publish └── Controller.apk └── src └── com └── beautifycode ├── android └── p2p │ └── sliderexample │ ├── Client.as │ ├── Controller.as │ └── components │ └── SliderUI.as └── helpers └── Debug.as /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Stratus-Android 4 | 5 | 6 | 7 | 8 | 9 | com.powerflasher.fdt.core.FlashBuilder 10 | 11 | 12 | 13 | 14 | 15 | com.powerflasher.fdt.core.FlashNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /Android_air_build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | -------------------------------------------------------------------------------- /Controller-App.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Stratus-Controller 6 | Stratus Controller 7 | Stratus Controller 8 | 0.1.0 9 | Copyright (c) 2010 Marvin Blase 10 | Beautify Air/Stratus Controller 11 | Stratus Controller 12 | 13 | 14 | 15 | 16 | 17 | mobileDevice 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ]]> 31 | 32 | 33 | 34 | 35 | 36 | Stratus Controller 37 | Controller.swf 38 | false 39 | true 40 | true 41 | false 42 | false 43 | 47 | 48 | 49 | 50 | icons/AIRApp_16.png 51 | icons/AIRApp_32.png 52 | icons/AIRApp_48.png 53 | icons/AIRApp_128.png 54 | 55 | 56 | true 57 | false 58 | 59 | 60 | 61 | adobe.VideoFile 62 | avf 63 | Adobe Video File 64 | application/vnd.adobe.video-file 65 | 66 | icons/AIRApp_16.png 67 | icons/AIRApp_32.png 68 | icons/AIRApp_48.png 69 | icons/AIRApp_128.png 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Author 2 | __Marvin Blase__ 3 | [Blog](www.beautifycode.com "Homepage") 4 | [Twitter](www.twitter.com/@beautifycode "Twitter") 5 | 6 | 7 | ## About 8 | Creates a P2P Connection via Stratus between anyone who is running the Client.swf and someone who is starting this Android App on his mobile. This means you can exchange data in realtime without Wi-Fi, Bluetooth or the like. Comes especially handy in using it for remote stuff or as HID. 9 | 10 | ## License 11 | Copyright (c) <2010> 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | -------------------------------------------------------------------------------- /assets/icons/AIRApp_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/assets/icons/AIRApp_128.png -------------------------------------------------------------------------------- /assets/icons/AIRApp_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/assets/icons/AIRApp_16.png -------------------------------------------------------------------------------- /assets/icons/AIRApp_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/assets/icons/AIRApp_32.png -------------------------------------------------------------------------------- /assets/icons/AIRApp_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/assets/icons/AIRApp_48.png -------------------------------------------------------------------------------- /assets/settings/exampleCert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/assets/settings/exampleCert.pfx -------------------------------------------------------------------------------- /build/Controller.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/build/Controller.swf -------------------------------------------------------------------------------- /publish/Controller.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beautifycode/Android-Flash-P2P/a4aa0a59c25936a890550a25e705778410b1781d/publish/Controller.apk -------------------------------------------------------------------------------- /src/com/beautifycode/android/p2p/sliderexample/Client.as: -------------------------------------------------------------------------------- 1 | package com.beautifycode.android.p2p.sliderexample{ 2 | import flash.display.Sprite; 3 | import flash.events.MouseEvent; 4 | import flash.events.NetStatusEvent; 5 | import flash.net.GroupSpecifier; 6 | import flash.net.NetConnection; 7 | import flash.net.NetGroup; 8 | 9 | /** 10 | * @author Marvin 11 | */ 12 | public class Client extends Sprite { 13 | private var spr:Sprite; 14 | private var nc:NetConnection; 15 | private var ng:NetGroup; 16 | private var secretKey:String = ""; 17 | private var server:String = "rtmfp://stratus.adobe.com/"; 18 | 19 | public function Client() { 20 | spr = new Sprite(); 21 | spr.graphics.beginFill(0x000000); 22 | spr.graphics.drawCircle(0, 0, 300); 23 | spr.graphics.endFill(); 24 | 25 | spr.x = 100; 26 | spr.y = 100; 27 | 28 | addChild(spr); 29 | connect(); 30 | } 31 | 32 | private function connect() : void { 33 | nc = new NetConnection(); 34 | nc.addEventListener(NetStatusEvent.NET_STATUS, ncStatusHandler); 35 | nc.connect(server + secretKey); 36 | } 37 | 38 | private function ncStatusHandler(event:NetStatusEvent) : void { 39 | trace(event.info.code); 40 | 41 | switch(event.info.code) { 42 | case "NetConnection.Connect.Success": 43 | setupGroup(); 44 | break; 45 | case "NetGroup.Connect.Success": 46 | // connected = true; 47 | break; 48 | case "NetGroup.Posting.Notify": 49 | colorByInput(event.info.message.count); 50 | break; 51 | } 52 | } 53 | 54 | private function setupGroup() : void { 55 | var groupspec:GroupSpecifier = new GroupSpecifier("remote-control"); 56 | groupspec.serverChannelEnabled = true; 57 | groupspec.postingEnabled = true; 58 | 59 | ng = new NetGroup(nc, groupspec.groupspecWithAuthorizations()); 60 | ng.addEventListener(NetStatusEvent.NET_STATUS, ncStatusHandler); 61 | } 62 | 63 | private function colorByInput(message:Number) : void { 64 | trace('message: ' + (message)); 65 | spr.alpha = message; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/com/beautifycode/android/p2p/sliderexample/Controller.as: -------------------------------------------------------------------------------- 1 | package com.beautifycode.android.p2p.sliderexample{ 2 | import com.beautifycode.android.p2p.sliderexample.components.SliderUI; 3 | import flash.display.Sprite; 4 | import flash.events.NetStatusEvent; 5 | import flash.events.TimerEvent; 6 | import flash.net.GroupSpecifier; 7 | import flash.net.NetConnection; 8 | import flash.net.NetGroup; 9 | import flash.sensors.Accelerometer; 10 | import flash.text.TextField; 11 | import flash.text.TextFieldAutoSize; 12 | import flash.utils.Timer; 13 | 14 | /** 15 | * @author Marvin 16 | */ 17 | public class Controller extends Sprite { 18 | private var nc:NetConnection; 19 | private var ng:NetGroup; 20 | private var secretKey:String = ""; 21 | private var server:String = "rtmfp://stratus.adobe.com/"; 22 | private var sequence:Number; 23 | private var sui:SliderUI; 24 | private var timer:Timer; 25 | private var debugTF:*; 26 | 27 | public function Controller() { 28 | var trackMC:Sprite = new Sprite(); 29 | trackMC.graphics.beginFill(0xFF0000); 30 | trackMC.graphics.drawRect(0, -300, 10, 300); 31 | trackMC.graphics.endFill(); 32 | 33 | trackMC.x = 50; 34 | trackMC.y = 350; 35 | 36 | var sliderMC:Sprite = new Sprite(); 37 | sliderMC.graphics.beginFill(0x000000); 38 | sliderMC.graphics.drawCircle(0, 0, 20); 39 | sliderMC.graphics.endFill(); 40 | 41 | sliderMC.x = 55; 42 | sliderMC.y = 350; 43 | 44 | addChild(trackMC); 45 | addChild(sliderMC); 46 | 47 | debugTF = new TextField(); 48 | debugTF.autoSize = TextFieldAutoSize.LEFT; 49 | debugTF.x = 200; 50 | debugTF.y = 100; 51 | debugTF.text = Accelerometer.isSupported + ""; 52 | 53 | addChild(debugTF); 54 | 55 | sui = new SliderUI(stage, "y", trackMC, sliderMC, 0, 100, 0); 56 | 57 | timer = new Timer(50, 0); 58 | timer.addEventListener(TimerEvent.TIMER, onTimer); 59 | 60 | connect(); 61 | } 62 | 63 | private function onTimer(event:TimerEvent) : void { 64 | var msg:Object = new Object(); 65 | 66 | msg.count = sui.currentValue / 100; 67 | msg.sender = ng.convertPeerIDToGroupAddress(nc.nearID); 68 | msg.sequence = sequence++; 69 | 70 | if(sui.isDown) ng.post(msg); 71 | } 72 | 73 | private function connect() : void { 74 | nc = new NetConnection(); 75 | nc.addEventListener(NetStatusEvent.NET_STATUS, ncStatusHandler); 76 | nc.connect(server + secretKey); 77 | } 78 | 79 | private function ncStatusHandler(event:NetStatusEvent) : void { 80 | trace(event.info.code); 81 | 82 | switch(event.info.code) { 83 | case "NetConnection.Connect.Success": 84 | setupGroup(); 85 | break; 86 | case "NetGroup.Connect.Success": 87 | timer.start(); 88 | break; 89 | } 90 | } 91 | 92 | private function setupGroup() : void { 93 | var groupspec:GroupSpecifier = new GroupSpecifier("remote-control"); 94 | groupspec.serverChannelEnabled = true; 95 | groupspec.postingEnabled = true; 96 | 97 | ng = new NetGroup(nc, groupspec.groupspecWithAuthorizations()); 98 | ng.addEventListener(NetStatusEvent.NET_STATUS, ncStatusHandler); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/com/beautifycode/android/p2p/sliderexample/components/SliderUI.as: -------------------------------------------------------------------------------- 1 | package com.beautifycode.android.p2p.sliderexample.components{ 2 | import flash.display.Sprite; 3 | import flash.events.Event; 4 | import flash.display.Stage; 5 | import flash.events.MouseEvent; 6 | import flash.events.TimerEvent; 7 | import flash.geom.Rectangle; 8 | import flash.utils.Timer; 9 | import flash.utils.getQualifiedClassName; 10 | 11 | /** * The SliderUI is a class that allows you to quickly create sliders with tracks without the need to use components. * There is a "percent" and a "currentValue" property that you can tap into to see what position the slider is at on the track. * * Please note that if you are using the SliderUI on the "y" axis your track's registration point needs to be on the * bottom (NOT the top) and the slider will go up to raise the value and down to lower it. If you do not pay attention * to this your slider will be "broken". * * @author Matt Przybylski [http://www.reintroducing.com] * @version 1.0 */ 12 | public class SliderUI extends Sprite { 13 | // - PRIVATE & PROTECTED VARIABLES ------------------------------------------------------------------------- 14 | private var _stage:Stage; 15 | private var _track:Sprite; 16 | private var _slider:Sprite; 17 | private var _timer:Timer; 18 | private var _percent:Number; 19 | private var _lowVal:Number; 20 | private var _highVal:Number; 21 | private var _startVal:Number; 22 | private var _currentVal:Number; 23 | private var _range:Number; 24 | private var _axis:String; 25 | private var _changeProp:String; 26 | 27 | public var isDown:Boolean; 28 | 29 | // - PUBLIC & INTERNAL VARIABLES --------------------------------------------------------------------------- 30 | // - CONSTRUCTOR ------------------------------------------------------------------------------------------- 31 | /** * Creates an instance of the SliderUI with the given parameters. If the $startVal parameter is set to something * higher than the $highVal or lower than the $lowVal parameter, the $startVal parameter is reset to one of those two values. * * @param $stage The stage that the track and slider are sitting on * @param $axis The axis that the slider will be used on * @param $track The track to be used for the slider * @param $slider The object that will function as the slider * @param $lowVal A number representing the low value of the slider * @param $highVal A number representing the high value of the slider * @param $startVal A number representing the value the slider should start at (default: 0) * * @return void */ 32 | public function SliderUI($stage:Stage, $axis:String, $track:Sprite, $slider:Sprite, $lowVal:Number, $highVal:Number, $startVal:Number = 0):void { 33 | this._stage = $stage; 34 | this._axis = $axis; 35 | this._track = $track; 36 | this._slider = $slider; 37 | this._lowVal = $lowVal; 38 | this._highVal = $highVal; 39 | this._startVal = $startVal; 40 | this._changeProp = (this._axis == "x") ? "width" : "height"; 41 | this._range = (Math.abs(this._lowVal) + this._highVal); 42 | this._slider.buttonMode = true; 43 | this._timer = new Timer(10); 44 | if (this._startVal < this._lowVal) 45 | this._startVal = this._lowVal; 46 | if (this._startVal > this._highVal) 47 | this._startVal = this._highVal; 48 | if (this._startVal < 0) { 49 | this._percent = (Math.abs(this._lowVal + Math.abs(this._startVal)) / this._range); 50 | } else { 51 | this._percent = (Math.abs(this._lowVal - this._startVal) / this._range); 52 | } 53 | this._currentVal = (this._lowVal + (this._range * this._percent)); 54 | if (this._axis == "x") { 55 | this._slider[this._axis] = (this._track[this._axis] + (this._percent * this._track[this._changeProp])); 56 | } else { 57 | this._slider[this._axis] = (this._track[this._axis] - (this._percent * this._track[this._changeProp])); 58 | } 59 | this.initEvents(); 60 | } 61 | 62 | // - PRIVATE & PROTECTED METHODS --------------------------------------------------------------------------- 63 | /** * Initializes the slider and timer events. */ 64 | private function initEvents():void { 65 | this._slider.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown); 66 | this._slider.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp); 67 | this._timer.addEventListener(TimerEvent.TIMER, updateInfo); 68 | } 69 | 70 | // - PUBLIC & INTERNAL METHODS ----------------------------------------------------------------------------- 71 | /** * Enables the controls of the SliderUI. * * @return void */ 72 | public function enable():void { 73 | this.initEvents(); 74 | } 75 | 76 | /** * Disables the controls of the SliderUI. * * @return void */ 77 | public function disable():void { 78 | this._slider.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown); 79 | this._slider.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp); 80 | this._timer.removeEventListener(TimerEvent.TIMER, updateInfo); 81 | } 82 | 83 | /** * Cleans up the SliderUI for garbage collection. * * @return void */ 84 | public function destroy():void { 85 | this.disable(); 86 | this._timer = null; 87 | } 88 | 89 | // - EVENT HANDLERS ---------------------------------------------------------------------------------------- 90 | /** * Starts the dragging of the slider and starts the timer to dispatch percentage. */ 91 | private function handleMouseDown($evt:MouseEvent):void { 92 | isDown = true; 93 | 94 | if (this._axis == "x") { 95 | this._slider.startDrag(false, new Rectangle(this._track.x, this._slider.y, this._track.width, 0)); 96 | } else { 97 | this._slider.startDrag(false, new Rectangle(this._slider.x, this._track.y, 0, -this._track.height)); 98 | } 99 | this._timer.start(); 100 | this._stage.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp); 101 | } 102 | 103 | /** * Stops the slider dragging and timer. */ 104 | private function handleMouseUp($evt:MouseEvent):void { 105 | isDown = false; 106 | 107 | this._slider.stopDrag(); 108 | this._timer.reset(); 109 | dispatchEvent(new Event("up", true, false)); 110 | this._stage.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp); 111 | } 112 | 113 | /** * Updates the info of the slider's position. */ 114 | private function updateInfo($evt:TimerEvent):void { 115 | this._percent = Math.abs((this._slider[this._axis] - this._track[this._axis]) / this._track[this._changeProp]); 116 | this._currentVal = (this._lowVal + (this._range * this._percent)); 117 | } 118 | 119 | // - GETTERS & SETTERS ------------------------------------------------------------------------------------- 120 | /** * Returns the percentage of the slider's position on the track, between 0 and 1. * * @return Number */ 121 | public function get percent():Number { 122 | return this._percent; 123 | } 124 | 125 | /** * Returns the current value of the slider's position on the track. * * @return Number */ 126 | public function get currentValue():Number { 127 | return this._currentVal; 128 | } 129 | 130 | 131 | // - END CLASS --------------------------------------------------------------------------------------------- 132 | } 133 | } -------------------------------------------------------------------------------- /src/com/beautifycode/helpers/Debug.as: -------------------------------------------------------------------------------- 1 | package com.beautifycode.helpers{ 2 | 3 | /** 4 | * @author Tobias Oberrauch 5 | */ 6 | 7 | public class Debug { 8 | 9 | public static function dump(element:*):void { 10 | trace(_dump(element)); 11 | } 12 | 13 | 14 | public static function Dtrace(param:*):void { 15 | var pattern:RegExp = /at.*[^)](\/.*())/gim; 16 | try { 17 | throw new Error(); 18 | } 19 | catch (e:Error) { 20 | var result:String = e.getStackTrace().match(pattern)[1]; 21 | trace(param + " (was called from: " + result.replace(pattern, "$1") + ")"); 22 | } 23 | } 24 | 25 | 26 | 27 | private static function _dump(element:*, depth:int = 1):String { 28 | var alert:String = ""; 29 | for(var key:String in element) { 30 | if(typeof element[key] == "object") { 31 | alert += _space(depth) + key + "\n"; 32 | depth++; 33 | alert += _dump(element[key], depth) + "\n"; 34 | depth--; 35 | } else if(element.numChildren > 0) { 36 | depth++; 37 | alert += _children(element, depth) + "\n"; 38 | depth--; 39 | } else { 40 | alert += _space(depth) + key + ": " + element[key] + "\n"; 41 | } 42 | } 43 | return alert; 44 | } 45 | 46 | 47 | private static function _children(element:*, depth:int = 1):String { 48 | var alert:String = ""; 49 | for (var i:int = 0;i < element.numChildren;i++) { 50 | alert += _dump(element.getChildAt(i), depth) + "\n"; 51 | } 52 | return alert; 53 | } 54 | 55 | 56 | private static function _space(depth:int = 1):String { 57 | var space:String = ''; 58 | for(var i:int = 1;i < depth;i++) { 59 | space += ' '; 60 | } 61 | return space; 62 | } 63 | } 64 | } --------------------------------------------------------------------------------