Firebase with Android
-
Upload
fumihiko-shiroyama -
Category
Software
-
view
910 -
download
3
Transcript of Firebase with Android
Firebase with Android
GCPUG TOKYO MARCH 2016
Firebase
Firebase
• Realtime Database
• Authentication & Access Control
• Static Web Site Hosting
Udacity
• Firebase Essential For Android
• https://www.udacity.com/course/firebase-essentials-for-android--ud009
Getting Started
www.firebase.com
dependencies { compile 'com.firebase:firebase-client-android:2.5.2+'}
android { ... packagingOptions { exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE-FIREBASE.txt' exclude 'META-INF/NOTICE' }}
<uses-permission android:name="android.permission.INTERNET" />
Custom Application
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Firebase.setAndroidContext(this); } }
AndroidManifest.xml
<application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
Writing Data
AndroidManifest.xml
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").setValue("hello firebase!");
Activity
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").setValue("hello firebase!");
Reference
Activity
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").setValue("hello firebase!");
Child Node
Activity
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").setValue("hello firebase!");
Writing
Not Limited to Primitive Types
public class BlogPost { private String author; private String title;
public BlogPost() { // empty default constructor
// necessary for Firebase to be able to deserialize blog posts }
public String getAuthor() { return author;
}
public String getTitle() { return title; }}
Understating Data Structure
NoSQL JSON Tree{ "users": { "mchen": { "friends": { "brinchen": true }, "name": "Mary Chen", // our child node appears in the existing JSON tree "widgets": { "one": true, "three": true } }, "brinchen": { ... }, "hmadi": { ... } }}
NoSQL JSON Tree{ "users": { "mchen": { "friends": { "brinchen": true }, "name": "Mary Chen", // our child node appears in the existing JSON tree "widgets": { "one": true, "three": true } }, "brinchen": { ... }, "hmadi": { ... } }}
NoSQL JSON Tree{ "users": { "mchen": { "friends": { "brinchen": true }, "name": "Mary Chen", // our child node appears in the existing JSON tree "widgets": { "one": true, "three": true } }, "brinchen": { ... }, "hmadi": { ... } }}
/users/mchen/widgets
NoSQL JSON Tree{ "users": { "mchen": { "friends": { "brinchen": true }, "name": "Mary Chen", // our child node appears in the existing JSON tree "widgets": { "one": true, "three": true } }, "brinchen": { ... }, "hmadi": { ... } }}
/users/mchen/widgets
Unique Identifier
Valid Types
• String
• Boolean
• Long
• Double
• Map<String, Object>
• List<Object>
Retrieving Data
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText( MainActivity.this, dataSnapshot.getValue(String.class), Toast.LENGTH_SHORT ).show(); } @Override public void onCancelled(FirebaseError firebaseError) { }});
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText( MainActivity.this, dataSnapshot.getValue(String.class), Toast.LENGTH_SHORT ).show(); } @Override public void onCancelled(FirebaseError firebaseError) { }});
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText( MainActivity.this, dataSnapshot.getValue(String.class), Toast.LENGTH_SHORT ).show(); } @Override public void onCancelled(FirebaseError firebaseError) { }});
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText( MainActivity.this, dataSnapshot.getValue(String.class), Toast.LENGTH_SHORT ).show(); } @Override public void onCancelled(FirebaseError firebaseError) { }});
Firebase firebaseRef = new Firebase("https://shiroyama-app-01.firebaseio.com/"); firebaseRef.child("message").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Toast.makeText( MainActivity.this, dataSnapshot.getValue(String.class), Toast.LENGTH_SHORT ).show(); } @Override public void onCancelled(FirebaseError firebaseError) { }});
Read Event Types
• Value
• Child Added
• Child Changed
• Child Removed
• Child Moved
Value Event
• ValueEventListener#onDataChange
• Retrieve whole data at once
• Called once at initial time, then every time data changes.
// Get a reference to our postsFirebase ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");// Attach an listener to read the data at our posts referenceref.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { System.out.println("There are " + snapshot.getChildrenCount() + " blog posts"); for (DataSnapshot postSnapshot: snapshot.getChildren()) { BlogPost post = postSnapshot.getValue(BlogPost.class); System.out.println(post.getAuthor() + " - " + post.getTitle()); } } @Override public void onCancelled(FirebaseError firebaseError) { System.out.println("The read failed: " + firebaseError.getMessage()); }});
// Get a reference to our postsFirebase ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");// Attach an listener to read the data at our posts referenceref.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { System.out.println("There are " + snapshot.getChildrenCount() + " blog posts"); for (DataSnapshot postSnapshot: snapshot.getChildren()) { BlogPost post = postSnapshot.getValue(BlogPost.class); System.out.println(post.getAuthor() + " - " + post.getTitle()); } } @Override public void onCancelled(FirebaseError firebaseError) { System.out.println("The read failed: " + firebaseError.getMessage()); }});
// Get a reference to our postsFirebase ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");// Attach an listener to read the data at our posts referenceref.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { System.out.println("There are " + snapshot.getChildrenCount() + " blog posts"); for (DataSnapshot postSnapshot: snapshot.getChildren()) { BlogPost post = postSnapshot.getValue(BlogPost.class); System.out.println(post.getAuthor() + " - " + post.getTitle()); } } @Override public void onCancelled(FirebaseError firebaseError) { System.out.println("The read failed: " + firebaseError.getMessage()); }});
Child Added Event
• ChildEventListener#onChildAdded
• Once for each existing child initially
• Every time new data is added
// Get a reference to our postsFirebase ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");
ref.addChildEventListener(new ChildEventListener() { // Retrieve new posts as they are added to the database @Override public void onChildAdded(DataSnapshot snapshot, String previousChildKey) { BlogPost newPost = snapshot.getValue(BlogPost.class); System.out.println("Author: " + newPost.getAuthor()); System.out.println("Title: " + newPost.getTitle()); }
//... ChildEventListener also defines onChildChanged, onChildRemoved, // onChildMoved and onCanceled, covered in later sections.});
Child Changed Event
• ChildEventListener#onChildChanged
• Anytime a child is changed including its descendants
@Overridepublic void onChildChanged(DataSnapshot snapshot, String previousChildKey) { String title = (String) snapshot.child("title").getValue(); System.out.println("The updated post title is " + title);}
Child Removed Event
• ChildEventListener#onChildRemoved
• Anytime a child is removed
@Overridepublic void onChildRemoved(DataSnapshot snapshot) { String title = (String) snapshot.child("title").getValue(); System.out.println("The blog post titled " + title + " has been deleted");}
Child Moved Event
• ChildEventListener#onChildMoved
• Anytime a child is moved
@Overridepublic void onChildMoved(DataSnapshot snapshot, String previousChildKey) { String title = (String) snapshot.child("title").getValue(); System.out.println("The updated post title is " + title);}
Detaching Callbacks
• ref.removeEventListener(originalListener);
• all listeners must be removed explicitly
• removing parent listener will NOT remove child's listeners
Reading Data Once
ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // do some stuff once } @Override public void onCancelled(FirebaseError firebaseError) { }});
ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // do some stuff once } @Override public void onCancelled(FirebaseError firebaseError) { }});
Querying Data
{ "lambeosaurus": { "height" : 2.1, "length" : 12.5, "weight": 5000 }, "stegosaurus": { "height" : 4, "length" : 9, "weight" : 2500 }}
public class DinosaurFacts { long height; double length; long weight;
public DinosaurFacts() { // empty default constructor // necessary for Firebase to be able to deserialize blog posts }
public long getHeight() { return height; }
public double getLength() { return length; }
public long getWeight() { return weight; }}
• orderByChild()
• orderByKey()
• orderByValue()
• orderByPriority()
orderByChild
Query queryRef = ref.orderByChild("height");orQuery queryRef = ref.orderByChild("dimensions/height");
orderByKey
Query queryRef = ref.orderByKey();
{ "lambeosaurus": { "height" : 2.1, "length" : 12.5, "weight": 5000 }, "stegosaurus": { "height" : 4, "length" : 9, "weight" : 2500 }}
orderByValue
Query queryRef = ref.orderByValue();
{ "scores": { "bruhathkayosaurus" : 55, "lambeosaurus" : 21, "linhenykus" : 80, "pterodactyl" : 93, "stegosaurus" : 5, "triceratops" : 22 }}
orderByPriority
Query queryRef = ref.orderByPriority();
orderByPriority
Query queryRef = ref.orderByPriority();
arbitrary priority you set
• limitToFirst()
• limitToLast()
• startAt()
• endAt()
• equalTo()
Query queryRef = ref.orderByChild("height").limitToFirst(2);Query queryRef = scoresRef.orderByValue().limitToLast(3);Query queryRef = ref.orderByChild("height").startAt(3);Query queryRef = ref.orderByKey().endAt("pterodactyl");Query queryRef = ref.orderByChild("height").equalTo(25);
Security
{ "rules": { "users": { "$user_id": { ".write": "$user_id === auth.uid" } } }}
{ "rules": { "users": { "$user_id": { ".write": "$user_id === auth.uid" } } }}
{ "rules": { "users": { "$user_id": { ".write": "$user_id === auth.uid" } } }} talks about this later
Authentication
Custom
• helper libraries to integrate with your own authentications
• https://www.firebase.com/docs/android/guide/login/custom.html#section-rest-token-helper-libraries
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");ref.authWithCustomToken(AUTH_TOKEN, new Firebase.AuthResultHandler() { @Override public void onAuthenticationError(FirebaseError error) { System.err.println("Login Failed! " + error.getMessage()); }
@Override public void onAuthenticated(AuthData authData) { System.out.println("Login Succeeded!"); }});
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");ref.authWithCustomToken(AUTH_TOKEN, new Firebase.AuthResultHandler() { @Override public void onAuthenticationError(FirebaseError error) { System.err.println("Login Failed! " + error.getMessage()); }
@Override public void onAuthenticated(AuthData authData) { System.out.println("Login Succeeded!"); }});
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");ref.authWithCustomToken(AUTH_TOKEN, new Firebase.AuthResultHandler() { @Override public void onAuthenticationError(FirebaseError error) { System.err.println("Login Failed! " + error.getMessage()); }
@Override public void onAuthenticated(AuthData authData) { System.out.println("Login Succeeded!"); }});
given from your server
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");ref.authWithCustomToken(AUTH_TOKEN, new Firebase.AuthResultHandler() { @Override public void onAuthenticationError(FirebaseError error) { System.err.println("Login Failed! " + error.getMessage()); }
@Override public void onAuthenticated(AuthData authData) { System.out.println("Login Succeeded!"); }});
• javadoc
• https://www.firebase.com/docs/java-api/javadoc/com/firebase/client/AuthData.html
• AuthData#getUid()
Unique Guaranteed
Tips
• SwipeRefresh should be used with ValueEvent(once)
Limitations
• No File Uploading APIs
• Server side batching
• Server side scheduling
• Server side event hook
Q & A
Samples
• Chat
• https://github.com/firebase/AndroidChat
• Drawing
• https://github.com/firebase/AndroidDrawing
THX!