LG Vertretungsplan App für Android
In English: LG Vertretungsplan App for Android
In den vergangenen Wochen entwickelte ich eine App für den Vertretungsplan meiner Schule.
Anmerkung: Alle Daten und Namen, die in den Screenshots zu sehen sind, sind rein fiktiv. Jede Ähnlichkeit zu echten Daten oder Personen, lebendig oder verstorben, ist purer Zufall. Die Screenshots enthalten keine Daten des echten Online-Vertretungsplans und verstoßen dadurch nicht gegen dessen Nutzungsbedingungen.
Bisherige Situation
Vor der Entwicklung der Android-app konnten Schüler meiner Schule den Vertretungsplan wie folgt einsehen:
- im Schulgebäude
- online (momentan beschränkt auf Schüler der Oberstufe)
Der Online-Vertretungsplan wurde in diesem Schuljahr eingeführt und ermöglicht es Schülern, den Vertretungsplan »gemütlich« nach der Schule oder vor Schulbeginn um ca. 7:30 Uhr einzusehen.
Auch wenn dies ein nettes Feature ist, hat es seine Probleme:
- Hässliche Nutzeroberfläche
- Schlechte Lesbarkeit durch mangelhafte Wahl ein Kontrast zwischen Text und Hintergrund
- Keine mobile Oberfläche, und eine schlechte Nutzererfahrung für mobile Nutzer (zu viel Scrolling, kaum erreichbare Steuerelemente)
Die Idee
Die grundlegende Idee war es, eine App zu entwickeln, die dem Nutzer nur die für ihn relevanten Daten präsentiert. Momentan würde das bedeuten, dass man nur die Kurse der aktuellen Klassenstufe zu Gesicht bekommt.
Um es übersichtlich zu halten, soll der Nutzer zunächst nur die relevantesten Daten sehen, und weitere Informationen beim Interagieren mit dem jeweiligen Eintrag erhalten.
Das Problem
In der Theorie war das Abrufen der notwendigen Daten der einfachste Teil. Ich würde die zuständige AG (»Arbeitsgemeinschaft«) kontaktieren und darum bitten, entweder Zugriff zum Quellcode zu erlangen, um eine maschinenlesbare API selbst zu implementieren, oder sie eine solche API implementieren zu lassen. Jedoch habe ich nicht einmal eine Antwort auf meine Anfrage erhalten.
Also war es doch nicht so einfach wie erwartet. Eine Zusammenarbeit war nicht vorhanden und die Kommunikation war spärlich. Um meinen letzten Stolz zu wahren, entschied ich mich, das Problem auf eigene Faust zu lösen, ohne deren Unterstützung.
Die Lösung
Glücklicherweise bin ich mehr oder weniger erfahren im Web Scraping, aufgrund vergangener Aufgaben, die das Sammeln von Daten aus verschiedenen Webseiten umfassten. Das hier war nichts anderes. Die Idee ist, dass man die Webseite so ausliest und nutzt, als wäre das Programm selbst ein Nutzer. In diesem Fall habe ich mit der Jsoup-Bibliothek und CSS-Selektoren gearbeitet. Jsoup beschreibt sich selbst als »praktische API zum Extrahieren und Manipulieren von Daten«. Natürlich verarbeiten Nutzer Webseiten nichts mittels CSS-Selektoren, aber es ist ein Anfang.
Die Schritte zum Sammeln der Vertretungsplandaten sind:
- Lade den HTML-Code für den Vertretungsplan, den wir abrufen wollen (
/heute
für heute und/morgen
für morgen) - Verarbeite den Code mittels Jsoup
- Frage alle Tabellenzeilen durch diesen CSS-Selektor ab:
#vertretungsplan tr
- Für jede Zeile: rufe alle
td
-Elemente ab, verarbeite ihre Daten und speise sie in eine Liste ein
Nachdem alle Daten verarbeitet wurden können sie wie vorgesehen dargestellt werden.
Ein weiteres Problem war die Authentifizierung.
Der Online-Vertretungsplan nutzt PHP-Session-Ids und Cookies für die Authentifizierung.
Der Authentifizierungsablauf sieht wie folgt aus:
Gebe deine Daten in das Anmeldeformular ein, führe eine POST-Request zur Indexseite aus um deine Session-ID für zukünftige Anfragen zu authentisieren, und erhalte ab dann Daten von /heute
und /morgen
.
Aber das würde bedeuten, dass man jedes Mal, wenn ein erneuter Login erforderlich ist, eine Authentifizierungsabfrage ausführen muss.
Und auch bei nicht authentisierten Anfragen müsste ich jedes die zurückgegebene Seite auf Fehler prüfen, da diese wahnsinnige Anwendung keinerlei Gebrauch von HTTP-Status-Codes macht.
Der HTML-Code ist ebenfalls fehlerhaft: HTML-IDs müssen laut Standard einzigartig sein, werden aber im Online-Vertretungsplan mehrfach auf der gleichen Seite genutzt.
Rechtschreibfehler sind ebenfalls mehrfach vorhanden.
Wie ich später herausgefunden habe, ist es egal, an welche Seite die POST-Request zur Authentifizierung gesendet wird.
Um also Traffic zu sparen sende ich die Authentifizierungsinformationen mit jeder Anfrage an /heute
und /morgen
.
Auf den ersten Blick mag dies wie ein Sicherheitsrisiko erscheinen, aber alle Anfragen werden mittels TLS (Transport Layer Security) übertragen und mit den Accounts sind keinerlei sensitive Daten verknüpft.
Zukünftige Pläne
Das größte geplante Feature sind Benachrichtigungen basierend auf einer nutzerdefinierten Liste von Kursen. In einem festen Intervall soll die App die Vertretungsplandaten erneut laden, eine Menge an Änderungen generieren und anhand dieser Benachrichtigungen zu den eingestellten Kursen anzeigen. Ich bin mir noch nicht sicher, ob ich ein Cloud-Sync-Feature einbauen werde, da die App momentan vollständig ohne einen serverseitigen Teil auskommt – abgesehen vom bereits vorhandenen Online-Vertretungsplan.
Open Source
Der vollständige Quellcode der App steht auf GitHub unter der BSD-2-Klausel-Lizenz zur Verfügung.