My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Design  
Foursquare for Android design doc
Phase-Design, Phase-Implementation, Featured
Updated Nov 23, 2009 by jlapenna

Foursquare for Android Design

Foursquare for Android split into two components; the API (com.joelapenna.foursquare) and the Android frontend (com.joelapenna.foursquared). The API is based off the foursquare beta API, available at http://groups.google.com/group/foursquare-api/web/api-documentation.

Foursquare API

The foursquare API is documented at http://groups.google.com/group/foursquare-api/web/api-documentation

The API itself is split into several key components based on the separation between document parsing, and http serving. In com.joelapenna.foursquare.http you will find the http client code used to acutally make requests to foursquare.com. com.joelapenna.foursquare.parsers contains xml parsers and com.joelapenna.foursquare.types contains java classes to represent the parsed XML.

HTTP

The foursquare http client is synchronous but supports multithreaded access.

This api supports basic and oauth based authentication and can be enabled or disabled using the Foursquare client's useOAuth constructor parameter.

The client is single-user only in that it is not out of the box able to support http requests from multiple simultaneous users.

The network protocol used to make requests to foursquare.com is HTTP. Requests go to URLs such as http://api.foursquare.com/api/v1/venues with the url query defining passed parameters such as http://api.foursquare.com/api/v1/venues?limit=10.

The foursquare api returns data in XML, examples of which are in /captures/api/v1 and outlined in the canonical api documents.

The ability to debug HTTP operations can be controlled by the FoursquaredSettings constant API_DEBUG.

After an http request is completed, the retrieved XML is passed to a parser. (See #Parsers)

Parsers

The XML returned by the foursquare servers follow a very simple schema, simply speaking that any attribute on a foursquare object is represented by an XML tag with the child being its value.

<username>jlapenna</username>
<badges>
  <badge />
  <badge />
</badges>

There is no common annotation in the returned XML to determine if an object has a list of properties or if it is a list of values in one common attribute (eg, if the foursquare object lists a series of attributes or if it has one attribute with multiple values) aside from explict examination. The xml type samples in captures/types/v1 describe the contents of each element for every supported foursquare type.

AbstractParser

AbstractParser is the base class used to construct any datatype parser. It is based on the XmlPullParser parsing strategy and API.

It is designed to skip elements it does not understand, it will also throw a =FoursquareException= whenever it encounters an <error> stanza.

It is necessary to implement a parser that extends AbstractParser for any xml element that can be encountered during the xml parse. It is expected and likely that a parser will support a "root" xml element and its child values, constructing using other parsers to understand its child attributes.

Types

The foursquare API constructs collections of objects as Groups which simply extend java's List. A Group may contain multiple groups or other FoursquareTypes. A Group also possesses a "type" which describes the contents of the Group.

Each type is autogenerated using a pair of python scripts that parse some example xml files. See #util/generate.py

Foursquare.java

This is the main access point for the foursquare API, abstracting and hiding both the HTTP and XML subcomponents of the framework.

Its usage is pretty clear and can be clearly understood from the method names and associated official documentation.

Foursquared (The Android Client)

The general architecture of the Foursquare Android client is centered around various resource managers and clients stored in the "almost" global Application context. It is global in the sense that any Activity or Service can latch onto the Application context with getApplication, cast it to a Foursquared instance and access the various components and methods available on the Foursquared object. (Note Foursquared not Foursquare. "d" denotes the android side of things).

TaskHandler

The TaskHandler is responsible for doing asynchronous operations in the applicatation that don't have a specific Activity context assocated with it, for example, when updating a users's foursquare city when they move. See #CityLocationListener.

Geolocation

Foursquared depends on two LocationListeners which attach themselves to various android LocationProviders. Each is based on capturing the "best" location where "best" is defined as "mostly accurate and mostly recent."

CityLocationListener

This listener is registered to the LocationManager only when the user is "logged in" to foursquare. It attaches itself to a "COARSE_LOCATION" provider and upon great location change, will attempt to have the application /switchcity to whatever location the user has just moved to.

BestLocationListener

This location listener will register itself with /every/ LocationProvider the LocationManager supports. It can be manually registered and unregistered by application components such as Activitys or Services.

The BestLocationListener supports two access interfaces. It supports an "Observable" interface that will notify on /best/ location updates as well as a getBestKnownLocation method that will return the same information.

The /best/ location is calculated based on update time and accuracy. The listener registeres with GPS, network and possibly other providers. As it recieves updates via the standard LocationManager.requestLocationUpdates, it determines if the update it recieved most recently is (first) actually more recent than its last location update and then if it is more accurate than the previous update. This way it is harder for an out of date GPS location to override a recent-but-less-accurate wifi triangulation or for a very accurate but a slightly old GPS update to be upsurped by a wildly inaccurate but to-the-second network location update.

RemoteResourceManager

Often in the course of constructing a view in the application, we need to request things like images from remote servers. An example: user profile photos. To do this we've implemented an asynchronous, multi-threaded http client that will fetch resources, store them to disk, and provide InputStream and File access to the requested objects.

The API also allows you to register as an Observer to recieve updates /whenever/ a remote resource request is completed.

Lastly, the RemoteResourceManager provides an ability to cleanly shutdown and wipe the cache used in order to reclaim disk space.

Caveats

oAuth is disabled right now in the foursquare UI as I don't think their oAuth "auth_exchange" protocol is reliable and my implementation isn't very good.

Tools

util/oget.py

HTTP client with oAuth support, just create a file like this in ~/.oget:

CONSUMER_KEY
CONSUMER_KEY_SECRET
USERNAME
PASSWORD

It works by authenticating with a consumer key/secret to get a client token, stores that in this file, then retrieves a page.

oget 'http://api.foursquare.com/v1/venues'

This actually stopped working after a backend upgrade. Try using curl -u user:password 'http://...' instead.

util/gen_class.py

Generate the java class for a particular foursquare datatype.

gen_class.py ../captures/types/v1/didyoumean.xml > ../main/src/com/joelapenna/foursquare/types/Didyoumean.java

util/gen_parser.py

Generate the parser for a particular foursquare datatype.

./gen_parser.py ../captures/types/v1/checkin_result.xml > ../main/src/com/joelapenna/foursquare/parsers/CheckinResultParser.java

util/generate.py

Generate the parser and .java files for all examples in captures/types/v1

generate.py

Both util/gen_class.py and util/gen_parser.py use the templates defined in captures/types/v1, these files are annotated 1-dimensional versions of the xml streams returned by the official API. Each script will read the xml and construct an internal representation of what the xml is describing.

Each xml tag in the capture may have a type attribute which is a hint to the generators of the target java type (and parser) that the tag represents. For example:

<?xml version="1.0" ?>
<user>
  <id>9711</id>
  <checkin type="Checkin"></checkin>
  <badges type="Group">
    <badge type="Badge"></badge>
  </badges>
</user>

This shows that the User java object will have two attributes protected by getters and setters. The abstract version of this class would look like:

class User implements FoursquareType {
  abstract public String getId();
  abstract public void setId(String id);
  abstract public Checkin getCheckin();
  abstract public void setCheckin(Checkin checkin);
  abstract public Group<Badge> getBadges();
  abstract public void setBadges(Group<Badge> badges);

As <id> does not list a type, it defaults to a string.

Comment by subraj...@gmail.com, Mar 16, 2010

Do you have any API documentation or examples for using this?

Comment by stembri...@gmail.com, Apr 14, 2010

Hi Joe, what are the possibilities of having an option to automatically check-in locations during a day?

Comment by vandaele...@gmail.com, Apr 21, 2010

I second subrajesh's question. This really needs documentation.

Comment by rfitzger...@gmail.com, Feb 12, 2011

Is there any way to make the app more efficient? I am running Motorola Droid Bluebery Froyo, and it is the only app that lags. Maybe reduce some of the code that is not necessary, if any? Otherwise, I like that you can post pics, and share with other socNet sites.

Comment by sanketpa...@gmail.com, Aug 23, 2011

Please give me any short and simple example of this API.


Sign in to add a comment
Powered by Google Project Hosting