Firebase Realtime Database and Kotlin Tutorial - Develop Cloud Based Task List App

Search for a command to run...

No comments yet. Be the first to comment.
Learn the Building Blocks of Basic User Interface in Unity app and Game development.

Get started with Magic Leap 2 development without a device.

As a developer sometime you will require to create windows icon file with extension ".ico". Normally you will get a png image with which you need to create the ico file. You can easily convert any png file to an ico file using GIMP. GIMP is a free so...
In this article, I would be sharing how you can show native menu bar in your flutter windows app. This is something which is still not provided by default by flutter. This article is starting point for adding the menu system in your windows app. You ...
C is one of the fastest language around. Many a times you might need to use it in your development activities to speed up some processes. For one of my requirement I need to interact with MYSQL in C. Although there are many different articles which e...
In this tutorial, you are going to learn about Firebase Realtime Database and Kotlin for Android. You will learn all these while developing a simple Cloud based Task List app.
Here are the definitions of the some of the Terminologies and Technologies used in this Firebase Realtime Database and Kotlin Tutorial.
Firebase is Google's mobile platform that helps you quickly develop high-quality apps and grow your business.
The Firebase Realtime Database is a cloud-hosted database. Data is stored as JSON and synchronized in realtime to every connected client.
Kotlin is now an official language on Android. It's expressive, concise, and powerful. Best of all, it's interoperable with our existing Android languages and runtime.
Kotlin is concise while being expressive. It contains safety features for nullability and immutability, to make your Android apps healthy and performant by default.
Here are the pre-requisites for the Firebase Realtime Database and Kotlin.
You can get the source file with the complete project files for the Firebase Realtime Database and Kotlin. Go ahead and click the below button to get the files. [activecampaign form=91]
To get started with the tutorial you will need to first create a Android project.
Here are the steps to create a project in Android Studio.

NOTE: Through out this tutorial I will be using appnimiacademy in the package name. You can replace it with your own domain name.
Set Target Android Devices.



This is how the Android Studio should look like once the project has been created.

To get started we will need to add the components to the Main Activity which are required for our FirkoTasky app.
Now let us go ahead and add a footer section at the bottom of the main activiy. It will contain the TextField and a Button to add a Task to the List.
Now go ahead and replace the whole TextView Tag in the "content_main.xml" with the the following code.
<RelativeLayout
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/colorPrimary"
android:visibility="gone"
android:layout_alignParentBottom="true">
</RelativeLayout>
In the above code
Now add a button to the Relative Layout. We will use this button to add a new task to the task list.
Add the following code inside the Relative Layout tag added above.
<ImageButton
android:id="@+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:gravity="end"
app:srcCompat="@android:drawable/ic_menu_save" />
Now add the following piece of code just above the ImageButton Tag inside the RelativeLayout.
<EditText
android:id="@+id/txtNewTaskDesc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnAdd"
android:layout_centerVertical="true"
android:textColor="@android:color/white"
></EditText>
Now you will need to add a ListView so that you can show all the exisiting Tasks in the Task List. To that paste the following code just above the Relative Layout added in the previous section.
<ListView
android:id="@+id/listviewTask"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toTopOf="@+id/footer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_alignParentTop="true"
/>
The whole xml will look like as below
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<ListView
android:id="@+id/listviewTask"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toTopOf="@+id/footer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_alignParentTop="true"
/>
<RelativeLayout
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/colorPrimary"
android:visibility="gone"
android:layout_alignParentBottom="true">
<EditText
android:id="@+id/txtNewTaskDesc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnAdd"
android:layout_centerVertical="true"
android:textColor="@android:color/white"
></EditText>
<ImageButton
android:id="@+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:gravity="end"
app:srcCompat="@android:drawable/ic_menu_save" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
The next component which we need to add is the rows for the Task in the list.
So let us go ahead and add a resource xml.


We are going to use Relative Layout for this xml. So go ahead replace the exisiting code for the layout with the following.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
</RelativeLayout>
We will need a checkbox to show whether a task has been completed or not.
Paste the following code inside the Relative Layout added above.
<CheckBox
android:id="@+id/chkDone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
The textview will contain the description of the Task. It will be aligned to the right of the Checkbox. Paste the following code below Checkbox in the Relative Layout.
<TextView
android:id="@+id/txtTaskDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/chkDone"
android:layout_toRightOf="@+id/chkDone"
android:text="Item Text"
/>
Add an image button to remove or delete a Task. Paste the following code below the TextView tag and inside the Relative Layout in the layout xml.
<ImageButton
android:id="@+id/btnRemove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:gravity="end"
app:srcCompat="@android:drawable/ic_menu_delete" />
Here is the completed xml:
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<CheckBox
android:id="@+id/chkDone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txtTaskDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/chkDone"
android:layout_toRightOf="@+id/chkDone"
android:text="Item Text"
/>
<ImageButton
android:id="@+id/btnRemove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@android:color/transparent"
android:gravity="end"
app:srcCompat="@android:drawable/ic_menu_delete" />
</RelativeLayout>
This is how the Design Tab will look like for the task_rows.xml:

We will show the footer when the user taps the Floating Button. Also we will need to change the the icon of button.
The floating button tag will look like ths:
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_input_add" />
When you goto the MainActivity.kt, you will find that there is already an action handler for the fab button. It shows a snacbar at the bottom.
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
We are going to replace this action with a call to one of our own function.
First go ahead and add a Function to showFooter. Add the following function to MainActivity.kt
fun showFooter(){
footer.visibility = View.VISIBLE
fab.visibility = View.GONE
}
In case you get compilations errors here, add the followin imports:
import android.view.View
import kotlinx.android.synthetic.main.activity_main.\*
import kotlinx.android.synthetic.main.content_main.\*
Now replace the OnClickAcionListner with the following code:
fab.setOnClickListener { view ->
showFooter()
}
Let us run the app and see where we have reached in our Firebase Realtime Database and Kotlin tutorial.
[video src="http://neerajjaiswal.com/wp-content/uploads/FirkoTasky-Run-1.mp4" height="470" width="282"][/video]
To get started with Firebase for the project goto menu Tools>Firebase in the Android Studio.

Once you click on it you will get the following wizard on the right. Expand the Firebase Relatime Database section and click on the Save and Retrive data link.

Once you click the link it will open the Firebase Realtime Database Assistant. The Wizard will look like following.

Click on the Connect to Firebase button. Ensure that you are connected to the internet.
If you are already logged into you Firebase Console account in the Android Studio then you will get the following popup. If you are not logged in then it will ask you login to your Firebase Console.

Click on the Connect to Firebase button. Ensure that you are connected to internet. Sometimes you might get an error like below on the bottom right.
> Firebase: Connect to Firebase failed. Please check your internet connection and try again. If errors persist, you can connect manually at https://console.firebase.google.com
If you get something like, just click on the Connect to Firebase once more. If things go as expected this time then you will be shown the following popup.

Just go ahead and click on Sync button. Once everything works as expected you will get a green text Connected mentioned on the Assistant as below.

Next go ahead and click on the "Add the Realtime Database to your app" button. It will show you the following popup warning you about the changes to be made to gradle scripts.

You go ahead and click on "Accept Changes". On Success you will see the following text in the Firebase Assistant tab.

Let move ahead with the Tutorial now that we have the Firebase integerated into the app. In this section we will Save a new Task to the Real Time DB.
We will need to have an Object class for Task in Kotlin, something similar to our good old POJO.

As shown above:

Here is the Kotlin code for the class. Replace the code in the Task.kt file with the following.
package com.appnimiacademy.firkotasky
class Task {
companion object Factory {
fun create(): Task = Task()
}
var objectId: String? = null
var taskDesc: String? = null
var done: Boolean? = false
}
package com.appnimiacademy.firkotasky
object Statics {
@JvmStatic val FIREBASE_TASK: String = "task"
}
Add the following line of code as Class variable in MainActivity.kt. With this code you will be declaring _db as class variable for reference to the Database.
lateinit var _db: DatabaseReference
Add the following import to remove the compilation error.
import com.google.firebase.database.DatabaseReference
Now initialise this variable by adding the following line of code to the onCreate function in MainActivity.kt
_db = FirebaseDatabase.getInstance().reference
Add the following function to the MainActivity class.
fun addTask(){
//Declare and Initialise the Task
val task = Task.create()
//Set Task Description and isDone Status
task.taskDesc = txtNewTaskDesc.text.toString()
task.done = false
//Get the object id for the new task from the Firebase Database
val newTask = _db.child(Statics.FIREBASE_TASK).push()
task.objectId = newTask.key
//Set the values for new task in the firebase using the footer form
newTask.setValue(task)
//Hide the footer and show the floating button
footer.visibility = View.GONE
fab.visibility = View.VISIBLE
//Reset the new task description field for reuse.
txtNewTaskDesc.setText("")
Toast.makeText(this, "Task added to the list successfully" + task.objectId, Toast.LENGTH_SHORT).show()
}
btnAdd.setOnClickListener{ view ->
addTask()
}
As we are just testing we will set the rule as public. To do that just follow the below mentioned steps.

Once done it should look something like this:

Now it is time to run the app once and validate that everthing is working fine. Here are the steps to follow to validate the app.


We have implemented the feature to add a new task. Now let us load the tasks added to the database to the listview.
The ListView needs an Adapter class to make it work.
Let us go ahed and create an adapter class that will be set for the list view.
package com.appnimiacademy.firkotasky
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.CheckBox
import android.widget.ImageButton
import android.widget.TextView
class TaskAdapter(context: Context, taskList: MutableList) : BaseAdapter() {
private val _inflater: LayoutInflater = LayoutInflater.from(context)
private var _taskList = taskList
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val objectId: String = _taskList.get(position).objectId as String
val itemText: String = _taskList.get(position).taskDesc as String
val done: Boolean = _taskList.get(position).done as Boolean
val view: View
val listRowHolder: ListRowHolder
if (convertView == null) {
view = _inflater.inflate(R.layout.task_rows, parent, false)
listRowHolder = ListRowHolder(view)
view.tag = listRowHolder
} else {
view = convertView
listRowHolder = view.tag as ListRowHolder
}
listRowHolder.desc.text = itemText
listRowHolder.done.isChecked = done
return view
}
override fun getItem(index: Int): Any {
return _taskList.get(index)
}
override fun getItemId(index: Int): Long {
return index.toLong()
}
override fun getCount(): Int {
return _taskList.size
}
private class ListRowHolder(row: View?) {
val desc: TextView = row!!.findViewById(R.id.txtTaskDesc) as TextView
val done: CheckBox = row!!.findViewById(R.id.chkDone) as CheckBox
val remove: ImageButton = row!!.findViewById(R.id.btnRemove) as ImageButton
}
}
lateinit var _adapter: TaskAdapter
Add the following code in he OnCreate function.
_adapter = TaskAdapter(this, _taskList!!)
Add the following code just below the above code.
listviewTask!!.setAdapter(_adapter)
Now that the adapter for the listview is set, let us retrieve the data from Firebase Database and load it to the Listview. For that we will have to do some interim operations.
Open the MainActivity class and add the following code to declare a variable for TaskList.
var _taskList: MutableList? = null
Now initialise the variable in OnCreate function.
_taskList = mutableListOf()
Create a function in MainActivity to load the task.
private fun loadTaskList(dataSnapshot: DataSnapshot) {
Log.d("MainActivity", "loadTaskList")
val tasks = dataSnapshot.children.iterator()
//Check if current database contains any collection
if (tasks.hasNext()) {
_taskList!!.clear()
val listIndex = tasks.next()
val itemsIterator = listIndex.children.iterator()
//check if the collection has any task or not
while (itemsIterator.hasNext()) {
//get current task
val currentItem = itemsIterator.next()
val task = Task.create()
//get current data in a map
val map = currentItem.getValue() as HashMap<String, Any>
//key will return the Firebase ID
task.objectId = currentItem.key
task.done = map.get("done") as Boolean?
task.taskDesc = map.get("taskDesc") as String?
_taskList!!.add(task)
}
}
//alert adapter that has changed
_adapter.notifyDataSetChanged()
}
Add a class variable for the Value Event Listener to Main Actvity. Call the loadTaskList from the onDataChange function.
var _taskListener: ValueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
loadTaskList(dataSnapshot)
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Item failed, log a message
Log.w("MainActivity", "loadItem:onCancelled", databaseError.toException())
}
}
Now add the following code at the end in the onCreate function to set the listener.
_db.orderByKey().addValueEventListener(_taskListener)
This is how it looks when the data is loaded to the listview.

Right now when you check or un check the checkbox for Task Completion Status, you nothing will happen. In this section we will write the code to add the functionality.
We will need a listener which will listen to the changes to the Task Rows. For that let us first crate an interfaceclass.
package com.appnimiacademy.firkotasky
interface TaskRowListener {
fun onTaskChange(objectId: String, isDone: Boolean)
}
Let us implement this interaface on MainActity where we are doing all the operations. Make the change to the class declaration so that it looks like the following:
class MainActivity : AppCompatActivity(), TaskRowListener {
You might get compilation errors as you have not implemented the functions of the interface. To do that add the following function to the end of MainActivity.
There needs to be ways in which the listview should be able to convey that that values have changed. To do that you will need to make changes in the Task Adapter.
Add the following class variable to the TaskAdapter.kt class:
private var _rowListener: TaskRowListener = context as TaskRowListener
Now set the listener for the done checkbox in the getView function of Task Adapter class.
listRowHolder.done.setOnClickListener {
_rowListener.onTaskChange(objectId, !done)
}
Run the app. Now when you check or uncheck the done check box the item in the Firebase Database changes its value instantly.

To delete or remove a task you are required to tap on the thrash icon of the Task row. So let us go ahead and implement the functionality.
Let us go ahead and add a function to handle task deleted in TaskRowListener Interface. Add this just below the line for onTaskChange
fun onTaskDelete(objectId: String)
override fun onTaskDelete(objectId: String) {
val task = _db.child(Statics.FIREBASE_TASK).child(objectId)
task.removeValue()
}
Let us set the listener to handle the clicks on the delete button in the TaskAdapter class.
listRowHolder.remove.setOnClickListener {
_rowListener.onTaskDelete(objectId) }
Run the app. Now when you tap on the delete button the item in the Firebase Database is deleted. It is highlighted with red color in the console before it is deleted.

By default the caching is off for Firebase. You can switch it on by adding the following line of code. For this app you can add it in the OnCreate function. For multiple acticity apps you will need to add it to the Application class.
FirebaseDatabase.getInstance().setPersistenceEnabled(true)
So we come to the end of this tutorial. I hope you liked it more than I loved it researching and writing it.
Firebase is an awesome tool which can help you get started with internet based apps withou any knowledge of server side programming.
Using it wisely can help you launch your apps to the world in no time.