University Politehnica of Bucharest [606599]

University ―Politehnica‖ of Bucharest
Faculty of Electronics, Telecommunications and Information Technology

Android application for classrooms reservation using machine readable QR code

Diploma Thesis

submitted in partial fulfillment of the req uirements for the Degree of Engineer in the domain
Electronics and Telecommunications study program Applied Electronics (ETC -ELAeng)

Thes is Advisors Student
Ș.L.Dr.Ing. Ioana DOGARU Andrei -Traian Mândriș
Prof.Dr.Ing. Radu DOGARU

Year 2018

Table of contents

List of figures ………………………….. ………………………….. ………………………….. ………………………….. …………………….. 9
List of abbreviations ………………………….. ………………………….. ………………………….. ………………………….. ………… 11
Introduction ………………………….. ………………………….. ………………………….. ………………………….. ……………………. 13
CHAPTER 1. Relevant theoretical concepts ………………………….. ………………………….. ………………………….. ….. 15
1.1 Object Oriented Programming Principles ………………………….. ………………………….. ………………………… 15
1.2 SOLID OOP Software Design Principles ………………………….. ………………………….. ………………………….. 17
CHAPTER 2. Technologies used ………………………….. ………………………….. ………………………….. …………………… 19
2.1 Java Programming Language ………………………….. ………………………….. ………………………….. ……………… 19
2.2 Android Operating System ………………………….. ………………………….. ………………………….. ………………….. 20
2.3 Android Studio ………………………….. ………………………….. ………………………….. ………………………….. ……….. 26
2.4 Google Firebase Cloud Platform ………………………….. ………………………….. ………………………….. ………….. 28
2.5 OAuth 2.0 Protocol ………………………….. ………………………….. ………………………….. ………………………….. …. 29
2.6 Gradle Build System ………………………….. ………………………….. ………………………….. ………………………….. .. 30
2.7 Git Versioning Control System ………………………….. ………………………….. ………………………….. ……………. 34
CHAPTER 3. Software Design and Implementation ………………………….. ………………………….. ………………….. 37
3.1 User’s Authentication and Registration ………………………….. ………………………….. ………………………….. .. 37
3.2 Main Activit y ………………………….. ………………………….. ………………………….. ………………………….. …………. 39
3.3 Scan QR Activity ………………………….. ………………………….. ………………………….. ………………………….. ……. 41
3.4 Model Classes ………………………….. ………………………….. ………………………….. ………………………….. …………. 42
3.5 Database Stru cture ………………………….. ………………………….. ………………………….. ………………………….. …. 45
CHAPTER 4. Application Walkthrough and UI Presentation ………………………….. ………………………….. ……. 49
Project conclusions ………………………….. ………………………….. ………………………….. ………………………….. ………….. 59
Bibliography ………………………….. ………………………….. ………………………….. ………………………….. ……………………. 61
Annexes ………………………….. ………………………….. ………………………….. ………………………….. ………………………….. . 63

List of f igures

Fig. 1. 1 Snippet exemplifying encapsulation principle ………………………….. ………………………….. …………………… 15
Fig. 1. 2 Snippet exemplifying encapsulation principle ………………………….. ………………………….. …………………… 15
Fig. 1. 3 Snippet exemplifying polymorphism principle ………………………….. ………………………….. ………………….. 16
Fig. 1. 4 Snippet exemplifying abstraction principle ………………………….. ………………………….. ……………………….. 16
Fig. 2. 1 Android Operating System Architecture ………………………….. ………………………….. ………………………….. . 21
Fig. 2. 2 Lifecycle of an Activity ………………………….. ………………………….. ………………………….. ……………………… 25
Fig. 2. 3 Android Studio IDE ………………………….. ………………………….. ………………………….. ………………………….. 27
Fig. 2. 4 Project structure (Project view) ………………………….. ………………………….. ………………………….. …………… 31
Fig. 2. 5 Project structure (Android view) ………………………….. ………………………….. ………………………….. …………. 31
Fig. 2. 6 Snippet of settings.gradle file ………………………….. ………………………….. ………………………….. ……………… 31
Fig. 2. 7 Snippet of Top -level Gradle build file ………………………….. ………………………….. ………………………….. …. 32
Fig. 2. 8 Example of App Level Gradle file ………………………….. ………………………….. ………………………….. ………. 33
Fig. 2. 9 Diagram of Git versioning control concept [22] ………………………….. ………………………….. ………………… 34
Fig. 2. 10 Working directory, staging area and git directory [22] ………………………….. ………………………….. ……… 35
Fig. 3. 1 Snippet of signing method ………………………….. ………………………….. ………………………….. ………………….. 37
Fig. 3. 2 Snippet of Google authentication method ………………………….. ………………………….. …………………………. 38
Fig. 3. 3 Snippet of registering method ………………………….. ………………………….. ………………………….. …………….. 39
Fig. 3. 4 Snippet of switching from LoginActivity to MainActivity ………………………….. ………………………….. ….. 39
Fig. 3. 5 Snippet showing the method implementation for moving to another Fragment ………………………….. ….. 40
Fig. 3. 6 Snippet with logout call method ………………………….. ………………………….. ………………………….. ………….. 40
Fig. 3. 7 Snippet with the start of the ScanQRActivity ………………………….. ………………………….. ……………………. 40
Fig. 3. 8 Snipping of the method which checks the permission for camera ………………………….. …………………….. 41
Fig. 3. 9 Snipping of the method which requests the permission ………………………….. ………………………….. ………. 41
Fig. 3. 10 UML D iagram for the model classes ………………………….. ………………………….. ………………………….. …. 42
Fig. 3. 11 Snippet with checkStartTimeAvailability method ………………………….. ………………………….. ……………. 43
Fig. 3. 12 Snippet with checkEndTimeA vailability method ………………………….. ………………………….. …………….. 44
Fig. 3. 13 Snippet of sortIntervals() method ………………………….. ………………………….. ………………………….. ………. 44
Fig. 3. 14 Snippet of bookClassroom() method ………………………….. ………………………….. ………………………….. ….. 44
Fig. 3. 15 Firebase NoSQL Database data storage JSON format ………………………….. ………………………….. ………. 45
Fig. 3. 16 Snippet with the save to database method ………………………….. ………………………….. ……………………….. 46
Fig. 3. 17 Snippet with onDataChange() method ………………………….. ………………………….. ………………………….. .. 46
Fig. 4. 1 Login Screen ………………………….. ………………………….. ………………………….. ………………………….. ……….. 49
Fig. 4. 2 Authentication using Google Sign on ………………………….. ………………………….. ………………………….. ….. 50
Fig. 4. 3 User Registration screen ………………………….. ………………………….. ………………………….. …………………….. 50
Fig. 4. 4 Calendar View ………………………….. ………………………….. ………………………….. ………………………….. ……… 51
Fig. 4. 5 Side Drawer Menu ………………………….. ………………………….. ………………………….. ………………………….. .. 52
Fig. 4. 6 Classroom List ………………………….. ………………………….. ………………………….. ………………………….. …….. 53
Fig. 4. 7 List of Events with ticked checkbox ………………………….. ………………………….. ………………………….. ……. 54
Fig. 4. 8 Events List for a classroom in a specific day ………………………….. ………………………….. …………………….. 54
Fig. 4. 9 Ending Time Picker ………………………….. ………………………….. ………………………….. ………………………….. . 55
Fig. 4. 10 Stating Time Picker ………………………….. ………………………….. ………………………….. …………………………. 55
Fig. 4. 11 Camera permission granted ………………………….. ………………………….. ………………………….. ………………. 56

Fig. 4. 12 QR Code Scan Activity Camera Request ………………………….. ………………………….. ………………………… 56

List of abbreviations

API – Application programming interface
OS – Operating System
USB – Universal Serial Bus
SE – Standard Edition
EE – Enterprise Edition
JVM – Java virtual machine
QR – Quick Response
OAuth – Open Authorization
SQL – Structured Query Language
NoSQL – Not only SQL
LTE – Long Term Evolution
NFC – Near Field Communication
GSM – Global System for Mobi le
CPU – Central Processing Unit
CI – Continuous In tegration
JSON – JavaScript Object Notation

13
Introduction

As technology improves, people are provided with new tools which can be used on day to day
activities in order to ease and speed things up. One of the main concerns regarding studying in a
modern environment consists in the effective coordination regarding the reservation of the classrooms
for holding classes.
Quite frequently, professors have hard times in finding an available classroom for a custom
activity, hence this paper proposes classroom bo oking application to address this need.
First off, every professor installs the application on their mobile phones, creates an account and
use it in order to effectively manage the time spent in finding an adequate classroom.
Secondly, all the users of the application also have the option of scanning a QR code that can
be found located on each door of all the classrooms. The scanning result will be processed by the
software app and will send the user to a different screen where he has the possibility to see the schedule
of the specific classroom on that date and also the option to book it for an interval of time. Thus, the
user does not have to browse through all the list of classrooms until he finds the room he’s standing
near it and by this, more time g ets saved.
There is an entire history for reserving methods which could be roughly broken down as
follows. Firstly, it started with people using only papers and writing tools for keeping track of all kind
of events taking place and after a while these meth ods have been replaced by software programs which
contained implementations of booking processes.
A few examples of this kind of type of applications which deliver appointment management
features are Microsoft Outlook, Thunderbird and many others.
The only issue, regarding the desktop version of these booking management applications, that
has been discussed about so far, is that they lack flexibility when it comes to where a user can set an
appointment from, but fortunately smartphones era has begun. Mobile applications running on different
operating systems such as Android, iOS, Windows OS, BlackBerry OS, Symbian, have been developed
over the last years.
On the other hand, QR technology has also been dramatically improved in the recent years and
has a long history which started with barcodes which were heavily used in inventory tracking. The
entire transaction is facilitated by the few characters of information held in the barcode on the item. But
even very shortly after their introduction, their limitation s were clear. There was an almost instant
demand to be able to encode more than just the 20 alphanumeric characters the traditional barcode
could hold. It soon became clear that in order to achieve speed and flexibility in a 2D code, that
positioning eleme nts were critical. [2]
Standard barcodes are interpreted along a single axis, this making them known as 1D or one –
dimensional codes. This single axis of data limits the amount of data available but makes the code
easily read by a scanner. QR codes are read along the X and Y axis, making them 2D or two –
dimensional codes. This allows more data to be stored inside the same area as a barcode. Due to the

14
complexity of the layout, some scanning devices may not scan the code correctly as it may be too small
to be r ead.[2]
The graduation thesis is split into three parts as follows:
First chapter consists of the theoretical part that brings along relevant software concepts and
software principles used in order to devise the solution. Here are described ideal software notions for
software architectural design.
Second chapter consists of the theoretical part, where all the technologies used in order to create
the practical part are enumerated and broadly described, specifying technical specifications along with
examples and schematics. Software tools which proved to be very helpful and assured the creation of
the application, such as integrated development environments, version control systems, build
automation systems, will also be presented and discussed upon.
Third ch apter describes the architecture of the application going through each activity that
together make the business logic of the solution. Specific significant sections of the source code which
together form the basic functionalities of the application, along with different application programming
interfaces (APIs) that have been used will be pointed out and detailed. Withal, the way the transactions
are being done, saving all the intervals of events together with the user who has done the reservation is
going to be exemplified describing the API provided by Google through the Firebase cloud platform.
Fourth chapter will consist in a walkthrough of the application, navigating through different
screens and following an actual use -case accompanied by screenshots.
In conclusion , taking into account the benefits of having a dedicated mobile application which
can handle the reservation process and integrate with a scanner which can scan a QR code, the solution
would considerably reduce the effort, the time spent and t he number of possible unwished conflicts.

15
CHAPTER 1. Relevant theoretical concepts

1.1 Object Oriented Programming Principles

1. Encapsulation – is the programming principle in which all the variables belonging to a class are getting
their ac cess modifier set as private and the only way the variables can be accessed is through getters
and setters, of course with the exception of java reflection techniques. By using this principle relevancy
of values gets improved by setting up certain rules wh ich can process the argument of the setter
method.

Fig. 1. 1 Snippet exemplifying encapsulation principle

2. Inheritance – is the principle which most of all represents an advantage when it comes to code
reusability. Classes can be extended and as a result, their children inherit all the methods and fields
which have an adequate access modifier.

Fig. 1. 2 Snippet exemplifying encapsulation principle

16
Class Dog will inherit the fields name and weight and also the method run.

3. Polymorphism – is the ability of an object to take on many forms. The most common use of
polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.[4]

Fig. 1. 3 Snippet exemplifying polymorphism principle

Therefore, the instance d will have all the methods from the class/interface which it is defined by, but
will use the overridden methods .

4. Abstraction – is the process in which all the details of implementation a re not displayed directly to the
user, only the functionality will be provided to the user. In other words, the user will have the
information on what the object does instead of how it does it. This thing can be achieved in Java using
abstract classes and interfaces .[4]
If an abstract class has abstract methods, all concrete classes which extend the abstract class must
provide an implementation for those methods.

Fig. 1. 4 Snippet exemplifying abstraction principle

17
1.2 SOLID O OP Software Design Principles

SOLID represents one of the most used standards from architectural design standpoint in
object -oriented software programming. Each letter in the abbreviation stands for a principle:
 Single Responsibility Principle
 Open/Close d Principle
 Liskov Substitution Principle
 Interface Segregation Principle
 Dependency Inversion

Single Responsibility Principle – ―A class should have one, and only one, reason to change.‖ ( Robert
C. Martin )
This principle makes software easier to be implemented and unexpected side -effects that might
be generated by future changes are prevented. It is quite known that requirements are not fixed and they
frequently change over time in such a way that they impact t he responsibility of at least one class. The
bigger the number of responsibilities of a class, the harder it gets impacted by changes. Also, all classes
or components which depend on the changed class are impacted as well.[8]
Therefore this principle stat es that a class should be built only for one single purpose, this way
avoiding all the mentioned problems.

Open/Closed Principle – Software entities such as classes and functions should be open for extension
but close for modification. Basically, develope rs should use the classes in the way they want without
modifying them. In case there is the need for a different behavior for a certain class, it should not be
modified, but instead it should be extended and inside the child class should be applied the nec essary
edits.

Liskov Substitution Principle – Subtypes must be substitutable for their base types. Named after
Barbara Liskov who first formulated it in 1988, this is the principle at the heart of any class inheritance
chain. If someone writes a function or a class that uses a parameter or a variable of some base class
then it should be able to pass an instance of some descendant class and the behavior should remain
exactly the same.
Suppose there is a class called Bird, that has a method fly, then there could be written a
descendant class Duck that overrode that method to do something pertaining to how ducks fly.
Everywhere that is expected an instance of Bird, could be passed an instance of Duck and everything
would perfectly work until an Ostrich class is creating which extends Bird. The problem here is that
although an Ostrich instance is substitutable for a Bird instance, it introduces a new breaking change to
every place a Bird is asked to fly resulting in an exception being thrown because ostriches don’t fly.
This descendant class breaks the Liskov substitution principle by introducing new behavior into
existing code by writing a descendant to the base class.

18
Interface Segregation Principle – Classes that implement interfaces should not be forced t o
implement methods they do not use.
Suppose there is an interface Stream which has methods like read and write. If there will be a
class called ReadOnlyDevice which implements this interface because it handles operations with data
streams, it will be for ced to offer an implementation for the write method as well. A class which
implements an interface must implement all methods provided by that interface. That is why interfaces
should be segregated into small ones, in this case it would’ve served better if the interface Stream was
split into InputStream interface with read method and OutputStream interface with write method.

Dependency Inversion Principle – High level modules should not depend on low level modules, both
should depend on abstraction. Abstra ctions should not depend on details, details should depend on
abstractions. Instead of depending on a concrete implementation it is better to depend on an interface,
then using the Liskov Substitution principle, an implementation to that interface could be written that
would stand in perfectly for the interface itself. [9]
By applying all the explained SOLID principles in software development things like low coupling, high
cohesion, and strong encapsulation can be achieved.

19
CHAPTER 2 . Technologies used

2.1 Java Programming Language

Java programming language was initially developed by Sun Microsystems which was
introduced by James Gosling and released in 1995 as central component of Sun Microsystems Java
platform (Java 1.0 [J2SE]) which after that was acquired by Oracle .[4]
The newest release of the Java Standard Edition is Java SE 8. With the progression of Java and
its widespread fame , multiple configurations were built to be able to be compatible with different types
of platforms. F or example: J2EE for Enterprise Applications, J2ME for Mobile Applications.
The new J2 forms were renamed as Java SE, Java EE, and Java ME respectively. Java is
guaranteed to be Write Once, Run Anywhere. [4]
Java is:
 Object Oriented − In Java, everything is an Object. Java can be easily extended since it is based on the
Object model.
 Platform Independent − unlike many other programming languages including C and C++, when Java is
compiled, it is not compiled into platform specific machine, rather into platfor m independent byte code.
This byte code is distributed over the web and interpreted by the Virtual Machine (JVM) on whichever
platform it is being run on.
 Simple − Java is designed to be easy to learn. If the basic concept of OOP Java are known and
underst ood, it would be easy to master the programming language .
 Secure − With Java's secure feature it enables to develop virus -free, tamper -free systems.
Authentication techniques are based on public -key encryption.
 Architecture -neutral − Java compiler generate s an architecture -neutral object file format, which makes
the compiled code executable on many processors, with the presence of Java runtime system.
 Portable − Being architecture -neutral and having no implementation dependent aspects of the
specification m akes Java portable.
 Robust − Java makes an effort to eliminate error prone situations by emphasizing mainly on compile
time error checking and runtime checking.
 Multithreaded − With Java's multithreaded feature it is possible to write programs that can per form
many tasks simultaneously. This design feature allows the developers to construct interactive
applications that can run smoothly.
 Interpreted − Java byte code is translated on the fly to native machine instructions and is not stored
anywhere. The deve lopment process is more rapid and analytical since the linking is an incremental
and light -weight process.
 High Performance – With the use of Just -In-Time compilers, Java enables high performance.
 Distributed − Java is designed for the distributed environm ent of the internet.

20
2.2 Android Operating System

Android is an operating system for mobile which was developed by Google corporation,
starting from a changed version of the Linux kernel together with other open source software and
primarily created fo r mobile devices with touchscreen feature such as tablets and smartphones.[7]
Android has been the main player in the market standing out as a game -changing platform for
the mobile development community. An innovative and open source p latform, Android is r esponding
to the increasing demands of the marketplace as it continues to expand to new types of devices beyond
phones and tablets, and further penetrates the far regions of the globe. [11]
The applications that represent an extension of the devices’ functionalities are written using
Android software development kit, and, frequently, using Java programming language leveraging the
Java libraries provided by Google. Other programming languages are also supported such as C, C++
and Kotlin, the support provide d by Google for the latter one being announced recently in 2017.
Google’s pr ogramming language, Go, is also supported but does not have rich applications
programming interfaces.[7]
A few of the core characteristics of Android Operating System are:
 Graph ical Interface
Android's default user interface is mainly based on direct manipulation , using touch inputs that loosely
correspond to real -world actions, like swiping, tapping, pinching, and reverse pinching to manipulate
on-screen objects, along with a virtual keyboard .
 Connectivity
Android accepts technologies for connectivity integration including GSM /EDGE , Bluetooth , LTE,
NFC . [13]
 Data Storage
Android has a dedicated database software which takes care of data storage, called SQLite.
 Development Environment
Android includes a software which emulates mobile devices and it also includes a debugger.
 Supported media files
Android a ccepts a wide range of media files formats. Some of them are:
– Audio: AAC LC, MP3, PCM/WAVE, AMR -NB
– Video: MPEG -4 SP, VP9, H.264 AVC Baseline Profile (BP) [13]
 Memory management
Because of the fact that mobile devices which run on Android are battery -powered, Android is
designed to manage processes to keep power consumption at a minimum. When an application is not in
use the system suspends its operation so that, while availab le for immediate use rather than closed, it
does not use battery power or CPU resources.
 Instant messaging
SMS and MMS are forms of instant messaging available.

21

Android operating system is an open source technology stack that has surpassed the number o f
400 million devices that it runs on, worldwide. This operating system is made of a wide range of
components which allow software developers and device manufacturers to work independently. [5]

This technology can be split in five groups of primary pie ces as follows:
 Applications
 Application frameworks
 Native libraries
 Android runtime
 Linux kernel

Fig. 2. 1 Android Operating System Architecture

22
1. Applications level – this is the level where all the application that a user can a ccess are located. There
are plenty of applications that come with Android operating system which most of them are being used
by users on a daily basis, applications which fulfill features such as making phone calls, sending
messages, sending emails, brows ing the Internet etc.
Other third -party applications which are also part of the Applications level can be downloaded and
installed on the device most commonly from Google Play Store, or by simply installing them via an
USB connection or from an SD card.[5]

2. Application Framework level – android operating system provides developers different tools and ways
to devise interactive, rich, visual, out of the box components in order to expose them to the users
through applications. Developers are provided with s ome services which offer them access to APIs that
are also used inside the main applications. Some of these services are:
a. Activity Manager -> all the concerns regarding communication between applications and their
lifetime are handled by the Activity Ma nager
b. Window Manager -> each display is bound to an instance of Window Manager [6]
c. Content Providers -> provides a way for applications to access the data they have stored[6]
d. Notification Manager – this service notifies the user of events that hap pen. This is how a user knows
that something in the background has happened.[6]
e. Telephony Manager – provides access to information about the telephony services on the device.[6]
f. Location Manager -> provides access to location services.
g. XMPP Servic e – communications protocol for message -oriented middleware based on XML
(Extensible Markup Language). It enables the near -real-time exchange of structured yet extensible data
between any two or more network entities, most used in chat messaging.
h. View S ystem -> set of views most commonly used for building up application interfaces.

3. Native Libraries Level – at this level native libraries and Android runtime are located in this same
place. Native libraries are the ones which are compiled and preinstalle d C/C++ binaries that the
Android operating system depends on.
Some of the libraries are:
a. Surface Manager – it is used for designing what each individual screen will be looking like. It also
takes care of some more discrete things that help Android run optimally, for instance transitions and
off-screen buffering.
b. SQLite – database which is used to save the information exchanged across the sessions of an Android
device and it is stored inside the internal memory of the device.
c. WebKit – it is the def ault browser engine in the Android devices and has the capability of allowing
the HTML to be rendered and displayed in an optimal, efficient and very quick way.

23
d. OpenGL/ES – it is in charge with processing the graphics. It can render eit her 2D or 3D obje cts on
Android .

Android Runtime – it is made of two main components:
-> core Java libraries Android provides
-> Dalvik virtual machine – Google’s version of Java programming language which is
optimized in order to run on mobile devices. Dalvik virtual machine uses core features of Linux
operating system, such as the multithreading. It also allows each Android application to run its
individual process together with its Dalvik virtual machine instance.

4. Linux Kernel – provides the closest access to the hardware. Initially Android Operating System was
based on Linux 2.6 kernel version, being optimized for mobile use. Recent versions of Android are
based on Linux 3.1 kernel version. In order to benefit most out of the close link between the kernel and
the hardware, drivers are written in the kernel space to operate as fast and as efficiently as possible.
These include things like controlling the internal radios, turning on the stereo and camera, dealing with
power and battery charging, and operating the ph ysical keyboard or buttons on the device. The Linux
kernel, like Android, is an open source project and is used widely, particularly on servers in enterprise
environments.[5]
Android applications are made of essential building blocks called application com ponents.
These components are loosely coupled by the AndroidManifest.xml file which describes the way they
interact with one another.

 Context: The context is the central control panel for an application which runs on Android OS. Context
provides a way fo r the developer to access or reference most of the application -specific functionalities.
Context class (android.content.Context) is a fundamental building block of any Android application
and provides access to application -wide features such as the applica tion’s private files and device
resources, as well as system -wide services. The application -wide Contextobject is instantiated as an
Application object (android.app.Application). [11]

 Activity: An activity symbolizes the logic behind one screen which has a graphical interface for
interaction with users. For instance, an application could have an activity which handles the login part,
another one which takes care of registering users and another for displaying a piece of information. If
the application is f ormed of more than one single activity then one of them has to be specified inside
the AndroidManifest.xml file as being the one which starts when the application is launched . Also , it is
known that an Activity is a subclass of Context which makes it have all the functionalities the Context
class has.[12]

24
An android application is a set of activities, each of them having a single and unique purpose. An
activity is made of two components, the layout which is an xml file that contains the user interface, and
a Java class that extends the Activity class.

On the other hand , speaking of the lifecycle of an Android Application, these can be
multi -process, meaning that the Android allows concurrency of applications . Applications can have
different types of behavi or such as, background behavior and they can be put on hold or paused when
types of events, for instance occurrence of an incoming call . Only one active application can be visible
to the user at a time —more specifically, a single application ’s Activity is in the foreground at a
time.[11]
Android OS keeps track of entire Activity objects that are running, by inserting them in a stack of
activities . The moment a new Activity begins , the Activity which is the top of the stack is put on hold
and the new Activit y gets pushe d and becomes the new stack’s top. When that Activity get completed
by finishing , it is taken away from the stack of activities and prior Activity in the stack resumes.
Applications are in charge for coordinating their state as well as their resources, memory and data.
They have to perfectly pause and resume.
The first step in creating a robust application is grasping all the different stages state goes through
within an Activity lifecycle. [11]

25

Fig. 2. 2 Lifecycl e of an Activity

 Fragment: As explained before, activities have unique goals, but each of them can be further cut into
smaller parts each part being called a fragment each in turn having a single goal within its paren t
activity. The Fragment class located inside the package android.app is commonly used for organization
of activity function alities in a way that offers more flexib ility in terms of user experience across
different screen sizes, aspect ratios , and orientations . Fragments are often used to hold the code and
screen logic for placing the same user interface component in multiple screens, which are represented
by multiple Activity classes. [11]

 Intent: The Android operating system leverages an asynchronous messaging mechanism to group task
request s with the proper activity. All request s are wrapped as intent s. It can be described each request

26
being a message which states an intent to do something. By using the class Intent from the
android.content package, is the main way that provides the communic ation between the application
components.[11]

 Service: A service is responsible with running an application in the background. It is a component
which is running in the background in order to fulfill long operations or to fulfill some application
request s. A service does not provide a user interface. For instance, a service can play music in the
background or execute various types of transactions, while other applications are running and are in the
foreground. A service can be implemented by extending the Service class , class which in turn extends
Context class . [12]

2.3 Android Studio

For creating the application an Integrated Development Environment (IDE) has been used
dedicated for android mobile development, called Android Studio. Android Studio is t he official
Integrated Development Environment for developing Android application, which is based on other
Integrated Development Environment called IntelliJ IDEA from JetBrains. Besides the IntelliJ's powerful
code editor and developer tools, Android Stud io offers even more features that enhance your
productivity when building Android apps, such as: [14]

 A flexible Gradle -based build system
 A fast and feature -rich emulator
 A unified environment where applications can be developed for all Android devices
 Instant Run to push changes to your running app without building a new APK
 Code templates and GitHub integration to help build common app features and import sample code
 Extensive testing tools and frameworks
 Lint tools to catch performance, usability, versi on compatibility, and other problems
 C++ and NDK support
 Built -in support for Google Cloud Platform , making it easy to integrate Google Cloud Messaging and
App Engine [14]

Each project in Android Studio contains one or more modules with source code files and resource files.
Types of modules include:
 Android app modules
 Library modules
 Google App Engine modules
By default, Android Studio displays project files in the Android project view, as shown in Fig 1.8. This
view is organized by modules to provide qui ck access to project's key source files.
All the build files are visible at the top level under Gradle Scripts and each app module contains the
following folders:
 manifests : Contains the AndroidManifest.xml file.
 java: Contains the Java source code files, including JUnit test code.

27
 res: Contains all non -code resources, such as XML layouts, UI strings, and bitmap images.
The Android project structure on disk differs from this flattened representation. To see the actual file
structure of the project, select Project from the Project dropdown (in Fig. 1.8, it's showing as Project ).
The view of the project files can also be customize d to focus on specific aspects of the app
development. For example, selecting the Problems view of the project displays links to t he source files
containing any recognized coding and syntax errors, such as a missing XML element closing tag in a
layout file. [14]

Fig. 2. 3 Android Studio IDE

28
2.4 Google Firebase Cloud Platform

Firebase is a platform -as-a-service (PaaS) product from Google which is dedicated f or web
applications and mobile applications. This platform is made of components which provides different
functionalities that can be used by software developers. First component of this platform was the real
time database which exposes an API that provide s a concurrent way of data saving in a cloud database.
Across years, Firebase expanded introducing new components that came with new functionalities such
as:
 Authentication service – Most apps need to know the identity of a user. Knowing a user's identity
allows an app to securely save user data in the cloud and provide the same personalized experience
across all of the user's devices. Firebase Authentication provides backend services to authenticate users
to the app and i t supports authentication using pa sswords, phone numbers, popular federated identity
providers like Google, Facebook and Twitter, and more. Firebase Authentication integrates tightly with
other Firebase services, and it leverages industry standards like OAuth 2.0 and OpenID Connect, so it
can be easily integrated with any custom backend.
The Firebase Authentication SDK provides methods to create and manage users that use their email
addresses and passwords to sign in. Firebase Authentication also handles sending password reset
emails. [15]

 Analytics service – Analytics integrates across Firebase features and provides the developer with
unlimited reporting for up to 500 distinct events that he can define using the Firebase SDK. Analytics
reports help understand clearly how users behave, whic h enables the owner of the application to make
informed decisions regarding app marketing and performance optimizations.
Analytics also integrates with a number of other Firebase features. For example, it automatically logs
events that correspond to notifi cation messages sent via the Notifications composer and provides
reporting on the impact of each campaign.

 Cloud Messaging – it is a messaging solution across platforms which provides a secure message
transmission channel.

 Cloud Storage – it is built for app developers who need to store and serve user -generated content, such
as photos or videos. The Firebase SDKs for Cloud Storage add Google security to file uploads and
downloads for the Firebase apps, regardless of network quality. Firebase SDKs can be u sed to store
images, audio, video, or other user -generated content.

 Realtime Database – is a NoSQL cloud -hosted database. Data is stored as JSON and synchronized in
realtime to every connected client. When a developer builds cross -platform apps with Fireb ase iOS,
Android, and JavaScript SDKs, all of the clients share one Realtime Database instance and
automatically receive updates with the newest data.
The Firebase Realtime Database provides the possibility to build rich, collaborative applications by

29
allowing secure access to the database directly from client -side code. Data is persisted locally, and even
while offline, realtime events continue to fire, giving the end user a responsive experience. When the
device regains connection, the Realtime Database s ynchronizes the local data changes with the remote
updates that occurred while the client was offline, merging any conflicts automatically.
The Realtime Database provides a flexible, expression -based rules language, called Firebase Realtime
Database Secur ity Rules, to define how data should be structured and when data can be read from or
written to. When integrated with Firebase Authentication, developers can define who has access to
what data, and how they can access it.
The Realtime Database is a NoSQL database and as such has different optimizations and functionality
compared to a relational database. The Realtime Database API is designed to only allow operations that
can be executed quickly. This enables developers to build a great realtime experience that can serve
millions of users without compromising on responsiveness. Because of this, it is important to think
about how users need to access the data and then structure it accordingly. [15]

2.5 OAuth 2.0 Protocol

OAuth 2.0 is the industry -standard p rotocol for authorization. OAuth 2.0 supersedes the work
done on the original OAuth protocol created in 2006. OAuth 2.0 focuses on client developer simplicity
while providing specific authorization flows for web applications, desktop applications, mobile p hones,
and living room devices. This specification and its extensions are being developed within the IETF
OAuth Working Group. [16]
OAuth 2.0 is a protocol that allows distinct parties to share information and resources in a
secure and reliable manner. [17]
Google APIs use the OAuth 2.0 protocol for authentication and authorization. Google supports
common OAuth 2.0 scenarios such as those for web server, installed, and client -side applications.
To begin, obtain OAuth 2.0 client credentials from the Google API Console. Then the client application
requests an access token from the Google Authorization Server, extracts a token from the response, and
sends the token to the Google API that you want to access. For an interactive demonstration of using
OAuth 2.0 with Google (including the option to use own client credentials), experiment with the OAuth
2.0 Playground.
This page gives an overview of the OAuth 2.0 authorization scenarios that Google supports, and
provides links to more detailed content. For details abou t using OAuth 2.0 for authentication,
see OpenID Connect.
The Google OAuth 2.0 endpoint supports applications that are installed on devices such as
computers, mobile devices, and tablets. When you create a client ID through the Google API Console ,
specify that this is an Installed application, then select Android, Chrome, iOS, or "Other" as the
application type.
The process results in a client ID and, in some cases, a client secret, which yo u embed in the
source code of your application. (In this context, the client secret is obviously not treated as a secret.)

30
The authorization sequence begins when your application redirects a browser to a Google URL; the
URL includes query parameters that i ndicate the type of access being requested. Google handles the
user authentication, session selection, and user consent. The result is an authorization code, which the
application can exchange for an access token and a refresh token.
The application should store the refresh token for future use and use the access token to access a
Google API. Once the access token expires, the application uses the refresh token to obtain a new
one.[16]

2.6 Gradle Build System

Gradle is an open -source build automation tool focused on flexibility and performance. Gradle build
scripts are written using a Groovy or Kotlin DSL.

 Highly customizable — Gradle is modeled in a way that customizable and extensible in the
most fundamental ways.
 Fast — Gradle completes tasks quickly b y reusing outputs from previous executions,
processing only inputs that changed, and executing tasks in parallel.
 Powerful — Gradle is the official build tool for Android, and comes with support for many
popular languages and technologies. [19]

Gradle is the newest addition to the Java build project automation tool family. It is open sourced
under Apache License 2.0 and its first version (0.7) was released in 2009, followed by version 2.0 in
2014. At the time of writing this book, version 2.7 is the curren t version of Gradle. Gradle has been
gaining a lot of adoption as it draws on lessons learned from other existing build tools such as Ant and
Maven. Several high -profile projects such as Android, Spring Framework, and Hibernate have
migrated the ir build sy stems to use Gradle.[20]
Some of its strongest features would be:
 Declarative Dependency Management – Most Java projects rely on other projects and open source
frameworks to function properly. It can be cumbersome to download these dependencies manually an d
keep track of their versions as you use them in your projects. To make things more complicated, these
dependencies might have their own dependencies (referred to as transitive dependencies) that need to
be resolved and downloaded. Gradle provides a conve nient way to declare your project dependencies.
After declaring them Gradle automatically downloads the dependencies , along with transitive
dependencies, and this way it allows using them in the project. [20]
 Declarative Builds – Gradle uses a Groovy based domain specific (DSL) for declaring builds. The
DSL provides a set of language elements that can be easily assembled to create build scripts that are
simple and clearly express their intent. [20]

 Plugins – Gradle makes it easy to augment and customize its functionality through plugins. Plugins are
distributable components that encapsulate reusable build and task logic. Using plugins, it is possible to
support additional languages, create new tasks, or modify existing task functionality and extend build

31
language by adding new keywords.[20]

 Gradle Wrapper – Gradle Wrapper is simply a batch file (gradlew.bat ) in the Windows environment
and a shell script for Linux/Mac environments. When it runs, the wrapper script downloads and installs
a fresh copy of Gradl e runtime on the machine and executes a Gradle build. Gradle Wrapper makes it
easy to spin upnew continuous integration (CI) servers that can run builds withou t any additional
configuration.

Android applications use Gradle as their build tool, normally th rough the only supported IDE, Android
Studio.[19] Gradle is a state -of-the-art API that easily supports customizations and is widely used in the
Java world. The Android plug -in for Gradle adds a wide range of features specific to Android apps,
including bu ild types, flavors, signing configurations, library projects, and more.[18]

Fig. 2. 5 Project structure (Android view)

Android projects are multiproject Gradle builds. The settings.gradle file shows which
subdirectories hold their own subprojects.
Example of settings.gradle file:

Fig. 2. 6 Snippet of settings.gradle file

If you add an Android Library project, it too will be added to this file.
Fig. 2. 4 Project structure ( Project
view)

32
The Gradle distribution does not include Android func tionality by default. Google provides an
Android plug -infor Gradle, which allows easy configuration of Android projects. The buildscript block
in the Fig. 2. 7 tells Gradle where to download that plug -in. As you can see, by default the plug -in is
downloaded from jcenter , which means the Bintray JCenter Artifactory repository. Other repositories
are supported (especially mavenCentral() , the default Maven repository), but JCenter is now the
default. All content from JCenter is served over a CDN with a secure H TTPS connection. It also tends
to be faster. [18]
The allprojects section indicates that the top -level project and any subprojects all default to using
the jcenter() and google() repositories to resolve any Java library dependencies .

Fig. 2. 7 Snippet of Top -level Gradle build file

33

Fig. 2. 8 Example of App Level Gradle file

The apply functionality in Gradle adds the Android plug -in to the build system, which
enables the android section Domain S pecific Language (DSL) configuration.
The android JSON object specifies details regarding compile and build options.
Last but not least, dependencies determines what libraries Gradle shall bring and make them available
for consumption inside the project. [18]

34
2.7 Git Versioning Control System

Git is a popular and widely used source management system that greatly simplifies the
development cycle. It enables users to create, use, and switch between branches for content
development as easily as people creat e and switch between files in their daily workflow. It is
implemented using a fast, efficient architecture that allows for ease of experimentation and refinement
of local changes in an isolated environment before sharing them with others. In short, it allo ws
everyday users to focus on getting the content right instead of worrying about source management,
while providing more advanced users with the ability to record, edit, and share changes at any level of
detail. [21]

Fig. 2. 9 Diagram of Git versioning control concept [22]

35
Git versioning system works with one server or cluster of servers which acts as the remote
repository center where all the code gets pushed to from all the client computer s. As it can be seen in
Fig. 2.9 the server has a base version from where computer A and computer B creates local copies
which afterwards they put their changes on top of the base version. Thus, if any server dies, and these
systems were collaborating via that server, any of the client reposi tories can be copied back up to the
server to restore it. Every clone is really a full backup of all the data. [22]
Git has three main states (as it can be seen in Fig. 2.10 ) that the files on the local repository can
reside in: committed , modified , and staged :
 Committed means that the data is safely stored in the local database.
 Modified means that the file has been changed but it has not been committed to database yet.
 Staged means that a modified file has been marked in its current version to go into nex t commit
snapshot.

Fig. 2. 10 Working directory, staging area and git directory [22]

The Git directory is where Git stores the metadata and object database for your project. This is the most
important part of Git, and it is what is copied when you clone a repository from another computer.
The working tree is a single checkout of one version of the project. These files are pulled out of the
compressed database in the Git directory and placed on disk for you to use or modify.
The staging area is a file, generally contained in your Git directory that stores information about what
will go into your next commit. Its technical name in Git parlance is the ―index‖, but the phrase ―staging
area‖ works just as well. [22]

36

37
CHAPTER 3. Software Design and Implementation

3.1 User’s Authentication and Registration

User authentication is part of the security layer that some applications should have it
implemented to some extent more or less than others. For this application the authen tication is
necessary in order for a user to present his identity. Knowing the identity of a user is relevant , since
each booking must have a name associated to it.
In this case, this software requirement is fulfilled using the API provided by Google’s pl atform,
Firebase in two ways:
 Using email and password
 Using Google Sign -In

Firstly, in order to have access to this API, from inside the project, the libraries have to be fetched.
This can be accomplished by using Gradle Build System which handles the li brary dependencies. The
following lines of code had to be written that specify Gradle the libraries that are going to be brought.

implementation 'com.google.firebase:firebase -auth:16.0.2'
implementation 'com.google.android.gms:play -services -auth:15.0.1'

The first line was required for the email and password authentication and on top of that the second
line was needed for the Google Sign -In.
Inside the Annex 1 can be found the source code for the LoginActivity java class which is
configured inside Android Manifest xml file (Annex 11) to be the launcher activity. Basically, this
means that once the application starts , the login screen loads and renders first. In this Login Activity, it
is firstly checked whether or not the Firebase authentication object has a user which is not equal to null
and in case this turns out to be true the activity is switched to the MainActivity.

Login using email and password

In case the user object is equal to null, the email and the password are going to be filled in the edit
texts from the layout file (Annex 13) and they will be used for the login method:

Fig. 3. 1 Snippet of signing method

38

For adding a listener that gets triggered on complete state of the authentication, it has been used a
lambda instantiation in order to create the object OnCompleteListener <AuthResult> and for offering an
overridden implementation of the method onComplete().

Login using Google Sign -In

There is also available the option to sign in using a Google account in case the user has one. This
had been achieved inside the LoginActiv ity class by instantiating inside the onCreate() method two
objects :
 GoogleSignInOptions – this is where the required data from the user is getting processed
 GoogleApiClient – this uses the data from the previous object and it represents the object
which a ssures the communication between the Google Sign -In API and the application

Fig. 3. 2 Snippet of Google authentication method

39

After the response received from the GoogleApiClient is positive the method
firebaseAuthWithGoogle() is called which validates the authentication. It creates a request to
googl e authorization server and after the user grants permission to the application to access the Google
Account data, permission which will be used by the application to request an access token from Google
authorization server. This token will be included in t he requests from the application to the Google
resource server where needed data about the user resides.

Register Activity

The application also offers the possibility to create an account which can be further used with the
first authentication method des cribed above (Login using email and password). The edit texts that
contain the email and password for which the account will be created, from the corresponding layout
file will be parsed and based on that in the RegisterActivity java class the following me thod will be
used in order to do the sign up:

3.2 Main Activity

After going through the LoginActivity, the MainActivity starts:

Fig. 3. 4 Snippet of switching from LoginActivity to MainActivity

This activity, firstl y instantiates a list of Classroom objects which will be used later on by the
reservation algorithm. To this list there are added six objects of type Classroom. It firstly starts by
displaying the Calendar Fragment.
Fig. 3. 3 Snippet of registering method

40

Inside this activity there are four fr agmen ts that get switched depending on the path the user
decides to navigate through. These are:
 Calendar Fragment
 Classrooms Fragment
 Events Fragment
 Scanned Room Fragment

The way the switching between fragments is achieved is through the method:

Fig. 3. 5 Snippet showing the method implementation for moving to another Fragment

First fragment that gets displayed once the activity starts is the CalendarFragment .

Navigation Menu

Inside the Main Activity it is implemented a navigation menu which has the selection logic
created using a Navigation View which will be displayed in all the fragments of the activity and has
three elements that have logic implemented:
 View Calendar – switches the fragment to the Calendar Fragment u sing the method
moveToFragment() .
 Logout –triggers the FirebaseAuth instance to sign out and after that, the LoginActivity is
launched, the current activity finishing.

Fig. 3. 6 Snippet with logout call method

 Scan QR Code – launches the ScanQRActivity

Fig. 3. 7 Snippet with the start of the ScanQRActivity

41
3.3 Scan QR Activity

First of all, this activity was built using pre -existing open -source library ZXing
(ZebraCrossing) and can be used only i f the API level of the Android OS is greater or equal to 23.
The activity can only be reached from the navigation menu , part of the Main Activity presented before.
It was built by making the java class, corresponding to the activity (ScanQRActivity), impl ement the
interface ZXingScannerView.ResultHandler and offer inside the activity an implementation for the
method handleResult( ) that provides the parsed text from the scanned QR code .

Fig. 3. 8 Snipping of the method which ch ecks the permission for camera

After the API level of the OS is check ed, the application needs the permission to access the camera and
firstly it has to be established , whether or not , the permission is already granted , by using the method
from the Fig. 3 .8.

Fig. 3. 9 Snipping of the method which requests the permission

In case the permission is not already granted, the static method requestPermission(), from the java class
ActivityCompat, will be called with the proper parame ters, specifying the access request for the
camera.
After scanning a QR code, the method handleResult() gets triggered , having inside the
parameter the deciphered text, which stands behind the QR code. This result is firstly validated against
a list of ac cepted codes which are specific for the classrooms. In case it is valid , it is going to be stored
inside a static field inside the same class. T hen the scanning activity ends, invoking the Main Activity
which accesses the static field where the result was stored and using it, it goes to the EventsFragment
showing the events of the scanned room.

42
3.4 Model Classes

The model of the application uses two classes , the Classroom class and the TimeLapse cl ass
presented below in the UML diagram:

As it can be seen fr om the UML Diagram from Fig. 3.10 , the relation between the two classes is
one-to-many, each classroom having one or more intervals of time.

Classroom class

It contains all the necessary methods in order to fulfill the process which b ooks a classroom
including the checking part for availability:
Fig. 3. 10 UML Diagram for the model classes

43
 checkStartTimeAvailability()

Fig. 3. 11 Snippet with checkStartTimeAvailability method

This method returns an array of 48 boolean values, each element representing half an hour. If the
value is set to true, then that half an hour cannot be selected in the time picker dialog as a starting
time, because it is unavailable since it is assigned to another interval of time belonging to that
classroom in that day. In order to determine the values of this array, the method iterates, using a
foreach syntax, through the list of TimeLapse objects and then filters them by date in order to
exclude from this checking process the intervals which don’t correspond to the selected date
received as a parameter. Afterwards, all the halves of hour, which are between a start time and an
end time of a filtered interval are found and the all the corresponding elements from the Boolean
array get updates. timeframe

44
 checkEndTimeAvailability()

Fig. 3. 12 Snippet with checkEndTimeAvailability method

Similarly, an array of Boolean values is also determined for the end time picker dialog, except here
the hours before the starting time of the interval are al so considered to be disabled.

 sortIntervals() – this method sorts the list of intervals from the classroom by calling the method sort
and passing to this as a parameter a Comparator object instantiated using lambda expression.

Fig. 3. 13 Snippet of sortIntervals() method

 bookClassroom() – used to reserve a classroom. This is accomplished by instantiating a new
TimeLapse object using the data, which comes as parameters of the method, and adding the interval
to the list of inte rvals of the classroom.
Fig. 3. 14 Snippet of bookClassroom() method

45

TimeL apse class

This class contains all the relevant information for creating an interval of time, used for booking
a classroom, like the hours of start and end time of a class, the name of the user which creates the
reservation, the date when the booking is made and last but not least the id of the classroom.

3.5 Database Structure

In order to build an application which handles multiusers transactions and synchronization on
different Android dev ices the database could not be implemented locally using the SQLite module
provided by Android. This way, in order to overcome this issue, the application uses the real -time
Firebase database which operates on cloud and provides access from the application s installed on
mobile devices. Firebase real -time database is a NoSQL database which stores the data in a JSON
format as seen in Fig. 3.1 5.

Fig. 3. 15 Firebase NoSQL Database data storage JSON format

46

In order to have access to the Firebase Database API the following Gradle dependency had to
be added:
implementation 'com.google.firebase:firebase -database:16.0.1'

Operations with the database are really simple to use, a few transactions being exemplified
below. The entire cla ss is attached in the Annex 9.
FirebaseDatabase db;
DatabaseReference classroomsRef;
DatabaseReference classroomRef;
db = FirebaseDatabase.getInstance();
classroomsRef = db.getReference("rooms");

A FirebaseDatabase object is created which will be used to get all the needed references, in this case
for the list of Classroom objects.

Fig. 3. 16 Snippet with the save to database method

Once the reference of the object is provided an update of the value can be done using the
method setValue () as presented in the Fig. 3.16 .

Fig. 3. 17 Snippet with onDataChange() method

To monitor every change of the database in order to keep the persistence context of the
application synchronized with the data from the database, Firebase offers a method, named
addValueEventListener(), which can be called usin g a Firebase reference(Fig. 3.17 ). Once the listener

47
detects a change on the remote database, it receives a DataSnapshot object which contains the current
state of the database with all the data and then it iterates through the in -memory list of Classroom
objects and updates their values.

48

49
CHAPTER 4. Application Walkthrough and UI Presentation

This Androi d mobile application is dedicated for booking classrooms , which are part of the
faculty buildings , by users which can authenticate by creating an account or by simply using their
Google accounts in an OAuth 2.0 secure environment.

Fig. 4. 1 Login Screen

Here as it can be seen in the Fig. 4.1, the first screen that appears once the application is
launched is the login screen which prompts the user to complete the authentication process in order to
let the other users, later on , who is making the reservations.

50

Fig. 4. 3 User Registration screen

If the user of the application does not have an account he gets the possibility to sign up, as
shown in the Fig. 4.3. After registering and creating th e account, the user can now browse through the
application.
Fig. 4.2 the pop up the user gets prompted with if he chooses to login using his Google account.
Either an account which was previously added to the Android device can be used for fast login or a
new one.

Fig. 4. 2 Authentication using Google Sign on

51

Fig. 4. 4 Calendar View

The Calendar View from the Fig. 4.4 is the screen which the application gets to, once the user
completes the login action. The current date is circled , all days prior to it being grayed out s ince there is
no point in reserving any classroom on a past date , hence only the subsequent days being available for
the user to choose .

52

Either by sliding from the left of the screen to the right or by just pressin g the triple bar menu shortcut
the drawer menu appears as shown in the Fig. 4.5. There are a few options for the user to go for like:
1. View Calendar – sends the user to the calendar view.
2. Scan QR Code – sends the user to the QR Code Scanning Activity which requests for camera
permission in order to do the scanning.
3. Logout – Logs out the user sending him back to the login screen
The rest of the options like Tools and Account are not available to access and they are displayed only
for design purpose.
Fig. 4. 5 Side Drawer Men u

53

Fig. 4. 6 Classroom List

Once a day is selected from the previous screen with the calendar , a list of classrooms get s
displayed as it can be seen in Fig. 4.6. Basically, a ny of the classrooms can be selected in order to book
it for a n interval of time.
According to the Fig. 4.6 , the drawer menu can still be accessed(the triple bar icon being
displayed) and not only from this screen but it is available through out the entire application except the
login screens.

54

Fig. 4. 8 Events List for a classroom in a specific day

Moving on, by selecting a classroom, its events are get ting displayed. Each event has three
components which are the time interval, the username who reserved the classroom and a checkbox.
The checkbox is designed to work inside a delete of event flow, meaning that if the checkboxes of
some chosen events are ticked (as in Fig. 4.7) and then the delete button, located in the left -bottom
corner, is pressed those events are deleted.
Inside this fr agment, the name of the classroom along with the chosen date are getting displayed
for orientation purposes.
From now on, user has the possibility by pressing the add button, located in the right -bottom
corner, to book the classroom.
Fig. 4. 7 List of Events with ticked checkbox

55

Fig. 4. 10 Stating Time Picker

After pressing the add button in the classrooms screen, a time picker popup gets displayed in
order to choose the starting time of the event. According to Fig. 4.10, certain hours are grayed out and
unavai lable to be chosen in order to prevent intervals overlapping. There are some intervals already set
and based on those the available hours for the starting time are shown.
The same goes for the ending time picker, where all the previous hours with respect to the
Fig. 4. 9 Ending Time Picker

56
starting time are grayed out, and only the hours before another already booked interval are getting
displayed as being available.

Fig. 4. 12 QR Code Scan Activity Camera Request

QR Code Scan Feature can be access ed from the dra wer menu presented in Fig. 4.5 . Firstly , the
user will get prompted with a popup where his permission will be asked in order for the application to
have access to the camera.
After providing the permission, a notification gets displayed for user information and camera
starts. If a valid QR code for a specific classroom gets scanned, the application will send the user to the
schedule of that room in the current date. Otherwise if the scanned QR code does not belong to the list
Fig. 4. 11 Camera permission granted

57
of the accepted QR codes for the list of classrooms, the user will be sent to the calendar view in order
to do the booking, since the code was not a valid one. At that point the operator can either choose to
browse through the list of classrooms and select from there the one he is interested into or he can try
one more time to scan the code.

58

59
Project conclusions

From the desire to build effective techniques to make the human life easier, many discoveries
have been made over the past years in the software domain. The purpose of the graduation thesis is to
prove the importance of this domain by building an application which is designed to be used on a daily
basis by the targeted people. It is very important to realize that this is part of the human process of
evolution and represents a must, since it fully impacts the way people operate.
The role of the application is to run on mobile devices and to offer services that allow booking
of classrooms under a university eco -system, this way increasing the effective management of the
facility rooms. Building the application required combining theoretical knowledge, accumulated in the
past years of faculty, with acquired practical technical skills. The most important factor in terms of
courses studied at faculty was the ―Object Oriented Programming‖ which represented an introduction
in the Java programming language which is used by the Android operating system.
The resulted solution is in accordance with the established objective which was creating a fully
functional flow of the application which offers:
 authentication and register processes taking plac e in a secure environment using the
Firebase platform
 the ability of booking an available classroom
 a quick method to see the schedule in the current date of a specific classroom by
scanning the QR code placed on its door

In terms of functionalities which can be implemented to the application, there are several
improvements which can be brought on top of the existing ones which are:
 Adding var ious types of filters when looking for a classroom to find out whether or not
the classroom has a projector , a specific number of seats, a whiteboard, AC.
 An integration with the main calendar of the device not only the one from the
application, in order t o display booked intervals for each user.
 Developing a similar version of the application which runs on iOS operating system.
 Sending notifications to the user before a certain amount of time which will act as
reminders

Concluding , the applications brings a lot of innovation to the education system providing
flexibility and an easy to interact with software that will allow the users to better organize their
schedule and also to contribute to a more productive utilization of the classrooms, reducing the tim e
spent on the specific administrative tasks.

60

61
Bibliography

[1] Joe Waters , QR Codes For Dummies , (Release Date: June 2012)
[2] Phil Dutson , Creating QR and Tag Codes (Release Date: May 2012)
[3] http://qrcode.meetheed.com/pos t04.php , accessed on: 15.04.2018
[4] www.tutorialspoint.com/java , accessed on: 16.04.2018
[5] Darren Cummings , Iggy Krajci , Android on x86: An Introduction to Optim izing for Intel®
Architecture (Release Date: January 201 4)
[6] https://developer.android.com/guide/components/ – Android Official Documentation , accessed on:
18.04.2018
[7] https://en.wikipedia.org/wiki/Android_(operating_system)#Development – Android Operating
System Architecture, accessed on: 30.04.2018
[8]https://stackify.com/solid -design -principles/ – SOLID Principles, accessed on: 03.05.2018
[9]http://www.tutorialsteacher.com/ioc/dependency -inversion -principle – SOLID Dependency
Inversion Principle, accesed on: 03.05.2018
[10]Ted Hagos , Learn Android Studio 3 : Efficient Android App Development (Release Date: February
2018)
[11]Joseph Annuzzi J r.; La uren Darcey; Shane Conder , Introduction to Android™ Application
Development: Android Essentials, Fifth Edition (Release Date: December 2 015)
[12] https://www.tutorialspoint.com /android – TutorialsPoint: Android Tutorial, accessed on:
12.05.2018
[13] https://developer.android.com/guide/topics/media/media -formats – Android: Connectivity,
accessed on: 16.05.2018
[14] https://developer.android.com/studi o/intro/ – Android Studio Introduction, accessed on:
20.05.2018
[15] https://firebase.google.com/docs – Firebase Official Documentation, accessed on: 16.04.2018
[16] https://developers.google.com/identity/protocols/OAuth2 – OAuth 2.0 Protocol, accessed on
22.05.2018
[17] Charles Bihis , Mastering OAuth 2.0 , (Published: December 201 5)
[18] Ken Kousen , Gradle Recipes for Android , (Published: January 201 6)
[19] https://docs.gradle.org/current/userguide/userguide.html#introduction – Gradle User Manual,
accessed on: 24.05.2018
[20] Sudha B elida; Balaji Varanasi (2015), Introducing Gradle
[21] John Wiley & Sons , Professional Git , (Published: December 201 6)
[22] https://git -scm.com/book/en/v2/Getting -Started -About -Version -Control
[23] https://opens ource.google.com/projects/zxing – ZXing – open source library , accessed on 17.04.2018
[24] https://firebase.google.com/docs/auth/android/password -auth – Firebase Email Authentication
Documentation, accessed on: 19.04.2018
[25] https://firebase.google.com/docs/auth/android/google -signin – Firebase Google Sign-In
Documentaion, accessed on: 19.04.2018

62
[26] https://firebase.google.com/docs/database/android/ start/ – Firebase Realtime Database, accessed on:
19.04.2018

63
Annex 1

LoginActivity.java
package com.etti.classroomsbooking.login;

import android.app.ProgressDialog;
import android.content.Intent;
import android.support.annotation. NonNull;
import android.support.v7.app.AppCom patActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.etti.classroomsbooking.MainActivity;
import com.etti.classroomsbooking.R;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.a pi.GoogleApiClient;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.GoogleAuthProvider;

import static android.widget.Toast. LENGTH_SHORT ;

//https://www.youtube.com/watch?v= -ywVw2O1pP8 – Firebase Google Sign on Tutorial
public class LoginActivity extends AppCompatActivity implements View.OnC lickListener {

private Button buttonSignIn ;
private EditText editTextEmail ;
private EditText editTextPassword ;
private TextView textViewSignIn ;
private ProgressDialog progressDialog ;
private FirebaseAuth firebaseAuth ;
private SignInButton gsoButton ;
private static final int RC_SIGN_IN = 1;
private GoogleApiClient mGoogleApiClient ;
public static final String TAG = "LOGIN_ACTIVITY" ;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_login );

editTextEmail = (EditText) findViewById(R.id. editTextEmail );
editTextPassword = (EditText) findViewById(R.id. editTextPassword );
buttonSignIn = (Button) f indViewById(R.id. buttonRegister );
textViewSignIn = (TextView) findViewById(R.id. textViewSignIn );
gsoButton = (SignInButton) findViewById(R.id. signInGoogle );
progressDialog = new ProgressDialog( this);
firebaseAuth = FirebaseA uth.getInstance ();

if (firebaseAuth .getCurrentUser() != null) {
finish();
startActivity( new Intent(getApplicationContext(), MainActivity. class));
}
// Configure Google Sign In
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions. DEFAULT_SIGN_IN )
.requestIdToken(getString(R.string. default_web_client_id ))

64
.requestEmail()
.build();

mGoogleApiClient = new GoogleApiClient.Bui lder(getApplicationContext()).enableAutoManage( this,
new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed( @NonNull ConnectionResult connectionResult) {
Toast.makeText (LoginActiv ity.this, "An error occured." , Toast. LENGTH_LONG ).show();
}
}).addApi(Auth. GOOGLE_SIGN_IN_API , gso).build();
gsoButton .setOnClickListener(view -> {
signIn();
});

buttonSignIn .setOnClickListener( this);
textViewSignIn .setOnClickListener( this);
}

@Override
public void onClick(View view) {
if (view == buttonSignIn ) {
userLogin();
}
if (view == textViewSignIn ) {
startActivity( new Intent(this, RegisterActivity. class));
}
}

private void userLogin() {
String email = editTextEmail .getText().toString().trim();
String password = editTextPassword .getText().toString().trim();

if (TextUtils. isEmpty(email)) {
//email is empty
Toast.makeText (this, "Please enter email" , LENGTH_SHORT ).show();
return;
}

if (TextUtils. isEmpty(password)) {
//password is empty
Toast.makeText (this, "Please e nter password" , LENGTH_SHORT ).show();
return;
}
progressDialog .setMessage( "Loging in…" );
progressDialog .show();
firebaseAuth .signInWithEmailAndPassword(email, password).addOnCompleteListener( this, task -> {
progressDialog .dismiss();
if (task.isSuccessful()) {
finish();
startActivity( new Intent(getApplicationContext(), MainActivity. class));
} else {
Toast.makeText (this, "Failed lo ging in." , LENGTH_SHORT ).show();
}
});
}

private void signIn() {
progressDialog .setMessage( "Loging in…" );
progressDialog .show();
Intent signInIntent = Auth. GoogleSignInApi .getSignInIntent( mGoogleApiCli ent);
startActivityForResult(signInIntent, RC_SIGN_IN );
}

@Override
public void onActivityResult( int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(…);
if (requestCode == RC_SIGN_IN ) {
Task<GoogleSignInAccount> task = GoogleSignIn. getSignedInAccountFromIntent (data);
try {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = task.getResult(ApiException. class);
firebaseAuthWithGoogle(account);

65
} catch (ApiException e) {
Log.w(TAG, "Google sign in failed", e);
}
}
}

private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider. getCredential (acct.getIdTo ken(), null);
firebaseAuth .signInWithCredential(credential)
.addOnCompleteListener( this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete( @NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithCredential:failure" , task.getException());
Toast.makeText (LoginActivity. this, "Authentication Failed." ,
LENGTH_SHORT ).show();
} else {
finish();
startActivity( new Intent(getApplicationContext(), MainActivity. class));
mGoogleApiClient .disconnect();
}
progressDialog .dismiss();
}
});
}
}

66
Annex 2
RegisterActivity.java

package com.etti.classroomsbooking.login ;

import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.Edi tText;
import android.widget.TextView;
import android.widget.Toast;

import com.etti.classroomsbooking.R;
import com.google.firebase.auth.FirebaseAuth;

public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {

private Button buttonRegister ;
private EditText editTextEmail ;
private EditText editTextPassword ;
private TextView textViewSignin ;
private ProgressDialog progressDialog ;
private FirebaseAuth firebaseAuth ;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_register );
firebaseAuth = FirebaseAuth. getInstance ();

progressDialog = new ProgressDialog( this);

buttonRegister = (Button) findViewById(R.id. buttonRegister );

editTextEmail = (EditText) findViewById(R.id. editTextEmail );
editTextPassword = (EditText) findViewById(R.id. editTextPassword );

textViewSignin = (TextView) findViewById(R.id. textViewSi gnin);

buttonRegister .setOnClickListener( this);
textViewSignin .setOnClickListener( this);
}

@Override
public void onClick(View view) {
if (view == buttonRegister ) {
registerUser();
}
if (view == textViewSignin ) {
finish();
startActivity( new Intent(getApplicationContext(), LoginActivity. class));
}
}

public void registerUser() {
String email = editTextEmail .getText().toString().trim();
String password = editTextPassword .getText().toString().trim();

if (TextUtils. isEmpty(email)) {
//email is empty
Toast.makeText (this, "Please enter email" , Toast. LENGTH_SHORT ).show();
return;
}

if (TextUtils. isEmpty(password)) {
//password is empty
Toast.makeText (this, "Please enter password" , Toast. LENGTH_SHORT ).show();

67
return;
}
progressDialog .setMessage( "Registering User…" );
progressDi alog.show();

firebaseAuth .createUserWithEmailAndPassword(email, password).addOnCompleteListener( this, task –
> {
if (task.isSuccessful()) {
progressDialog .dismiss();
Toast.makeText (this, "Registered Succe ssfully" , Toast. LENGTH_SHORT ).show();
} else {
progressDialog .dismiss();
Toast.makeText (this, "Failed to register, please try again" ,
Toast.LENGTH_SHORT ).show();
}
});
}
}

68
Annex 3
MainActivity.java

package com.etti.classroomsbooking;

import android.support.v4.app.Fragment;
import android.content.Intent;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.w idget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.view.Vi ewGroup;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import com.etti.classroomsbooking.fragments.CalendarFragment;
import com.etti. classroomsbooking.fragments.ScannedRoomFragment;
import com.etti.classroomsbooking.login.LoginActivity;
import com.etti.classroomsbooking.model.Classroom;
import com.etti.classroomsbooking.model.TimeLapse;
import com.google.firebase.auth.FirebaseAuth;
import com.google.zxing.Result;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import me.dm7.barcodescanner.zxing.ZXingScannerView;

import static com.etti.classroomsbooking.ScanQRActivity. scannedQRCode ;
import static com.etti.classroomsbooking.util.Constant. REQUEST_CODE_QR ;
import static com.etti.classroomsbooking.util.Constant. TIME_INTERVAL ;
import static com.etti.classroomsbooking.util.Constant. USER;
import static com.etti.classroomsbooking.util.Utility. getFormattedTimeInterval ;
import static com.etti.classroomsbooking.util.Utility. getStringDateFromTimeMillis ;

public class MainActivity extends AppCompatActivity implements ZXingScannerView.ResultHa ndler {

private FirebaseAuth firebaseAuth ;
private DrawerLayout drawer;
private SimpleAdapter adapter;
private boolean mReturningWithResult = false;
private TextView navHeaderTitle ;
private List<Classroom> classrooms ;

@Overrid e
protected void onActivityResult( int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_QR && scannedQRCode != -1) {
mReturningWithResult = true;
}
}

@Override
protected void onPostResume() {
super.onPostResume();
if (mReturningWithResult ) {
moveToFragment( new ScannedRoomFragment());
}
mReturningWithResult = false;

69
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. drawer_layout );
Toolbar toolbar = findViewById(R.id. toolbar);
setSupportActionBar(toolbar);

ActionBar actionbar = getSupportActionBar();
actionbar.setDisplayHomeAsUpEnabled( true);
actionbar.setHomeAsUpIndicator(R.drawable.ic_menu2);
firebaseAuth = FirebaseAuth.getInstance();

classrooms = new ArrayList<>();
classrooms.add( new Classroom( 0, "A01"));
classrooms.add( new Classroom( 1, "A02"));
classrooms.add( new Classroom( 2, "A03"));
classrooms.add( new Classroom( 3, "B01"));
classrooms.add( new Classroom( 4, "B02"));
classrooms.a dd(new Classroom( 5, "B03"));
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

moveToFragment( new CalendarFragment());
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.set NavigationItemSelectedListener(item -> {
int id = item.getItemId();
switch (id) {
case (R.id.nav_logout):
FirebaseAuth.getInstance().signOut();
startActivity( new Intent(getAppl icationContext(), LoginActivity. class));
finish();
break;
case (R.id.scan_qr):
Intent i = new Intent(this, ScanQRActivity. class);
startActivityForResult(i, REQU EST_CODE_QR);
break;
case (R.id.view_calendar ):
moveToFragment( new CalendarFragment());
}
drawer.closeDrawer(GravityCompat. START);
return true ;
});
View header = navigationView.getHeaderView( 0);
navHeaderTitle = header.findViewById(R.id. nav_header_title );
navHeaderTitle .setText( "Welcome, \n" + firebaseAuth .getCurrentUser().getEmail());
}

public List<Classroom> getClassrooms() {
return this .classrooms ;
}

public void setClassrooms(List<Classroom> classrooms) {
this.classrooms = classrooms;
}

public void buildEventsListView(ListView listView, Classroom classroom, long selectedDateInMillis)
{
ArrayList<TimeLapse> classroomIntervals = classroom.getIntervals();
if (classroomIntervals == null) {
return;
}
classroom.sortIntervals();
Map<String, String> eventsDetails = new LinkedHashMap<>();
for (TimeLapse interval : classroomIntervals) {

if (getStringDateFromTimeMillis (selectedDateInMillis).equals(interval.getDate())) {
String timeInterval = getFormattedTimeInterval (interval);
eventsDetails.put(timeIn terval, interval.getUserName());
}
}
List<Map<String, String>> listItems = new ArrayList<>();
adapter = new SimpleAdapter( this, listItems, R.layout. event_item ,
new String[]{ TIME_INTERVAL , USER, "CHECKBOX" }, new int[]{R.id. textView1 ,

70
R.id.textView2 , R.id.eventCheckBox });
Iterator iterator = eventsDetails.entrySet().iterator();

while (iterator.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.nex t();
Map<String, String> pair = new HashMap<>();
pair.put( TIME_INTERVAL , entry.getKey());
pair.put( USER, entry.getValue());
listItems.add(pair);
}
listView.setOnItemClickListener( new AdapterVi ew.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ViewGroup row = (ViewGroup) listView.getChildAt(position);
CheckBox checkBox = r ow.findViewById(R.id.eventCheckBox);
checkBox.setChecked( true);
}
});
listView.setAdapter(adapter);
}

public void notifyAdapter() {
adapter.notifyDataSetChanged();
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
drawer.openDrawer(GravityCompat.START);
return true ;
}
return super .onOptionsItemSelecte d(item);
}

public void moveToFragment(Fragment fragment) {
this.getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment, fragment.getTag())
.addToBackStack(fragment.getTag())
.commit();
}

@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityComp at.START);
return;
}
super.onBackPressed();
}

@Override
public void handleResult(Result result) {

}
}

71
Annex 4
ScanQRActivity.java

package com.etti.classroomsbooking;

import android.app.Activity;
import android.content .Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation. Nullable ;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android. support.v7.app.AppCompatActivity;
import android.widget.Toast;

import com.google.zxing.Result;

import me.dm7.barcodescanner.zxing.ZXingScannerView;

import static android.Manifest.permission. CAMERA;
import static com.etti.classroomsbooking.util.Constant. ACCEPTED_QR_CODES ;

// Reference: ZXing – open source library (https://opensource.google.com/projects/zxing)
public class ScanQRActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {

private static final int REQ_CAMERA = 1;
private ZXingScannerView scannerView ;
public static int scannedQRCode ;

@Override
public void onCreate( @Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scannerView = new ZXingScannerView( this);
setContentView( scannerView );

if (Build.VERSION_CODES. M <= Build.VERSION. SDK_INT) {
if (isPermissionGranted()) {
Toast.makeText (ScanQRActivity. this, "Persmission granted!" , Toast. LENGTH_LONG ).show();
} else {
requestForPermission();
}
} else {
Toast.makeText (ScanQRActivity. this, "Android API SDK must be higher than 23 for this
feature!" , Toast. LENGTH_LONG ).show();
finish();
startActivity( new Intent(getApplicationContext(), MainActivity. class));
}
}

private boolean isPermissionGranted() {
return PackageManager. PERMISSION_GRANTED ==
ContextCompat. checkSelfPermission (ScanQRActivity. this, CAMERA);
}

private vo id requestForPermission() {
ActivityCompat. requestPermissions (this, new String[]{ CAMERA}, REQ_CAMERA );
}

@Override
protected void onResume() {
super.onResume();
if (Build.VERSION_CODES. M <= Build.VERSION. SDK_INT) {
if (isPermissionGranted()) {
if (scannerView == null) {
setContentView( new ZXingScannerView( this));
}
scannerView .setResultHandler( this);
scannerView .startCamera();
}
}

72
}

@Override
protected void onDestroy() {
super.onDestroy();
scannerView .stopCamera();
}

@Override
public void handleResult(Result result) {
try {
if (ACCEPTED_QR_CODES .contains(result.getText())) {
scannedQRCode = Integer. parseInt (result.getText().substring( 10));
scannerView .stopCamera();
Intent resultIntent = getIntent();
resultIntent.putExtra( "SCANNED_CODE" , "" + result);
setResult(Activity. RESULT_OK , resultIntent);
} else {
scannedQRCode = -1;
}
finish();
} catch (NumberFormatException e) {
}
}
}

73
Annex 5
Utility.java

package com.etti.classroomsbooking.util;

import android.support.annotation. NonNull;

import com.etti.classroomsbooking.model.TimeLapse;

import java.util.Calendar;

public class Utility {
public static String getStringDateFromTimeMillis( long currentDateInMillis) {
Calendar calendar = Calendar. getInstance ();
calendar.setTimeInMillis(currentDateInMillis);
int day = calendar.get(Calendar. DAY_OF_MONTH );
int month = calendar.get(Calendar. MONTH) + 1;
int year = calendar.get(Calendar. YEAR);
String date = "" + formatTime (day) + "-" + formatTime (month) + "-" + year;
return date;
}

public static String formatTime( int x) {
if ((x < -9 && x > -100) || (x < 100 && x > 9)) {
return "" + x;
} else {
return "0" + x;
}
}

@NonNull
public static String getFormattedTimeInterval(TimeLapse interval) {
double startTime = interval.getStartTime();
double endTime = interval.getEn dTime();
String startTimeFormatted = formatTime ((int) startTime) + ":" + (startTime % 1 == 0.0 ? "00" :
"30");
String endTimeFormatted = formatTime ((int) endTime) + ":" + (endTime % 1 == 0.0 ? "00" : "30");
return "" + startTimeForm atted + " – " + endTimeFormatted;
}
}

74
Annex 6
Constant.java

package com.etti.classroomsbooking.util;

import java.util.Arrays;
import java.util.List;

public class Constant {
public static final String DATE_IN_MILLIS = "DATE_IN_MILLIS" ;
public static final String ROOM = "ROOM";
public static final String ROOM_POSITION = "ROOM_POSITION" ;
public static final String USER = "USER";
public static final String TIME_INTERVAL = "TIME_INTERVAL" ;
public static final int REQUEST_CODE_ QR = 2984;
public static final List<String> ACCEPTED_QR_CODES = Arrays. asList(new String[]{ "classroom -0",
"classroom -1", "classroom -2", "classroom -3", "classroom -4", "classroom -5"});
}

75
Annex 7
CalendarFragment.java

package com.etti.classroomsbo oking.fragments;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widge t.DatePicker;

import com.etti.classroomsbooking.MainActivity;
import com.etti.classroomsbooking.R;
import com.etti.classroomsbooking.model.Classroom;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.Calendar;

import static com.etti.classroomsbooking.util.Constant. DATE_IN_MIL LIS;
import static java.util.Calendar. MONDAY;

public class CalendarFragment extends Fragment {
private static final String TAG = CalendarFragment. class.getSimpleName();
DatePicker datePicker ;
FloatingActionButton floatingActionButton ;
Long dateInMillis ;
DatabaseReference roomsRef ;
FirebaseDatabase db;

public CalendarFragment() {
// Required empty public constructor
}

public static CalendarFragment newInstance(String param1, String param2) {
CalendarFrag ment fragment = new CalendarFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout. fragment_calendar , container, false);

datePicker = (DatePicker) view.findViewById(R.id. calendarDatePicker );
datePicker .setMinDate(System. currentTimeMillis () – 10000);
datePicker .setFirstDayOfWeek( MONDAY);
floatingActionButton = view.findViewById(R.id. floatingActionButton );
MainActivity mainActivity = (MainActivity) getActivity();
floatingActionButton .setOnClickListener(v -> {
Bundle args = new Bundle();
dateInMillis = getDateInstance( datePicker ).getTimeInMillis();
args.putLong( DATE_IN_MILLIS , dateInMillis );
Fragment classroomsFragment = new ClassroomsFragment();
classroo msFragment.setArguments(args);
mainActivity .moveToFragment(classroomsFragment);
});

db = FirebaseDatabase. getInstance ();
roomsRef = db.getReference( "rooms");
roomsRef .addValueEventListener( new ValueEventListener () {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot iterator : dataSnapshot.getChildren()) {

76
Classroom classroomFromDB = iterator.getValue(Classroom. class);
if (mainActivity .getClassrooms() == null) {
return;
}
mainActivity .getClassrooms().set(classroomFromDB.getId(), classroomFromDB);
}
}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});

return view;
}

public Calendar getDateInstance(DatePicker datePicker) {
Calendar calendar = Calendar. getInstance ();
calendar.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth());
return calendar;
}

}

77
Annex 8
ClassroomsFragment.java

package com.etti.classroomsbooking.fragments;

import android.os.Bundle;
import android.support.v4.ap p.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.etti.classroomsbooking.MainActivity;
import com.etti.classroomsbooking.R;
import com.etti.classroomsbooking.model.Classroom;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.math.BigDecimal;
import java.util.HashMap;

import static com.etti.classroomsbooking.util.Constant. ROOM;
import static com.etti.classroomsbookin g.util.Constant. ROOM_POSITION ;

public class ClassroomsFragment extends Fragment {
private static final String TAG = ClassroomsFragment. class.getSimpleName();
ListAdapter adapter;
ListView listView ;

public ClassroomsFragment() {
// Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout. fragment_classrooms , container, false);
listView = view.findViewById(R.id. list_classrooms );
String[] roomNames = { "A01", "A02", "A03", "B01", "B02", "B03"};
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout. simple_list_item_1 ,
roomNames );
listView .setAdapter( adapter);
listView .setOnItemClickListener((parent, view1, position, id) -> {
Bundle args = getArguments();
args.putInt( ROOM_POSITION , position);
Fragment eventsFragment = new EventsFragment();
eventsFragment.setArguments(args);
((MainActivity) getActivity()).moveToFragment(eventsFragment);
});

return view;
}

}

}

78
Annex 9
EventsFragment.java

package com.etti.classroomsbooking.fragments;

import com.etti.classroomsbooking.model.TimeLapse;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.FirebaseDatabase;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app. Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

import com.etti.classroomsbooking.MainActivity;
import com.etti.classroomsbooking.R;
import com.etti.classroomsbooking.model.Classroom;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import com.wdullaer.materialdatetimepicker.time.Timepoint;
import com.google.firebase.database.DatabaseReferen ce;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.etti.classroomsbooking.util.Constant. DATE_IN_MILLIS ;
import static com.etti.classroomsbooking.util.Constant. ROOM_POSITION;
import static com.etti.classroomsbooking.util.Utility. getStringDateFromTimeMillis ;

public class EventsFragment extends Fragment {

private static final String TAG = EventsFragment. class.getSimpleName();
Long dateInMillis ;
DatabaseRefer ence classroomsRef ;
DatabaseReference classroomRef ;
FirebaseDatabase db;
FirebaseAuth auth;
MainActivity mainActivity ;

public EventsFragment() {
// Required empty public constructor
}

public static EventsFragment newI nstance(Bundle bundle) {
EventsFragment fragment = new EventsFragment();
Bundle args = bundle;
fragment.setArguments(args);
return fragment;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGrou p container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout. fragment_events , container, false);
ListView listView = view.findViewById(R.id. list_events );
FloatingActionButton addEventB utton = view.findViewById(R.id. floatingActionButton2 );

Bundle args = getArguments();
dateInMillis = getArguments().getLong( DATE_IN_MILLIS );
int position = args.getInt( ROOM_POSITION );
long selectedDateInMillis = args.getLong (DATE_IN_MILLIS );
mainActivity = (MainActivity) getActivity();
Classroom selectedClassroom = ((MainActivity) getActivity()).getClassrooms().get(position);
mainActivity .buildEventsListView(listView, selectedClassroom, selectedDateInM illis);

79

TextView classroomNametextView = view.findViewById(R.id. classroomNameView );
TextView dateOfEvents = view.findViewById(R.id. dateOfEvents );
classroomNametextView.setText( "Classroom " + selectedClassroom.getName());
dateOfEvents.setText( getStringDateFromTimeMillis (dateInMillis ));
db = FirebaseDatabase. getInstance ();
classroomsRef = db.getReference( "rooms");

auth = FirebaseAuth. getInstance ();

addEventButton.setOnClickListener(v -> {
displayStartTimePicker( selectedClassroom , listView );
});

FloatingActionButton cancelMeetingsButton = view.findViewById(R.id. cancelSelectedMeetings );
if (cancelMeetingsButton != null) {
cancelMeetingsButton.setOn ClickListener(v -> {
int count = listView .getCount();
ArrayList<TimeLapse> intervalsFromSpecifiedDate = (ArrayList<TimeLapse>)
selectedClassroom .getIntervals().stream().filter(interval ->
interval.getDate().equals( getStringD ateFromTimeMillis (selectedDateInMillis ))).collect(Collectors. toList
());
ArrayList<TimeLapse> otherIntervals = (ArrayList<TimeLapse>)
selectedClassroom .getIntervals().stream().filter(interval ->
!interval.getDate().equals( getStringDateFromTi meMillis (selectedDateInMillis ))).collect(Collectors. toLis
t());
for (int i = 0; i < count; ++i) {
ViewGroup row = (ViewGroup) listView .getChildAt(i);
CheckBox check = row.findViewById(R.id. eventCheckBo x);
if (check.isChecked()) {
intervalsFromSpecifiedDate.set(i, null);
}
}
intervalsFromSpecifiedDate.removeAll(Collections. singleton (null));
for (TimeLapse timeLapse : otherIntervals) {
intervalsFromSpecifiedDate.add(timeLapse);
}
selectedClassroom .setIntervals(intervalsFromSpecifiedDate);
saveBookingToDB( selectedClassroom );
mainActivity .buildEventsListView( listView , selectedClassroom , dateInMillis );

});
}
return view;
}

public void displayStartTimePicker( final Classroom classroom, ListView listView) {
String selectedDat e = getStringDateFromTimeMillis (dateInMillis );
TimePickerDialog tpd = TimePickerDialog. newInstance ((view, hourOfDay, minute, second) -> {
double startPickedTime = getComposedHour(hourOfDay, minute);
displayEndTimePicker(star tPickedTime, classroom , selectedDate , listView );
}, true);

boolean[] disabledHours = classroom.checkStartTimeAvailability(selectedDate);
List<Timepoint> selectableTimes = new ArrayList<>();
for (int i = 0; i < 48; i++) {
if (disabledHours[i] != true) {
double j = (double) i / 2;
selectableTimes.add( new Timepoint(( int) j, (int) ((j % 1) * 60)));
}
}

Timepoint[] tps = new Timepoint[selectableTimes.size()] ;
tps = selectableTimes.toArray(tps);

tpd.setSelectableTimes(tps);
tpd.setTitle( "Choose starting time" );
tpd.show(getActivity().getFragmentManager(), "Choose starting time" );
}

public void displayEndTimePicker( double startPickedTime, Classroom classroom, String selectedDate,
ListView listView) {
TimePickerDialog tpdE = TimePickerDialog. newInstance ((view, hourOfDay, minute, second) -> {
classroom .bookClassroom( startPickedTime , getComposedHour(hour OfDay, minute),

80
auth.getCurrentUser().getEmail(), dateInMillis );
saveBookingToDB( classroom );
mainActivity .buildEventsListView( listView , classroom , dateInMillis );
((MainActivity) getActivity()).notifyAdapter();
}, true);
boolean[] disabledHoursE = classroom.checkEndTimeAvailability(selectedDate, startPickedTime);
List<Timepoint> selectableTimesE = new ArrayList<>();
for (int i = 0; i < 48; i++) {
if (disabledHoursE[i] != true && (double) i / 2 > startPickedTime) {
double j = (double) i / 2;
selectableTimesE.add( new Timepoint(( int) j, (int) ((j % 1) * 60)));
}
}
Timepoint[] tps = new Timepoint[selectableTimesE.size()];
tps = selectableTimesE.toArray(tps);

tpdE.setSelectableTimes(tps);
tpdE.setTitle( "Choose ending time" );
tpdE.show(getActivity().getFragmentManager(), "Choose ending time" );
}

private void saveBookingToDB(Classroom cla ssroom) {
classroom.sortIntervals();
classroomRef = classroomsRef .child("classroom" + classroom.getId());
classroomRef .setValue(classroom);
}

private double getComposedHour( int hourOfDay, int minute) {
double minutes = minute == 0 ? 0 : 0.5;
return hourOfDay + minutes;
}

public static String getTAG() {
return TAG;
}
}

81
Annex 10
ScannedRoomFragment.java

package com.etti.classroomsbooking.fragments;

import com.etti.classroomsbooking.ScanQ RActivity;
import com.etti.classroomsbooking.model.TimeLapse;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.FirebaseDatabase;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

import com.etti.classroomsbooking. MainActivity;
import com.etti.classroomsbooking.R;
import com.etti.classroomsbooking.model.Classroom;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import com.wdullaer.materialdatetimepicker.time.Timepoint;
import com.google.firebase.da tabase.DatabaseReference;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.etti.classroomsbooking.util.Utility. getStringDateFromTimeMillis ;

public class ScannedRoomFra gment extends Fragment {
private static final String TAG = ScannedRoomFragment. class.getSimpleName();
Long dateInMillis ;
DatabaseReference rootRef;
DatabaseReference classroomsRef ;
DatabaseReference classroomRef ;
FirebaseDatabase db;
FirebaseAuth auth;
MainActivity mainActivity ;

public ScannedRoomFragment() {
// Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
dateInMillis = System. currentTimeMillis ();
View view = inflater.inflate(R.layout. fragment_events , container, false);
ListView listView = view.findViewById(R.id. list_events );
TextView classr oomNametextView = view.findViewById(R.id. classroomNameView );
TextView dateOfEvents = view.findViewById(R.id. dateOfEvents );
FloatingActionButton addEventButton = view.findViewById(R.id. floatingActionButton2 );
FloatingActionButton can celMeetingsButton = view.findViewById(R.id. cancelSelectedMeetings );

long selectedDateInMillis = System. currentTimeMillis ();
mainActivity = (MainActivity) getActivity();
Classroom selectedClassroom = ((MainActivity)
getActivity()).g etClassrooms().get(ScanQRActivity. scannedQRCode );
mainActivity .buildEventsListView(listView, selectedClassroom, selectedDateInMillis);

classroomNametextView.setText( "Classroom " + selectedClassroom.getName());
dateOfEvents.setText( getStringDateFromTimeMillis (dateInMillis ));
db = FirebaseDatabase. getInstance ();
rootRef = FirebaseDatabase. getInstance ().getReference();
classroomsRef = db.getReference( "rooms");

82
auth = FirebaseAuth. getInstance ();

addEventButton.setOnClickListener(v -> {
displayStartTimePicker( selectedClassroom , listView );
});

if (cancelMeetingsButton != null) {
cancelMeetingsButton.setOnClickListener(v -> {
int count = listView.getCount();
ArrayList<TimeLapse> intervalsFromSpecifiedDate = (ArrayList<TimeLapse>)
selectedClassroom .getIntervals().stream().filter(interval ->
interval.getDate().equals( getStringDateFromTimeMillis (selectedDateInMillis ))).coll ect(Collectors. toList
());
ArrayList<TimeLapse> otherIntervals = (ArrayList<TimeLapse>)
selectedClassroom .getIntervals().stream().filter(interval ->
!interval.getDate().equals( getStringDateFromTimeMillis (selectedDateInMillis ))).collect(C ollectors. toLis
t());
for (int i = 0; i < count; ++i) {
ViewGroup row = (ViewGroup) listView .getChildAt(i);
CheckBox check = row.findViewById(R.id. eventCheckBox );
if (check.isChecked()) {
intervalsFromSpecifiedDate.set(i, null);
}
}
intervalsFromSpecifiedDate.removeAll(Collections. singleton (null));
for (TimeLapse timeLapse : otherIntervals) {
intervalsFromSpecifiedDate.add(timeLapse);
}
selectedClassroom .setIntervals(intervalsFromSpecifiedDate);
saveBookingToDB( selectedClassro om);
mainActivity .buildEventsListView( listView , selectedClassroom , dateInMillis );
}
);
}
return view;
}

public void displayStartTimePicker( final Classroom classroom, ListView listView ) {
String selectedDate = getStringDateFromTimeMillis (dateInMillis );
TimePickerDialog startTimePickerDialog = TimePickerDialog. newInstance (new
TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(Ti mePickerDialog view, int hourOfDay, int minute, int second) {
double startPickedTime = getComposedHour(hourOfDay, minute);
displayEndTimePicker(startPickedTime, classroom , selectedDate , listView );
}
}, true);

boolean[] disabledHours = classroom.checkStartTimeAvailability(selectedDate);
List<Timepoint> selectableTimes = new ArrayList<>();
for (int i = 0; i < 48; i++) {
if (disabledHours[i] != true) {
double j = (double) i / 2;
selectableTimes.add( new Timepoint(( int) j, (int) ((j % 1) * 60)));
}
}

Timepoint[] selectableStartTimes = new Timepoint[selectableTimes.size()];
selectableStartTimes = selectableTi mes.toArray(selectableStartTimes);

startTimePickerDialog.setSelectableTimes(selectableStartTimes);
startTimePickerDialog.setTitle( "Pick meeting start time" );
startTimePickerDialog.show(getActivity().getFragmentManager(), "Pick meet ing start time" );
}

public void displayEndTimePicker( double startPickedTime, Classroom classroom, String selectedDate,
ListView listView) {
TimePickerDialog endTimePickerDialog = TimePickerDialog. newInstance (new
TimePickerDialog.OnTimeSetL istener() {
@Override
public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) {
classroom .bookClassroom( startPickedTime , getComposedHour(hourOfDay, minute),
auth.getCurrentUser().getEmail( ), dateInMillis );
saveBookingToDB( classroom );

83
mainActivity .buildEventsListView( listView , classroom , dateInMillis );
((MainActivity) getActivity()).notifyAdapter();
}
}, true);
boolean[] disabledHoursEndTime = classroom.checkEndTimeAvailability(selectedDate,
startPickedTime);
List<Timepoint> selectableTimesE = new ArrayList<>();
for (int i = 0; i < 48; i++) {
if (disabledHoursEndTime[i] != true && (double) i / 2 > startPickedTime) {
double j = (double) i / 2;
selectableTimesE.add( new Timepoint(( int) j, (int) ((j % 1) * 60)));
}
}
Timepoint[] selectableEndTimes = new Timepoint[selectableTimesE.size() ];
selectableEndTimes = selectableTimesE.toArray(selectableEndTimes);

endTimePickerDialog.setSelectableTimes(selectableEndTimes);
endTimePickerDialog.setTitle( "Pick meeting end time" );
endTimePickerDialog.show(getActivity() .getFragmentManager(), "Pick meeting end time" );
}

private void saveBookingToDB(Classroom classroom) {
classroom.sortIntervals();
classroomRef = classroomsRef .child("classroom" + classroom.getId());
classroomRef .setValue(cl assroom);
}

private double getComposedHour( int hourOfDay, int minute) {
double minutes = minute == 0 ? 0 : 0.5;
return hourOfDay + minutes;
}
}

84
Annex 11

<?xml version= "1.0" encoding= "utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package= "com.etti.classroomsbooking" >

<application
android:allowBackup= "true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon= "@mipmap/ic_launcher_round"
android:supportsRtl= "true"
android:theme="@style/AppTheme.NoActionBar" >
<activity android:name=".login.RegisterActivity" />
<activity android:name=".login.LoginActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity >
<activity android:name=".MainActivit y">
icon
</activity >
<activity android:name=".ScanQRActivity" >
icon
</activity >
</application >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android. permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
</manifest >

85
Annex 12
<?xml version= "1.0" encoding= "utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
xmlns:app="http://schemas.android.com/apk/res -auto"
tools:context=".fragments.CalendarFragment" >

<DatePicker
android:id="@+id/calendarDatePicker"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_centerInParent= "true"
android:layout_gr avity="center" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignEnd= "@+id/calendar DatePicker"
android:layout_alignParentBottom= "true"
android:layout_marginBottom= "17dp"
android:clickable= "true"
app:srcCompat= "@android:drawable/ic_media_play" />

</RelativeLayout >

86
Annex 13

<?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_pare nt"
android:layout_height= "match_parent"
tools:context= ".login.LoginActivity" >

<LinearLayout
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_alignParentStart= "true"
android:layout_centerVertical= "true"
android:orientation= "vertical" >

<TextView
android:id="@+id/textViewLogin"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignParentTop= "true"
android:layout_centerHorizontal= "true"
android:layout_gravity= "center"
android:layout_marginTop= "77dp"
android:text="User Login" />

<EditText
android:id="@+id/edit TextEmail"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_margin= "15dp"
android:hint="Enter your email"
android:inputType= "textEmailAddress" />

<EditText
android:id="@+id/editTextPassword"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_margin= "15dp"
android:hint="Enter your password"
android:inputType= "textPassword" />

<Button
android:id="@+id/buttonRegister"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_margin= "15dp"
android:text="Login" />

<TextView
android:id="@+id/textViewSignIn"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:text="Don't have an account? Sign up here!"
android:textAlignment= "center" />

</LinearLayout >

<com.google.android.gms.common.SignInButton
android:id="@+id/signInGoogle"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_alignPar entBottom= "true"
android:layout_alignParentStart= "true"
android:layout_marginBottom= "38dp"></com.google.android.gms.common.SignInButton >

</RelativeLayout >

87
Annex 14
<?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= ".login. RegisterActivity" >

<LinearLayout
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_centerHorizontal= "true"
android:layout_centerVertical= "true"
android:orientation= "vertical ">

<TextView
c
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignParentTop= "true"
android:layout_centerHorizontal= "true"
android:layout_marginTop= "77dp"
android:layout_gravity= "center"
android:text="User Registration" />

<EditText
android:id="@+id/editTextEmail"
android:layout_margin= "15dp"
android:inputType= "textEmai lAddress"
android:hint="Enter your email"
android:layout_width= "match_parent"
android:layout_height= "wrap_content" />

<EditText
android:id="@+id/editTextPassword"
android:layout_margin= "15dp"
android:inputType= "textPassword"
android:hint="Enter your password"
android:layout_width= "match_parent"
android:layout_height= "wrap_content" />

<Button
android:id="@+id/buttonRegiste r"
android:layout_margin= "15dp"
android:text="Register User"
android:layout_width= "match_parent"
android:layout_height= "wrap_content" />

<TextView
android:id="@+id/textViewSignin"
android:textAlignment= "center"
android:text="Already registered? Sign in here!"
android:layout_width= "match_parent"
android:layout_height= "wrap_content" />

</LinearLayout >

</RelativeLayout >

88
Annex 15
<?xml version= "1.0" encoding= "utf-8"?>
<android.support.v4.widget.DrawerLayout 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" >

<LinearLayout
android:layout_width= "match_parent"
android:layout_height= "match_parent" >

<TextView
android:id="@+id/textView"
android:layout_width= "158dp"
android:layout_height= "225dp"
android:layout_alignParentLeft= "true"
android:layout_alignParentStart= "true"
android:layout_alignParentTop= "true"
android:layout_marginLeft= "145dp"
android:layout_marginStart= "145dp"
android:layout_marginTop= "52dp"
android:text="Welcome!" />

<Button
android:id="@+id/buttonLogout"
android:layout_ width="wrap_content"
android:layout_height= "wrap_content"
android:layout_alignParentBottom= "true"
android:layout_centerHorizontal= "true"
android:layout_marginBottom= "70dp"
android:text="Logout" />

<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width= "wrap_content"
android:layout_height= "match_parent"
android:layout_gravity= "start"
android:fitsSystemWindows= "true"
app:menu="@menu/drawer_view" />
</LinearLayout >

</android.support.v4.widget.DrawerLayout >

89
Annex 16

<?xml version= "1.0" encoding= "utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/androi d"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
tools:context= ".fragments.ClassroomsFragment" >

<ListView
android:id="@+id/list_classrooms"
android:layout_width= "match_parent"
android:layout_height= "510dp"
android:layout_alignParentStart= "true"
android:layout_alignParentTop= "true"
android:layout_marginTop= "57dp"
android:background= "@color/colorEvents2" />

</RelativeLayout >

90
Annex 17
<?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://sch emas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
tools:context= ".fragments.EventsFragment" >

<ListView
android:id="@+id/list_events"
android:layout_width= "match_parent"
android:layout_height= "428dp"
android:layout_alignParentTop= "true"
android:layout_marginTop= "89dp"
android:choiceMode= "multipleChoice" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/floatingAct ionButton2"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignParentEnd= "true"
android:layout_below= "@+id/list_events"
android:layout_marginEnd= "30dp"
android:clickable="true"
android:src="@drawable/ic_add_black_24dp" />

<TextView
android:id="@+id/classroomNameView"
android:layout_width= "231dp"
android:layout_height= "37dp"
android:layout_above= "@+id/list_events"
android:layout_alignParentStart= "true"
android:layout_marginBottom= "-89dp"
android:layout_marginStart= "11dp"
android:text="TextView"
android:textSize= "25dp"
android:textColor= "@color/colorEvents" />

<TextView
android:id="@+id/dateOfEvents"
android:layout_width= "91dp"
android:layout_height= "35dp"
android:layout_alignParentEnd= "true"
android:layout_alignTop= "@+id/classroomNameView"
android:layout_marginEnd= "15dp"
android:text="TextView"
android:textColor= "@color/colorEvents"
android:fontFamily= "sans-serif-medium"/>

<android.support.design.widget.FloatingActionButton
android:id="@+id/cancelSelectedMeetings"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignParentStart= "true"
android:layout_below= "@+id/list_events"
android:layout_marginStart= "30dp"
android:clickable= "true"
android:src="@drawable/ic_delete_black_24dp" />

</RelativeLayout >

91
Annex 18
<?xml version= "1.0" encoding= "utf-8"?><!– Use DrawerLayout as root container for activity –>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/androi d"
xmlns:app="http://schemas.android.com/apk/res -auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:fitsSystemWindows ="true"
tools:openDrawer= "start">

<FrameLayout
android:id="@+id/content_frame"
android:layout_width= "match_parent"
android:layout_height= "match_parent" >

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width= "match_parent"
android:layout_height= "?attr/actionBarSize"
android:background= "?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
</FrameLayou t>

<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width= "wrap_content"
android:layout_height= "match_parent"
android:layout_gravity= "start"
android:fitsSystemWindows= "true"
app:headerLayout= "@layout/nav_header"
app:menu="@menu/drawer_view" />
</android.support.v4.widget.DrawerLayout >

92
Annex 19

<?xml version= "1.0" encoding= "utf-8"?>
<RelativeLayout xmlns:android="http://schemas.androi d.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res -auto"
android:layout_width= "match_parent" android:layout_height= "match_parent"
android:orientation= "vertical"
android:background= "@color/colorEvents2" >

<TextView
android:id="@+id/textView1"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_alignParentStart= "true"
android:text="TextView"
android:textColor= "@color/colorEvents"
android:textSize= "21sp"
android:textStyle= "bold" />

<TextView
android:id="@+id/textView2"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_alignParentStart= "true"
android:layout_below= "@+id/textView1"
android:text="TextView"
android:textColor= "@android:color/black"
android:textSize= "16sp"
android:textStyle= "bold"
android:fontFamily= "sans-serif-thin"/>

<CheckBox
android:id="@+id/eventCheckBox"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignBottom= "@+id/textView2"
android:layout_alignParentEnd= "true" />

</RelativeLayout >

93
Annex 20

<?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= "192dp"
android:background= "?attr/colorPrimaryDark"
android:padding= "16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation= "vertical"
android:gravity= "bottom" >

<TextView
android:id="@+id/nav_header_title"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:text="Welcome!"
android:textAppearance= "@style/TextAppearance.AppCompat.Body1" />

</LinearLayout >

94
Annex 21
<?xml version= "1.0" encoding= "utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<group android:checkableBehavior= "single" >
<item
android:id="@+id/view_calendar"
android:icon="@drawable/ic_baseline_calendar_today_24px"
android:title="View Calendar" />
<item
android:id="@+id/scan_qr"
android:icon="@drawable/ic_menu_camera"
android:title="Scan QR Code" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manag e"
android:title="@string/tools" />
<item
android:id="@+id/nav_account"
android:icon="@drawable/ic_baseline_account_circle_24px"
android:title="Account" />
<item
android:id="@+id/nav_logout"
android:icon="@drawable/ic_logout"
android:title="Logout" />
</group>
</menu>

Similar Posts