My favorites | English | Sign in

Google Desktop APIs (Labs)

Proper Offline Behaviour

This article was written and submitted by an external developer. The Google Desktop Team thanks Teodor Filimon for his time and expertise.


Teodor Filimon, Gadget Developer
November 2007
"Something cannot emerge from nothing."  -  Frank Herbert

Introduction

More and more gadgets, especially in the Web 2.0 era, have to communicate with the online world to provide fresh data and interactivity between users. Unlike a web-based gadget, a Desktop gadget also has to know what to do when the user is offline.

Detection

First of all, we have to realize that gadgets can do a lot of things while online, such as fetching news, feeds or images and interacting with other users of the same gadget. There are several ways to see if the computer is online or offline:

  • framework.system.network.online can be used for general purposes.
    function isNetworkOnline() {
      return framework.system.network.online;
    }
  • If you're using the Google Talk API, it might be a good idea to keep an eye on the googleTalk.talk_status property. It can return three values:

    gddTalkStatusNotRunning
    Google Talk is not running; maybe it's not installed.
    gddTalkStatusDisconnected
    Google Talk is running but disconnected; there may not be an Internet connection.
    gddTalkStatusConnected
    Google Talk is running and connected.

    These values are actually represented by the integers 0, 1 and 2. I used this property in Cupid's gadget for offline detection:

    function refresh(){
    
      //...
    
      //check if Google Talk is not running or not installed
      if (googleTalk.talk_status==gddTalkStatusNotRunning) {
        NoFriendsOnline();
        ShowMessage(1);
        return 0;
      }
    
      //check if Google Talk is running but not connected
      if (googleTalk.talk_status==gddTalkStatusDisconnected) {
        NoFriendsOnline();
        ShowMessage(2);
        return 0;
      }
    
      //notice how the function will stop when a return will be executed
      //therefore it will get here only when Google Talk is connected
      Bookmark.visible=true;
      ShowMessage(0);
    
    }

More about offline and online detection can be found in this article.

Interface Issues

Ultimately the user should be able to see the current connection status. However, the changes in the interface should be suggestive as you can see in Figure 1. The most important UI element (big red heart) is replaced by an appropriate status message.

What to do when Google Talk is not running and/or not installed
Figure 1: Telling the user what to do

Notice how the gadget doesn't pop up an intrusive error dialog or output a message like "Error 235: Connection not found". :) Instead it guides the user to make the most out of the gadget. You can go further by applying different modes to the interface, as described in this article. For example, when the user goes offline, the gadget could shrink down and give up the visual space required by the online functionality.

Data Handling

So you've made a gadget that gathers the latest news and posts from a feed or just parses a big XML file. It needs to fetch the items periodically to keep the data fresh. But what if there is no Internet connection the next time the gadget is loaded? The best solution is storing the data using options. If the array consists of JavaScript objects, you can use JSON to serialize the objects to a string and deserialize the string to objects.

A good example of persisting data to options is the Tabbed ToDo List gadget. Within the source, you can see exactly what functions to call for the conversions to and from JSON strings. The tasks, tabs, and checkbox values are continually persisted and recreated with the help of JSON.

function change(){
  //memorizes the new todolist
  options("todoList")=todoList.toJSONString();
  options("tabs")=tabs.toJSONString();
  options("values")=values.toJSONString();
  //todoList, tabs and values are all arrays
}

function show(){
  //shows the remembered todo list
  todoList=options("todoList").parseJSON();
  values=options("values").parseJSON();
  tabs=options("tabs").parseJSON();
  //...
}

These methods are defined in a .js script file downloadable from the JSON site. That script has to be included in your main.xml file just as you would include main.js.

Good Practices

We've seen how to add offline robustness to a gadget across sessions, but we should also be mindful of CPU and memory usage.

A common, potentially expensive operation is sorting an array. You might want to order items by value and interest to the user, such as unchecked tasks in a to-do list or unread items in a news feed. In such cases don't forget about the Ranking API, which sorts items based on various criteria like number of clicks, publishing time, etc.

The most expensive activity in terms of CPU is one that repeats periodically. The setInterval and setTimeout functions are widely used, but should be used carefully. Infinite call cycles should be avoided and timers should be destroyed when they're not used.

function myFunction(){
  alert("Alert");
}

token=setInterval("myFunction()",10000);
//this timer will call myFunction once every 10 seconds

//when the timer isn't needed it should be deleted
//we can do this using the token returned by setInterval
clearInterval(token);
//you can also delete a timeout, using clearTimeout

You can find out more about these functions, including some that can be particularly helpful for animations, by checking out the documentation for the view object.

Similar safeguards should be used to optimize memory usage as well. Declaring variables locally is usually better then globally. Objects should also be deleted or set to null if they aren't used anymore. For example, audioclips should be set to null once they've been played and are no longer needed.

Conclusion

To create the best application possible, it's important to be aware of these workarounds, safeguards, and best practices and to apply them appropriately when needed.

Many gadgets, everyone!

Resources

Author Bio

Teodor Filimon

I'm a natural born programmer. My first contact with a techno-gadget was Star Trek (remember those cool sensors?). I used to fill up a whole room with drawings of them when I was only 3 years old. Generally, I find a lot of inspiration for intuitive interfaces in things with "star" in their names (like Star Wars, Stargate,... :-) . I like the border between interface and function—it's the essence of a program, I think. Anyway, I'm a software engineering student now, and you can learn more about me and what I'm thinking and doing at my website or blog. My most popular gadgets are DigiWatch and TV Set.


Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.