Download as pdf or txt
Download as pdf or txt
You are on page 1of 23

Companion App: A mental health tracker built using Flutter

and Firebase.
Project Description
This project involves building a simple app in Flutter that tracks the mental health of its
users and tries to help them get through their condition by suggesting tasks and keeping
record of their progress. Beginners in Flutter will find this project challenging to complete,
intermediate folks might learn new things about accessibility, design practices and
fine-tuning the app for the audience in question and will have fun building the app. Folks
who are at an advanced stage of development might find this project a decent addition to
their portfolio.

Author
Jayesh Sharma

Collaborator(s)
Kevin Paulose, Kiran Suresh

Project Language(s)
Java

Difficulty
Intermediate

Duration
65 hours

Prerequisite(s)
Flutter, Firebase (intermediate)

Overview
Objective
The project focuses on building a mental health tracker. You will try to get an idea of the
mental state of your user (in the least intrusive ways), find out if they are suffering and then
suggest measures they can take to get out of their present condition. A user answers some
questions and based on the answers that they provide, you will suggest tasks to them and
maintain a record of their mental state for displaying on a dashboard.

Project Context
Mental health is an important issue in the world today. With a large population now
working from home and staying away from loved ones, the mental health situation has
deteriorated. As such, it becomes important to track and remedy any problems before they
get too serious. We try achieving this using the Companion App.
Keeping in mind that users might be suffering from mental illness and wouldn't want to
engage much with an app, you'll have to design the app to be very friendly and welcoming.
By the end of this project, you'll have a beautiful and fast app that is fun to use and also
serves your goal. Try implementing the best practices while building the app; the following
sections will detail the implementation goals and suggest some ways to achieve them.

The app's walkthrough can be seen here:


https://www.youtube.com/embed/AdQA9cpkRCk

The file structure for the completed app would be similar to the image below. You can come
back to this image to understand what part of the app you've built and the files that are yet
to be written.
> 111 android
> 111 assets
> llios
V lllib
v 111 Questions
• Question1 .dart
• Question2.dart
• Question3.dart
v 111 Screens
• Dashboard.dart
• DoctorPage.dart
• Login.dart
• Tasks.dart
t authentication.dart
◄ U
• CustomTabBar.dart
• main.dart
> 11 test
1

.gitignore
O .metadata
Ii pubspec.lock
pubspec.yaml
README.md
Project Stages

The project can be broadly classified into three sections:


1) Setting up the UI with the custom tabbar, fullscreen questions and other screens.
2) Adding login and user profile features.
3) Using Firebase Storage to track user information and the state.

Each of these sections have multiple tasks and are covered in detail later.

High-Level Approach
• Build the UI, with the custom tabbar and the Tasks, Dashboard, and Doctor screens.
• Add the questions screen and figure out fullscreen mode. Add double tap to disappear
on the cards.
• Write a simple algorithm to display tasks based on user answers.
• Set-up your Firebase project for authentication and storage.
• Add Google sign-in feature to track user profile.
• Connect your local variables to the Firebase storage to make your app cloud-enabled.

Applications
• This application can be built into a full-fledged health-care app with proper research
and a few additions.
• The skills learnt while building this app will allow you to build commercial and useful
apps in the future.

Task 1
Start building your screens
We will set up the basic skeleton of the app first. Use your creativity to build an intuitive
app and design the elements in such a way that they are appealing to people of all
backgrounds. Make sure the workflow is easy to understand and follow. Ditch any design
choice that would require the user to take a complex route to achieving a goal that can be
done in a simpler way.
If you are building a Flutter app for the first time, refer this page. I recommend installing
VSCode and the Flutter and Dart plugins to start developing apps.

Requirements
• Research about good design practices. Learn how you can make your app more
accessible and user friendly.
• Evaluate your choice of widgets to use; fancier ones are appealing but keep utility in
mind while making the choice. Check here for some cool widgets.
• Create a Flutter project and start designing your screens.
• Build a custom tabbar as shown in the image. To achieve that, you can look up code
online. You don't need to write one on your own.

• Add the Tasks screen, which shows tasks only when your algorithm (see Task 3) tells it
to.
• Add the Dashboard screen; you will show comparison data over a week (or some other
period) here; for instance, "User met x more people this week compared to the last
one".
,.J'\ l
' __,.
,......��L,

PARTY
" ''
Congratulations! You met more people today

Share Dismiss

,.J'\ l
' ,.,,
�w-�L,

( PARTY
�, ..
• Research about the drawer layout options in Flutter and add one to your app.

...

References
• Setting up Flutter app
Expected Outcome
All the screens should be built as shown in the images. The app doesn't have any logic
implemented yet, just the facade. Dashboard.dart, Tasks.dart and CustomTabBar.dart
should be written by this stage.

Bring it On!
• Implement double back press to exit as shown in image below.
Task 2
Questions Screen and UI refinement
This task focuses on making the app friendly to its target audience. You have to remember
that potential users of this app would be suffering from mental illness and as such it won't
be wrong to assume that asking a lot of questions won't be the best choice. In addition, the
mechanism adopted for asking said questions need to be the least intrusive one you can
think of. That way, we get the required information at minimum inconvenience to the
end-user.
Another detail worth mentioning is the double-tap to disappear feature. Once the user is
done with a task, the user can get rid of it from the screen using just a double-tap. Easy,
intuitive and satisfying - just the way we want it!
An important thing to note while building the screens and using the variables that power
your app, is state management.

State Management
There are different options you can take to manage state in your application. I'll list a few of
them below:

Streams (BLoC)
The BLoC principle can be used to provide fast, reactive state management. The changes in
variables are reflected almost instantly.
It however, requires some initial set-up and boilerplate code to get it running. Research
articles on how to build reactive apps on Flutter and this might help you get started on it.

Redux
A familiar way to manage state for web developers. You can look up resources that can get
you up to speed with it.
The Redux package on pub.dev is linked here.

Constructors
You can transfer variables between different screens using their constructors. It is the
easiest way to achieve state management.
It however gets a bit complex with increasing state variables and might lead to
complications, further into development.
You can compare both approaches and see which one works best. You're also free to find
out other best practices to achieve the goal.

Requirements
• Create a full-screen experience for the Questions UI. This is done to avoid any
distractions and make the user focus on just the question on the screen.
• Find out what widgets can be used to get answers from the user in a fun way.

• The questions tab at the top of the Tasks section should only appear once in a day.
Figure out how to implement this.

• The tasks to be done are displayed as cards in the Tasks section. Implement gesture
controlled removal of them once they are completed by the user.
ii

Go o u ! e et a few . eop e tod y


• Use appropriate local variables to enable toggling of the cards visibility and for storing
the answers to the questions (these variables will later be connected to cloud storage).
Refer the state management practices while creating and using these variables.

References
• Hide StatusBar
• Slider class
• Gesture Detector

Tip
• Use bright colors for your questions screen to make them appealing.
• Use widgets like sliders to avoid typing for answers. You are free to use other good
options as well.
• Use animations between the different questions to add flavour to the app. Refer to the
walkthrough video at the top to see what animations I've used.
• Displaying questions only once a day : To achieve this, you can add a variable that
tracks the time at which the questions were answered. Save it along with other state
variables in your cloud database. The code for this could be similar to this block:

Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
(!client.answered && !timeUp) ? askQuestion() : Container()],
)

NOTE: The answered variable is true when the questions have been answered for the day.
timeUp is true when 24 hours have passed since the questions were last displayed.

Bring it On!
• Are there better ways to frame the questions?
• Can you display virtual rewards on completing a question? (Similar to those that pop
up after submitting assignments on the Microsoft Teams app)

Expected Outcome
The UI should be complete by now. Dummy cards in the Tasks section can be removed by
double tapping on them. The questions appear once a day and the UI for asking questions is
complete.
Implementing logic for displaying the tasks and checking if the questions have been
answered for the day, will be completed in the next steps. The Questions directory should
be completed by this stage. The file Tasks.dart would have been modified to implement
the changes mentioned in the Requirements section.

Task 3
Write a simple algorithm
Once you have all the answers to the questions, you will need to determine whether the
person needs help or not. In other words, whether you need to suggest some tasks for them
to feel better. How you achieve this algorithm is largely up to you; the complexity can range
from a simple comparative check to more advanced classification techniques.

Requirements
• Find out the different ways in which you can predict an outcome from a set of known
variables (here, the user answers).
• Implement one of the methods in your app. Add the logic to the Tasks.dart file to
show the activity cards selectively.

References
• Classification in Machine Learning
• Different Classification Techniques

Tip
• You can use a simple threshold check (say, if answer1 > some threshold) to start off.
The algorithm can be tweaked later. It is not the primary focus of the project.
• If you plan on using more sophisticated measures, you'll also need to find a source of
data that complies with your chosen questions. Only then will you be able to accurately
predict outcomes.

Expected Outcome
You should have an algorithm ready that chooses to show or hide the task cards depending
on the answers provided by the user.

Task 4
Set up your Firebase project
We need a backend for our application to provide services like authentication, cloud
storage etc. Firebase is one of the easiest ways to get started with building a backend. You
can learn more about Firebase from the links provided in the References section.
Requirements
• Research about Firebase and the features it offers.
• Learn about other alternatives and why Firebase is being used, in particular.
• Set up your Firebase project for use in future steps and complete configuring your
Flutter app with Firebase.

References
• Some links for Firebase1, 2, and 3
• Firebase vs AWS Lambda
• Firebase Alternatives
• Adding Firebase to your Flutter app

Expected Outcome
You must have created a new project in Firebase and configured your app to work with the
project. See the references for the steps to do the same.
Task 5
Add Google sign-in feature
We are using Firebase for providing authentication services like Google sign-in. Much of the
workflow is very easy to follow and build, and a little research online can help you get
started.

Once Firebase is set up, we can use one of the authentication providers available (like
Google) to add the login feature to our app. This way, user data can be stored and tracked
for use across the app. We can also customise suggestions for the user and control access to
the app as whole. User information procured from the Google account can also be used for
setting up communication with the doctors to prevent users from entering information
again.

Requirements
• Create the login page. I've used the default provided by the library. Add the code in the
Login.dart file.
• Figure out how to set up Google sign-in. Write the code for authentication in a separate
file and plug it into the login page. The code that enables this goes into the
authentication.dart file.
• Verify that you can log a user in and get their information.

References
• Firebase Authentication links1 and 2.
• Login page idea
Tip
• You don't have to design the login page yourselves. Avoid writing code that is easily
available on the internet. I've only added one link for the design, you can find multiple
others, some of which are really cool. Feel free to play around with those ideas.

Bring it On!
• Can you implement password based authentication in your app? Learn more here.
• You can then implement features like sign-up and password reset.
• Try adding other authentication providers (Facebook, Microsoft and such) to supply
options to the user.

Expected Outcome
You should have the login page ready and your app must support logging users in by now.
None of the functionality in the app currently has anything to do with the user currently.
We'll make that connection in the next task.

Task 6
Connect local variables to Firebase storage.
Local variables like the answers to the questions, scores and suggestions for the users
should be tied to the current user account. This can be done by creating cloudstore
documents for the answers.
You should be tracking parameters like when the last answer was provided (recall that you
have to show questions only once in a day), which tasks have been completed by the user
and a record of the mental states and tasks completed over a period of time (say, a week) to
show on the Dashboard. All files that have variables which need to be persisted or to be
made available across the app should have code implemented to connect these variables to
Cloud Firestore.
Developers use the Firebase SDKs for Cloud Storage to upload and download files directly
from clients. Cloud Storage stores your files in a Google Cloud Storage bucket, making them
accessible through both Firebase and Google Cloud.

Requirements
• Explore Cloud Firestore in Firebase. Find out how it's different from a Realtime
Database.
• Design a structure for the documents to be stored on the database.
• Make sure to link the data with the current user.
• Research about using the Firebase library in Flutter to handle Cloud firestore
transactions.
• Connect all local variables to the ones in the document on firestore and implement
code to perform transactions (for example, when the value changes you have to update
the cloud version of the variable too; or fetching the cloud version of the variable for
use in some part of the app).
• Verify that updates from the app are reflected in your Firebase console.

References
• Cloud Firestore or Realtime Database
• Cloud Firestore package
• Extensive guide for using Firestore in Flutter

Tip

Here's one way to design the document. The fields have the following meanings:
1) answered: tracks if all the questions have been answered.
2) hour: tracks at what hour they were answered. Used in the app to figure out if the next
batch of questions has to be displayed yet or not.
3) notDoneX: whether the X number task has been completed by the user or not.
4) uid: The user id to which all these variables belong to.

Bring it On!
• A challenge to solve could be using MySQL instead, for storage. This version would
have local storage and can address privacy concerns and shield against poor network
problems. An implementation of a local database in MySQL can easily be found online
and then integrated into your own app.

Expected Outcome
Your app must be fully ready by now. The user states are saved and tasks are displayed for
each user subject to the answers provided by them.

Task 7
Build for release
Once you have run the app in debug mode on your phone or emulator and you feel that it is
ready to be deployed, we can go ahead with deployment. An optional step before building
your app for release is obfuscating your code.Obfuscation hides function and class names in
your compiled Dart code, making it difficult for an attacker to reverse engineer your
proprietary app. Your application backend is already deployed on Firebase.

Requirements
• Make sure your Cloud Firestore has the correct rules for deployment. Check this link to
learn more about Firebase security and rules.
• Follow the steps here to build your Android app for release.
• Follow the steps here to build your iOS app for release.

References
• Publish your app to Google Play Store
• Flutter build modes

Bring it On!
• Set up a continuous delivery pipeline for your Flutter app. Refer this link to learn more.

Expected Outcome
Your app must now be ready to be rolled into app stores.

You might also like