Firebase with Android

Post on 07-Jan-2017

905 views 3 download

transcript

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!