17
Adobe AIR: Preventing Users from Closing the App
One of the really cool additions to Adobe AIR 1.5.2 was the ability to invoke preventDefault() upon a FullScreenEvent when using StageDisplayState.FULL_SCREEN_INTERACTIVE. I always had a workaround for Windows but my method would always crash the app when run on a Mac. The ability to go full screen and lock that down is essential to kiosk-type applications. This does not prevent a user from closing out the app in some other way, however.
While working on an AIR-based kiosk project this week, I was given the request to prevent COMMAND+Q from closing the application on a Mac. They really wanted this thing locked down to the point where the only way to get out of the app would be to enter some random key combination. Took a little bit of digging around to figure out how to both prevent the default closing action but still allow the app to close in the event that the correct key commands were entered. I share this here as I can see others having this same need.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="400" applicationComplete="init()"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.events.CloseEvent; import flash.events.Event; import flash.display.StageDisplayState; import flash.events.KeyboardEvent; import flash.events.FullScreenEvent; private var commandEntered:Boolean; private function init():void { this.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE; this.addEventListener(Event.CLOSING, appClosing, false, 0, true); stage.addEventListener(KeyboardEvent.KEY_DOWN, killApp, false, 0, true); stage.addEventListener(FullScreenEvent.FULL_SCREEN, displayStateChanged, false, 0, true); } private function displayStateChanged(e:FullScreenEvent):void { e.preventDefault(); } private function killApp(e:KeyboardEvent):void { e.preventDefault(); if(e.keyCode == 70 && e.ctrlKey && e.altKey){ commandEntered = true; this.close(); }else{ commandEntered = false; } } private function appClosing(e:Event):void { if(!commandEntered){ e.preventDefault(); } } ]]> </fx:Script> <s:Label text="CTRL + ALT + f" horizontalCenter="0" verticalCenter="0" fontWeight="bold" fontSize="32"/> </s:WindowedApplication> |
UPDATE: If you have a stateful application, you may want to consider the following information, as it may be disruptive in handling these events properly: http://beingwicked.com/development/flex-initialize-and-the-hassles-of-changing-state/
20
YouTube AS3 Example Using Flash Professional
Based on comments received in my previous article I’ve decided to also produce an example using Flash Professional CS4. The approach is different in some ways, but very similar in others.
View the Example:
References:
The ActionScript 3 YouTube Chromeless Player is Now Live
YouTube ActionScript 3.0 Player API Reference
Download the Example:
YouTubeAS3_CS4.zip
View Code for Flash Professional:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | package { import flash.system.Security; import flash.display.MovieClip; import flash.display.Loader; import flash.events.Event; import flash.net.URLRequest; import fl.data.DataProvider; import fl.controls.ComboBox; import fl.controls.TextArea; public class YouTubeAS3 extends MovieClip { public var VidHolder:MovieClip; public var VidSelection:ComboBox; public var traceArea:TextArea; private var player:Object; private var loader:Loader; private var vidCollection:DataProvider; public function YouTubeAS3():void { Security.allowInsecureDomain("*"); Security.allowDomain("*"); vidCollection = new DataProvider(); vidCollection.addItem({data:"KhAplw0Z8zQ", label:"Wreckage"}); vidCollection.addItem({data:"d54AA2YWll0", label:"Window View"}); vidCollection.addItem({data:"Sv83GeuyN8A", label:"The Fearless Man"}); vidCollection.addItem({data:"9t5guYGbuZs", label:"Ephemeral"}); VidSelection.dataProvider = vidCollection; VidSelection.addEventListener(Event.CHANGE, cueVideo); loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit); loader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3")); } private function onLoaderInit(event:Event):void { VidHolder.addChild(loader); loader.content.addEventListener("onReady", onPlayerReady); loader.content.addEventListener("onError", onPlayerError); loader.content.addEventListener("onStateChange", onPlayerStateChange); loader.content.addEventListener("onPlaybackQualityChange", onVideoPlaybackQualityChange); } private function onPlayerReady(event:Event):void { traceArea.text += "player ready:" + Object(event).data + "\r"; player = loader.content; player.setSize(VidHolder.width, VidHolder.height); VidSelection.selectedIndex = 0; VidSelection.dispatchEvent(new Event(Event.CHANGE)); } private function cueVideo(event:Event):void { traceArea.text += "switch to:" + event.target.selectedItem.label + "\r"; player.cueVideoById(event.target.selectedItem.data); } private function onPlayerError(event:Event):void { traceArea.text += "player error:" + Object(event).data + "\r"; } private function onPlayerStateChange(event:Event):void { traceArea.text += "player state:" + Object(event).data + "\r"; } private function onVideoPlaybackQualityChange(event:Event):void { traceArea.text += "video quality:" + Object(event).data + "\r"; } } } |
14
Google FINALLY Releases AS3 Player for YouTube
Absolutely wonderful that Google has finally released an AS3 version of their chromeless player for use in Flex/AS3 projects. No more weird proxy hacks!!!
I’ve thrown together a quick example and have posted the code below. Really simple stuff to set up and use. Google seems to be more and more friendly to the Flash world lately. There are at least two major projects I’m going to implement this in as soon as I get the time to do so. Very nice- I’m quite pleased!
View the Example:
References:
The ActionScript 3 YouTube Chromeless Player is Now Live
YouTube ActionScript 3.0 Player API Reference
Download the Example:
YouTubeAS3.fxp
View Code for Flash Builder 4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" applicationComplete="init()" width="480" height="500"> <fx:Script> <![CDATA[ import flash.system.Security; import mx.collections.ArrayCollection; import mx.events.ListEvent; import flash.display.Loader; import flash.events.Event; private var player:Object; private var loader:Loader; [Bindable] private var vidCollection:ArrayCollection; private function init():void { Security.allowInsecureDomain("*"); Security.allowDomain("*"); vidCollection = new ArrayCollection(); vidCollection.addItem({data:"KhAplw0Z8zQ", label:"Wreckage"}); vidCollection.addItem({data:"d54AA2YWll0", label:"Window View"}); vidCollection.addItem({data:"Sv83GeuyN8A", label:"The Fearless Man"}); vidCollection.addItem({data:"9t5guYGbuZs", label:"Ephemeral"}); loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit); loader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3")); } private function onLoaderInit(event:Event):void { VidHolder.rawChildren.addChild(loader); loader.content.addEventListener("onReady", onPlayerReady); loader.content.addEventListener("onError", onPlayerError); loader.content.addEventListener("onStateChange", onPlayerStateChange); loader.content.addEventListener("onPlaybackQualityChange", onVideoPlaybackQualityChange); } private function onPlayerReady(event:Event):void { traceArea.text += "player ready:" + Object(event).data + "\r"; player = loader.content; player.setSize(VidHolder.width, VidHolder.height); VidSelection.selectedIndex = 0; VidSelection.dispatchEvent(new ListEvent(ListEvent.CHANGE, true, false)); } private function cueVideo(event:ListEvent):void { traceArea.text += "switch to:" + event.target.selectedItem.label + "\r"; player.cueVideoById(event.target.selectedItem.data); } private function onPlayerError(event:Event):void { traceArea.text += "player error:" + Object(event).data + "\r"; } private function onPlayerStateChange(event:Event):void { traceArea.text += "player state:" + Object(event).data + "\r"; } private function onVideoPlaybackQualityChange(event:Event):void { traceArea.text += "video quality:" + Object(event).data + "\r"; } ]]> </fx:Script> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <mx:Canvas id="VidHolder" left="0" right="0" top="0" bottom="140"></mx:Canvas> <mx:ComboBox id="VidSelection" editable="false" dataProvider="{vidCollection}" left="10" right="10" bottom="110" height="22" change="cueVideo(event)"></mx:ComboBox> <s:TextArea left="10" right="10" editable="false" top="398" bottom="10" id="traceArea"/> </s:Application> |
18
Scaling Your Images in Flash Player? Smooth Those Things!!!
I actually forgot to apply the “smoothing” property to a flash.display.Bitmap display object being scaled inside Flash Player. Just look at the difference such an oversight made!
Since I was using a flash.display.Loader display object to load the image up, and Loader has no smoothing property, I totally spaced on this and it’s been out there for months rendering images in a pretty crappy way. I just needed to assign the image data to a Bitmap object and use that for display instead.
1 2 3 4 5 6 | private function imageLoaded(e:Event):void { var imageBitmap:Bitmap = imageLoader.content as Bitmap; imageBitmap.smoothing = true; imageDrag.addChild(imageBitmap); //scale away! } |
Easy.
Learn from my blunder- always make sure to enable smoothing!
20
Runtime Armatures in Flash CS4
I have such terrible luck with Runtime Armatures in Flash CS4. It’s really not funny anymore.
Most recently stumbled across the following compilation error (fatal warning?) when working with the “New Flash Component” feature of Flash Builder 4:
Warning: 5002: The main timeline’s frame scripts have been ignored because a compiled clip contains a definition for fl.livepreview.LivePreviewParent. To override the fl.livepreview.LivePreviewParent definition, place a custom class file within your classpath.
Obviously, Flash is generating code for the Runtime Armature which is conflicting with code for the Flash Component for use in Flash Builder. Ugh…
I’m working on some demos for my FITC presentation during the MAX unconference in October. This is by no means a show stopper but what an annoyance… Half the time when working with Runtime Armatures in CS4, Flash will just totally crash and burn. I have great luck with Armatures during authoring- the runtime stuff just always seems to bite me.
Bug filed:
http://bugs.adobe.com/jira/browse/FB-22221
UPDATE: I have confirmation that this is fixed in Flash CS5.











