How to Read Data From Firebase Database
Firebase for Android: Database tutorial Android 17.03.2017
Introduction
With Firebase, y'all tin store and sync information to a NoSQL cloud database. The data is stored every bit JSON, synced to all connected clients in realtime, and available when your app goes offline. It offers APIs that enable y'all to authenticate users with email and password, Facebook, Twitter, GitHub, Google, bearding auth, or to integrate with existing hallmark arrangement. Other than the Realtime Database and Authentication, information technology offers a myriad of other services including Cloud Messaging, Storage, Hosting, Remote Config, Examination Lab, Crash Reporting, Notification, App Indexing, Dynamic Links, Invites, AdWords, AdMob.
In this tutorial, you'll create a uncomplicated ToDo app that will show how to save and retrieve data from Firebase, how to authenticate users, set read/write permissions on the information and validate the information on the server.
Suppose we take to store an Item to our reference then nosotros will create a model class every bit below.
public course Item { individual String championship; public Item() {} public Item(String title) { this.championship = title; } public String getTitle() { return title; } public void setTitle(String title) { this.title = championship; } }
Firebase stores data in JSON format. In our database, each user will take an array of to-do items named items
. Each particular
will have a title
.
Let'due south look at basic operations. First we need to get the Firebase Database Reference. You can use DatabaseReference
to become the reference.
private DatabaseReference db; db = FirebaseDatabase.getInstance().getReference("path");
The information is stored in the JSON Tree grade so yous need to get the reference of an specified path.
Nosotros can practice write operations by setValue()
method. It will take a model java class object that will hold all the variables to be stored in the reference. The same method will exist used to update the values at it overwrites the data of the specified reference.
Now to save the Item we will use setValue()
method.
Detail item = new Item(title); db.child(id).setValue(detail);
To go a unique id use push().getKey()
method
String id = db.push().getKey();
Use following snippet for update the Detail
// getting the specified detail reference DatabaseReference db = FirebaseDatabase.getInstance().getReference().kid(id); // updating detail Particular item = new Item(championship); db.setValue(item);
Firebase utilizes listeners to watch for changes in a specified node (read the Detail). It is similar to an event handler in the sense that a code is triggered based on a certain circumstance. In our case, whenever changes in that node's information occur, the listener automatically provides the awarding updated information, called a snapshot. The application tin can then use information from the snapshot to update the UI.
There are several types of listeners for Firebase, and each listener type has a different kind of callback that is triggered when the listener is activated. There are two types of listeners: ValueEventListener
and ChildEventListener
.
A ValueEventListener
listens for data changes to a specific location in your database - i.due east a node. ValueEventListener
has 1 event callback method, onDataChange()
to read a static snapshot of the contents at a given path, equally they existed at the fourth dimension of the consequence. This method is triggered once when the listener is fastened and again every time the information, including children, changes. The upshot callback is passed a snapshot containing all data at that location, including child information. If there is no data, the snapshot returned is zilch
. If the Effect can not exist completed, a second callback method, onCancelled()
is called.
A ChildEventListener
listens for changes to the children of a specific database reference, for instance the root node of a database. It has the post-obit callback methods:
-
onCancelled(DatabaseError mistake)
. This method will exist triggered in the event that this listener either failed at the server, or is removed as a result of the security and Firebase rules. -
onChildAdded(DataSnapshot snapshot, String previousChildName)
. This method will be triggered when a new child is added to the location to which this listener was added. -
onChildChanged(DataSnapshot snapshot, Cord previousChildName)
. This method volition be triggered when the information at a child location has changed. -
onChildMoved(DataSnapshot snapshot, String previousChildName)
. This method will be triggered when a child location'south priority changes. -
onChildRemoved(DataSnapshot snapshot)
. This method will be triggered when a child is removed from the location to which this listener was added.
For read operation we volition attache a ValueEventListener
to the reference.
db.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Item particular = dataSnapshot.getValue(Particular.class); System.out.println(item); } @Override public void onCancelled(DatabaseError databaseError) { Arrangement.out.println("The read failed: " + databaseError.getCode()); } });
Whenever you will change something in the database the method onDataChange()
will be executed. Information technology contains all the information within the specified path in the reference. We can use the DataSnapshot
object to read all the data within the reference. If some fault occurres onCancelled()
method volition be called. onDataChange()
method will also called once after the app launch and hence yous can read the data at starting also.
To query the Item we can apply Query class. Listeners are fastened, and they will be triggered when the corresponding data changes. Instances of Query
are obtained by calling startAt()
, endAt()
, or limit()
on a DatabaseReference
.
private void findItem(String championship) { Query query = db.orderByChild("title").equalTo(title); query.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, Cord s) { // do something } @Override public void onChildChanged(DataSnapshot dataSnapshot, String southward) {} @Override public void onChildRemoved(DataSnapshot dataSnapshot) {} @Override public void onChildMoved(DataSnapshot dataSnapshot, Cord south) {} @Override public void onCancelled(DatabaseError databaseError) { Log.d(TAG, "Item not establish: this item is not in the list"); } }); }
To delete the Item nosotros tin can employ removeValue()
method. More nearly Crud operation you tin can read here.
To go started, create a new projection named ToDo. Fix Minimum SDK as API 15 in the side by side window and select Empty Action in the next. Click Finish on the last window, leaving the settings at their default.
To configure the project to employ the Firebase platform, open the Firebase Assistant window by clicking on Tools > Firebase. Now from the assistant go to Hallmark and click E-mail and password aithentication. Next, press the Connect to Firebase button and brand sure that the Create new Firebase projection option is selected. Finaly, click Add Firebase Authentication.
Echo the aforementioned steps for Realtime Database.
Now yous have connected Firebase platform with Authentication and Realtime Database. As well yous can manage your Firebase data from Firebase console.
Instance of Hallmark and Realtime database
Create an empty activity by selecting the File -> New -> Action -> Empty Activity menu particular and name it LogInActivity
. Create some other and proper name it SignUpActivity
.
Change the contents of the activity_log_in.xml layout file to:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="me.proft.todofirebase.LogInActivity"> <EditText android:id="@+id/etEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:ems="ten" android:inputType="textEmailAddress" android:hint="@string/email_hint" > <requestFocus /> </EditText> <EditText android:id="@+id/etPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/etEmail" android:layout_below="@+id/etEmail" android:ems="10" android:hint="@string/password_hint" android:inputType="textPassword" /> <Button android:id="@+id/btnLogin" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/etPassword" android:layout_below="@+id/etPassword" android:text="@string/login_button_label" /> <TextView android:id="@+id/tvSignUp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/btnLogin" android:layout_centerHorizontal="truthful" android:layout_marginTop="69dp" android:text="@string/sign_up_text" /> </RelativeLayout>
Change the contents of the activity_sign_up.xml layout file to:
<?xml version="i.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="me.proft.todofirebase.SignUpActivity"> <EditText android:id="@+id/etEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:ems="10" android:inputType="textEmailAddress" android:hint="@cord/email_hint" > <requestFocus /> </EditText> <EditText android:id="@+id/etPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/etEmail" android:layout_below="@+id/etEmail" android:ems="10" android:inputType="textPassword" android:hint="@string/password_hint" /> <Button android:id="@+id/btnSignup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/etPassword" android:layout_below="@+id/etPassword" android:text="@string/sign_up_button_label" /> </RelativeLayout>
These layouts are for the Login and SignUp views.
Add the post-obit to values/strings.xml.
<string name="password_hint">Countersign</string> <string proper name="email_hint">Electronic mail</string> <string proper noun="sign_up_button_label">Sign Upward</string> <string name="signup_error_message">Delight make sure y'all enter an email address and password!</string> <cord proper noun="signup_error_title">Error!</cord> <cord proper name="signup_success">Account successfully created! Y'all tin now Login.</cord> <cord name="login_error_message">Please make certain y'all enter an email address and password!</cord> <cord name="login_error_title">Mistake!</cord> <string proper name="login_button_label">Login</string> <string proper noun="sign_up_text">Sign Upward!</cord> <string name="title_activity_login">Sign in</string> <string name="add_item">Add New Item</cord> <string name="action_logout">Logout</string>
The app will brandish the ToDo items in a list view that volition occupy most of the screen. At the bottom of the screen, will exist an edit text field and a push to add items to the list. And then, change activity_main.xml to the below:
<?xml version="1.0" encoding="utf-viii"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-machine" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ListView android:id="@+id/lvItems" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="ane"> </ListView> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="bottom"> <EditText android:id="@+id/etTitle" android:layout_width="match_parent" android:layout_height="wrap_content"/> <Push android:id="@+id/btnAdd" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/add_item"/> </LinearLayout> </LinearLayout>
Before retrieving and saving data from the Firebase server, you need to set up authentication and add together rules that restrict access to information and validate user input before it'south saved.
The Firebase API has built-in methods for email/password, Facebook, Twitter, GitHub, Google and anonymous authentication. We will employ email and password hallmark.
Caput over to the Firebase console and open your project's Dashboard by clicking on the project. If y'all select Database from the left panel, you volition be able to come across projection's data that is in JSON format.
Firebase stores all database information as JSON objects. There are no tables or records. When you lot add data to the JSON tree, it becomes a fundamental in the existing JSON structure.
At the moment y'all can only come across the root node.
From the left console, click on Authentication and so select the Sign In Method tab on the right. Enable Electronic mail/Countersign authentication from the given providers.
In Android Studio, add together the post-obit method to MainActivity
.
private void loadLogInView() { Intent intent = new Intent(this, LogInActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); }
This navigates to the Login view and clears the action stack. This prevents the user going dorsum to the main activity when they press the Back button from the Login view.
Add together the following variables to the class.
private FirebaseAuth auth; private FirebaseUser user;
Then add the following to the bottom of onCreate()
.
// initialize Firebase Auth auth = FirebaseAuth.getInstance(); user = auth.getCurrentUser(); if (user == nil) { // not logged in, launch the Log In activity loadLogInView(); }
Here you bank check for the logged in user. If the user isn't logged in, getCurrentUser()
will return aught
, otherwise it will return a FirebaseUser
object which will contain details of the logged in user. If the user isn't logged in, loadLogInView()
is called which redirects the user to the Login view.
Change LogInActivity
.
public grade LogInActivity extends AppCompatActivity { protected EditText etEmail; protected EditText etPassword; protected Button btnLogin; protected TextView tvSignUp; private FirebaseAuth auth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_log_in); // initialize FirebaseAuth auth = FirebaseAuth.getInstance(); if (auth.getCurrentUser() != null) { Intent intent = new Intent(LogInActivity.this, MainActivity.class); startActivity(intent); } tvSignUp = (TextView) findViewById(R.id.tvSignUp); etEmail = (EditText) findViewById(R.id.etEmail); etPassword = (EditText) findViewById(R.id.etPassword); btnLogin = (Button) findViewById(R.id.btnLogin); tvSignUp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View five) { Intent intent = new Intent(LogInActivity.this, SignUpActivity.grade); startActivity(intent); } }); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String email = etEmail.getText().toString().trim(); String countersign = etPassword.getText().toString().trim(); if (electronic mail.isEmpty() || password.isEmpty()) { AlertDialog.Builder architect = new AlertDialog.Builder(LogInActivity.this); architect.setMessage(R.string.login_error_message) .setTitle(R.string.login_error_title) .setPositiveButton(android.R.string.ok, null); AlertDialog dialog = builder.create(); dialog.evidence(); } else { auth.signInWithEmailAndPassword(e-mail, password) .addOnCompleteListener(LogInActivity.this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (job.isSuccessful()) { Intent intent = new Intent(LogInActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } else { AlertDialog.Architect builder = new AlertDialog.Builder(LogInActivity.this); builder.setMessage(task.getException().getMessage()) .setTitle(R.string.login_error_title) .setPositiveButton(android.R.string.ok, null); AlertDialog dialog = builder.create(); dialog.show(); } } }); } } }); } }
This initiates the view elements and the FirebaseAuth
object, which is the entry signal of the Firebase Authentication SDK. An issue listener is added to the SignUp text view that will open the SignUp action when tapped. Another event listener on the Login button performs validation on the user input, ensuring the user entered text for both fields. It then calls the Firebase server with signInWithEmailAndPassword()
. The function takes the user electronic mail and password and returns a Task
of AuthResult
. You bank check if the Task
is successful and redirect the user to the MainActivity
, otherwise bear witness them an error message.
Apart from signInWithEmailAndPassword()
, y'all tin use the following to log in the user:
-
signInWithCredential(AuthCredential)
method tries to sign in a user with the given AuthCredential. Use this method to sign in a user into your Firebase Authentication system. First retrieve the credential either straight from the user, in case of EmailAuthCredential, or from a supported authentication SDK, such as Google Sign-In or Facebook. -
signInAnonymously()
method signs in the user anonymously without requiring whatever credential. This method creates a new account in your Firebase Authentication organisation, except in the case where there was already an anonymous user signed in into this app. -
signInWithCustomToken(String)
metod tries to sign in a user with a given Custom Token. Apply this method after you retrieve a Firebase Auth Custom Token from your server, to sign in a user into your Firebase Authentication system.
With the Login functionality done, let'southward ready upwardly Sign Up.
Alter SignUpActivity
as shown.
public class SignUpActivity extends AppCompatActivity { protected EditText etPassword; protected EditText etEmail; protected Push button btnSignup; private FirebaseAuth auth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); // initialize FirebaseAuth auth = FirebaseAuth.getInstance(); etPassword = (EditText)findViewById(R.id.etPassword); etEmail = (EditText)findViewById(R.id.etEmail); btnSignup = (Button)findViewById(R.id.btnSignup); btnSignup.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String password = etPassword.getText().toString().trim(); Cord electronic mail = etEmail.getText().toString().trim(); if (countersign.isEmpty() || email.isEmpty()) { AlertDialog.Builder builder = new AlertDialog.Architect(SignUpActivity.this); architect.setMessage(R.string.signup_error_message) .setTitle(R.string.signup_error_title) .setPositiveButton(android.R.string.ok, null); AlertDialog dialog = builder.create(); dialog.show(); } else { auth.createUserWithEmailAndPassword(email, countersign) .addOnCompleteListener(SignUpActivity.this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Chore<AuthResult> job) { if (task.isSuccessful()) { Intent intent = new Intent(SignUpActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } else { AlertDialog.Builder builder = new AlertDialog.Architect(SignUpActivity.this); builder.setMessage(task.getException().getMessage()) .setTitle(R.cord.login_error_title) .setPositiveButton(android.R.cord.ok, zippo); AlertDialog dialog = builder.create(); dialog.testify(); } } }); } } }); } }
The createUserWithEmailAndPassword()
method tries to create a new user account with the given email address and password. If successful, information technology also signs the user into the app. A Task
of AuthResult
is returned with the effect of the operation. You check to run across if registration was successful and redirect the user to MainActivity
, otherwise testify them an error bulletin. In your app, yous can check for the exception thrown to decide on the error message you will show to your users. The following are the possible exceptions thrown in case of an error in creating an account.
- FirebaseAuthWeakPasswordException thrown if the password is not strong plenty
- FirebaseAuthInvalidCredentialsException thrown if the email address is malformed
- FirebaseAuthUserCollisionException thrown if there already exists an account with the given email
If registration is successful, you volition be directed to the MainActivity
. If you look at the Firebase console, y'all should be able to meet the created user nether Auth > Users.
The Firebase team built an open source library called FirebaseUI that simplifies the procedure of calculation Hallmark and connecting common UI elements to the Firebase database. Read the documentation to learn more about the library.
Authority and Data Validation
Identifying your user is only one part of security. One time you know who they are, you need a way to control their admission to data in your Firebase database.
Firebase has a declarative language for specifying rules that live on the Firebase servers and determine the security of your app. You can edit them on the Database > Rules tab.
The Security rules allow you lot to control access to each office of your database. Past default, Firebase has security rules that require users to be authenticated.
{ "rules": { ".read": "auth != null", ".write": "auth != nix" } }
Firebase Database Rules take a JavaScript-like syntax and come up in four types:
-
.read
describes if and when information is allowed to be read by users. -
.write
describes if and when data is allowed to exist written. -
.validate
defines what a correctly formatted value will look like, whether it has child attributes, and the data type. -
.indexOn
specifies a child to index to support ordering and querying.
.read
and .write
rules cascade, so the following ruleset grants read access to any data at path /foo/
(tin likewise refer to information technology as the node foo
) equally well every bit any deeper paths such as /foo/bar/baz
. Notation that .read
and .write
rules shallower in the database override deeper rules, so read admission to /foo/bar/baz
would even so be granted in this example even if a dominion at the path /foo/bar/baz
evaluated to false. .validate
rules do not pour.
Alter the rules every bit shown and hit Publish.
{ "rules": { "users": { "$uid": { ".read": "auth != nil && auth.uid == $uid", ".write": "auth != zippo && auth.uid == $uid", "items": { "$item_id": { "championship": { ".validate": "newData.isString() && newData.val().length > 0" } } } } } } }
In the higher up rules, auth != null && auth.uid == $uid
restricts read and write permission of data on the users
node (as well every bit its child nodes) to the user whose uid
matches the id of the logged in user (auth.uid
). The $uid
is a variable that holds the value at that node and not the proper noun of the node itself. With this rule, not only will the user need to be authenticated to read or write whatsoever data to the node and its children, but they will also only accept access to their own data.
The Firebase Database Rules include built-in variables and functions that allow y'all to refer to other paths, server-side timestamps, authentication information, and more.
Validation rules are cracking but they shouldn't replace data validation lawmaking in your app. You should still validate input in you app to improve performance.
Saving and Retrieving Data
Modify MainActivity
as shown.
public course MainActivity extends AppCompatActivity { private FirebaseAuth auth; private FirebaseUser user; private DatabaseReference db; @Override protected void onCreate(Package savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // initialize Firebase Auth auth = FirebaseAuth.getInstance(); user = auth.getCurrentUser(); db = FirebaseDatabase.getInstance().getReference(); if (user == null) { // not logged in, launch the Log In activeness loadLogInView(); } else { final EditText etTitle = (EditText) findViewById(R.id.etTitle); final Button btnAdd = (Push button) findViewById(R.id.btnAdd); final Cord userId = user.getUid(); final ListView lvItems = (ListView) findViewById(R.id.lvItems); last ArrayAdapter<Cord> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1); lvItems.setAdapter(adapter); btnAdd.setOnClickListener(new View.OnClickListener() { public void onClick(View five) { String title = etTitle.getText().toString(); //db.child("users").kid(userId).kid("items").push().child("title").setValue(championship); Item item = new Item(title ); db.child("users").child(userId).child("items").push button().setValue(item); etTitle.setText(""); } }); // delete items when clicked lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { db.child("users").kid(userId).child("items") .orderByChild("title") .equalTo((String) lvItems.getItemAtPosition(position)) .addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (dataSnapshot.hasChildren()) { DataSnapshot firstChild = dataSnapshot.getChildren().iterator().next(); firstChild.getRef().removeValue(); } } @Override public void onCancelled(DatabaseError databaseError) {} }); } }); // use Firebase to populate the list db.kid("users").child(userId).child("items").addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { adapter.add((String) dataSnapshot.child("title").getValue()); } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) {} @Override public void onChildRemoved(DataSnapshot dataSnapshot) { adapter.remove((String) dataSnapshot.kid("title").getValue()); } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) {} @Override public void onCancelled(DatabaseError databaseError) {} }); } } private void loadLogInView() { Intent intent = new Intent(this, LogInActivity.form); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } }
Y'all create a reference to the root node of the database with FirebaseDatabase.getInstance().getReference()
. Yous so set a listener on the Add New Item push button that saves data to Firebase when clicked.
In that location are 4 methods for writing information to the Firebase Realtime Database:
-
setValue()
writes or replaces information to a defined path, such asusers/<user-id>/<username>
. Y'all can utilizesetValue()
to save dissimilar types of data to a Firebase database: String, Long, Double, Boolean, Map<Cord, Object>, List<Object>, custom Java objects. -
push()
adds to a list of data. Every time you callpush()
, Firebase generates a unique key that can also be used every bit a unique identifier, such every bituser-posts/<user-id>/<unique-post-id>
. -
updateChildren()
updates some of the keys for a defined path without replacing all of the data. -
runTransaction()
update complex information that could be corrupted by concurrent updates.
In our code, information is saved with:
String championship = etTitle.getText().toString(); Particular particular = new Item(title ); db.child("users").child(userId).child("items").push().setValue(item);
.kid
gets a reference to the specified node if it exists or creates it if it doesn't be. The above will relieve the entered text at the path /users/<user-id>/items/<item-id>/title
.
.push button()
generates a new kid location using a unique fundamental. You use it to generate a unique key for each item added.
.setValue()
writes or replaces data to the defined path.
To think data from Firebase, add together a listener to the database reference with addChildEventListener()
. Y'all can heed for the following types of events that retrieve information:
-
ValueEventListener: onDataChange()
reads and listens for changes to the entire contents of a path. -
ChildEventListener: onChildAdded()
retrieves lists of items or listen for additions to a list of items. Suggested use withonChildChanged()
andonChildRemoved()
to monitor changes to lists. -
ChildEventListener: onChildChanged()
listens for changes to the items in a list. Use withonChildAdded()
andonChildRemoved()
to monitor changes to lists. -
ChildEventListener: onChildRemoved()
listens for items beingness removed from a list. Use withonChildAdded()
andonChildChanged()
to monitor changes to lists. -
ChildEventListener: onChildMoved()
listens for changes to the lodge of items in an ordered list.onChildMoved()
events e'er follow theonChildChanged()
event that caused the item's order to change (based on your current society-by method).
The listener receives a DataSnapshot
, which is a snapshot of the data. A snapshot is a picture of the data at a particular location in a Firebase database at a single indicate in fourth dimension. Calling getValue()
on a snapshot returns the Java object representation of the information. The possible types returned past getValue()
are Boolean
, String
, Long
, Double
, Map<Cord, Object>
, and Listing<Object>
. If no data exists at the location, the snapshot will return cipher
and it's a good idea to cheque for zilch
earlier you try using the data. Finally, add together the retrieved data to the list view.
Also we set an onClick
listener on the ListView
and queries the database when an item is tapped. It searches the Firebase database for the item with a title equal to the string at the tapped location. With a more complex app you might desire to search for something that is unique to the object, like an id. It and so removes the start occurrence of the item from the database. The listing view is automatically updated.
Create menu in res/menu/menu_main.xml and add item with the following Logout item.
<item android:id="@+id/action_logout" android:orderInCategory="100" android:title="@string/action_logout" app:showAsAction="never"/>
Open MainActivity
and add following snippet.
@Override public boolean onCreateOptionsMenu(Carte menu) { getMenuInflater().inflate(R.menu.menu_main, bill of fare); return super.onCreateOptionsMenu(carte); } @Override public boolean onOptionsItemSelected(MenuItem particular) { switch (item.getItemId()) { example R.id.action_logout: auth.signOut(); loadLogInView(); break; default: break; } render true; }
This menu item will logout the user.
If yous run the app and add together some items, they will be added to the listing and to the database.
Authenticate Using Facebook Login
Head over to Facebook Developer website to create your app and get your application ID by clicking on the Add together a new app button. You lot can read detailed educational activity in Android Facebook SDK integration tutorial .
To enable authenticate using Facebook in Firebase follow these steps
- Become to your Firebase project panel.
- Click Authentication under Develop department.
- Select Sign-in method tab and enable Facebook Sign-In past giving Facebook App Id and App Hugger-mugger.
To start working with Facebook authentication we need to add Firebase Authentication dependencies to our android project. Delight add the following dependency in your module-level gradle and compile.
compile 'com.google.firebase:firebase-auth:ten.0.ane' compile 'com.facebook.android:facebook-android-sdk:[four,5)'
Example of layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <com.facebook.login.widget.LoginButton android:id="@+id/btnLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="truthful" /> </LinearLayout>
Example of Activity
.
public class FacebookActivity extends AppCompatActivity { private TextView tvStatus; private LoginButton btnLogin; private CallbackManager callbackManager; private FirebaseAuth firebaseAuth; Cord TAG = "DBG"; @Override protected void onCreate(Package savedInstanceState) { super.onCreate(savedInstanceState); callbackManager = CallbackManager.Factory.create(); setContentView(R.layout.activity_facebook); firebaseAuth = FirebaseAuth.getInstance(); btnLogin = (LoginButton)findViewById(R.id.btnLogin); btnLogin.setReadPermissions("public_profile,user_photos,user_birthday,user_work_history"); btnLogin.registerCallback(callbackManager, new FacebookCallback<LoginResult>() { @Override public void onSuccess(LoginResult loginResult) { AccessToken token = loginResult.getAccessToken(); Log.d(TAG, "onSuccess: " + token.getUserId()); handleFacebookAccessToken(loginResult.getAccessToken()); } @Override public void onCancel() { Log.d(TAG, "onCancel: Login attempt canceled."); } @Override public void onError(FacebookException eastward) { Log.d(TAG, "onError: Login endeavour failed."); } }); if (AccessToken.getCurrentAccessToken() != nil) { goMainScreen(); } } private void handleFacebookAccessToken(AccessToken accessToken) { AuthCredential credential = FacebookAuthProvider.getCredential(accessToken.getToken()); firebaseAuth.signInWithCredential(credential).addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { Log.d(TAG, "onComplete: " + task.getResult().getUser().getUid()); if(!chore.isSuccessful()) Toast.makeText(getApplicationContext(), "Error login", Toast.LENGTH_LONG).show(); else Toast.makeText(getApplicationContext(), "Successful login", Toast.LENGTH_LONG).evidence(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception east) { e.printStackTrace(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { callbackManager.onActivityResult(requestCode, resultCode, data); } public void goMainScreen(){ Intent intent = new Intent(this, ItemsActivity.grade); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }
How to run several queries sequentially
Starting with Google Play services version nine.0.0, you tin use a Tasks API which provides
- asynchronous method calls, similar to
PendingResult
in previous versions of Google Play Services - concatenation tasks i after another
- enable the executor, etc to be specified for each chore and thread switching very easily (between background and chief thread).
- allow errors to be captured and dealt with at a convenient time
Tasks API would be expert for background piece of work that returns a single value such every bit general network requests, reading files off disk, etc.
If you lot desire to work with the Task API
without having to integrate Firebase into your app, you can get the library with a dependency in your build.gradle:
compile 'com.google.android.gms:play-services-tasks:ix.6.i'
Just, if yous are integrating Firebase, you'll get this library included for free, and so no need to call it out specifically in that instance.
So, instead of nesting listeners, you can create a sequence of tasks.
The result will be sent to addOnSuccessListener
if all tasks execute successfully. If any of them fail during the use case execution, the sequence will be aborted and the exception is passed to addOnFailureListener
.
Let's create simple Task
public Job<String> getName() { final TaskCompletionSource<Cord> tcs = new TaskCompletionSource<>(); tcs.setResult("John"); //tcs.setException(Exception()); render tcs.getTask(); }
Allow's execute it
// Activity activity = MainActivity.this; // first approach getName().addOnSuccessListener(action, new OnSuccessListener<String>() { @Override public void onSuccess(Cord proper name) { Log.d(TAG, "onSuccess: " + name); } }); // second approach getName().addOnCompleteListener(activity, new OnCompleteListener<String>() { @Override public void onComplete (Chore task) { if (chore.isSuccessful()) { // exercise something with proper name ... String name = (String) chore.getResult(); Log.d("Www", "onComplete: " + proper noun); } else { // handle the failure ... Exception e = task.getException(); } } });
And so, with OnCompleteListener
, y'all tin can have a single listener that handles both success and failure, and you detect out which ane by calling isSuccessful()
on the Chore
object passed to the callback. Practically speaking, this is functionally equivalent to registering both an OnSuccessListener
and an OnFailureListener
. The style y'all choose is generally a matter of preference.
Besides we can run several tasks sequentially. Let'south create GetUser
and GetPhoto
tasks.
class GetUser implements Continuation<Void, Task<Cord>> { @Override public Task<String> and so(Task<Void> task) { final TaskCompletionSource<String> tcs = new TaskCompletionSource(); //tcs.setException(fault.toException()); tcs.setResult("John"); return tcs.getTask(); } } class GetPhoto implements Continuation<Cord, Task<String>> { @Override public Task<String> and so(Task<String> task) { final TaskCompletionSource<Cord> tcs = new TaskCompletionSource(); String name = task.getResult(); //tcs.setException(error.toException()); tcs.setResult("John's photos"); render tcs.getTask(); } }
Run it sequentially with following control
Tasks.<Void>forResult(null) .continueWithTask(new GetUser()) .continueWithTask(new GetPhoto()) .addOnSuccessListener(action, new OnSuccessListener<Cord>() { @Override public void onSuccess(String southward) { Log.d("WWW", "onSuccess!!!!"); } });
The primary difference between continueWith
and continueWithTask
is ane of the generic types of the Continuation you pass to it.
You can think of a Continuation
as something that converts some input blazon to some output type. If you lot define a Continuation<IN, OUT>
, where IN is the input type passed to its and so method via a Task<IN>
, and OUT is the blazon that method returns.
When calling continueWith, you pass a Continuation<IN, OUT>
, and the then method is expected to compute and render the OUT value given a Task<IN>
value every bit input. You lot might choose to do this if you don't have whatever blocking piece of work to do for the conversion, such as reducing an integer array to the sum of its elements or counting the number of words in a Cord
.
When calling continueWithTask
, you pass a Continuation<IN, Chore<OUT>>
, and the and so method is expected to return a Task<OUT>
that eventually generates the OUT value, given the IN value as input. Yous might choose this if y'all are able to consul the conversion work to an existing reusable Task
. continueWithTask
is perfect when you desire to utilize a Continuation
and a TaskCompletionSource
together.
Practically speaking, you aren't required to choose one or the other to do your piece of work. It'south a matter of preferred style, or if you have a nice Task
gear up to delegate your conversation rather than a Continuation
. Typically you just apply a Continuations
if y'all have a pipeline of conversions to concatenation together.
The Task API
provides a couple methods (whenAll
) to aid you lot know when several Tasks
are all consummate. These static utility methods create a new Job
that gets triggered in response to the completion of a collection of Tasks
that you provide.
Let's create getName
and getPhoto
tasks.
public Task<String> getName() { final TaskCompletionSource<Cord> tcs = new TaskCompletionSource<>(); tcs.setResult("John"); //tcs.setException(Exception()); return tcs.getTask(); } public Task<String> getPhoto() { final TaskCompletionSource<String> tcs = new TaskCompletionSource<>(); tcs.setResult("John's photos"); //tcs.setException(Exception()); return tcs.getTask(); }
Collect all tasks to array
Chore<?>[] tasks = new Task[] { getName(), getPhoto() };
As well create job that will offset afterwards all.
class FinishTask implements Continuation<Void, Task<Void>> { @Override public Chore<Void> then(@NonNull Task<Void> task) throws Exception { concluding TaskCompletionSource<Void> tcs = new TaskCompletionSource<>(); if (job.isSuccessful()) { Log.d(TAG, "then: isSuccessful" + proper noun); tcs.setResult(cipher); } else { Log.d(TAG, "then: NOT isSuccessful"); } render tcs.getTask(); } }
Run with following control
Tasks.whenAll(tasks).continueWithTask(new FinishTask()).addOnSuccessListener(activeness, new OnSuccessListener<String>() { @Override public void onSuccess(String s) { Log.d(TAG, "onSuccess!!!!"); } });
How to fetch list of items and combine them via RxJava2
For this purpose nosotros tin RxJava2.
You tin place following snippet somewhere in Utils.java
public static Observable<List<Particular>> getItems(String id) { return Appreciable.create(new ObservableOnSubscribe<List<Item>>() { @Override public void subscribe(ObservableEmitter<Listing<Item>> east) throws Exception { String itemIndex = String.format("%s_%d", id, Item.STATE_ACCEPT); ValueEventListener listener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { List<Detail> items = new ArrayList<>(); if (dataSnapshot.getChildrenCount() > 0) { for (DataSnapshot ds : dataSnapshot.getChildren()) { Item item = ds.getValue(Detail.grade); items.add together(detail); } due east.onNext(items); due east.onComplete(); } else { e.onNext(Collections.<Detail>emptyList()); } } @Override public void onCancelled(DatabaseError databaseError) { e.onError(new FirebaseException(databaseError.getMessage())); } }; Query query = Utils.getDB().child(Constants.FIREBASE_ITEMS_DB).orderByChild("itemIndex").equalTo(itemIndex); query.addListenerForSingleValueEvent(listener); } }); }
You lot can use it somewhere in Activeness
.
Appreciable<List<Particular>> itemA = Utils.getItems(itemAId); Observable<List<Item>> itemB = Utils.getItems(itemBId); Observable.zip(itemA, itemB, (a, b) -> { List<Item> items = new ArrayList<>(); items.addAll(a); items.addAll(b); return items; }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe((items) -> { for (Item particular : items) { ... } });
You tin can spy more examples here.
Useful links
- Using Firebase Analytics
- How to Create an Android Chat App Using Firebase
Source: https://en.proft.me/2017/03/17/android-firebase-tutorial/
0 Response to "How to Read Data From Firebase Database"
Post a Comment