Table of Contents
gadgets.realtime and the APIs built on top of it allow gadget developers to write applications that communicate asynchronously with another endpoint, whether that endpoint is another instance of the application (on another machine, or in another browser, for example), the container hosting the gadget, or an application hosted in the cloud.
The obvious application of these APIs is 1:1 gaming -- at its most basic a Tic-Tac-Toe game between two users. However there are many other more complex (and arguably -- depending on your thoughts about games -- more interesting) scenarios that these APIs enable; for instance, a chat application that translates text as participants type it, or a shared whiteboard, or an application that lets a couple choose the best flight for their upcoming vacation.
gadgets.realtime is meant as a generic base for asynchronous communication. It provides a way for a gadget to join a session, send messages to that session, and receive messages from the session. What the session "is" is defined by the container, and the underlying gadgets.realtime session architecture can be obscured by the implementation of other features built on top of it, as we have done with .
gadgets.sharedstate
Currently the only API available using gadgets.realtime is . This API assumes that the context for realtime communication is set up already; in our initial developer launch this is done by the chat UI.
gadgets.sharedstate
We plan to add more APIs using gadgets.realtime, including a more general message-passing API and a presence API to subscribe to the online availability of your OpenSocial contacts. These APIs, in addition to gadgets.sharedstate, will be provided in the iGoogle and orkut canvas pages. We'll also provide a wrapper to make it easy for gadgets written using the gadgets.sharedstate API to be used on the iGoogle canvas page.
As we refine the user experience, we'll open up the gadgets-in-moles experience to orkut users. We'll follow a similar path of early developer preview, then support for wider audiences as the UX is refined, for canvas-page support.
The realtime APIs are implemented as gadget features. So, you can write a gadget like any other, but you'll need a <Require feature="sharedstate"/> line in the <ModulePrefs> section of your gadget.xml. For more information on general gadget authoring, see the Gadgets API page on code.google.com.
Currently the gadgets.realtime features are only available for gadgets running inside chat "moles" (what we call the little modeless boxes in the lower-right of your web browser). We plan to expand the availability of these features to the canvas page of other gadget containers, specifically iGoogle and orkut.
Here is a sample "Hello world" gadget:
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello World with gadgets.sharedstate">
<Require feature="google.sharedstate"/>
</ModulePrefs>
<Content type="html">
<![CDATA[
<div id='state'></div>
<ul>
<li><a href="javascript:void(0)" onclick="setState('Hello');">Hello</a></li>
<li><a href="javascript:void(0)" onclick="setState('Goodbye');">Goodbye</a></li>
</ul>
<script>
gadgets.sharedstate.initialize(function(myId, otherIds) {
me = myId;
});
gadgets.sharedstate.setStateChangeHandler(function(newState) {
if (!newState) {
document.getElementById('state').innerHTML = "Nobody has said anything yet.";
} else {
var who = newState.from == me ? 'I say: ' : 'The other person says: ';
document.getElementById('state').innerHTML = who + newState.message;
}
});
var setState = function(message) {
var state = {from: me, message: message};
gadgets.sharedstate.updateState(state);
}
</script>
]]>
</Content>
</Module>
The gadgets.sharedstate API is extremely simple, as you can see above. It simply allows the two endpoints which are joined to a session to modify a shared state object (which is limited to 2048 bytes in JSON representation) and be notified when the shared object has changed. See the API Reference section for more details.
There are two ways to test your gadgets.sharedstate gadget. You can use the test harness to quickly modify and debug your gadget, then use the sandbox to use the gadget in a real chat application (and maybe show it off to your friends!).
The Test Harness is a bare-bones development environment to make it easy to write & test your gadgets.sharedstate gadgets. To use it, navigate to:
http://talkgadget.google.com/talkgadget/apptestharness?gadget=yourgadget.xml
We'll add more functionality to this harness as time goes on, including better debugging, latency simulation, gadget resizing, and support for other gadgets.realtime APIs.
First make sure that you've got two Google accounts that can send IM messages back and forth to each other. If you don't already have two accounts you'd like to use, create some Gmail accounts such as yourname-test1@gmail.com and yourname-test2@gmail.com.
Once you've created these accounts, you can open two separate browsers, each pointed at http://talkgadget.google.com/talkgadget/sandbox and signed in with the different accounts. From one instance, invite the other account to chat. Now you're ready to start testing.
Click on the other account in your roster, which brings up a chat mole. Click Video & More, then Send Application. An edit box will appear on top of the mole; type in the address of your gadget xml and click Invite. This will create an instance of your gadget running in each browser, for each account. Standard browser-debugging applies, but note that your JavaScript will be pre-processed by the Google Gadget server.
You can use the Google Gadgets Editor to write your gadgets. With this tool, you don't need to host your gadget XML files yourself; the Gadget Editor will provide a URL that you can paste into the Test Harness URL or the Send Application text box.
gadgets.sharedstategadgets.sharedstate is an API built on top of gadgets.realtime. Its purpose is to make communication between application instances very simple in the case where both instances are already known and the container can provide a small amount of shared storage (Google containers will provide 2048 bytes for the JSON representation of the shared object).
Since gadgets live in a web page, with the intrinsic volatility that goes along with that (the user could close the browser, refresh the page, switch computers), the sharedstate API can come in very handy for gadget developers. While 2048 bytes might not sound like much, it is generally enough to store a game board and perhaps a couple of user preferences, or at the very least a persistent hint for the gadget to retrieve the most up-to-date state from another store.
Note: gadgets.sharedstate is the first API to be supported on top of gadgets.realtime. This API is available for gadgets running inside Talk "moles" (modeless dialogs in the lower right of a web page). This API will also be supported in iGoogle with some extra functionality to specify the other endpoint of the sharedstate session.
/**
* Initializes the sharedstate API.
*
* @param {function(myId, otherIds)} initHandler A function that is called
* when the sharedstate session is initialized. myId {string} is a unique
* identifier for this gadget endpoint that will persist between
* refreshes. otherIds {Array.string} is an array of other participants
* in the shared state session. Like myId, these id's are guaranteed to
* persist between sessions. These id's are OpenSocial-agnostic, for
* cases in which the gadget might not be running in an OpenSocial
* context.
*
*/
gadgets.sharedstate.initialize = function(initHandler) {}
/**
* Sets the handler to be called when the state changes.
*
* @param {function(state)} stateChangeHandler A function that is called when
* the shared state changes. The state object passed to this function is
* an exact copy of the state object set by this gadget or the other
* instance of the gadget. Note that calling setState() will result in a
* call back to this handler as verification that the state has been set.
*/
gadgets.sharedstate.setStateChangeHandler = function(handler) {}
/**
* Sets the shared state. As noted above, the shared state change handler
* will be called by the container to verify that the state has been set.
*
* @param {Object} state The new state. The format of this object is defined
* by the gadget.
*/
gadgets.sharedstate.setState = function(state) {}
gadgets.realtimeThis API defines a basic method for communicating asynchronously in sessions. Sessions are whatever the gadget container defines them as; some standard sessions are defined below but the API is designed to be adapted to many uses. This API is not generally meant to be called directly by gadgets but is meant to be used as a building block for other APIs. The API defines 3 methods:
/**
* Joins a session. Receives messages from the session and allows
* the application to send messages to the session.
*
* @param {string} session The session name.
* @param {function(Object)} messageHandler The handler for messages
* sent from this session. By convention, messages passed to this
* handler are of the form:
* {
* m: message_id,
* data: message_data
* }
* Also by convention a session will send a status message as the
* first message to a session. This message defines success or
* failure to join the session.
* {
* m: SESSION_JOIN_STATUS,
* data: status_code // corresponds to HTTP response code
* }
*/
gadgets.realtime.joinSession = function(session, messageHandler) {};
/**
* Leaves a previously joined session. Leaving a session cannot fail.
*
* @param {string} session The session name.
*/
gadgets.realtime.leaveSession = function(session) {};
/**
* Sends a message to a session. If there is a failure sending the message,
* a message will be sent of the form:
* {
* m: MESSAGE_SEND_ERROR,
* data: error_code // corresponds to HTTP response code
* }
*
* @param {string} session The session name.
* @param {Object} message The message to send. By convention message
* objects have an 'm' member specifying the message type and a
* 'data' member specifying the message data, but this is *not*
* enforced by the API. The object is sent as-is.
*/
gadgets.realtime.sendMessage = function(session, message) {};
The basic usage is:
// Join a session. When a message from that session is received, // show an alert.gadgets.realtime.joinSession('mySession', function(message) { alert('Message: ' + message.m + ', data: ' + message.data); }); // Send a message to the session. The container defines what happens // when this message is received.gadgets.realtime.sendMessage('mySession', {m: 'hello', data: 'world'}); // Leave the session.gadgets.realtime.leaveSession();
This is a simple application to let you play rochambeau with your friends. This demonstrates a very simple use of the gadgets.sharedstate API.
http://code.google.com/apis/talk/examples/rps.xml
A full-featured chess game. A more complex game using the gadgets.sharedstate API.
http://code.google.com/apis/talk/examples/chess.xml
An application that translates what your friend says into the language your browser is set to. An example of using other Google APIs in conjunction with the gadgets.sharedstate API.