Building a Flickr Browser Using Flash Builder 4 and the Flex 4 SDK
Flex 4 introduces a boatload of new features, and today we’ll take a look at some of the latest architectural changes that make component development and skinning much easier. To start with, you’ll need to download the Flash Builder Trial. This will give you the Flex 4 SDK as well. Flash Builder, while still in beta, has a number of powerful features for developers and is already a step forward from Flex Builder.
You’ll also need Flash Player 10, and for development purposes it should be the debugging version. To use the Flickr API you’ll want an API key, which you can then import into Flash Builder.
This article will assume some familiarity with Flex and ActionScript in general, but it’s unnecessary to be particularly advanced to benefit from it. By the end, you’ll be able to make Flex talk to Flickr’s API, download and display images, and do some basic skinning in Flex 4. You can download all the finished code for this project as a Flash Builder project archive, which you can then import into Flash Builder.
And make sure to take the quiz at the end to test your developer credentials.
The granddaddy of all image-sharing services on the Internet is Flickr, and making mashups using its public API has become like a rite of passage. In this article we’ll plumb the depths of Flickr’s enormous library of images, which are licensed under the Creative Commons 2.0 license, allowing you to use them freely provided you attribute them. This makes Flickr a fabulous resource for web developers and designers in particular, so our project will be a tool to help find and browse these images.
We begin with the ActionScript 3 Flickr API library, written by the engineers at Adobe. It’s freely available, as is the AS3 Core Library upon which it depends. We’ll use both in this project, so download them once you’ve installed Flash Builder.
Open the archive containing the AS3 Core Library, and inside the lib
directory you’ll find as3corelib.swc
. Copy this file to the libs
directory of your Flash Builder project, and Flash Builder will do the rest.
Next open the archive for the Flickr library. There is an swc
file contained within, but as of our last check it was compiled for Flex 2, so we’ll instead drop the source code into our project. Open the src
directory from the archive and copy the com
directory you find inside. Drop it into the src
directory of your Flash Builder project, then click the menu in Flash Builder and choose . This will ensure that the new code and libraries are picked up by the compiler.
Our first task is to load the Flickr API libraries and connect to the API itself. In your main MXML file, modify your <s:Application>
tag to look like this:
<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" minWidth="1024" minHeight="768" xmlns:flickr="com.adobe.webapis.flickr.*">
Below that, add a script
block and enter the following statements:
import com.adobe.webapis.flickr.events.FlickrResultEvent;import com.adobe.webapis.flickr.FlickrService;import com.adobe.webapis.flickr.PagedPhotoList;private static const FLICKR_API_KEY:String = "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"; //Your Flickr API keyprivate static const COMMONS_LICENSE_ID:Number = 2;private static const MAX_RETURNED_RECORDS:Number = 50;public var flickrService:FlickrService = new FlickrService(FLICKR_API_KEY);
The above code contains import statements for the Flickr API classes we’ll need, a few constant definitions, and the instantiation of a new FlickrService
object that we’ll use to make all our Flickr API connections. Now we’re ready to begin. Create the following function and set it to be called on the application creationComplete
event:
private function onComplete() : void { flickrService.addEventListener(FlickrResultEvent.PHOTOS_SEARCH, onSearchResult);}
<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" minWidth="1024" minHeight="768" xmlns:flickr="com.adobe.webapis.flickr.*" creationComplete="onComplete()">
When we initialized the variable flickrService
and instantiated the FlickrService
object, we made a remote call to Flickr itself, passing in our API key to make an authenticated link. We can now use that service to make requests, but before we do we set up a listener in the onComplete
function to act upon the results of a search.
Now that we have that in place we need the search itself. To allow the user to enter a search query, we’ll add a TextInput
element and search button beneath our script block like so:
<s:HGroup width="260" height="27" textAlign="center" x="68" y="89"> <s:Label text="Search" color="0xFFFFFF"/> <s:TextInput id="tags"/> <s:Button name="searchBtn" label="Search" click="searchBtnClick(event)"/></s:HGroup>
Note the <s:HGroup>
tag. In Flex 3 and previous versions, we’d have used an <mx:HBox>
tag, but now we can use the group tags instead, which have less overhead than the HBox
and VBox
containers. The search button also contains a call to a new function, searchBtnClick
, which is where we’ll put the search code. Add this function to your script block:
private function searchBtnClick(event:MouseEvent) : void { flickrService.photos.search("", this.tags.text, "any", "", null, null, null, null, COMMONS_LICENSE_ID, "owner_name", MAX_RETURNED_RECORDS); }
For anyone who’s wondering, the odd layout to this piece of code, where it puts each parameter on a separate line, is simply for ease of reading and editing. The layout actually has no effect on the working of the code.
Okay, here we make the first real request to the Flickr API. Using the photos.search
method, we send a number of values that essentially say “look for images under the Creative Commons 2.0 license whose tags match our search query.” The MAX_RETURNED_RECORDS
parameter is used to limit the number of items returned in one hit. For more detailed information on the API and all its methods, please do check out the API Documentation.
For this to work we’ll need the receiving function. We previously set up an event listener to call this function whenever we have the results of a search query to act upon. Add the following to your code:
private function onSearchResult(event:FlickrResultEvent) : void { if (event.success) { var resultsList:PagedPhotoList = event.data.photos; photos = new ArrayCollection( resultsList.photos ); } else { Alert.show("Flickr search error: " + event.data.error); } }
The FlickrResultEvent
has everything we need tidily built into it, including a handy success property to indicate success, as you can see on the first line of the function. In our case, we check this property and simply show an error message, including the error information sent back from Flickr. If the transaction is a success, we create a PagedPhotoList
object from the XML data we receive from Flickr, and use it to generate an ArrayCollection
that we can bind to.
At this point, your application should compile and run with no errors. If you were to expose the contents of event.data.photos
, you’d see an XML packet that looked similar to this (taken from the Flickr API documentation on flickr.photos.search
):
<photos page="2" pages="89" perpage="10" total="881"> <photo id="2636" owner="47058503995@N01" secret="a123456" server="2" title="test_04" ispublic="1" isfriend="0" isfamily="0" /> <photo id="2635" owner="47058503995@N01" secret="b123456" server="2" title="test_03" ispublic="0" isfriend="1" isfamily="1" /> <photo id="2633" owner="47058503995@N01" secret="c123456" server="2" title="test_01" ispublic="1" isfriend="0" isfamily="0" /> <photo id="2610" owner="12037949754@N01" secret="d123456" server="2" title="00_tall" ispublic="1" isfriend="0" isfamily="0" /> </photos>
We’ve also added an extra parameter to our search; sending "owner_name"
tells the API to send the full name of the owner of the photograph, so we can use it for attribution.
Now that we have some data coming back from the Flickr API, we need a way to display it. What we’re interested in are the photos themselves, so what better than to display a list of the thumbnails? In Flex 3 we might have used a TileList
for this, but that class has been replaced with the very handy class named List
; we can use List
to recreate the TileList
functionality, but with more options and better performance. Add a List
to your code now, below the search button:
<s:List id="imageDisplay" dataProvider="{photos}" width="530" height="400" x="58" y="124"> <s:layout> <s:TileLayout requestedColumnCount="5" requestedRowCount="8" horizontalGap="2" verticalGap="2"/> </s:layout> <s:itemRenderer> <fx:Component> <mx:Image source="{'http://static.flickr.com/' + data.server + '/' + data.id + '_' + data.secret + '_t.jpg'}" height="100" width="100" /> </fx:Component> </s:itemRenderer> </s:List>
We achieve the old TileList
functionality by specifying a special layout class TileLayout
, and it’s to this class we give the parameters of the layout, such as the horizontal gap to keep between each item in the list.
We’re using an inline item renderer, which simply pulls the image thumbnail in and displays it. The string you see being assembled within the Image
element’s source
attribute is the proper URL for the given image in the list. The addition of _t.jpg
means we link to the thumbnail from Flickr, instead of the full image.
If you compile and run your app, enter a search term like monkey
, and click the search button, you’ll see images appearing inside your List
box. It may take a few seconds to make the transaction happen, but once it’s finished we see a list of images retrieved from Flickr that match our criteria: they use the tag monkey
and only are licensed with a Creative Commons 2.0 license.