Archive for September, 2009
Desktop and Browser Facebook Apps with AIR and Flex
Last week I was presenting at AUG Poznań and today remotely via Adobe Connect at AUG Trójmiasto, where I showed how to build applications usign AS3 API for Facebook that is available at Google Code. My goal was not only to show how to use Facebook API but also how you can build desktop and browser versions of the same app using conditional compilation in Flex. I took the approach of two Flash Builder projects one with minimum set of Flex (browser) code and AIR (desktop) project with common sources for both. Flex project actually links to AIR project src-common folder in Flash Builder. The structure of both projects looks like this:

Below you can also find example of MainView.mxml code that is common for both projects. Within that example you can see sections that will be compiled based on specified options for each project. I actually defined two compiler options CONFIG::AIR and CONFIG::FLEX. You can find more info about defining compiler options and conditional compilation here. Another very good approach especially in more complex cases is described here on Adobe Developer Connection.
Here is the link to my Demo of AS3 API on Facebook and also below is the badge with desktop version.
You can look at the source code of each example by right-clicking and choosing View Source option. Also you can download Flash Builder project archives from here and here, one with Flex and the other with AIR code.
<?xml version="1.0" encoding="utf-8"?> <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" width="100%" height="100%" currentState="CONNECTING"> <fx:Script> <![CDATA[ import com.facebook.Facebook; import com.facebook.commands.batch.BatchRun; import com.facebook.commands.friends.GetFriends; import com.facebook.commands.users.GetInfo; import com.facebook.data.batch.BatchCollection; import com.facebook.data.batch.BatchResult; import com.facebook.data.friends.GetFriendsData; import com.facebook.data.users.FacebookUser; import com.facebook.data.users.GetInfoData; import com.facebook.data.users.GetInfoFieldValues; import com.facebook.events.FacebookEvent; import com.facebook.net.FacebookCall; import flash.net.URLRequest; import flash.net.navigateToURL; import mx.collections.ArrayCollection; import mx.controls.Alert; CONFIG::AIR { // DesktopSessionHelper import required for AIR and Facebook Connect import com.facebook.utils.DesktopSessionHelper; import com.facebook.session.DesktopSession; // Session variable when running as AIR app protected var session:DesktopSessionHelper; } CONFIG::FLEX { // FacebookSessionUtil import required for Flex (browser) app import com.facebook.utils.FacebookSessionUtil; // Session variable when running as Flex (browser) app protected var session:FacebookSessionUtil; } /** * Facebook class used to access FB remote API's */ protected var fbook:Facebook; /** * Logged-in FB user */ [Bindable] protected var user:FacebookUser; /** * Collection of logged-in user friends */ [Bindable] protected var userFriends:ArrayCollection; /** * AIR init function */ CONFIG::AIR public function init():void { // Creating session based on API key session = new DesktopSessionHelper("795c0879607643aa3c5a363d09ce5384"); // Registering handler when connected session.addEventListener(FacebookEvent.CONNECT, onConnect); } /** * Flex init function */ CONFIG::FLEX public function init():void { // When running in iFrame API key and secret values are not necessary // these are passed with flashVars from GET parameters session = new FacebookSessionUtil(null, null, loaderInfo); // Registering handler when connected session.addEventListener(FacebookEvent.CONNECT, onConnect); // Setting fbook from session properties fbook = session.facebook; // Checking if fb_sig_session_key was set from IFrame GET params if(loaderInfo.parameters.fb_sig_session_key) { // Verifying FB session session.verifySession(); } else { // This application cannot run as external FB app Alert.show("You cannot run this application outside Facebook!"); } } protected function onConnect(event:FacebookEvent):void { var uid:String; // Checking if connection was successful if (event.success) { // Conditional block that sets fbook variable after connection CONFIG::AIR { // Creating instance of Facebook class fbook = new Facebook(); // Starting new FB session with apiKey and session secret // received after connection in session variable fbook.startSession(new DesktopSession( session.apiKey, session.sessionData.secret, session.sessionData.session_key)); uid = session.sessionData.uid; } CONFIG::FLEX { uid = fbook.uid; } // Creating batch to make two data request at one FB call var batchRun:BatchRun; var batch:BatchCollection = new BatchCollection(); // Batch item GetInfo returning info about current user batch.addItem(new GetInfo([uid], [GetInfoFieldValues.ALL_VALUES])); // Batch item GetFriends returning friends list of current user batch.addItem(new GetFriends(null, uid)); // Posting batch to FB batchRun = fbook.post(new BatchRun(batch)) as BatchRun; // Registering batch run results handler batchRun.addEventListener(FacebookEvent.COMPLETE, onBatchRunResult); } else { // In case of not successful connection Alert.show(event.error.errorMsg); } } /** * Handler for batch run results */ protected function onBatchRunResult(event:FacebookEvent):void { // Setting results variable from event object var batchResult:BatchResult = event.data as BatchResult; // Getting data from first batch result item var userInfo:GetInfoData = batchResult.results[0] as GetInfoData; // Setting current user object user = userInfo.userCollection.source[0] as FacebookUser; // Getting data from second batch result item var friendsInfo:GetFriendsData = batchResult.results[1] as GetFriendsData; // Building array of returned friends ID's var friendsUids:Array = new Array(); for each(var friend:FacebookUser in friendsInfo.friends.source) { friendsUids.push(friend.uid); } // Doing another call to FB to get friends detailed info var call:FacebookCall = fbook.post(new GetInfo(friendsUids, [GetInfoFieldValues.ALL_VALUES])); // Registering handler call.addEventListener(FacebookEvent.COMPLETE, onGetFriendsInfo); // Changing state to connected currentState = "CONNECTED"; } /** * Friends details request handler */ protected function onGetFriendsInfo(event:FacebookEvent):void { userFriends = new ArrayCollection((event.data as GetInfoData) .userCollection.source); } ]]> </fx:Script> <s:states> <s:State name="CONNECTING"/> <s:State name="CONNECTED" /> </s:states> <mx:ProgressBar includeIn="CONNECTING" label="Connecting..." indeterminate="true" labelPlacement="center" horizontalCenter="0" verticalCenter="0"/> <s:Label text="Hello {user.first_name}!" horizontalCenter="0" verticalCenter="-100" fontSize="29" includeIn="CONNECTED"/> <mx:AdvancedDataGrid id="adgFriends" dataProvider="{userFriends}" designViewDataType="flat" horizontalCenter="0" verticalCenter="19" includeIn="CONNECTED"> <mx:columns> <mx:AdvancedDataGridColumn headerText="Name" dataField="first_name"/> <mx:AdvancedDataGridColumn headerText="Last Name" dataField="last_name"/> </mx:columns> </mx:AdvancedDataGrid> <mx:LinkButton label="Get AIR (desktop) version..." horizontalCenter="0" verticalCenter="150" color="#ABA5A5" fontWeight="bold" textDecoration="underline" fontSize="14" click="navigateToURL(new URLRequest('http://www.riaspace.net/examples/fb-as3demo/air/'))"/> </s:Group>
AS3 Facebook API – zdalna prezentacja dla AUG Trójmiasto
W dniu dzisiejszym (godz. 18:00) w ramach spotkania grupy AUG Trójmiasto poprowadzę zdalną prezentację odnośnie tworzenia aplikacji dla Facebook’a z wykorzystaniem technologii Flex i AIR. Dodatkowym tematem prezentacji będzie tworzenie aplikacji działających w przeglądarce i na desktop’ie z wykorzystaniem tego samego kodu. Do tego posłużę się metodą kompilacji warunkowej oraz odpowiednią konfiguracją projektów we Flash Builder’ze.
Wszystkich zapraszam do obejrzenia mojej prezentacji przez Adobe Connect dostępnej pod tym adresem.
Spotkanie AUG Poznań
W najbliższy czwartek (24.09) odbędzie się spotkanie grupy AUG Poznań. Wszystkich z okolic Poznania serdecznie zapraszam! Oczywiście dlatego też gdyż sam będę uczestniczył i prezentował w trakcie tego spotkania
Mój temat to: Budowanie aplikacji z wykorzystaniem ActionScript 3 Facebook API
Staż studencki w Adobe

Interview with me in Belorussian “Computer News”
Last week Belorussian “Computer News” newspaper has published interview with me, here is the electronic version: http://kv.by/index2009354301.htm I encourage anyone to read, especially if you know Russian
– sorry for the mistake in the beginning with Belorussian
What do we do when not Flexing…
Last week I was out for few days to catch some wind, last days of summer and of course relax before upcoming busy busy busy, weeks and months… As you probably know MAX LA is coming very soon and I’m also planning very intensive activities around Flash Platform this fall – now it is top secret but stay tuned!
In order to clean my head I decided to visit Prasonissi (mecca for wind and kite surfers). I have a feeling that we developers have tendency to forget that doing any sports or having active leisure away from our computers, emails, blogs, favorite IDE’s is very important!
So what do you do when you are not Flexing?
MAX 2009 my TA’s, session and widget!
I just got confirmations that I will be a TA (Teaching Assistant) on couple of sessions during MAX LA this year.
Duane Nickull – Building Flex and Adobe AIR Service Clients 2009
Monday, October 5 11:30AM (Duration: 90 minutes)
Leo Schuman – Flex 101: Introduction to Flex 4
Monday, October 5 05:00PM (Duration: 90 minutes)
Leo Schuman – Flex 101: Introduction to Flex 4
Tuesday, October 6 08:30AM (Duration: 90 minutes)
Matt Boles – Creating Custom Components in Flex 4
Tuesday, October 6 01:00PM (Duration: 90 minutes)
Dave Watts – Building Data-Centric Applications with Flash Builder 4 and ColdFusion 9
Wednesday, October 7 11:00AM (Duration: 90 minutes)
Matt Boles – Creating Custom Components in Flex 4
Wednesday, October 7 01:30PM (Duration: 90 minutes)
And of course don’t forget about my session Flex and Adobe AIR In Government: The e-Deklaracje Desktop that is on October 5 05:00PM, here is also direct link to it. Look also at some of my previous posts with more details about it!
Here is really cool MAX widget to check out:
Polscy programiści RIA
O
statnio coraz częściej zdarza mi się dostawać zapytania odnośnie poszukiwanych programistów (tzw. freelancerów) do współpracy przy projektach typu RIA. Z tego względu postanowiłem zrobić podstronę Polscy programiści RIA gdzie każdy zajmujący się tworzeniem aplikacji w technologiach Adobe Flex lub AIR będzie mógł zamieścić link do swojej strony oraz krótkie info o sobie w postaci komentarza. Wszystkich developerów zapraszam do autopromocji na moim blogu!
W tej chwili jest to pewnego rodzaju eksperyment ale kto wie może kiedyś uda nam się z tego stworzyć coś bardziej zaawansowanego
*** Sorry to my English only speaking readers this is strictly Polish RIA community related stuff
***
My approach to MVP pattern with Swiz Framework
Recently I noticed that MVP (Model View Presenter) pattern especially using Swiz Framework is becoming very popular. That is why I decided to port one of my old examples to checkout this approach. It is a simple Flex based notes editor, really really trivial one. As an inspiration and some guides I used one of Ben Clinkinbeard blog posts and also Soenke Rohde blog post. With my approach I introduce assumption that all/most PresentationModel classes extend AbstractPresentationModel class that also extends AbstractController from Swiz package. My abstract class adds dispatcher property that returns reference to CentralDispatcher (I guess this could be also a nice addition to Swiz itself). The assumption here is that communication between different PresentationModel classes is done only through events. Of course PresentationModel has direct access to views and model as with standard MVP, additionally I threat service delegates also as part of model. I guess this could be also called MVPS pattern
Working application is here and application source code here.
I’m waiting for your comments, especially about approach to currentState switching in ApplicationPresentationModel.as and assumptions like event based communication between PresentationModel classes.
Here is just an overview diagram of the architecture, it doesn’t represent all dependencies between application components.



