Skip to content

Instantly share code, notes, and snippets.

@gdaniels
Created August 28, 2012 04:39
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gdaniels/3495006 to your computer and use it in GitHub Desktop.
Save gdaniels/3495006 to your computer and use it in GitHub Desktop.
BaaS Android API Comparison

This is a quick comparison of some of the Android flavors of various BaaS APIs. It attempts to simply show the same ideas (library initialization, user authentication, data read/write, etc) with the various APIs, to give the AeroGear team some context as to possible directions.

There is a nice list of providers here (current as of 08/2012):

And also a comparison of StackMob/Kinvey/Parse here:

We should at some point also have a similar survey of backend REST APIs for comparison purposes.


##Open Questions

  1. Data-binding to classes or generic property bags?
  2. How to handle data relations?
  3. How to handle binary data?
  4. Explicit class schemas or schemaless?
  5. How to best handle local caching + sync?
  6. Provide atomic counters? (most of these libraries do)
  7. Manage clients with API keys?

#StackMob

##Summary

###Initialization

final String API_KEY = "YOUR API KEY HERE";
final String API_SECRET = "YOUR API SECRET HERE";
//leave this as a blank string if you don't have a user object.
//if you leave it blank, however, you must not call login, logout or any of the twitter or facebook methods,
//so we highly recommend that you set up a user object
final String USER_OBJ_NAME = "users";
//0 for sandbox, 1 or higher for a deployed API
final Integer API_VERSION = 0;
StackMob stackmob = new StackMob(API_KEY, API_SECRET, USER_OBJ_NAME, API_VERSION);

###Data-bound classes

public class Task extends StackMobModel {
     
    private String name;
    private Date dueDate;
    private int priority = 0;
    private boolean done = false;
     
    public Task(String name) {
        super(Task.class);
        this.name = name;
    }
 
    //Add whatever setters/getters/other functionality you want here
}

Storing an object:

Task blogPostTask = new Task("Write blog post");
blogPostTask.save(); // Takes optional callback argument

Getting a collection of objects:

StackMobModelQuery<Task> tasksQuery = new StackMobModelQuery<Task>(Task.class);
// Can now specify any constraints, i.e. tasksQuery.fieldIsLessThan("priority", "5")
tasksQuery.send(new StackMobQueryCallback<Task>() {
 
    @Override
    public void success(List<Task> tasks) {
        //You now have a list of every Task ever saved
    }
 
    @Override
    public void failure(StackMobException e) {
        //handle failure case
    }
});

###Login/auth

Map<String, String> args = new HashMap<String, String>();
args.put("username", "johndoe");
args.put("password", "mypassword");
StackMobCommon.getStackMobInstance().login(args, new StackMobCallback() {
    @Override public void success(String response) {
        //login succeeded
    }
    @Override public void failure(StackMobException e) {
        //login failed
    }
});

###Register user with Facebook

StackMobCommon.getStackMobInstance().registerWithFacebookToken(fbToken, username, new StackMobCallback() {
    @Override public void success(String response) {
        //registration succeeded
    }
    @Override public void failure(StackMobException e) {
        //registration failed
    }
});

#Kinvey

###Summary

###Initialization

KinveySettings = KinveySettings.loadFromProperties(getApplicationContext());
sharedClient = KCSClient.getInstance(getApplicationContext(), settings);

###Data-bound classes

Kinvey uses inline metadata to define and customize object mappings.

public class MyEntity implements MappedEntity {
    private String uname;
    private String id;
 
    @Override
    public List<MappedField> getMapping() {
        return Arrays.asList(new MappedField[] { new MappedField("uname", "name"), 
                                                new MappedField ("id", "_id") });
    }
 
    // Getters and setters for all fields are required
    public String getUname() { return uname; }
    public void setUname(String n) { uname = n; }
    public String getId() { return id; }
    public void setId(String i) { id = i; }
 
}

Modifying/saving an item:

MyItemMappedEntity item = ...;
 
item.setTitle("Idle Blue");
 
sharedClient.mappeddata("items").save(item, new ScalarCallback<Void>() {
 
  @Override
  public void onFailure(Throwable e) { ... }
 
  @Override
  public void onSuccess(Void r) { ... }
 
});

Getting a collection of items:

sharedClient.mappeddata("items").all(ListEntity.class, new ListCallback<Item>()     {
    @Override
    public void onSuccess(List<Item> result) { ... }
 
    @Override
    public void onFailure(Throwable error) { ... }
 
});

###Generic objects (property bags)

EntityDict album = sharedClient.entity("albums");
album.putProperty("title", "Idle Blue");
album.save(new ScalarCallback<Void>() {
 
    @Override
    public void onFailure(Throwable e) { ... }
 
    @Override
    public void onSuccess(Void r) { ... }
 
});

#Parse

###Summary

###Initialization

Parse.initialize(this, "Your Application Id", "Your Client Key"); 

###Login

ParseUser.logInInBackground("Jerry", "showmethemoney", new LogInCallback() {
  public void done(ParseUser user, ParseException e) {
    if (user != null) {
      // Hooray! The user is logged in.
    } else {
      // Signup failed. Look at the ParseException to see what happened.
    }
  }
});

###Login/Register with Facebook

ParseFacebookUtils.logIn(this, new LogInCallback() {
  @Override
  public void done(ParseUser user, ParseException err) {
    if (user == null) {
      Log.d("MyApp", "Uh oh. The user cancelled the Facebook login.");
    } else if (user.isNew()) {
      Log.d("MyApp", "User signed up and logged in through Facebook!");
    } else {
      Log.d("MyApp", "User logged in through Facebook!");
    }
  }
});

###Creating/updating objects

ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground(); // or saveEventually() for offline!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment