Article
Map Your OpenSocial Data Using Flex
Mapping OpenSocial
Mapping people is a more complicated task than mapping geotagged images. Each of the major social networks (Facebook, MySpace, LinkedIn, and the like) make available their own APIs to use when searching for people. However, these networks are gradually unifying via a standard called OpenSocial.
OpenSocial was originally conceived as a common API for social networking applications. However, the release of version 0.8 offers a REST API that you can use to perform queries of a social network.
The only problem is that no major social networking sites have implemented 0.8 so far, so unfortunately we can’t take advantage of this feature just yet.
Don’t lose heart! This is an exciting space, and the goal posts are constantly changing. So what should you do when you hit a wall? Build your own door!
For this example, we’re going to create a dummy OpenSocial REST response in PHP. While this won’t allow us to actually perform any OpenSocial queries, it’ll be a proof of concept, showing that the REST API will certainly be ready to go once the social networks begin implementing version 0.8, which shouldn’t be too far away.
Here we go. Since REST is a URL-based API, we need to perform some URL rewriting to turn a URL like this …
http://localhost/~jherr/people/@me/self
… into this:
http://localhost/~jherr/index.php?q=/people/@me/@self
The best tool for the job is Apache mod_rewrite. If you’re new to mod_rewrite, check out this comprehensive tutorial. Ensure that you have the mod_rewrite module installed, and add the following code to your .htaccess file:
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ ~jherr/index.php?q=$1 [L,QSA]
</IfModule>
This rewrites the REST request URL into a URL that resembles an invocation of our index.php file.
The code for our index.php file looks like this:
Listing 4. The index.php file
<?php
header( 'Content-type: text/xml' );
?>
<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<person xmlns="http://ns.opensocial.org/2008/opensocial">
<name>
<unstructured>Jane Doe</unstructured>
</name>
<about_me>Living in Fremont</about_me>
<address>
<longitude>-121.987259</longitude>
<latitude>37.54987</latitude>
</address>
</person>
</content>
…
<title/>
<updated>2003-12-13T18:30:02Z</updated>
<author/>
<id>urn:guid:example.org:34KJDCSKJN2HHF0DW20394</id>
</entry>
For this demo, we’ve manually created a person and structured their data in the XML OpenSocial 0.8 XML format. Until this version is supported by one or more of the social networking applications, you’ll need to resort to generating this XML data yourself.
The Flex code that maps the XML returned by our index.php file is shown below:
Listing 5. The OpenSocial Flex application
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="onStartup()">
<mx:Script>
<![CDATA[
import com.google.maps.InfoWindowOptions;
import com.google.maps.MapMouseEvent;
import com.google.maps.overlays.MarkerOptions;
import com.google.maps.overlays.Marker;
import mx.rpc.events.ResultEvent;
import com.google.maps.services.GeocodingEvent;
import com.google.maps.services.ClientGeocoder;
import com.google.maps.controls.ZoomControl;
import com.google.maps.controls.MapTypeControl;
import com.google.maps.MapEvent;
import com.google.maps.LatLng;
import com.google.maps.Map;
import mx.core.UIComponent;
private var map:Map = new Map();
private namespace OS='http://ns.opensocial.org/2008/opensocial';
private namespace Atom='http://www.w3.org/2005/Atom';
private function onStartup() : void {
var uic:UIComponent = new UIComponent();
uic.setStyle( 'top', 0 );
uic.setStyle( 'left', 0 );
uic.width = width;
uic.height = height;
addChildAt( uic, 0 );
map.key = 'Your Google Maps Key';
map.width = width;
map.height = height;
map.addEventListener( MapEvent.MAP_READY, onMapReady );
uic.addChild( map );
}
private function onMapReady( event:MapEvent ) : void {
map.setZoom( 10 );
map.addControl( new MapTypeControl() );
map.addControl( new ZoomControl() );
osSearch.send();
}
private function createMarker( person:XML ) : void {
use namespace OS;
var pMarker:Marker = new Marker( new LatLng( person.address.latitude, person.address.longitude ),
new MarkerOptions( {
label:person.name.unstructured,
tooltip:person.name.unstructured,
hasShadow:true } ) );
pMarker.addEventListener(MapMouseEvent.CLICK,function( event:MapMouseEvent ) : void {
pMarker.openInfoWindow( new InfoWindowOptions( { content: person.name.unstructured.toString() } ) );
} );
map.addOverlay( pMarker );
}
private function onOpenSocialResult( event:ResultEvent ) : void {
map.clearOverlays();
var first:Boolean = true;
use namespace OS;
for each ( var person:XML in event.result..person ) {
createMarker( person );
if ( first ) {
map.setCenter( new LatLng( person.address.latitude, person.address.longitude ) );
first = false;
}
}
}
]]>
</mx:Script>
<mx:HTTPService id="osSearch" url="http://localhost/~jherr/people/@me/@self"
resultFormat="e4x" result="onOpenSocialResult(event)" />
</mx:Application>
As you may have noticed, this code is very similar to the the code we used in our Flickr application. However, instead of requesting data from Flickr, this time we’re requesting data from our localhost URL.
The onOpenSocialResult method in the code above takes XML data produced by our index.php file, calculates the latitude/longitude pairs for each of the person XML objects, and adds a Marker for this person to the map. Then when the user clicks the Marker, our application displays an info window containing the person’s name.
Figure 6 demonstrates what this looks like.
As I mentioned earlier, this article is slightly ahead of the curve—none of the services currently supporting OpenSocial support the 0.8 REST format. However, it’s clear that they soon will, and this code should serve as a useful foundation for you to make a start with querying data from social networks using the OpenSocial 0.8 standard.
Where to Go from Here
We covered a lot of ground in this article, no? First, we demonstrated how to use Flex to build Flash applications. We then learned how to embed a beautiful, dynamic Google Map into a Flex application. Then we looked at how to retrieve and process data from an XML data source (whether it be via the Flickr API or the OpenSocial API). Finally, I demonstrated how to plot that data as interactive markers on a map.
The techniques used in this example should provide you with some great starting points for your own geocoding/mapping applications (don’t forget to download the code archive for this article). I look forward to seeing what you create!
Quiz Yourself!
Test your understanding of this article with a short quiz, and receive a FREE PDF of my book, Getting Started With Flex 3. The first 100 people to complete the quiz will also receive a paper copy delivered to their doors for FREE, thanks to Adobe Systems.