Firebase: Realtime Database Reading and Writing FIREBASE
- Firebase Tutorial
- Features of Firebase
- Android Studio
- Firebase - Environment Setup (with android studio)
- Firebase Assistance - Android Studio
- Firebase Authentication
- Firebase: Google Sign-In Authentication
- Firebase: Facebook Sign-In Authentication
- Firebase: Sign-In Authentication Using Phone Number
- Firebase UI: Authentication using email/password
- Firebase UI: Authentication using email link
- Firebase SDK: Authentication using email/password
- Firebase SDK: Authentication using the email link
- Firebase: Realtime Database
- Firebase: Real-time database setup and configuration
- Firebase: Data Organization in Real-time Database
- Firebase: Realtime Database Reading and Writing
- Firebase: Realtime Database Update and Delete
Firebase: Realtime Database Reading and Writing
Firebase: Realtime Database Reading and Writing
In the previous section(Firebase: Data Organization in Real-time Database), we created an android application and added Firebase with it. We have already implemented all the required libraries and plugins also. There is a database that we have created before naming fir-realtimedatabaseexam-60676
.
Writing into Database
Inside your code, we have to retrieve an instance of our database using getInstance()
method and then reference the location we have to write to. You have to remember that the database is organized around JSON nodes.
And attach an asynchronous listener to the reference. The listener is triggered one time for the initial state of the data, and again any time when the data changes.
- Private lateinit var database:DatabaseReference
- //??.
- Database=FirebaseDatabase.getInstance().reference
- myRef=database.getReference("message")
- myRef.setValue("Hello,World!")
You can save a range of data types (String, Long, Double, and Boolean, etc.) of the database. In this way, we can save Kotlin objects. When you save an object, the responses from any getters will be saved as children of this location and JSON format.
A class that defines the user as a custom java object carries a default constructor that takes no arguments and has public getters for the properties to be assigned.
Writing an object (User.kt, Signing.kt)
We will write an actual object, which is the user object. The user in our User.kotlin
class and Signing or register activity write that object. So, when we use the Kotlin object, the contents of our object are automatically mapped to the child location in a nested fashion. Using the object, we make our code more readable and easier to maintain and good to write the object.
- data class User(
- var username:String?=null,
- var email:String?=null
- )
We can add user object with setVaue()
function
- private fun writeNewUser(userId:String, name:String,email:String?)){
- val user=User(name,email)
- database.child("users").child(userId).setValue(user)
- }
You can use the set value method to write a new user. You can still update a child without rewriting the entire object.
Reading into Database
To read data at a path and to listen for any changes if the data changes, we have to use the addValueEventListener()
or addListenerForSingleValueEvent()
method to add a ValueEventListener to a database reference. These two methods will add a valueEventListener
to a DatabaseReference.
You can use the onDataChange()
method to read a static snapshot of the contents on a given path. It is triggered once when the listener is attached and again every time the data changes, including the children. It passes a snapshot containing all the data at the location, including child data. If there is no data, the snapshot will return false when we call exists()
and null when we call getValue()
In a few cases, we may want a callback to be called once and then immediately removed. It is useful for data that only needs to be loaded once and is not expected to change frequently or require active listening. Listening does have some overhead, so if we only need to read it once, we don't need to do the callback.
For example, when initializing user interface elements that you don't expect to change, but we want to use the addListenerForSingleValueEvent()
only when you need to read one part of the data. It doesn't change a law once and only once.
Example:
We are implementing an android application. It is a user logging and registration application that has three XML files and four Kotlin files. The activity_main.xml
is used for the registration page. The activity_signing.xml
is used for login, and activity_welcome.xml
is used for data retrieving from the database. Similarly, there is four Kotlin file, i.e., MainActivity, Signing, welcome, and User.
When the users register themselves, they are added into the firebase console user section, and the data corresponding them is stored into the database. The signing functionality is the same as we have done in our authentication section. When a user successfully registers or sign-up, he will switch to the welcome page where he found his data.
activity_main.xml, activity_signing, and activity_welcome
MainActivity.kt
- package com.example.firebaserealtimedatabase
- import android.content.Intent
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- import android.text.TextUtils
- import android.util.Log
- import android.view.View
- import android.widget.Toast
- import com.google.firebase.auth.FirebaseAuth
- import com.google.firebase.database.DatabaseReference
- import com.google.firebase.database.FirebaseDatabase
- import kotlinx.android.synthetic.main.activity_main.*
- class MainActivity : AppCompatActivity() {
- //Creating member variables of FirebaseAuth
- private var mAuth: FirebaseAuth?=null
- //Creating member variables of FirebaseDatabase and DatabaseReference
- private var mFirebaseDatabaseInstances: FirebaseDatabase?=null
- private var mFirebaseDatabase: DatabaseReference?=null
- //Creating member variable for userId and emailAddress
- private var userId:String?=null
- private var emailAddress:String?=null
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- //Get Firebase Instances
- mAuth=FirebaseAuth.getInstance()
- //Get instance of FirebaseDatabase
- mFirebaseDatabaseInstances= FirebaseDatabase.getInstance()
- //if already logged in go to sign in screen
- if(mAuth!!.currentUser!=null){
- startActivity(Intent(this,welcome::class.java))
- finish()
- }
- }
- fun onLoginClicked(view: View) {
- startActivity(Intent(this,Signing::class.java))
- finish()
- }
- //calling onRegisterClicked button
- fun onRegisterClicked(view: View) {
- //Validation checking
- if(TextUtils.isEmpty(username.text.toString())){
- Toast.makeText(applicationContext,"Enter Username!",Toast.LENGTH_LONG).show()
- }
- if(TextUtils.isEmpty(email.text.toString())){
- Toast.makeText(applicationContext,"Enter email address!",Toast.LENGTH_LONG).show()
- }
- if(TextUtils.isEmpty(password.text.toString())){
- Toast.makeText(applicationContext,"Enter password!",Toast.LENGTH_LONG).show()
- }
- if(password.text.toString().length<6){
- Toast.makeText(applicationContext,"Password is too short",Toast.LENGTH_LONG).show()
- }
- //Making progressBar visible
- progressBar!!.visibility=View.VISIBLE
- //creating user
- mAuth!!.createUserWithEmailAndPassword(email.text.toString(),password.text.toString())
- .addOnCompleteListener(this){task ->
- Toast.makeText(this,"createUserWithEmail:onComplete"+task.isSuccessful,Toast.LENGTH_SHORT).show()
- progressBar.visibility=View.GONE
- // When the sign-in is failed, a message to the user is displayed. If the sign-in is successful, auth state listener will get notified, and logic to handle the signed-in user can be handled in the listener.
- if(task.isSuccessful){
- //Getting reference to ?users? node
- mFirebaseDatabase=mFirebaseDatabaseInstances!!.getReference("users")
- //Getting current user from FirebaseAuth
- val user=FirebaseAuth.getInstance().currentUser
- //add username, email to database
- userId=user!!.uid
- emailAddress=user.email
- //Creating a new user
- val myUser=User(username.text.toString(),emailAddress!!)
- //Writing data into database using setValue() method
- mFirebaseDatabase!!.child(userId!!).setValue(myUser)
- startActivity(Intent(this,welcome::class.java))
- finish()
- }else{
- Toast.makeText(this,"Authentication Failed"+task.exception,Toast.LENGTH_SHORT).show()
- Log.e("MyTag",task.exception.toString())
- }
- }
- }
- }
welcome.kt
- package com.example.firebaserealtimedatabase
- import android.content.Intent
- import android.nfc.Tag
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- import android.util.Log
- import android.view.View
- import androidx.constraintlayout.solver.widgets.Snapshot
- import com.google.firebase.auth.FirebaseAuth
- import com.google.firebase.database.*
- import kotlinx.android.synthetic.main.activity_main.*
- class welcome : AppCompatActivity() {
- //Creating member variables
- private var mFirebaseDatabase: DatabaseReference?=null
- private var mFirebaseInstance: FirebaseDatabase?=null
- var userId:String?=null
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_welcome)
- //Getting instances of FirebaseDatabase
- mFirebaseInstance= FirebaseDatabase.getInstance()
- //get reference to 'users' node
- mFirebaseDatabase=mFirebaseInstance!!.getReference("users")
- val user=FirebaseAuth.getInstance().currentUser
- //add it only if it is not saved to database
- if (user != null) {
- userId=user.uid
- }
- addUserChangeListener()
- }
- private fun addUserChangeListener(){
- //User data change Listener
- mFirebaseDatabase!!.child(userId!!).addValueEventListener(object: ValueEventListener{
- override fun onDataChange(dataSnapshot: DataSnapshot){
- val user=dataSnapshot.getValue(User::class.java)
- //Check for null
- if(user==null){
- Log.e(TAG,"User data is null")
- return
- }
- Log.e(TAG,"User data is changed!"+user.name+","+user.email)
- //Display newly updated name and email
- email.setText(user.email)
- username.setText(user.name)
- }
- override fun onCancelled(error: DatabaseError){
- //Failed to read value
- Log.e(TAG,"Failed to read user",error.toException())
- }
- })
- }
- fun onLogout(view: View) {
- FirebaseAuth.getInstance().signOut()
- startActivity(Intent(this, MainActivity::class.java))
- }
- companion object{
- private val TAG=database::class.java.simpleName
- }
- }
User.kt
- package com.example.firebaserealtimedatabase
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- class User{
- lateinit var name:String
- lateinit var email:String
- //Default constructor required for calls to
- //DataSnapshot.getValue(User.class)
- constructor(){
- }
- constructor(name:String,email:String){
- this.name=name
- this.email=email
- }
- }
Signing.kt
- package com.example.firebaserealtimedatabase
- import android.content.Intent
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- import android.text.TextUtils
- import android.util.Log
- import android.view.View
- import android.widget.Toast
- import com.google.firebase.auth.FirebaseAuth
- import kotlinx.android.synthetic.main.activity_main.*
- class Signing : AppCompatActivity() {
- private var mAuth: FirebaseAuth?=null
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_signing)
- //Initialize Firebase Auth
- mAuth=FirebaseAuth.getInstance()
- }
- public override fun onStart() {
- super.onStart()
- //if user logged in, go to sign in screen
- if(mAuth!!.currentUser!=null){
- startActivity(Intent(this,welcome::class.java))
- finish()
- }
- }
- override fun onResume() {
- super.onResume()
- progressBar.visibility= View.GONE
- }
- fun loginButtonClicked(view: View){
- if(TextUtils.isEmpty(email.text.toString())){
- Toast.makeText(applicationContext,"Enter Username!", Toast.LENGTH_LONG).show()
- return
- }
- if(TextUtils.isEmpty(password.text.toString())){
- Toast.makeText(applicationContext,"Enter password!", Toast.LENGTH_LONG).show()
- return
- }
- progressBar.visibility=View.VISIBLE
- //Authenticate user
- mAuth!!.signInWithEmailAndPassword(email.text.toString(),password.text.toString())
- .addOnCompleteListener(this){task ->
- progressBar.visibility=View.GONE
- if(task.isSuccessful){
- val intent=Intent(this,welcome::class.java)
- startActivity(intent)
- finish()
- }else{
- if(password.text.toString().length<6){
- password.error="Password is too short, enter minimum 6 characters"
- }
- Toast.makeText(this,"Authentication Failed"+task.exception,Toast.LENGTH_SHORT).show()
- }
- }
- }
- }