February 26, 2009
February 20, 2009
Examples for reading & writing appData
Example of update appData
private function updateData():void
{
var dr:DataRequest = container.newDataRequest();
dr.add(dr.newUpdatePersonAppDataRequest("VIEWER", "testdatakey1", 'test'));
dr.send(updatePersonAppDataCallback);
}
private function updatePersonAppDataCallback(dataResp:DataResponse):void
{
Alert.show("updatePersonAppDataCallback(). \n dataResp.hadError()=" + dataResp.hadError()
+ "\n dataResp.getErrorMessage()=" + dataResp.getErrorMessage());
}
Examples of fetch appData
private function fetchData():void
{
var dr:DataRequest = container.newDataRequest();
//var idSpec:IdSpec = container.newIdSpec({ com.nextgenapp.opensocial.IdSpec.Field.USER_ID : "VIEWER"}); // does not work. has compile error.
//var idSpec:IdSpec = container.newIdSpec({ "USER_ID" : "VIEWER"}); // do this instead.
var idSpecParam:Object = {};
idSpecParam[com.nextgenapp.opensocial.IdSpec.Field.USER_ID] = "VIEWER";
var idSpec:IdSpec = container.newIdSpec(idSpecParam);
dr.add(dr.newFetchPersonAppDataRequest(idSpec, ["testdatakey1"], null), opt_key);
dr.send(fetchPersonAppDataCallback);
}
private function fetchPersonAppDataCallback(dataResp:DataResponse):void
{
trace("fetchPersonAppDataCallback()");
Alert.show("fetchPersonAppDataCallback()");
if (dataResp.hadError()) {
Alert.show("error: " + dataResp.getErrorMessage());
}
var appData:Object = dataResp.get(opt_key).getData();
Alert.show("appData=" + appData);
// appData should have a member (user's id). inside that, it should have a member
var appDataDisplay:String = "";
for (var propNameLevel1:String in appData) {
appDataDisplay += ("\n" + propNameLevel1 + " : " + appData[propNameLevel1]);
for (var propNameLevel2:String in appData[propNameLevel1]) {
appDataDisplay += ("\n----" + propNameLevel2 + " : " + appData[propNameLevel1][propNameLevel2]);
}
}
Alert.show("appData expanded=" + appDataDisplay);
}
A full sample code can be found here: http://opensocial-tutorial-trial.googlecode.com/svn-history/r180/trunk/os-as-lib-081-test/src/AppDataExampleOrkut.mxml
February 18, 2009
requestSendMessage Example with Callback
private function sendEmail():void
{
var msgParams:Object = {};
msgParams[com.nextgenapp.opensocial.Message.Field.TITLE] = 'test title';
msgParams[com.nextgenapp.opensocial.Message.Field.TYPE] = com.nextgenapp.opensocial.Message.Type.EMAIL;
var message:Message = container.newMessage("test msg body", msgParams);
container.requestSendMessage(["VIEWER"], message, sendEmailCallback);
}
private function sendEmailCallback(respItem:ResponseItem):void
{
// note: requestSendMessage() returns ResponseItem, not DataResponse.
trace("sendEmailCallback");
Alert.show("sendEmailCallback. haderror=" + respItem.hadError());
if (respItem.hadError()) {
// get the response item
Alert.show("sendEmailCallback. errorCode=" + respItem.getErrorCode() + ". errorMessage=" + respItem.getErrorMessage());
}
}
A full sample code can be found here: http://opensocial-tutorial-trial.googlecode.com/svn-history/r180/trunk/os-as-lib-081-test/src/SendMsgExampleOrkut.mxml
requestSendMessage() callback returns a ResponseItem, not DataResponse.
This is common knowledge if you have use requestSendMessage() before. requestSendMessage()’s callback function gives you a ResponseItem, not DataResponse. In other functions like fetchPeopleRequest, it will return a DataResponse.
Since the javascript api behaves this way, our actionscript library will behave the same way.
Eg.
private function sendEmail():void
{
var msgParams:Object = {};
msgParams[com.nextgenapp.opensocial.Message.Field.TITLE] = 'test title';
msgParams[com.nextgenapp.opensocial.Message.Field.TYPE] = com.nextgenapp.opensocial.Message.Type.EMAIL;
var message:Message = container.newMessage("test msg body", msgParams);
container.requestSendMessage(["VIEWER"], message, sendEmailCallback);
}
private function sendEmailCallback(respItem:ResponseItem):void
{
// note: requestSendMessage() returns ResponseItem, not DataResponse.
trace("sendEmailCallback");
Alert.show("sendEmailCallback. haderror=" + respItem.hadError());
if (respItem.hadError()) {
// get the response item
Alert.show("sendEmailCallback. errorCode=" + respItem.getErrorCode() + ". errorMessage=" + respItem.getErrorMessage());
}
}
Changing constant value to small case
eg.
public static const THUMBNAIL_URL:String = "THUMBNAIL_URL";
However, according to the spec, the value has been standardize to lower-case.
An excerpt of the spec on http://wiki.opensocial.org/index.php?title=Opensocial.Person_(v0.8)
opensocial.Person.Field.THUMBNAIL_URL
Person's photo thumbnail URL, specified as a string. This URL must be fully qualified. Relative URLs will not work in gadgets. This field may be used interchangeably with the string 'thumbnailUrl'.
So we will start changing the value to lower case soon.
eg.
public static const THUMBNAIL_URL:String = "thumbnailUrl";
requestSendMessage() is implemented
Here is the excerpt example code:
var msgParams:Object = {};
msgParams[com.nextgenapp.opensocial.Message.Field.TITLE] = 'test title';
msgParams[com.nextgenapp.opensocial.Message.Field.TYPE] = com.nextgenapp.opensocial.Message.Type.EMAIL;
var message:Message = container.newMessage("test msg body", msgParams);
container.requestSendMessage(["VIEWER"], message);
A full sample code can be found here: http://opensocial-tutorial-trial.googlecode.com/svn-history/r180/trunk/os-as-lib-081-test/src/SendMsgExampleOrkut.mxml
Difference between email & notification on Orkut
Facebook Developer Garage Palo Alto - Feeds and Social Distribution
http://www.facebook.com/home.php#/event.php?eid=137109600304&ref=ts
February 17, 2009
DataResponse.getErrorMessage() showing undefined for updatePersonAppData
February 16, 2009
Preliminary AppData implementation
To update app data
var dr:DataRequest = container.newDataRequest();
dr.add(dr.newUpdatePersonAppDataRequest("VIEWER", "testdatakey1", "testdata1"));
dr.send(updatePersonAppDataCallback);
To fetch app data
var dr:DataRequest = container.newDataRequest();
var idSpecParam:Object = {};
idSpecParam[com.nextgenapp.opensocial.IdSpec.Field.USER_ID] = "VIEWER";
var idSpec:IdSpec = container.newIdSpec(idSpecParam);
dr.add(dr.newFetchPersonAppDataRequest(idSpec, ["testdatakey1"], null));
dr.send(updatePersonAppDataCallback);
The usage of the api is exactly the same as the opensocial javascript api.
If you have any questions about usage of these 2 functions or you feel the interface method is that the best, please send your suggestions to us.
fetchPersonAppData data structure
- person_id
   - [key, value]
   - [key, value]
- person_id
   - [key, value]
   - [key, value]
This structure retain the maximum flexibility so that it can return multiple person and multiple key at the same time. However, it can easily confuse first-time users of our library if we return the raw data. We are thinking whether we should return a more structured data back to the caller.
Structure:
AppData
   - PersonData
     - DataElement
     - DataElement
   - PersonData
     - DataElement
     - DataElement
AppData.getPersonDatas() returns an Array of PersonData object. Each PersonData contains an array of DataElement. Each DataElement is a [key, value] pair.
Advantage of returning a structured data
It will be easier for the user of our library to decipher the data. Flex Builder's code-helper will be useful in this case. Without refering back at the javascript documentation, user can still figure out the data structure of the data being returned.
Disadvantage
It will be a departure from the javascript API.
If you have strong feeling about going one way or the other, please let us know.
WeekendApps - OpenSocial
What is WeekendApps ?
(description copied from WeekendApps Wiki)
WeekendApps is a 3-day hackathon. Arrive on Friday, join a team, build an app, launch on Sunday. Sign up here: http://weekendapps.com
February 14, 2009
opensocial javascript api rants
1. cumbersome
Instead of one call like:
opensocial.person.getViewer();it takes 4 lines to do the same thing. The following code is not actual code, it only illustrates the point.
var req = opensocial.newDataRequest();
var personReq = req.newFetchPersonRequest();
req.add(personReq, “…”);
req.send();
2. usually, when there is objects, it is easy to infer the data structure. With getField()/setField() instead of property, it is harder to infer data structure. Also, we don’t get the benefit of the code-helper by IDE.
Solution?
To address #1:
Perhaps we should have some new api call build on top of the existing api to make things more terse:
Eg.
OpensocialShortcut.person.getViewer();
OpensocialShortcut.person.getFriends();
OpensocialShortcut.data.update();
OpensocialShortcut.data.fetch();
To address #2:
On the actionscript api, perhaps we should have extension to allow people to access object properties like this:
person.name.firstName
person.gender.getKey()
instead of
person.getField(opensocial.Person.Field.NAME).getField(opensocial.Name.Field.FIRST_NAME);
person.getField(opensocial.Person.Field.GENDER).getKey();
---------
What do you think? Is it better to have the API call featured like the one shown in “Solution” section?
February 11, 2009
Difference between MySpace and Orkut – part2
Orkut
The Person object's NAME property contains an opensocial.Name object. GENDER property contains an opensocial.Enum object.
MySpace
The Person object returned by MySpace JavaScript API have string for NAME and GENDER.
Difference between MySpace and Orkut – part 1
We implement the MySpace newFetchPersonRequest() first. Then we try to implement newFetchPersonRequest() for Orkut. Then we found out that there are a few thing that MySpace sample code is different from the Orkut code.
The following are Javascript code. On Actionscript side, we abstract the difference, so the Actionscript API is the same across the two containers.
var dataRequest = opensocial.newDataRequest();
var OWNERReq = dataRequest.newFetchPersonRequest(oParam.view, param);
dataRequest.add(OWNERReq, 'viewer');
on MySpace code, it has
var os = opensocial.Container.get(); // different from standard
var dataRequest = os.newDataRequest();
var OWNERReq = os.newFetchPersonRequest(oParam.view, param);
dataRequest.add(OWNERReq); // different from standard, does not require the extra name.
Overview
This blog will show the development activities and some general rants and discussion about opensocial-actionscript-client project. opensocial-actionscript-client is an opensource library for actionscript (and Flex/Flash) to use opensocial API. :)
The code is opensourced and hosted at:
http://code.google.com/p/opensocial-actionscript-client
The download is located at:
http://code.google.com/p/opensocial-actionscript-client/downloads/list
New update are shown at:
http://code.google.com/p/opensocial-actionscript-client/updates/list
What is opensocial-actionscript-client api
Opensocial-actionscript-client is an OpenSocial library for Actionscript/Flex/Flash. This is an opensource library. It allows Actionscript/Flex/Flash client to access OpenSocial API.
A Little More Detail About the Architecture
The library uses Opensocial Javascript API, not REST API. It was a careful and necessary decision to go for Javascript API for the following reasons:
1. Some containers have a closed-off crossdomain.xml (which means Flash cannot connect to their server)
2. Not all containers support REST API yet
These are restrictions that cannot be overcome, unless the containers (the social networks sites) change their policies.
Current OpenSocial Version
Currently, the API uses OpenSocial 0.8, the latest version at the moment.
Contribution/Feedback
You are welcome to contribute or add to the library. It is opensource! :)
Design Concept
The main goal for this project is to develop a client-based actionscript-to-opensocial framework reusable across multiple container platforms. This means being able to write once a flash client application and run anywhere on any platform opensocial is supported. Our initial release will not have the complete implementation. However, as this is a framework and open source, we’ll build the features on an as-needed basis. We’ll also rely on the community to help expand and support the features for opensocial and other container specific platforms.
Currently, MySpace has an actionscript library which implements opensocial API using RESTful interface for communication with the backend server. There are two issues for the flash client in using this approach:
- If the client is directly communicating with the container itself, it must assume that the container has a ‘crossdomain.xml’ policy on its server to bypass the security restrictions of Flash applications. Otherwise, the aforementioned API will not work.
- The RESTful APIs as defined by Google’s opensocial are meant for Server-to-Server communication. So in essence, it’s not meant for a flash application to use such mechanism to communicate with the opensocial containers.
Here’s where our framework will come in. We want to create a framework/library which can be used by client-side flex application that can bypass security issues such as the cross-domain policy. This can be done by creating a framework/library which sits on top of the opensocial javascript library. By doing this, we will be bypassing the flash security restrictions which requires ‘crossdomain.xml’. Since this will also be using the Javascript implementations provided by the platform containers, it will also bypass any security restrictions of Javascript itself. The diagram shows our current design.
The framework/library will consist of an actionscript library which runs on top of a Actionscript/Javascript Bridge. The actionscript library will consists of all opensocial functions and classes created for a specific version. The Actionscript/Javascript bridge will link the library to the platform’s Javascript opensocial implementation using Flash’s ExternalInterface class and an XML file corresponding to the opensocial implementation. There are a couple benefits of doing it this way:
1. Using the bridge in this manner allows us to write everything in actionscript. There is no javascript code that needs to be loaded separately with this library. All Javascript code will be incorporated into the bridge through the XML files generated.
2. Having such decoupling promotes reusability. We now can create the library based on different versions of the opensocial API.
3. Designing it this way also creates flexibility. We now can build applications which can run on any opensocial platform by switching in and out the Container’s implementation. This means no change in the application code whatsoever.
4. As mentioned earlier, the Javascript opensocial implementation is a requirement for all opensocial containers. This means that applications running on our framework can technically run any opensocial network and work immediately as long as they have not used container specific opensocial calls.
Data Structure
The following are the initial design of actionscript classes created for this framework based on opensocial v. 0.81:
- Activity – opensocial Activity
- Address – opensocial Address
- CreateActivityPriority – opensocial CreateActivityPriority
- DataRequest – opensocial DataRequest
- Environment – opensocial Environment
- IdSpec – opensocial IdSpec
- MediaItem – opensocial MediaItem
- Message – opensocial Message
- Name – opensocial Name
- NavigationParameters – opensocial NavigationParameters
- OSContainer – Represents the opensocial container
- Organization – opensocial Organization
- OrkutContainer – Implementation of OSContainer for Orkut
- OrkutOSFactory – Bridge to map actionscript opensocial calls with javascript calls using XML files for Orkut
- OSXmlFactory – Factory to load XML representation of opensocial Javascript function
- Permission – opensocial Permission
- Person – opensocial Person
- Phone – opensocial Phone
- Hi5Container – Implementation of OSContainer for Hi5
- Hi5OSFactory – Bridge to map actionscript opensocial calls with javascript calls using XML files for Hi5
- MySpaceContainer – Implementation of OSContainer for MySpace
- MySpaceOSFactory – Bridge to map actionscript opensocial calls with javascript calls using XML files for MySpace
- XMLLoader – Helper class to load the XML file
Figure 1