SlideShare a Scribd company logo
S
Parse
Tushar Acharya
MUTUAL MOBILE
Why Parse?
Mobile apps are
HARD
HELL
YEAH!
Typical Mobile App
Database REST APIs Server
+ Users
+ Security
Networking Caching The Fun Stuff!
no
no
no
no
no
What is Parse
S Complete back-end for applications
S Store key/value data (think NoSQL)
S Store Files
S Compact APIs for numerous platforms
S Mobile - Android, iOS, Unity
S Web - Javascript, PHP
S Desktop - Mac OS X, .Net + Xamarin
S IoT - Arduino, Embedded C
What’s in it for me?
S User Management
S Blocking and Async API calls
S Local Datastore, Query Caching
S Location “Stuff”
S Push Notfication, Analytics, Cloud Code, lot more!
S Its FREE!!
Parse Object
S Contains key-value pairs of JSON-compatible data.
S Schema-less – need not specify what keys exist, ahead of
time
S Each ParseObject has a class name, ~ Table Name in
RDBMS
S Ex:{task: “parse presentation”, date: “07/08/15”, done: false}
S Each object has default fields – objectId, createdAt,
updatedAt and ACL.

Object Model
ToDoItem.java
@ParseClassName("ToDoItem")
public class ToDoItem extends ParseObject {
public static final String COLUMN_TASK = "task";
public String getTask() {
return getString(COLUMN_TASK);
}
public void setTask(String name) {
put(COLUMN_TASK, name);
}
…
}
Creating an object
ToDoItem item = new ToDoItem();
item.setTask(name);
item.setDate(new Date(2015,7, 17));
item.setDone(false);
item.setPosition(1);
item.saveInBackground();
S Save synchronously or asynchronously.
S Defaults fields are created/updated automatically on save.

Retrieving Objects
ToDoItem.java
public static ParseQuery<ToDoItem> getQuery() {
return ParseQuery.getQuery(ToDoItem.class);
}
Usage
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.orderByDescending("createdAt");
query.findInBackground();
Supported Data Types
S Int
S Double
S String
S Java.util.Date
S Bytes
S Boolean
S Arrays
Local Datastore
ToDoItem item = new ToDoItem();
item.setTask(name);
item.setDate(new Date(2015,7, 17));
item.setDone(false);
item.setPosition(1);
item.pinInBackground();
S Recursively saves everything in the object
S Can be fetched in a query along with various filters.
query.fromLocalDatastore();
User Management
S Sign Up
S Log In
S Email verification
S Forgot Password
S Facebook/Twitter Login
S Anonymous Login
User Signup - Email
ParseUser user = ParseUser.create(ParseUser.class);
user.setUserName(“willywonka);
user.setPassword(“ilovechocolates);
user.setEmail(“willywonka@chocolatefactory.com”);
user.signUpInBackground(callback);
S Add custom params using user.put(“phoneNumber”, 123);
S Unique email and userName should be unique
S Password stored as hashes using bcrypt
S Setup email verification parameters in Parse Settings.
User Login
S Use userName and password for login
ParseUser.logInInBackground(”willywonka", "ilovechocolates", 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
}
}
});
S After login, ParseUser.getCurrentUser() is set to the logged in user.
S User can logout using ParseUser.logOut()
Facebook Login
S Setup and configure Facebook app and store the app id.
S Add Facebook app id to AndroidManifest.xml
S Launch ParseLoginActivity and handle onActivityResult in
the calling activity.
S Handle success/error response accordingly.
S Done!
Twitter Login
S Setup and configure Twitter app and store consumer key and
secret key.
S Add to Parse application’s settings page.
S Login from device using below code -
ParseTwitterUtils.logIn(this, new LogInCallback() {
@Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
//User cancelled the Twitter login.
} else if (user.isNew()) {
//User signed up and logged in via Twitter!
} else {
//User logged in via Twitter!
}
}
});
Anonymous Login
S When we want to associate data with a user without
signup.
S Can link later with Facebook, Twitter or existing user.
ParseAnonymousUtils.logIn(new LogInCallback() {
@Override
public void done(ParseUser user, ParseException e) {
if (e != null) {
//Anonymous login failed
} else {
//Anonymous user logged in
}
}
});
Queries
S Parse provides lot of query constraints to allow near RDB granularity –
S whereEqualTo, whereNotEqualTo
S whereGreaterThan, whereLessThan
S setLimit, setSkip
S orderByAscending, orderByDescending
S whereContainedIn, whereNotContainedIn
S whereExists, whereDoesNotExist
S whereStartsWith … and many more
Queries
S whereEqualTo
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereEqualTo(”done", true);
query.selectKeys(Arrays.asList(“task”, “date”));
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ���ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Queries
S whereGreaterThan
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereGreaterThan(”date", new Date(2015,8,29));
query.whereLessThan(”date", new Date(2015,9,9));
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ”ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Queries
S setLimit, setSkip
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereEqualTo(”done", true);
query.setLimit(10);
query.setSkip(10*page);
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ”ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Queries
S orderByDescending
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.orderByDescending(”updatedAt”); // Latest First
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ”ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Queries
S whereContainedIn
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereContainedIn(”date", [new Date(2015,8,29),
new Date(2015,8,30), new Date(2015,8,31)]);
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ”ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Queries
S whereDoesNotExist
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereDoesNotExists(”done”);// 
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ”ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Queries
S whereStartsWith
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereStartsWith(”task", “Home”);
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
Log.d(”Query", ”ToDos = " + toDos.size());
} else {
Log.d(”Query", "Error: " + e.getMessage());
}
}
});
Query Caching
S Save result of a query for later use.
S Give name to the query and pin them.
ParseQuery<ToDoItem> query = ToDoItem.getQuery();
query.whereGreaterThanOrEqualTo(”date", new Date(2015,8,1));
query.whereLessThan(”date", new Date(2015,9,1));
query.findInBackground(new FindCallback<ToDoItem>() {
public void done(List<ToDoItem> toDos, ParseException e) {
if (e == null) {
ParseObject.pinAllInBackground(“TODO_AUG”, toDos);
}
}
});
S Fetch by querying local data store with “TODO_AUG” as pin
Query Caching
S If we aren't using local datastore, we can use the per-query
cache for ParseQuery.
query.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ELSE_CACHE);
query.findInBackground(callback);
S Parse provides several different cache policies –
S IGNORE_CACHE
S CACHE_ONLY, NETWORK_ONLY
S CACHE_ELSE_NETWORK NETWORK_ELSE_CACHE
S CACHE_THEN_NETWORK
Security
S Parse implements framework level security by default.
S Developer has to implement class level & object level
security.
S Parse Security Dashboard allows us to –
S Restrict class creation from client.
S Restrict addition of fields from client.
S Restrict querying of data from client.
Security
Security
Security - ACLs
S For every object, we can specify which users are allowed
to read the object, and which users are allowed to modify
it.
S ACL is an object which stores these security parameters
and is attached to a ParseObject. 
ToDoItem todo = new ToDoItem();
todo.setTask(”Get groceries!");
todo.setACL(new ParseACL(ParseUser.getCurrentUser()));
todo.saveInBackground();
Security - ACLs
S Permissions can also be granted on a per-user basis
ToDoItem todo = new ToDoItem();
ParseACL groupACL = new ParseACL();
for (ParseUser user : userList) {
groupACL.setReadAccess(user, true);
groupACL.setWriteAccess(user, true);
}
groupMessage.setACL(groupACL);
groupMessage.saveInBackground();
Security - ACLs
S Permissions can also be granted to all users at once.
ParseObject publicPost = new ParseObject("Post");
ParseACL postACL = new ParseACL(ParseUser.getCurrentUser());
postACL.setPublicReadAccess(true);
publicPost.setACL(postACL);
publicPost.saveInBackground();
S Useful in scenario where only author can edit and
everyone else should be able to read – like a message
board.
Security - ACLs
S Default ACL can be set for all objects created on a
particular android client.
ParseACL defaultACL = new ParseACL();
defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);

Automatically adds current user to ACL
Files
S ParseFile stores application files in the cloud that are too
large to fit in a regular ParseObject.
S Allows images, documents, videos, music, and any other
binary data.
S Each file has max size limitation of 10 MB.
Static Files
S Static files can directly be uploaded into Parse Cloud.
S Configure Parse app with sub-domain in settings.
S Access those files at url -
https://<app-name>.parseapp.com/<file_name>
S Limitations – 500 MB or 500 files, whichever hits first
Dynamic Files
S Any byte data can be saved in ParseFile.
byte[] data = ”I am AWESOME!".getBytes();
ParseFile file = new ParseFile("resume.txt", data);
file.saveInBackground();
S Filename extension is mandatory as it determines what
type of file it is.
S Each uploaded file gets unique identifier so no collisions.
Dynamic Files
S Any saved ParseFile can be added to a ParseObject
ParseObject jobApplication = new ParseObject("JobApplication");
jobApplication.put("applicantName", "Joe Smith");
jobApplication.put("applicantResumeFile", file);
jobApplication.saveInBackground();
S The ParseFile can be fetched using syntax –
ParseFile resume = (ParseFile) jobApplication.get("applicantResumeFile");
Q & A
What’s next?
S Cloud Code
S Basic Operations
S Queries
S CommonJS Modules
S JavaScript Promises  Amazing Paradigm
S Background Jobs
S Bolts on Android

More Related Content

Intro to Parse

  • 3. HELL YEAH! Typical Mobile App Database REST APIs Server + Users + Security Networking Caching The Fun Stuff! no no no no no
  • 4. What is Parse S Complete back-end for applications S Store key/value data (think NoSQL) S Store Files S Compact APIs for numerous platforms S Mobile - Android, iOS, Unity S Web - Javascript, PHP S Desktop - Mac OS X, .Net + Xamarin S IoT - Arduino, Embedded C
  • 5. What’s in it for me? S User Management S Blocking and Async API calls S Local Datastore, Query Caching S Location “Stuff” S Push Notfication, Analytics, Cloud Code, lot more! S Its FREE!!
  • 6. Parse Object S Contains key-value pairs of JSON-compatible data. S Schema-less – need not specify what keys exist, ahead of time S Each ParseObject has a class name, ~ Table Name in RDBMS S Ex:{task: “parse presentation”, date: “07/08/15”, done: false} S Each object has default fields – objectId, createdAt, updatedAt and ACL. 
  • 7. Object Model ToDoItem.java @ParseClassName("ToDoItem") public class ToDoItem extends ParseObject { public static final String COLUMN_TASK = "task"; public String getTask() { return getString(COLUMN_TASK); } public void setTask(String name) { put(COLUMN_TASK, name); } … }
  • 8. Creating an object ToDoItem item = new ToDoItem(); item.setTask(name); item.setDate(new Date(2015,7, 17)); item.setDone(false); item.setPosition(1); item.saveInBackground(); S Save synchronously or asynchronously. S Defaults fields are created/updated automatically on save. 
  • 9. Retrieving Objects ToDoItem.java public static ParseQuery<ToDoItem> getQuery() { return ParseQuery.getQuery(ToDoItem.class); } Usage ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.orderByDescending("createdAt"); query.findInBackground();
  • 10. Supported Data Types S Int S Double S String S Java.util.Date S Bytes S Boolean S Arrays
  • 11. Local Datastore ToDoItem item = new ToDoItem(); item.setTask(name); item.setDate(new Date(2015,7, 17)); item.setDone(false); item.setPosition(1); item.pinInBackground(); S Recursively saves everything in the object S Can be fetched in a query along with various filters. query.fromLocalDatastore();
  • 12. User Management S Sign Up S Log In S Email verification S Forgot Password S Facebook/Twitter Login S Anonymous Login
  • 13. User Signup - Email ParseUser user = ParseUser.create(ParseUser.class); user.setUserName(“willywonka); user.setPassword(“ilovechocolates); user.setEmail(“willywonka@chocolatefactory.com”); user.signUpInBackground(callback); S Add custom params using user.put(“phoneNumber”, 123); S Unique email and userName should be unique S Password stored as hashes using bcrypt S Setup email verification parameters in Parse Settings.
  • 14. User Login S Use userName and password for login ParseUser.logInInBackground(”willywonka", "ilovechocolates", 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 } } }); S After login, ParseUser.getCurrentUser() is set to the logged in user. S User can logout using ParseUser.logOut()
  • 15. Facebook Login S Setup and configure Facebook app and store the app id. S Add Facebook app id to AndroidManifest.xml S Launch ParseLoginActivity and handle onActivityResult in the calling activity. S Handle success/error response accordingly. S Done!
  • 16. Twitter Login S Setup and configure Twitter app and store consumer key and secret key. S Add to Parse application’s settings page. S Login from device using below code - ParseTwitterUtils.logIn(this, new LogInCallback() { @Override public void done(ParseUser user, ParseException err) { if (user == null) { //User cancelled the Twitter login. } else if (user.isNew()) { //User signed up and logged in via Twitter! } else { //User logged in via Twitter! } } });
  • 17. Anonymous Login S When we want to associate data with a user without signup. S Can link later with Facebook, Twitter or existing user. ParseAnonymousUtils.logIn(new LogInCallback() { @Override public void done(ParseUser user, ParseException e) { if (e != null) { //Anonymous login failed } else { //Anonymous user logged in } } });
  • 18. Queries S Parse provides lot of query constraints to allow near RDB granularity – S whereEqualTo, whereNotEqualTo S whereGreaterThan, whereLessThan S setLimit, setSkip S orderByAscending, orderByDescending S whereContainedIn, whereNotContainedIn S whereExists, whereDoesNotExist S whereStartsWith … and many more
  • 19. Queries S whereEqualTo ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereEqualTo(”done", true); query.selectKeys(Arrays.asList(“task”, “date”)); query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 20. Queries S whereGreaterThan ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereGreaterThan(”date", new Date(2015,8,29)); query.whereLessThan(”date", new Date(2015,9,9)); query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 21. Queries S setLimit, setSkip ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereEqualTo(”done", true); query.setLimit(10); query.setSkip(10*page); query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 22. Queries S orderByDescending ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.orderByDescending(”updatedAt”); // Latest First query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 23. Queries S whereContainedIn ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereContainedIn(”date", [new Date(2015,8,29), new Date(2015,8,30), new Date(2015,8,31)]); query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 24. Queries S whereDoesNotExist ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereDoesNotExists(”done”);//  query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 25. Queries S whereStartsWith ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereStartsWith(”task", “Home”); query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { Log.d(”Query", ”ToDos = " + toDos.size()); } else { Log.d(”Query", "Error: " + e.getMessage()); } } });
  • 26. Query Caching S Save result of a query for later use. S Give name to the query and pin them. ParseQuery<ToDoItem> query = ToDoItem.getQuery(); query.whereGreaterThanOrEqualTo(”date", new Date(2015,8,1)); query.whereLessThan(”date", new Date(2015,9,1)); query.findInBackground(new FindCallback<ToDoItem>() { public void done(List<ToDoItem> toDos, ParseException e) { if (e == null) { ParseObject.pinAllInBackground(“TODO_AUG”, toDos); } } }); S Fetch by querying local data store with “TODO_AUG” as pin
  • 27. Query Caching S If we aren't using local datastore, we can use the per-query cache for ParseQuery. query.setCachePolicy(ParseQuery.CachePolicy.NETWORK_ELSE_CACHE); query.findInBackground(callback); S Parse provides several different cache policies – S IGNORE_CACHE S CACHE_ONLY, NETWORK_ONLY S CACHE_ELSE_NETWORK NETWORK_ELSE_CACHE S CACHE_THEN_NETWORK
  • 28. Security S Parse implements framework level security by default. S Developer has to implement class level & object level security. S Parse Security Dashboard allows us to – S Restrict class creation from client. S Restrict addition of fields from client. S Restrict querying of data from client.
  • 31. Security - ACLs S For every object, we can specify which users are allowed to read the object, and which users are allowed to modify it. S ACL is an object which stores these security parameters and is attached to a ParseObject.  ToDoItem todo = new ToDoItem(); todo.setTask(”Get groceries!"); todo.setACL(new ParseACL(ParseUser.getCurrentUser())); todo.saveInBackground();
  • 32. Security - ACLs S Permissions can also be granted on a per-user basis ToDoItem todo = new ToDoItem(); ParseACL groupACL = new ParseACL(); for (ParseUser user : userList) { groupACL.setReadAccess(user, true); groupACL.setWriteAccess(user, true); } groupMessage.setACL(groupACL); groupMessage.saveInBackground();
  • 33. Security - ACLs S Permissions can also be granted to all users at once. ParseObject publicPost = new ParseObject("Post"); ParseACL postACL = new ParseACL(ParseUser.getCurrentUser()); postACL.setPublicReadAccess(true); publicPost.setACL(postACL); publicPost.saveInBackground(); S Useful in scenario where only author can edit and everyone else should be able to read – like a message board.
  • 34. Security - ACLs S Default ACL can be set for all objects created on a particular android client. ParseACL defaultACL = new ParseACL(); defaultACL.setPublicReadAccess(true); ParseACL.setDefaultACL(defaultACL, true);  Automatically adds current user to ACL
  • 35. Files S ParseFile stores application files in the cloud that are too large to fit in a regular ParseObject. S Allows images, documents, videos, music, and any other binary data. S Each file has max size limitation of 10 MB.
  • 36. Static Files S Static files can directly be uploaded into Parse Cloud. S Configure Parse app with sub-domain in settings. S Access those files at url - https://<app-name>.parseapp.com/<file_name> S Limitations – 500 MB or 500 files, whichever hits first
  • 37. Dynamic Files S Any byte data can be saved in ParseFile. byte[] data = ”I am AWESOME!".getBytes(); ParseFile file = new ParseFile("resume.txt", data); file.saveInBackground(); S Filename extension is mandatory as it determines what type of file it is. S Each uploaded file gets unique identifier so no collisions.
  • 38. Dynamic Files S Any saved ParseFile can be added to a ParseObject ParseObject jobApplication = new ParseObject("JobApplication"); jobApplication.put("applicantName", "Joe Smith"); jobApplication.put("applicantResumeFile", file); jobApplication.saveInBackground(); S The ParseFile can be fetched using syntax – ParseFile resume = (ParseFile) jobApplication.get("applicantResumeFile");
  • 39. Q & A
  • 40. What’s next? S Cloud Code S Basic Operations S Queries S CommonJS Modules S JavaScript Promises  Amazing Paradigm S Background Jobs S Bolts on Android

Editor's Notes

  1. 3rd Party Login Data and UI Flow Email Verif Forgot Password
  2. Direct sign in if app installed else webview