I just got back from the OpenSocial Hackathon, Episode I, sponsored by Silicon Valley Web Builder, conducted at the Google Campus. It was a fun night. We learned a lot about the OpenSocial API and building applications impromptu-style. Thanks to SVWB for organizing the event, Google for having us, the OpenSocial Google Team for presenting and guiding us, and the Hi5 guys for their help.
I spent most of my time working on integrating Flex and the OpenSocial API because A) I love Flex, and B) the REST API is not available yet. So my self-assigned task was to get a Flex app to use the Flex-Javascript bridge provided by Adobe to work inside a gadget deployed in an OpenSocial container and be able to display data retrieved from my profile using the JavaScript API. With minutes left in the event, I succeeded in doing so within the Hi5 container. Here is what I did:
1) Src’ed the FABridge.js file in my gadget XML file.
2) Embedded the SWF directly in my gadget XML file using the object tag (found in your index.template.html file), rather than use gadgets.flash.embedFlash or _IG_EmbedFlash because they never worked for me.
3) Cached my swf on gmodules.com
To do this, visit this url: http://gmodules.com/ig/proxy?url=<place-swf-url-here>. This will cause gmodules.com to download the swf at the specified url and save it locally. Also, you will need to append “?id=X” to the url each time you update the swf (where X is a number that you increment each time you update the SWF) because once cached, gmodules does not replace the SWF at a particular address if you visit the same url again.
This is necessary because modules deployed on Hi5 get served from gmodules.com, which means the domain of your javascript file that you embedded in your gadget XML file will be gmodules.com, and the Flash player will throw a “Security sandbox violation” error when your SWF tries to call a function using ExternalInterface if it is being loaded from your server. By caching your SWF on gmodules.com, you can bypass this problem of crossdomain security. (I tried flash.system.Security.allowDomain but it didn’t work for me).
Also, when actually served, the gadget will not reside on just “gmodules.com” but rather will be on “0.gmodules.com” (zero dot gmodules.com) or some other subdomain. Thankfully, even though we cached using just “gmodules.com”, we can still access our SWF using “0.gmodules.com”. So once you realize which server your gadget is coming from, update the src attribute of your embed tag in your gadget XML file to use the same domain and subdomain when referencing your SWF.
When using this workaround, don’t forget to update the gadget XML file’s embed url each time you advance the SWF file id in the gmodules.com cache.
4) Other notes:
Don’t forget to add <Require feature=”flash” /> to the ModulePrefs section of your gadget file.
Don’t forget to call ExternalInterface.addCallback(“<function-name>”, <function-name>); in your Flex onCreationComplete function to expose your functions.
Don’t forget to make your Flex functions public (though I think that may not be necessary).
Be sure to assign an id in your object tag in your gadget XML file, and use this JavaScript function to reference it:
var flexApp = getFlexApp(<object-tag-id>) ;
function getFlexApp(appName)
{
if (navigator.appName.indexOf (“Microsoft”) !=-1) {
return window[appName];
} else {
return document[appName];
}
}
Then you can make calls like getFlexApp(<object-tag-id>).myFunction(<args>);
Also, you can’t use the getXXX() functions in Flex on the objects returned from the OpenSocial API as specified in the docs (like Person.getDisplayName()), and the objects returned from the various containers (Hi5, Orkut, etc) aren’t implemented the same way (Hi5: Person.fields_.name vs. Orkut: Person.obj_.Name), so you may have to construct objects on the JavaScript side using the getter functions so that Flex can work with the data.
Here is the Flex to JavaScript bridge I created:
Flex:
private function getFriends():void
{
ExternalInterface.call(“getFriends”);
}
JavaScript:
function getFriends()
{
var req = opensocial.newDataRequest();
req.add(req.newFetchPeopleRequest(‘VIEWER_FRIENDS’), ‘viewerFriends’);
req.send(onLoadFriends);
}
function onLoadFriends(data)
{
var viewerFriends = data.get(‘viewerFriends’).getData();
var vFriends = new Array();
viewerFriends.each(function(person) {
vFriends.push(person.getDisplayName());
});
getFlexApp(‘OpenSocial’).setFriends(vFriends);
}
5) Questions to the community:
What are my alternatives to the caching workaround to deal with the crossdomain issues?
Thanks, -Ariel Jakobovits (arieljake at gmail dot com)
Filed under: Hacking | Tagged: opensocial api flex javascript bridge swf hi5
