\chapter{Android-App} \section{Technologiebeschreibung} \subsection{Android SDK} Die Android-Entwicklung wurde, aufgrund der Ausgereiftheit und den Emulatoren, mit Android-Studio realisiert. Android-Studio verwaltet auch das SDK und unterstützt beim aktuell halten der Bibliotheken. \\ Das minimale API-Level, welches das Endgerät haben darf wurde auf 23 "Marshmallow" festgelegt. Dadurch werden ca. 85\% der Geräte unterstützt und ist aktuell genug um gewisse Features, wie das neue Berechtigungssystem, zu unterstützen. Die Zielversion ist das aktuelle Android 10 mit API-Level 29. In dieser Version wurden erneut Berechtigungen geändert, wodurch im Code einige Anpassungen gemacht werden mussten (siehe: \ref{sec:Probleme}) \subsection{Kotlin} Die Entscheidung fiel auf Kotlin als Programmiersprache, da die Sprache von Google für die Entwicklung von Android-Apps bevorzugt wird. Außerdem bietet dies die Gelegenheit eine neue Programmiersprache zu erlernen. Dadurch jedoch musste viel Zeit investiert werden um zum Einen die Sprache und zum Anderen die Entwicklungsumgebung, sowie der Aufbau einer Android-App zu lernen. Dafür wurden zwei von insgesamt fünf Sprints eingeplant, weswegen die App nur die Grundfunktionen besitzt.\\ Die Kotlin-Version bei Fertigstellung ist die aktuellste Version (1.3.72). \subsection{Retrofit} Für die Kommunikation mit dem Backend wurde die Bibliothek Retrofit in der Version 2.8.1 verwendet. Retrofit ist ein HTTP-Client für Android mit dem man REST-Endpunkte simpel ansprechen kann. Zusammen mit der Gson-Bibliothek lassen sich JSON-Nachrichten senden und empfangen. \\ Das angefragte API wird mit Klassen und Methoden in der Anwendung modelliert. Dadurch ist es möglich nur die Felder abzufragen, welche auch benötigt werden. Genaueres in Kapitel \ref{subsec:AnzeigeDaten}. \subsection{Material Design} Material ist eine Bibliothek, die Komponenten und Richtlinien bereitstellt. Nach einmaligem Einbinden der Bibliothek können die Komponenten verwendet werden, indem der Komponente der Style zugewiesen wird. \section{Farbschema und Designsprache} In einem gemeinsamen Meeting mit dem Web-Frontend einigten wir uns auf Farbcodes, die auf beiden Oberflächen verwendet werden. So haben wir uns auf ein dunkles Schema festgelegt, mit den Farben aus dem Logo für Schrift und Akzente. Als Schriftart wird Montserrat verwendet. \\ %Einfügen Ausschnit MainActivity \section{Umsetzung} \subsection{Design der Activities} Insgesamt besitzt die App die vier Activities: Login, MainActivity, Register und Settings. Wobei die Register- und die Settings-Activity aus zeitlichen Gründen ohne Funktion sind. Sie haben auch noch die alten unschönen Eingabefelder, sind aber für die Funktion der gesamten Anwendung nicht sonderlich relevant, weshalb entschieden wurde diese zu vernachlässigen und den Fokus auf die Funktionalität zulegen. \\ Jeder Bildschirm hat eine Top-Bar auf der, je nachdem auf welchem Bildschirm man sich befindet, unterschiedliche Inhalte angezeigt werden.Beim Einloggen und Account erstellen wird außer dem Logo und dem Namen der App nichts angezeigt. In den Einstellungen erscheint anstatt dem Logo ein Zurück-Button und auf dem Hauptbildschirm gibt es ein Menü zum Ausloggen und zu den Einstellungen zu gelangen. \begin{figure}[H] \centering \begin{minipage}[b]{.4\linewidth} \includegraphics[width=\linewidth]{img/android/login} \caption{Login Activity} \end{minipage} \hspace{.1\linewidth} \begin{minipage}[b]{.4\linewidth} \includegraphics[width=\linewidth]{img/android/register} \caption{Register Activity} \end{minipage} \end{figure} Links die Eingabefelder mit Material Design und rechts die alten selber erstellten. \begin{figure}[H] \centering \begin{minipage}[b]{.4\linewidth} \includegraphics[width=\linewidth]{img/android/main} \caption{Main Activity} \end{minipage} \hspace{.1\linewidth} \begin{minipage}[b]{.4\linewidth} \includegraphics[width=\linewidth]{img/android/settings} \caption{Settings Activity} \end{minipage} \end{figure} Wie zu erkennen ist lag der Fokus der Implementierung deutlich auf der Main Activtiy, da sie auch das Wichtigste der App beinhaltet. Prominent ist dabei der 'START'-Knopf an der Unterseite, mit dem die Aufzeichnung gestartet werden kann (genaueres im Kapitel \ref{subsec:main}). \subsection{Authentifizierung} Zur Authentifizierung benutzen wir JWT, welches bei jeder Anfrage ans Backend mit geschickt werden muss. Das Token erhält man beim Einloggen mit den richtigen Daten und muss persistiert werden, bis sich der Benutzer ausloggt. Dazu speichere ich das Token im privaten Speicher der App. In allen weiteren Activities kann dann auf den Speicher zugegriffen werden und das Token beim Erstellen des \verb|AuthenticationInterceptor|s mitgegeben werden. Beim Ausloggen wird einfach die Datei mit dem Token aus dem Speicher gelöscht. \\ Der \verb|AuthenticationInterceptor| ist Kind von der \verb|Interceptor|-Klasse aus der \verb|okhttp3|-Bibliothek, welche in Retrofit eingebunden ist. Mithilfe des Interceptors können REST-Abfragen Header-Daten mitgegeben werden. In unserem Fall ist das das \verb|Authorization|-Feld mit dem Token. \begin{verbatim} class AuthenticationInterceptor(pToken: String) : Interceptor { private val token = pToken override fun intercept(chain: Interceptor.Chain): Response { val original = chain.request() val builder = original.newBuilder() .header("Authorization", token) val request = builder.build() return chain.proceed(request) } } \end{verbatim} Der Interceptor wird dem HTTP-Client hinzugefügt, welcher später bei der Erzeugung des Retrofit-Builders notwendig ist. \begin{verbatim} val httpClient = OkHttpClient.Builder() val interceptor = AuthenticationInterceptor(token) httpClient.addInterceptor(interceptor) \end{verbatim} \subsection{Anzeige der Daten in der Main Activity}\label{subsec:AnzeigeDaten} Die Daten werden per REST-Aufruf mithilfe vom Retrofit-Framework vom Backend geholt. Um Anfragen zusenden benötigt man einen Retrofit-Builder. Diesem wird die anzufragende URL, ein JSON-Konverter und ein HTTP-Client mitgegeben. Aus diesem Builder und einer Service-Klasse, in der die Methoden definiert sind, wird ein Objekt erzeugt mit dem die Methoden aufrufbar sind. val builder = Retrofit.Builder() .baseUrl("http://plesk.icaotix.de:5000") .addConverterFactory(GsonConverterFactory.create()) .client(httpClient.build()) val retrofit = builder.build() service = retrofit.create(GeofenceService::class.java) \subsection{Geofencing} \section{Funktionen der App} \subsection{Login Screen} \subsection{Main Activity}\label{subsec:main} \section{Probleme und Lösungen}\label{sec:Probleme} \section{Deployment}