How to Create a Medicine Tracker Android App with Firebase?
Last Updated :
20 Aug, 2024
A medicine tracker app can be a useful tool for individuals who need to take multiple medications on a regular basis. It can help users track when they need to take their medications and provide alerts and reminders to ensure they don't miss a dose. This article will look at how to build a medicine tracker app using Kotlin and Firebase. A sample video is given below to get an idea about what we are going to do in this article.
Step-by-Step Implementation
Step 1: Create a New Project in Android Studio
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.
Step 2: Set up the development environment
Add firebase real-time database dependency in build.gradle(app) file
implementation 'com.google.firebase:firebase-database-ktx:20.1.0'
Add View binding inside android{} block in build.gradle(app) file
XML
buildFeatures {
viewBinding = true
}
Step 3: Create a new Firebase Project
Have a look at Adding Firebase to Android App also add a Real-time database to your firebase project.
Step 4: Design the app's user interface
Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. Comments are added inside the code to understand the code in more detail.
Note: New Activity to Add Medicines and activity_medicine_add fragment.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/medicine_layout">
</androidx.recyclerview.widget.RecyclerView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="15dp"
android:layout_marginBottom="15dp"
app:srcCompat="@android:drawable/ic_input_add"
tools:layout_editor_absoluteX="254dp"
tools:layout_editor_absoluteY="360dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_medicine_add.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".MedicineAddActivity">
<EditText
android:id="@+id/etMedicineName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textSize="20dp"
android:background="@color/white"
android:hint="Enter Medicine Name"
android:textColor="@color/black">
</EditText>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="100"
android:orientation="horizontal">
<TextView
android:id="@+id/etMedicineTime"
android:layout_width="50dp"
android:layout_height="50dp"
android:text="Medicine Time"
android:textSize="20dp"
android:layout_weight="50"
android:textAlignment="center"
android:textColor="@color/black"
android:padding="10dp"
android:layout_margin="10dp">
</TextView>
<ImageView
android:id="@+id/selectTime"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="50"
android:padding="10dp"
android:layout_margin="10dp"
android:src="@drawable/ic_baseline_access_time_24">
</ImageView>
</LinearLayout>
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Save">
</Button>
</LinearLayout>
medicine_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".MedicineAddActivity">
<EditText
android:id="@+id/etMedicineName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textSize="20dp"
android:background="@color/white"
android:hint="Enter Medicine Name"
android:textColor="@color/black">
</EditText>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="100"
android:orientation="horizontal">
<TextView
android:id="@+id/etMedicineTime"
android:layout_width="50dp"
android:layout_height="50dp"
android:text="Medicine Time"
android:textSize="20dp"
android:layout_weight="50"
android:textAlignment="center"
android:textColor="@color/black"
android:padding="10dp"
android:layout_margin="10dp">
</TextView>
<ImageView
android:id="@+id/selectTime"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="50"
android:padding="10dp"
android:layout_margin="10dp"
android:src="@drawable/ic_baseline_access_time_24">
</ImageView>
</LinearLayout>
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Save">
</Button>
</LinearLayout>
Step 5: Create MedicineAlarmReceiver class for notifications
This class, named "MedicineAlarmReceiver", is a subclass of the Android class "BroadcastReceiver" and is used to receive broadcast notifications.
Kotlin
class MedicineAlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Create the notification channel (required for Android 8.0 and higher)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// unique id for the channel
val channelId = "medicine_reminders"
// name of the channel
val channelName = "Medicine Reminders"
// importance level of the channel
val importance = NotificationManager.IMPORTANCE_HIGH
// creating channel
val channel =
NotificationChannel(channelId, channelName, importance)
// enabling lights for the channel
channel.enableLights(true)
// setting light color for the channel
channel.lightColor = Color.RED
// enabling vibration for the channel
channel.enableVibration(true)
val notificationManager = context.getSystemService(NotificationManager::class.java)
notificationManager?.createNotificationChannel(
channel
) // registering the channel with the system
}
// Create the notification
// unique id for the notification
val notificationId = 1
// title of the notification
val title = "Medicine Reminder"
// text of the notification
val text = "It's time to take your medicine."
val intent =
Intent(
context,
MainActivity::class.java
) // intent to launch when the notification is clicked
val pendingIntent =
PendingIntent.getActivity(
context,
0,
intent,
0
) // creating a pending intent to wrap the intent
// creating the builder object
val builder =
NotificationCompat.Builder(context, "medicine_reminders")
.setSmallIcon(
R.drawable.ic_baseline_mediation_24
) // setting the small icon for the notification
.setContentTitle(title) // setting the title for the notification
.setContentText(text) // setting the text for the notification
.setContentIntent(pendingIntent) // attaching the pending intent to the notification
.setAutoCancel(
true
) // setting the notification to be automatically cancelled when clicked
.setPriority(
NotificationCompat.PRIORITY_HIGH
) // setting the priority level of the notification
// Display the notification
// getting the notification manager
val notificationManager =
NotificationManagerCompat.from(context)
// displaying the notification
notificationManager.notify(notificationId, builder.build())
}
}
Step 6: Create a data class User
Kotlin
data class User (
val medicineName : String ,
val time : String
)
Step 7: Create UserAdapterClass for recycler View
Kotlin
class UserAdapter(private val list: ArrayList<User>) :
RecyclerView.Adapter<UserAdapter.ViewHolder>() {
// ViewHolder to hold reference to each item of the recycler view
class ViewHolder(val binding: MedicineLayoutBinding) : RecyclerView.ViewHolder(binding.root) {}
// inflating the layout and creating the ViewHolder when needed
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
MedicineLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
// binding data to the view in the viewholder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.name.text = list[position].medicineName
holder.binding.time.text = list[position].time
}
// returning the size of the data set
override fun getItemCount(): Int {
return list.size
}
}
Step 8: Create a new activity MedicineAdd and add these lines of code to it
We will be using a TimePicker dialog in this activity in order to add medicine time.
Kotlin
class MedicineAddActivity : AppCompatActivity(), TimePickerDialog.OnTimeSetListener {
// reference to the database
private lateinit var database : DatabaseReference
// reference to the layout binding object
private lateinit var binding: ActivityMedicineAddBinding
// variables to store the current time
var hours = 0
var minutes = 0
// variables to store the selected time
var myHours : Int = 0
var myMinutes : Int= 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// inflating the layout and binding it to the binding object
binding = ActivityMedicineAddBinding.inflate(layoutInflater)
setContentView(binding.root)
// setting a click listener on the select time button
binding.selectTime.setOnClickListener{
val cal = Calendar.getInstance()
// getting the current time
hours = cal.get(Calendar.HOUR)
minutes = cal.get(Calendar.MINUTE)
// creating a new time picker dialog
val timePickerDialog = TimePickerDialog(this,this,hours,minutes,true)
timePickerDialog.show()
}
}
// method called when the user sets the time on the time picker dialog
override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
myHours = hourOfDay
myMinutes = minute
// updating the text view that displays the selected time
binding.etMedicineTime.text = "$myHours:$myMinutes"
// setting a click listener on the save button
binding.save.setOnClickListener{
saveData()
}
}
}
Step 9: Save Data in firebase real-time database
The method starts by getting an instance of the FirebaseDatabase and getting a reference to the "Users" node in the database. The method then retrieves the value of the text from the "etMedicineName" TextView, trims it, and stores it in the variable medicineName.
Kotlin
private fun saveData() {
// Reference to the "Users" node in the Firebase Database
database = FirebaseDatabase.getInstance().getReference("Users")
// Retrieve the value of the text from the "etMedicineName" TextView
val medicineName = binding.etMedicineName.text.toString().trim()
// Create a string with the selected time in the format "hours:minutes"
val time = "$myHours:$myMinutes"
// check if the medicineName is not empty
if (medicineName.isNotEmpty()){
// create a new User object with the
// entered medicine name and selected time
val user = User(medicineName,time)
// save the user object to the Firebase Database
// under the "medicineName" key
database.child(medicineName).setValue(user).addOnSuccessListener {
// Clearing the EditText after saving the data
binding.etMedicineName.text.clear()
binding.etMedicineTime.text = "Select Time"
Toast.makeText(this, "Success: Data saved to Firebase", Toast.LENGTH_SHORT).show()
}.addOnFailureListener{
Toast.makeText(this, "Error: Failed to save data to Firebase", Toast.LENGTH_SHORT).show()
}
}
// call the setAlarm method to
// set the alarm based on the selected time
setAlarm()
}
Step 10: Set Alarm for medicine
The method starts by getting an instance of the AlarmManager service and creating a new Intent for the MedicineAlarmReceiver class. Then, it creates a PendingIntent that wraps the intent and requests the broadcast to be delivered to the MedicineAlarmReceiver
Kotlin
private fun setAlarm() {
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, MedicineAlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0)
// Set the alarm to trigger at the specified time
val calendar = Calendar.getInstance()
calendar.timeInMillis = System.currentTimeMillis()
calendar.set(Calendar.HOUR_OF_DAY, myHours)
calendar.set(Calendar.MINUTE, myMinutes)
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
}
Step 11: Implement MainActivity
In this step, we’ll implement the MainActivity, which will display the list of medicines and provide an interface for adding new medicines
MainActivity.kt
package com.example.medicinetracker
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.medicinetracker.databinding.ActivityMainBinding
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var database: DatabaseReference
private lateinit var userAdapter: UserAdapter
private val medicineList = mutableListOf<User>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Initialize Firebase Database
database = FirebaseDatabase.getInstance().reference.child("Users")
// Set up RecyclerView
userAdapter = UserAdapter(medicineList)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = userAdapter
// Load medicines from Firebase
loadMedicines()
// Set up "Add Medicine" button
binding.btnAddMedicine.setOnClickListener {
val intent = Intent(this, MedicineAddActivity::class.java)
startActivity(intent)
}
}
private fun loadMedicines() {
database.addValueEventListener(object : com.google.firebase.database.ValueEventListener {
override fun onDataChange(snapshot: com.google.firebase.database.DataSnapshot) {
medicineList.clear()
for (medicineSnapshot in snapshot.children) {
val medicine = medicineSnapshot.getValue(User::class.java)
medicine?.let { medicineList.add(it) }
}
userAdapter.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {
// Log the error
Log.e("MainActivity", "Error loading medicines: ${error.message}")
// Display a user-friendly message
Toast.makeText(this@MainActivity, "Failed to load medicines. Please try again later.", Toast.LENGTH_LONG).show()
}
})
}
}
Output:
Similar Reads
How to Create Dynamic WebView in Android with Firebase?
Converting a website into an application seems like a basic task to do on Android. With the help of WebView, we can show any webpage in our Android Application. We just have to implement the widget of WebView and add the URL inside the WebView which we have to load. So if you are looking for loading
6 min read
How to Create Dynamic PDF Viewer in Android with Firebase?
If you are creating apps for students or for educational purposes then you need to add some PDF files for displaying some data inside our app. These PDF files are updated on regular basis. For loading this PDF from the server we prefer to use PDF Viewer which will load the PDF from the URL in Androi
7 min read
How to Delete a Firebase User from Android App?
We have seen in many of the apps that if have the choice to delete the user or can say your account permanently. Here we are going to see how we can implement that in our app and can delete our account permanently from the firebase authentication. Here while writing our code we will remove the user
3 min read
How to Create Language Translator in Android using Firebase ML Kit?
In the previous article, we have seen using Language detector in Android using Firebase ML kit. In this article, we will take a look at the implementation of Language translator in Android using Firebase ML Kit in Android. What we are going to build in this article? We will be building a simple appl
5 min read
How to Create a Social Media App on Android Studio?
Social media is not a new term for us. Our daily life is incomplete, or we can say we human beings survive on food, water, air, and social media. We are dependent to such an extent that we tend to share every bit of information about ourselves on social media platforms. Similarly, Android Studio is
8 min read
How to Create a Chatbot in Android with BrainShop API?
We have seen many apps and websites in which we will get to see a chatbot where we can chat along with the chatbot and can easily get solutions for our questions answered from the chatbot. In this article, we will take a look at building a chatbot in Android. What we are going to build in this artic
11 min read
How to create a Face Detection Android App using Machine Learning KIT on Firebase
Pre-requisites:Firebase Machine Learning kitAdding Firebase to Android AppFirebase ML KIT aims to make machine learning more accessible, by providing a range of pre-trained models that can use in the iOS and Android apps. Let's use ML Kitâs Face Detection API which will identify faces in photos. By
8 min read
How to Build a Simple TikTok Clone Android App using Firebase?
TikTok is a mobile application that can be downloaded on smartphones and tablets. It is available on both iOS and Android operating systems and can be downloaded for free from the respective app stores. TikTok is a social media platform where users can view short video content i.e. 15 to 60 secs. A
5 min read
How to Build a QR Code Android App using Firebase?
QR (Quick Response) code is a type of two-dimensional barcode that contains information encoded in a pattern of black and white squares. It was first developed in 1994 by a company named Denso Wave. Qr codes can be scanned by a smartphone or a dedicated QR code scanner, which uses the device's camer
6 min read
How to Use Performance Console in Firebase with Android?
You can use the Firebase Performance Monitoring service to learn more about the performance traits of your Apple, Android, and web apps. As you roll out new features or make configuration changes, Firebase Performance Monitoring, a real-time app performance monitoring tool, enables you to keep a clo
6 min read