Skip to content

martinreimer/VHB-FitnessStudioApp

Repository files navigation

Mitglieder- und Kursverwaltung für Fitnessstudios

Projektbeschreibung

Projektziele

Die App soll die Verwaltungsarbeit eines Premium-Fitnessstudio-Betreibers erleichtern. Premium-Fitnessstudios bieten ihren Mitgliedern wöchentlich verschiedene Kurse an, die seit der Corona-Pandemie hohen Verwaltungsaufwand erfordern. Denn während vor der Pandemie die Kursräume auch überfüllt sein durften und alle Mitglieder ohne vorherige Anmeldung an Kursen teilnehmen konnten, ist die Kursteilnahme jetzt auf eine bestimmte Teilnehmeranzahl zur Einhaltung von Abstandsregeln begrenzt und eine Anmeldung zum Kurs wurde wegen der Nachvollziehbarkeit von Infektionsketten zur Pflicht. Die App ermöglicht es den Betreibern, ihren Wochen-Kursplan zu verwalten und weitere nützliche Infos zu ihrem Studio wie Trainerinfos oder die Anfahrtsbeschreibung bereitzustellen. Für Mitglieder des Studios bietet die App eine einfache und übersichtliche Möglichkeit, Infos zum Studio einzusehen und sich zu Kursen an- oder abzumelden.

Wesentliche Funktionen der App

Registrierung/Login

Die Benutzer melden sich mit der Rolle Admin/Trainer oder der Rolle Mitglied an der App an

image

Hauptmenü

Je nach Rolle des angemeldeten Benutzers werden die entsprechenden Menüpunkte angezeigt

image

Pflege des Wochen-Kursplans

Die Übersicht der Kurse wird auf einem Tabbed Screen mit Wochentagen angezeigt. Pro Wochentag wird der Zeitplan dargestellt:

image

Die Detailansicht der Kurse dient zur Einsicht von Kursdaten und zum Pflegen eines Kurses:

image

Buchen/Stornieren von Kursen

Die Übersicht der anstehenden Kurse mit farblich hervorgehobenen gebuchten Kursen ist auf einer Kalender-Ansicht zu finden:

image

In der Detailansicht eines Kalender-Events kann ein Kurs gebucht oder eine Buchung storniert werden:

image

Pflege von Studio-Kontaktinformationen

image

Einsicht von Studio-Kontaktinformationen

image

Pflege und Einsicht von Trainern

Auf einer Übersichtsseite werden alle Trainer in Listenform dargestellt.

image

Auf der Detailansicht sind die Lizenzen, Aus- und Fortbildungen der Trainer zu finden:

image

Pflege und Einsicht von Mitgliedern

Auf einer Übersichtsseite werden alle Mitglieder in Listenform dargestellt.

image

Auf der Detailansicht können Kontaktdaten eingesehen und bearbeitet werden.

image

Hinweise zur Inbetriebnahme der App

Datenbank

Die App beihaltet eine lokale Room-Datenbank. Zur Inbetriebnahme der App müsste eine zentrale Datenbank angebunden werden, auf die jeder angemeldete Benutzer zugreift, um den aktuellen Stand vom Kurswochenplan, von Buchungen, Mitgliedern, Trainern und deren Profilbildern zu erhalten. Es wurde außerdem auf die Validierungsfunktion einer Buchung verzichtet, d.h. zur Inbetriebnahme müsste geprüft werden, ob noch Kursplätze verfügbar sind oder der Kurs bereits ausgebucht ist. In vielen Studios gibt es außerdem die Möglichkeit, sich bei ausgebuchten Kursen auf die Warteliste setzen zu lassen. Das könnte über einen weiteren Buchungsstatus erweitert werden.

Registrierung

Die App beinhaltet keinerlei Verifikation der Email-Adresse oder eines gültigen Mitglieds- oder Trainer-Accounts. Zur Inbetriebnahme müsste die App um einen Bestätigungslink per Email und um die Genehmigung einer neuen Registrierung durch den Studiobetreiber oder berechtigte Benutzer erweitert werden.

Ausblick

Weitere Funktionen, die für einen Live-Betrieb der App wünschenswert wären, sind:

  • Die Möglichkeit, dass Trainer nicht nur die Anzahl der Buchungen für einen Kurs, sondern auch die angemeldeten Benutzer einsehen können.
  • Funktionen für eine bessere Vermarktung des Studios, z.B. über Bereiche zum Hochladen von Bildern und Videos oder bevorstehende Veranstaltungen.
  • Einsicht von Preis- und Leistungsinformationen des Studios.

Kompilierbarkeit

Um einen kompilierbaren Clone der App zu erhalten, sind folgende Eigenschaften zu beachten:

  • API-Level: minSdk 26, targetSdk 31
  • Android Studio Default JDK Version: 11.0.11
  • Android Studio Version: Android Studio Bumblebee | 2021.1.1 Patch 2
  • Damit die Google-Map-Komponente verwendet werden kann, ist der API-KEY im local.properties-File folgendermaßen zu ergänzen:
    MAPS_API_KEY=AIzaSyBRKAuXtcb5S3yeIeQrM3pkUacBD9vuLik
    

Ausführbare Datei

Die APK-Datei zur App ist hier zu finden.

Projektvorgehen

Das Projekt wurde vollständig in einem eigenen Github-Repository entwickelt. Die wesentlichen Commits wurden zur Veranschaulichung in dieses Class-Room-Repository projiziert. Im initialen Projekt-Kick-Off-Meeting wurden die Vorgehensweise für unser Projekt sowie die wesentlichen Funktionen, die die App erhalten soll, gemeinsam definert und in einer Meilenstein-/Terminplanung über Github-Project verwaltet:

image

mockups_img classdiagramm

Nach der Erstellung von Mockups- und Klassendiagrammen wurde in einer weiteren gemeinsamen Besprechung die Aufgabenaufteilung festgelegt. Für die Entwicklung der App wurde ein Kanban-Board benutzt, auf dem die einzelnen Funktionen der App in Tasks aufteilt wurden.

image

In weiteren wöchentlichen MS-Teams-Meetings wurden Fortschritt, Probleme und weiteres Vorgehen besprochen.

Funktionen

Übersicht der Aufwandspunkte nach Anforderungskatalog

Feature-Beschreibung Kategorie Aufwand beschrieben in Funktion(en)
Daten verschlüsselt speichern Sicherheit 1 Registrierung
Wiederverwendbare Layoutbausteine: Fragments User Interface 1 Kurse buchen
Shared Preferences persistieren Persistenz 1 Studio-Kontaktinformationen pflegen
Intents mit Payload Kommunikation (intern) 1 Registrierung, Kursplan pflegen
Tabbing (Swipe to change screen) User Interface 1 Kursplan pflegen
Nebenläufige Aktionen Software-Engineering 2 alle Datenbankoperationen, Studio-Kontaktinformationen einsehen
Notification User Interface 1 Kurse buchen
Datenbank auf dem Gerät Persistenz 2 Registrierung,Kursplan pflegen,Trainer pflegen,Mitglieder verwalten
Eigener Adapter Software-Engineering 2 Mitglieder verwalten,Trainer pflegen,Kursplan pflegen
Service für längere Hintergrundaufgaben Software-Engineering 2 Kurse buchen
Map-Komponente dynamisch/interaktiv User Interface 3 Studio-Kontaktinformationen einsehen
Fingerabdruck-Login für App Sensoren 3 Anmeldung

Funktion: Anmeldung

Grundsätzlich bestehen zwei Möglichkeiten des Logins über die LoginActivity. Zum einen der normale Weg über Eingabe von E-Mail-Adresse und Passwort als Identifier und zum anderen der Weg über den Fingerabdruck Login:

Normale Eingabe

Die hier angezeigten Eingabefelder sind mit einem TextChangeListener ausgestattet, ohne den der inaktiv geschaltete „Einloggen“-Button nicht zu benutzen ist. Nach ausfüllen der benötigten Felder kann eine Anfrage über den jetzt aktiven Button gestellt werden. Um unnötige Datenbankabfragen zu verhindern, durchlaufen die Benutzereingaben eine Vorabüberprüfung auf die passende Form (Mail-Adressen Format). Da die Userpasswörter in verschlüsselter Form in der Datenbank hinterlegt sich, ist ein weiterer Punkt im Ablauf des Prozesses das Hashen des Passwortes mit Hilfe der tohash() Funktion des HashHelper. Wurde der User in der Datenbank gefunden, wird seine ID und Rolle in den SharedPreferences gespeichert und je nach gefundener Rolle die passende Activity gestartet. Das hat den Grund das späteren Datenbankoperationen die ID des Nutzers benutzen können, ohne diese diese per Intent Extra weiterreichen zu müssen. Ist die Userrolle als „member“ hinterlegt wird per Intent die MemberMainActivity gestartet. Entspricht die Rolle „admin“, gelangt der User in die mit mehr Rechten und Menüpunkten ausgestattet AdminMainActivity. Hat der User falsche Logindaten verwendet wird ihm dies über einen Toast mitgeteilt.

Fingerabdruck Login

Um den Fingerabdruck Login benutzen zu können muss diese Option zunächst im Einstellungen Menüpunkt in der SettingsActivity aktiviert werden und in den SharedPreferences hinterlegt. Beim nächsten Aufrufen der Login Activity wird diese Information von dort abgefragt. Ein BiometricManager prüft, ob die entsprechende Hardware im Device des Benutzers vorhanden ist und zeigt den Button im Interface an. Hat der Benutzer die Benutzung aktiviert und verfügt über die entsprechende Hardware, wird der Button angezeigt. Die BiometricPrompt Klasse verwaltet alle Funktionen des Fingerabdrucksensors. Es zeigt den selbst mit Text ausstattbaren Authentifizierungsdialog und gleicht den gescannten Fingerabdruck mit dem im System Hinterlegten ab. Wie beim normalen Login wird anschließend die Rolle und ID aus den SharedPreferences ausgelesen und entsprechende Activities über einen Intent gestartet.

Element 16

Funktion: Registrierung

Erster Registrierungsschritt

Der Registrierungsprozess besteht aus drei Activities, in denen vom User Angaben zu seiner Person verlangt werden.

In der FirstStepRegisterActivity muss jedes Eingabefeld ausgefüllt werden, um sicherzustellen das möglichst vollständige Datensätze der Benutzer in die Datenbank eingefügt werden können. Dies wird durch einen TextChangeListener realisiert, der nach jeder Eingabe das komplette Formular auf Vollständigkeit prüft und in diesem Fall den „Fortfahren“ Button aktiv schaltet. Wird dieser Button betätigt startet die Eingabevalidierung und Felder wie die E-Mail-Adresse werden mittels einer Pattermatcher Funktion aus der Libary auf eine ihre Grundform überprüft. Aus Sicherheitsgründen wird die Passworteingabe mittels des inputType=„TextPassword“ verdeckt angezeigt, kann jedoch bei Bedarf über das Augensymbol an der linken Seite sichtbar gemacht werden. Ebenfalls der Sicherheit wegen muss der User sein Passwort wiederholen und kann nur mit einer mindestlänge von 5 Zeichen fortfahren. Die Eingabe des Geburtsdatums erfolgt durch den übliche DatePickerDialog.

Element 12

Zweiter Registrierungsschritt

Die Funktionen in der SecondStepRegisterActivity gleichen im Wesentlichen denen des Ersten. Ein kleines Dropdown Menü, das durch einen AutoCompleteTextView in Verbindung mit einem ArrayAdapter implementiert wurde, lässt den User sich eine Rolle zuweisen. Im Hintergrund wurden die Userdaten durch einen mit Extra beladenen Intent weitergegeben, zwischengespeichert und in gleicher Weise an die letzte Registrierungsaktivity weitergegeben.

Element 15

Dritter Registrierungsschritt

Hier in der ThirdStepRegisterActivity werden aus Usabiliygründen alle, durch die Intents weitergegebenen, Informationen des Users erneut angezeigt, um sie vom User auf ihre Korrektheit zu prüfen. Ist der User einverstanden, kann er die Registrierung durch den Button abschließen. Hier bei wird mit Hilfe, der von unserem DatabaseHelper bereitgestellten Funktionen die User, entsprechend ihrer ausgewählten Rolle, als Member bzw Admin erstellt, in die Datenbank geschrieben und die entsprechende Hauptmenüaktivity per Intent gestartet.

Element 13

Verschlüsseltes Speichern

Um die Passwörter nicht als Klartext in die Datenbank schreiben zu müssen, wird vor der Übergabe des Passwortstrings dieser mittels HashHelper-Klasse verschlüsselt. Diese produziert mit dem Secure Hash Algorithmus (SHA-512) aus einer Zeichenkette einen 64-Byte-Hashwert.

Rolle Trainer/Admin

Funktion: Kursplan pflegen

Für die Verwaltung des Wochen-Kursplans wurde eine Tabbed Activity erstellt. Die CourseActivity benutzt den View activity_course.xml und kümmert sich mithilfe des SectionsPagerAdapters um die Anzeige der Tabreiter. Die Tab-Überschriften werden über einen Array im Ressource String File mit den Wochentagen Montag bis Sonntag befüllt. Pro Tabreiter wird ein Zeitplan angezeigt, welcher im DayViewFragment mithilfe der öffentlichen Github-Library Android-Week-View (com.github.quivr:android-week-view:2.3.3) realisiert wurde.

image

Zum Hinzufügen eines neuen Kurses kann der Plus-Button betätigt werden, der zur Activity CourseAddActivity führt. Die Detailansicht des Kurses wurde im wiederverwendbaren Layoutbaustein activity_course_details_view.xml definiert. Alternativ zum Plus-Button kann ein Long-Click auf einen leeren Bereich im Zeitplan gemacht werden, welcher die Uhrzeit in der Detailansicht mit dem angeklickten Zeitpunkt vorbefüllt. In der Kurs-Detailansicht können nun alle relevanten Felder befüllt werden. Dazu gehören der Kursname, Beschreibung, Start-Uhrzeit, Dauer, Trainer, Location und die maximale Teilnehmerzahl. Alle Felder sind Pflichtfelder und werden beim Speichern des Kurses validiert. Zur Auswahl des Start-Zeitpunkts kann über Long-Click in das Feld ein Zeitwähler geöffnet werden. Die Trainer können über einen Spinner, der als View und Dropdown-View list_array_adapter.xml anzeigt, der über den eigenen Adapter CoachArrayAdapter realisiert ist, ausgewählt werden. Außerdem kann ein Gültigkeitsdatum des Kurses festgelegt werden. Bei Long-Click wird ein Datumswähler-Dialog angezeigt. So kann der Stundenplan im Voraus zum Beispiel für das nächste Quartal gepflegt werden, ohne dass die aktuellen Kurse verändert werden müssen(bis auf das gültig-bis Datum). Zum Speichern des Kurses ist im Action-Menü ein Speichern-Button verfügbar. Beim Speichern wird der Kurs über den nebenläufigen Task AddCourseTask in der Datenbank persistiert.

image

Wird in der Kurs-Plan-Ansicht ein bestehender Kurs angeklickt so wird ein Intent mit den Kursinformationen als Payload zur Activity CourseEditActivity gestartet. Die Activity benutzt denselben Layoutbaustein activity_course_details_view.xml zur Detailansicht der Kurse. Im Action-Menü werden Buttons zum Speichern und zum Löschen des Kurses angezeigt. Beim Löschen wird der Kurs über den nebenläufigen Task DeleteCourseTask aus der Datenbank entfernt, zum Speichern wird der nebenläufigen Task UpdateCourseTask verwendet. Ansonsten arbeitet die Activity mithilfe der CourseHelper-Klasse mit denselben Funktionen wie die CourseAddActivity.

Funktion: Studio-Kontaktinformationen pflegen

Die Informationen über den Betrieb eines Fitnessstudios bleiben nicht für immer gleich, bespielsweise können sich die Öffnungszeiten häufig ändern. Diese Informationen müssen für den Administrator veränderbar sein, ohne dass die ganze App geupdated werden muss. Daher haben wir die ContactInfoManagerActivity (XML: activity_manage_contact_info.xml) entwickelt. Der Administrator kann darauf über den "Kontakt Manager"-Button im Menü zugreifen. Der Admin kann dort den Namen des Studios, die Addresse, die E-Mail, die Nummer und die Öffnungszeiten einstellen. Diese Werte werden zunächst validiert und nach erfolgreicher Validierung im Preference Manager im <key, value> Format abgespeichert. Falls keine Werte vom Admin eingestellt werden, werden Default Werte verwendet, welche im Ressource String File gespeichert sind.

Funktion: Trainer pflegen

Die Trainerliste wird über die Activity CoachListActivity, den zugehörigen eigenen Adapter CoachArrayAdapter und den XML-View list_array_adapter.xml realisiert.

image

Über einen Klick auf ein List-Item gelangt der Benutzer in die Trainer-Detailansicht CoachDetailsActivity mit zugehörigem XML-View activity_coach_details_view.xml. Zur selben Activity wir den Benutzer über den Plus-Button geleitet. In der Detailansicht des Trainers kann der Benutzer den Namen und die Beschreibung wie Lizenzen oder Ausbildungsstand des Trainers pflegen. Über den Kamera-Button kann ein Profilbild hinterlegt werden.

image

  • Mit der Option "Foto machen" wird die Kamera-App gestartet und der Benutzer kann ein neues Foto schießen. Dazu wurde ein File-Provider im Manifest definiert und der Bilder-Pfad im XML-Resource-File hinterlegt. Die URI zum Profilbild-Pfad wird in der Trainer-Datenbanktabelle abgespeichert.
  • Mit der Option "Foto aus Galerie wählen" kann der Benutzer ein Foto aus der Galerie hochladen. Die URI wird ebenso in der Trainer-Datenbanktabelle abgespeichert, womit das Profilbild beim nächsten Start der App und auch in der Listenansicht der Trainer wieder in ein Bitmap umgewandelt wird.
Funktion: Mitglieder verwalten

Mitglieder werden in der Datenbank angelegt, indem sich die Mitglieder selber registrieren. Der Administrator benötigt die Möglichkeit die registrierten Mitglieder zu verwalten. Zum Beispiel soll er die Möglichkeit haben Mitglieder aus der Datenbank entfernen zu können, die nicht für das Studio bezahlen oder die Hausverbot haben. Außerdem sollte er zum Beispiel die Adresse eines Mitglieds ändern können, falls sich diese ändern sollte. Um diese Funktionalität anbieten zu können wurden folgende Klassen mit XML-Darstellung erstellt:

Rolle Mitglied

Funktion: Kursplan anzeigen

Ist ein Benutzer mit der Rolle Mitglied angemeldet, werden dieselben Activities und XML-Views wie in Funktion: Kursplan pflegen im Read-Only-Modus verwendet:

image image

Funktion: Kurse buchen

Die Activity BookingActivity zeigt den XML-View activity_booking.xml, welcher die Android-Week-View beinhaltet. Diese zeigt eine Kalendersicht im Wochenformat und beinhaltet alle anstehenden Kurse eine Woche im Voraus als Events des Android-Week-Views.

image

Beim Klick auf ein Event wird die Kurs-Detailansicht über das Fragment BookingFragment mit dem wiederverwendbaren Layoutbaustein activity_course_details_view geöffnet und das Mitglied kann sich über den Action-Button zum Kurs anmelden. Daraufhin wird der Kurs in der Kalenderansicht farblich hervorgehoben. Vor Abspeichern des Kurses wird ein zufälliger numerischer requestCode erzeugt, mit dem in der BookingActivity ein Alarm eine Stunde vor Kursbeginn gesetzt wird. Der Alarm bekommt als Parameter einen PendingIntent, der einen Broadcast auslöst. Bei Empfang des Broadcasts eine Stunde vor Kursbeginn startet der BookingReminderReceiver den Service BookingReminderService, welcher eine Notification auslöst.

image

Der Kurs wird anschließend in der Datenbank mit der UserId und der requestId des Alarm-Services abgespeichert. Mit Klick auf die Notification kann der Benutzer in die Kurs-Buchen-Ansicht wechseln. Zum Abmelden von einem Kurs kann das Mitglied in einen gebuchten Kurs klicken und dort den Action-Button seine Buchung stornieren. Die Buchung erhält den Status storniert in der Datenbank und über die requestId wird der laufende Alarm abgebrochen, so dass der Benutzer keine Notification eine Stunde vor Kursbeginn mehr für einen Kurs erhält, für den er nicht mehr eingebucht ist.

Funktion: Trainereinsicht

Es werden dieselben Activities und XML-Views wie in Funktion: Trainer pflegen im Read-Only-Modus verwendet:

image image

Funktion: Mitgliedereinsicht

Das Mitglied erhält über das Mitglieder Menü (XML: activity_member_main.xml) eine kleine Ansicht über dessen Eigenschaften. Es wird zum einen der Vorname angezeigt und das Datum an dem sich das Mitglied registriert hat. Sollte das Mitglied seine Daten verändern oder sein Konto löschen wollen, müsste er sich an den Admin wenden.

Funktion: Studio-Kontaktinformationen einsehen

Über die ContactInfoActivity (XML: activity_contact_info.xml) erhalten die Mitglieder Informationen über die Kontaktinformationen des Studios. Diese Informationen werden aus dem Preference Manager geladen. Sollte der Admin keine aktuellen Kontaktinformationen bereitstellen, werden Default Werte aus dem Ressource String File geladen. Neben den aufgelisteten Informationen wurde auch eine Maps-Komponente in die Ansicht integriert. Diese Maps-Komponente zeigt die Adresse des Studios in einer Karte an. Die Karte beinhaltet einen Marker an der Studio-Adresse, welche über einen Background-Thread mit dem GeocoderTask aufgelöst wird. Bei Klick auf die Infobox mit der Adresse wird Google Maps geöffnet und ein Routenplaner zum Studio gestartet. Klickt der Benutzer auf einen anderen Bereich in der Karte wird die Karte in einer neuen Full-Screen-Activity mit denselben Funktionen geöffnet (Activity MapsActivity mit XML-View activity_maps.xml). Diese Funktion soll es dem Mitglied ermöglichen schneller das Fitnessstudio zu finden.

Demo

Wegen des Uploadlimits von 25 MB ist unser Präsentationsvideo hier zu finden: https://www.dropbox.com/s/6xjtch4rc33w5v7/AbgabevideoFitnessApp.mp4?dl=0

Team

Vorstellung

Lucas Schmieder

Martin Reimer

Julia Strahberger

Zuständigkeiten

Lucas Schmieder

  • Mockups
  • Splash Screen
  • Anmeldung/Registrierung
  • Hauptmenüs
  • Launcher-Icon
  • App-Video

Martin Reimer

  • Use Case Diagramm
  • Klassendiagramm
  • Fingerabdruck-Sensor
  • Mitglieder-Verwaltung
  • Kontaktverwaltung
  • Shared Preferences
  • Verschlüsselung von Passwörtern

Julia Strahberger

  • Projektorganisation
  • Kursverwaltung
  • Kursbuchung
  • Trainerverwaltung
  • Profilbild-Upload
  • Notification
  • Google Map-Komponente

Guidelines zur Nutzung dieses Repositorys

Allgemeine Hinweise und Vorgaben

  • Das Repository besteht im initialen Stand aus einem einzelnen Master-Branch. Versuchen Sie bei der Arbeit am Projekt darauf zu achten, dass sich in diesem Branch stets die aktuell lauffähige und fehlerfreie Version Ihrer Anwendung befindet. Nutzten Sie für die eigentliche Entwicklung ggf. weitere Branches.
  • Gehen Sie sorgfältig bei der Erstellung von Issues und Commit Messages vor: Die Qualität dieser Artefakte fließt nicht in die Bewertung ein, trotzdem sollten Sie versuchen, Ihr Vorgehen anhand nachvollziehbarer Versionseinträge und klarere Aufgabenbeschreibung gut zu dokumentieren.
  • Halten Sie diese Readme-Datei(en) stets aktuell.
  • Diese sollte auch wichtige Informationen für die Nutzung beinhalten (Handbuch).
  • Spätestens zur Projektabgabe legen Sie eine Release-Version des finalen Stands Ihrer Anwendung an und hängen an diese eine installierbare (Debug-) APK-Datei an.
  • Achten Sie insbesondere darauf anzugeben, welches API-Level / NDK-Version ihrem Projekt zugrunde liegt und auf die 'Kompilierbarkeit' ihres finalen Codes.

About

An Android app for managing a hypothetical fitness studio, developed collaboratively with two fellow students as part of the VHB.org 'App-Programmierung mit Android' course during Winter Semester 2021/2022.

Resources

License

Stars

Watchers

Forks

Contributors