April 23, 2009

OpenSocial Spec 0.9 is published


Opensocial 0.9 spec is published on Apr 16 according to OpenSocial API blog (http://blog.opensocial.org/2009/04/opensocial-community-defines-version-09.html)
 
 
major features:
1. lightweight javascript API
2. proxied content  
3. data pipelining
4. templates and OSML
 

1. Lightweight javascript API will be a great news for developers.  I have blogged earlier about how cumbersome the JS API is.  Lightweight javascript API is a great improvement.  

eg.  examples coming from OpenSocial Release Notes:

Requesting the viewer in OpenSocial v0.8

var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER), "req"); req.send(callback); 

Requesting the viewer in OpenSocial v0.9

osapi.people.getViewer().execute(callback);

Once that Orkut and Myspace support lightweight javascript api in Spec 0.9.  I think we shall change our opensocial-actionscript-client interface to follow lightweight javascript api.  Right now, our interface mimics the regular javascript api in OpenSocial Spec 0.8.  

2. templates - people who are familiar with JSP EL will find this to be very similar.  This should make the code more readable.

3. OSML - each containers will be required to implement a set of standard tags such as Name Badge.  This is another timesaver.  


March 5, 2009

Dimension of app on myspace, orkut, and facebook


Each platform has different size limit for apps that appearing on their canvas and profile.  I hope this can be a collaborative effort, please feel free to chime in.  


Myspace
canvas: 960 x (no limit?)
narrow profile: 300 x ?
wide profile: 430 x ?

Reference: What is an Myspace app

orkut
canvas: 765x600
profile: 470x280

Reference: Anatomy of an orkut app


facebook
canvas: 760 x (no limit?)
main profile: ?
narrow profile: ?
wide profile: ?
application tab: ?

Reference:
You can see this in developer application.  When you create an application, it will ask you whether your canvas should be new size (760 px) or old size (68x px).

February 26, 2009

Create Activity feature added to the library


Updated Today (21 minutes ago)by swswsw
Labels:example
The library is capable of doing requestCreateActivity() now.

Example of requestCreateActivity

        private function createActivity():void {
               
var params:Object = {};
               
params[com.nextgenapp.opensocial.activity.Field.TITLE] = "test activitiy title";
               
var activity:Activity = container.newActivity(params);
               
                container
.requestCreateActivity(activity, com.nextgenapp.opensocial.CreateActivityPriority.HIGH, createActivityCallback);
       
}
       
private function createActivityCallback(respItem:ResponseItem):void
       
{
               
// note: requestSendMessage() returns ResponseItem, not DataResponse.  
                trace
("createActivityCallback");
               
Alert.show("createActivityCallback.  haderror=" + respItem.hadError());
               
if (respItem.hadError()) {
                       
// get the response item
                       
Alert.show("createActivityCallback.  errorCode=" + respItem.getErrorCode() + ".  errorMessage=" + respItem.getErrorMessage());
                       
                       
if ("forbidden" == respItem.getErrorCode()) {
                               
Alert.show("user denied permission.  you have to ask user for permission.");
                       
}
               
}
       
}

A full sample code can be found here: http://opensocial-tutorial-trial.googlecode.com/svn/trunk/os-as-lib-081-test/src/ActivityExampleOrkut.mxml

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.

The following is javascript api behavior:
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

Currently, field constants have upper-case value.
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

We have implemented opensocial.requestSendMessage().

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

I am wondering: is there a difference between email & notification on Okrut? I tried requestSendMessage() with email and notification. They seem to do exactly the same thing. Both result in an email being sent. Is there a differnce?

Facebook Developer Garage Palo Alto - Feeds and Social Distribution

Facebook will host a Facebook Developer Garage in Palo Alto. If you are a facebook app developer and you are in San Francisco Bay Area . This should definitely worth your while to attend. :)
http://www.facebook.com/home.php#/event.php?eid=137109600304&ref=ts

February 17, 2009

DataResponse.getErrorMessage() showing undefined for updatePersonAppData

I was testing updatePersonAppData on orkut. I deliberately tried to create an error by giving a wrong id such as "" instead of "VIEWER". I find that hadError() does return true, but getErrorMessage() returns undefined. I kind of expected getErrorMessage() to return something interesting to help us debug. Sadly, it returns undefined.

February 16, 2009

Preliminary AppData implementation

Preliminary AppData implementation is completed and tested. You can update and fetch AppData. Escape character is not yet supported.

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

opensocial javascript API's fetchPersonAppData returns an object with the following 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

My friend Waleed is organizing a WeekendApps event focused on OpenSocial. It should be fun and exciting. It will be hold on Feb 20, 2009. For more details, please see http://weekendapps.com.

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

Opensocial javascript api is very flexible, this is a benefit when there are multiple containers need to implement the same standard. It also allows batch multiple commands. I think people already know its advantages, so I’m not going to rant about advantages. I’m just going to do some ranting about some of the shortcomings that comes with these flexibilities.

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

Person object returned by JavaScript API have different types for properties.

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

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

Opensocial-actionscript-client blog

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:

  1. 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.
  2. 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