Chapter 6.4 and small changes in the code

This commit is contained in:
wiecktobi 2020-06-10 23:07:10 +02:00
parent 089df551a7
commit de3b086a45
8 changed files with 60 additions and 9 deletions

View File

@ -182,16 +182,16 @@ class MainActivity : AppCompatActivity() {
, it.enddate.substring(11, 16) , it.enddate.substring(11, 16)
, it.duration)) , it.duration))
} }
} else {
println("No Records!")
}
if (running) { if (running) {
recordList.add(RecordEntry(workingSince!!, "PENDING", -1)) recordList.add(RecordEntry(workingSince!!, "PENDING", -1))
} }
adapter.data = recordList adapter.data = recordList
recView.layoutManager = layoutManager recView.layoutManager = layoutManager
recView.adapter = adapter recView.adapter = adapter
} else {
println("No Records!")
}
} else { } else {
println("Response for todays records was not successful") println("Response for todays records was not successful")
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -29,6 +29,7 @@
\begin{minipage}[b]{.4\linewidth} \begin{minipage}[b]{.4\linewidth}
\includegraphics[width=\linewidth]{img/android/login} \includegraphics[width=\linewidth]{img/android/login}
\caption{Login Activity} \caption{Login Activity}
\label{Abb:login}
\end{minipage} \end{minipage}
\hspace{.1\linewidth} \hspace{.1\linewidth}
\begin{minipage}[b]{.4\linewidth} \begin{minipage}[b]{.4\linewidth}
@ -42,6 +43,7 @@
\begin{minipage}[b]{.4\linewidth} \begin{minipage}[b]{.4\linewidth}
\includegraphics[width=\linewidth]{img/android/main} \includegraphics[width=\linewidth]{img/android/main}
\caption{Main Activity} \caption{Main Activity}
\label{Abb:main}
\end{minipage} \end{minipage}
\hspace{.1\linewidth} \hspace{.1\linewidth}
\begin{minipage}[b]{.4\linewidth} \begin{minipage}[b]{.4\linewidth}
@ -131,7 +133,7 @@
\subsection{Geofencing} \subsection{Geofencing}
Die Geofencing-Funktion ist die zentrale Funktion für die App und auch für das gesamte Projekt. Deshalb war es wichtig, dass sie frühzeitig funktioniert. \\ Die Geofencing-Funktion ist die zentrale Funktion für die App und auch für das gesamte Projekt. Deshalb war es wichtig, dass sie frühzeitig funktioniert. \\
Um die Positon eines Gerätes zu bestimmen bedarf es einer Berechtigung, die vom Benutzer bestätigt werden muss. Für Geräte mit API-Level 28 und niedriger muss dafür die \verb|ACCESS_FINE_LOCATION|-Berechtigung gesetzt werden und für API-Level 29 und höher \verb|ACCESS_BACKGROUND_LOCATION|. \\ Um die Position eines Gerätes zu bestimmen bedarf es einer Berechtigung, die vom Benutzer bestätigt werden muss. Für Geräte mit API-Level 28 und niedriger muss dafür die \verb|ACCESS_FINE_LOCATION|-Berechtigung gesetzt werden und für API-Level 29 und höher \verb|ACCESS_BACKGROUND_LOCATION|. \\
Der Geofence wird initialisiert, wenn für den Benutzer Geo-Daten gespeichert sind. Ist dies der Fall, so wird ein \verb|GeofencingClient| angelegt, dem dann der Geofence hinzugefügt wird. Der Geofence wird erzeugt mit den Parametern: Breitengrad, Längengrad, Radius, der Lebenszeit des Fence und den Übergangstypen. Die Typen sind in unserem Fall \verb|GEOFENCE_TRANSITION_ENTER| und \verb|GEOFENCE_TRANSITION_EXIT|, da wir immer reagieren wollen, wenn der Nutzer den Bereich verlässt oder betritt. Der Geofence wird initialisiert, wenn für den Benutzer Geo-Daten gespeichert sind. Ist dies der Fall, so wird ein \verb|GeofencingClient| angelegt, dem dann der Geofence hinzugefügt wird. Der Geofence wird erzeugt mit den Parametern: Breitengrad, Längengrad, Radius, der Lebenszeit des Fence und den Übergangstypen. Die Typen sind in unserem Fall \verb|GEOFENCE_TRANSITION_ENTER| und \verb|GEOFENCE_TRANSITION_EXIT|, da wir immer reagieren wollen, wenn der Nutzer den Bereich verlässt oder betritt.
\begin{lstlisting}[language=Kotlin] \begin{lstlisting}[language=Kotlin]
geofencingClient = LocationServices.getGeofencingClient(this) geofencingClient = LocationServices.getGeofencingClient(this)
@ -163,7 +165,7 @@
\end{lstlisting} \end{lstlisting}
Die \verb|GeofenceBroadcastReceiver|-Klasse definiert was bei den jeweiligen Events ausgeführt werden soll. In unserem Fall ist dies das Verändern einer boolean Shared-Prefrences-Variable, je nachdem ob der Bereich betreten oder verlassen wurde. Warum diese Art und Weise gewählt wurde lesen Sie in Kapitel \ref{sec:Probleme}.\\ Die \verb|GeofenceBroadcastReceiver|-Klasse definiert was bei den jeweiligen Events ausgeführt werden soll. In unserem Fall ist dies das Verändern einer boolean Shared-Prefrences-Variable, je nachdem ob der Bereich betreten oder verlassen wurde. Warum diese Art und Weise gewählt wurde lesen Sie in Kapitel \ref{sec:Probleme}.\\
Das Code-Beispiel zeigt die Aktion beim Betreten des Bereichs. Das Code-Beispiel zeigt die Aktion beim Betreten des Bereichs.
\begin{lstlisting}[language=Kotlin][language=Kotlin] \begin{lstlisting}[language=Kotlin]
context!!.getSharedPreferences("LOCATION", Context.MODE_PRIVATE) context!!.getSharedPreferences("LOCATION", Context.MODE_PRIVATE)
?.edit() ?.edit()
?.putBoolean("ENABLED", true) ?.putBoolean("ENABLED", true)
@ -175,7 +177,56 @@ context!!.getSharedPreferences("LOCATION", Context.MODE_PRIVATE)
\section{Funktionen der App} \section{Funktionen der App}
Wie oben beschrieben besteht die Android-App aus den vier Activities. Die Register- und Settings-Activity sind aus zeitlichen Gründen ohne Funktion und layouttechnisch nicht überarbeitet. Der Fokus lag stark auf der Main-Activity, das Kernstück der App darstellt. Im Folgenden die Funktionalitäten der Activities Login und Main.
\subsection{Login Screen} \subsection{Login Screen}
In der Abbildung \ref{Abb:login} ist der Login Screen zu sehen. Er besteht aus der Top-Action-Bar mit Logo und App-Name, den Eingabefeldern und zwei Buttons. Alle Komponenten sind aus der Material-Design-Bibliothek. \\
Zum Einloggen werden die Daten in die jeweiligen Felder eingegeben. Wenn ein Feld markiert ist, wird das ausgewählte Feld blau umrandet und der Hinweis wird auf die obere Linie verschoben. Das Passwortfeld zeigt nur kurz den eingegebenen Buchstaben an und wird dann zu einem \verb|*|, sodass das Passwort nicht offen lesbar ist. \\
Der Login-Button sendet die Daten an das Backend und prüft ob die Daten korrekt sind. Wenn dies der Fall ist, enthält die Antwort das Token, welches in den privaten Speicher abgelegt wird, und die App wechselt zum Hauptbildschirm. War der Login nicht erfolgreich, wird dem Benutzer eine Pop-Up-Meldung angezeigt und nichts weiter unternommen. Mit dem betätigen des Registrieren-Knopfes wird man auf die Register-Activity weitergeleitet.
\subsection{Main Activity}\label{subsec:main} \subsection{Main Activity}\label{subsec:main}
Auf dem Hauptbildschirm erscheint in der Top-Action-Bar ein drei Punkte Menü (Kebab-Menü), von dem aus man zu den Einstellungen gelangen oder sich ausloggen kann. Beim Ausloggen wird die Datei mit dem Benutzer-Token gelöscht und die Login-Activity aufgerufen.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/android/main_menu}
\caption{Menü auf dem Hauptbildschirm}
\label{Abb:menu}
\end{figure}
Direkt unter der Top-Action-Bar wird der Benutzer mit dem Vornamen begrüßt (Abb.: \ref{Abb:main}). \\
In der Bedienfläche kann der Benutzer den Timetrack-Account auswählen und dessen Details ansehen, seine heutigen Arbeitszeiten ansehen und die Aufzeichnung starten oder stoppen. \\
Die Auswahl des Accounts erfolgt über ein Dropdown-Menü. Bei Auswahl wird sofort die zugehörige Beschreibung und die Vergütung angezeigt. Wenn die Aufzeichnung am laufen ist, wird das Dropdown-Menü ausgeblendet. Das verhindert, dass der Benutzer eine Aktivität für einen andern Account stoppen kann als er sie gestartet hat. Ist für den Benutzer noch kein Account vorhanden, wird "None" im Menü angezeigt und die beiden Felder für Beschreibung und Vergütung werden ausgeblendet. \\
Für die Anzeige der heutigen Arbeitszeiten habe ich eine RecyclerView verwendet. Das Layout dazu wird in einer extra XML-Datei definiert und mit Daten in einer Adapter-Klasse befüllt. Durch eine Backendabfrage bekomme ich die nötigen Daten dafür. Bei aktiver Aufzeichnung wir ein Element angezeigt mit der Startzeit und der Info, dass das Ende offen ist.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/android/main_recording}
\caption{Laufende Aufzeichnung}
\label{Abb:menu}
\end{figure}
Der Start-Stop-Button schält die Aufzeichnung um, in dem ein Backend-Endpunkt angesprochen wird. In der App habe ich eine boolean-Variable \verb|running|, welche gespeichert hält ob die Aufzeichnung aktiv ist. Anhand ihr wird entschieden wie der Start-Stop-Button aussieht und ob beim Verlassen des Geofence noch gestoppt werden muss. Der Button ist nicht Auswählbar wenn sich der Nutzer außerhalb seines Arbeitsplatzes befindet und zeigt dies auch an (Abb.: \ref{Abb:outside}). Ist der Nutzer dann im Bereich, wird "Start" angezeigt und der Button ist freigeschaltet. Während der Aufzeichnung trägt der Button die Schrift "Stop".
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/android/btn_outside}
\caption{Nutzer außerhalb seines Geofence}
\label{Abb:outside}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/android/btn_start}
\caption{Aufzeichnung kann gestartet werden}
\label{Abb:menu}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/android/btn_stop}
\caption{Laufende Aufzeichnung}
\label{Abb:menu}
\end{figure}
Um versehentliches stoppen der Aufzeichnung zu verhindern, muss der Nutzer in einem Pop-Up-Dialog seine Aktion bestätigen.
\begin{figure}[H]
\centering
\includegraphics[width=0.4\linewidth]{img/android/confirm_stop}
\caption{Bestätigungs Dialog zum stoppen}
\label{Abb:menu}
\end{figure}
\section{Probleme und Lösungen}\label{sec:Probleme} \section{Probleme und Lösungen}\label{sec:Probleme}
\section{Deployment} \section{Deployment}