Corona-Ampel - Session 4 (09.12.)

Corona-Ampel - Session 4: Finale Arbeiten
Am letzten Tag werden die App auf unseren Smartphones testen, Texte für den Store vorbereiten und auch eine Fehlerbehandlung einbauen.

Zur vorherigen Session geht’s hier lang: Corona-Ampel - Session 3 (02.11.)

Zeitrahmen

Zur Orientierung hier noch einmal der Zeithorizont:

Datum Grobes Ziel Link
18.11. Einführung und Tools kennenlernen -
25.11. API-Integration, GPS-Plugin und einfache Anzeige im UI Teil 2
02.12. Ampel-Anzeige, evtl. Umsetzen des Entwurfes vom Design-Team Teil 3
09.12. Finale Arbeiten Teil 4

Ziele

In der heutigen Session wollen wir zunächst eine einfach gehaltene Fehlerbehandlung einbauen. Dies ist notwendig, wenn das Smartphone keine GPS Position ermitteln konnte bzw. durfte, oder auch falls die Web-Schnittstelle keine passenden Daten zur Position gefunden hat.

Sobald dies abgeschlossen ist, probieren wir die App (das erste Mal) auf Android Smartphones, lernen auch was notwendig ist für iOS-Geräte.

Abschließend bereiten wir die App-Store-Listings vor, d.h. (primär) Texte schreiben und Screenshots von der Anwendung erstellen.

Vorbereitung

Öffnet den CoronaAmpel Ordner auf eurem Desktop. Öffnet den Quellcode in Visual Studio Code, startet eine Kommandozeile (Rechtsklick > git bash here) und führt das Kommando npm start aus. Alternativ schaut euch die Beschreibung vom ersten Mal an.

Falls der Ordner nicht mehr vorhanden ist, so kannst du hier der Code vom ersten Mal: Corona Ampel.zip. Nach dem Download entpacken, eine Kommandozeile in dem Ordner öffnen und in der Kommandozeile npm install und anschließend npm start ausführen.

Anschließend zur Kontrolle den Browser öffnen (http://localhost:4200) und die App angucken. Es sollte das Ergebnis vom letzten Mal zu sehen sein.

Hier grob die Übersicht für heute:

  1. Fehlerbehandlung in der App
  2. Pull-to-Refresh
  3. Android Build
  4. App Store Listings

Die Fehlerbehandlung in der App

In diesem Abschnitt wollen wir den Nutzer der App informieren, falls etwas schief gegangen ist. Spontan fallen mir mehrere Möglichkeiten ein:

  • Der Nutzer lehnt den Zugriff auf das GPS-Modul des Smartphones ab.
  • Die Web-Schnittstelle kann keine Daten zur GPS Position ermitteln.
  • Das Gerät ist offline bzw. die Internetverbindung zu langsam.

Über all dies sollten wir den Nutzer informieren und die Möglichkeiten anbieten den Fehler zu beheben.

Hast du die vorherigen Sessions verfolgt, dann wurden die verschiedenen Anfragen an die Web-Schnittstelle oder das GPS-Plugin mittels then..catch-Blöcken aufgebaut. Zur Erinnerung der catch-Block wird ausgeführt sobald das Promise nicht in den Erfolgsfall führt (intern wird Promise.reject) aufgerufen. Probieren wir das mal aus. Unter der Annahme das der Code zum Laden der Daten wie folgt aussieht (home.page.ts):

this.geolocation.getCurrentPosition()
  .then(pos => {
    console.log(pos);
    const lat = pos.coords.latitude;
    const lng = pos.coords.longitude;
    const url = `${baseUrl}?lat=${lat}&lng=${lng}`;
    return this.http.get<{ data: ICovid19Response }>(url)
      .toPromise();
  })
  .then(body => {
    console.log(body)
    this.covidData = body.data;
  })
  .catch(err => {
    console.error(err);
});

Wir sehen zwei then-Blöcke und einen catch-Block. In dieser Struktur werden alle Fehler, egal ob vom GPS Plugin getCurrentPosition() oder dem Http-Request http.get(...) innerhalb dieses einen Blockes ausgeführt. Mit dem Statement console.error schreiben wir den Fehler auf die Console, aber das hilft nur uns Entwicklern. Um eine Fehlermeldung für das GPS-Plugin zu werfen, machen wir folgendes:

  1. Öffne die Seite im Browser http://localhost:4200.
  2. Im Chrome klickst du nun auf das Info-Icon links neben der URL `http://localhost:4200:
    • Chrome Reset Geolocation
    • Das Vorgehen ist bei Firefox oder Edge ähnlich.
  3. Wähle beim Zugriff auf die Geolocation Block oder Ask aus, um den Zugriff zu blockieren bzw. euch den Fragedialog aus der vorherigen Session anzuzeigen.

Ziel des Ganzen ist es den Zugriff zu blockieren, um einen Fehler zu schmeißen. Lade die Seite neu und der Browser blockiert den Zugriff oder es wird nachgefragt und du wählst “Blockieren/Nein” aus. Nun passiert folgendes: die Ladeanimation läuft unendlich lang weiter und in der Console wurde ein Fehler aufgezeichnet. Zur Console kommst du, indem du F12 oder Strg + Shift + I drückst. Wähle in den Entwicklertools Console aus und du solltest folgende Meldung sehen:

Geolocation Error

Von Interesse ist der rot hinterlegte Fehler GeolocationPositionError. Dieser hat einen Code (1), einen Zeile in der er geschmissen worden ist (home.page.ts:46) und eine Nachricht (message). Die Nachricht gibt auch Aufschluss darüber was passiert ist: User denied Geolocation, also der Nutzer hat den Zugriff verweigert (denied). Dies ist nicht die einzige Fehlermeldung vom Plugin.

Hinweis: Die Fehlerbehandlung die wir hier lernen und durchführen ist recht rudimentär.

Fehlerbehandlung bei Ablehnung des GPS-Zugriffes

Für die Fehlerbehandlung des GPS-Plugins nehmen wir folgende Schritte vor:

  1. Anzeigen des Fehlers für den Nutzer
  2. Option anbieten den Zugriff erneut zu erteilen, falls der Nutzer den Zugriff abgelehnt hat

Zunächst wollen wir im catch-Block den spezifischen Fehler identifizieren. Dazu können wir mit dem message-Attribut des err-Objektes arbeiten. Mittels switch-Blockes wollen wir je nach Nachricht eine unterschiedliche Nachricht speichern. Dazu legen wir eine string Variable an und setzen ihren Wert je nach case Block. Falls du von switch..case bisher noch nichts gehört hast: dabei handelt es sich um ein kompaktere Schreibweise von vielen if..else if..else-Blöcken.

.catch((err: Error) => {
  console.error(err);
  let errorMessage = '';

  switch (err.message) {
    case 'User denied Geolocation':
      errorMessage = 'Zugriff auf die Standortdaten wurde abgelehnt. Bitte erlaube den Zugriff ein deinen App-Einstellungen.';
      break;
    default:
      errorMessage = 'Fehler beim Laden der Daten.';
      break;
  }
})

Die Nachricht wollen wir in einen ion-toast verpacken:

Ion Toast GPS

Dazu fügen wir einen neuen Import an den Anfang der home.page.ts und fügen den ToastController zum constructor hinzu:

import { ToastController } from '@ionic/angular';

export class HomePage {
  constructor(
    private http: HttpClient,
    private geolocation: Geolocation,
    private toastCtrl: ToastController,
  ) { }
}

Innerhalb unseres catch-Blocks wollen wir toast.Ctrl nutzen um mittels create Methode einen Toast zu erzeugen. Wir geben die Argumente errorMessage, eine Farbe (color) und einen Button zum Neuladen mit. Die create Methode erzeugt den Toast asynchron in einem Promise, sodass wir hier ebenfalls einen then-Block hinzufügen und in diesem dann toast.present() aufrufen, um den Toast schließlich anzuzeigen:

.catch((err: Error) => {
  console.error(err);
  let errorMessage = '';

  switch (err.message) {
    ...
  }

  this.toastCtrl.create({
    message: errorMessage, // Nachricht, die der Toast anzeigt
    color: 'danger', // Farbe, selbe Vorgehensweise wie bei den ion-button
    buttons: [
      {
        icon: 'reload-outline', // icon vom Button - siehe https://ionicons.com/
        handler: () => this.loadCovidData(), // Neuladen der Daten beim Blick auf das Icon
      }
    ]
  }).then(toast => {
    toast.present(); // Anzeigen des Toasts
  });
})

Beim Testen vergiss nicht die Geolocation auf “Blockieren/Ablehnen” zu setzen. Drückst du das Neuladen-Icon, so verschwindet der Toast und taucht kurz danach wieder auf, denn die Berechtigung fehlt ja immer noch.

Fehlerbehandlung, wenn die Web-Schnittstelle keine Daten liefert

Ähnlich wie der fehlenden Berechtigung für die GPS-Position wollen wir einen Toast anzeigen, wenn die Web-Schnittstelle keine Daten liefern kann. Ist dies der Fall wird ein Http-Code 406 mit folgendem Inhalt zurückgegeben:

{ 
  "error": {
    "name": "EINVALID_DATA",
    "message": "Position could not be identified."
  }
}

Die Struktur ist etwas anders als das Standard-Error-Objekt in JavaScript, daher wollen wir obigen Fehler umwandeln und anschließend den switch..case Code erweitern. Dazu gehen wir in den ersten then-Block:

this.geolocation.getCurrentPosition()
  .then(pos => {
    console.log(pos);
    const lat = pos.coords.latitude;
    const lng = pos.coords.longitude;
    const url = `${baseUrl}?lat=${lat}&lng=${lng}`;
    return this.http.get<{ data: ICovid19Response }>(url)
      .toPromise()
  })
  ....

Zunächst wollen wir den Fehler kurz einmal ausprobieren. Setze dazu die Werte von lat und lng auf beispielsweise 12 und 0 (irgendwas außerhalb Deutschlands). Gehe in die Anwendung, erlaube den Zugriff auf die Standortdaten und schaue in die Console. Folgendes wird nun passieren:

  • In der App wird ein Toast mit dem Text “Fehler beim Laden der Daten.” angezeigt - dies kommt von unserem default Block.
  • In der Console befinden sich zwei (rot hinterlegte) Fehler:
    • GET https://covid-api-rki.vercel.app/api/v1/county-data-by-position?lat=12&lng=0 406 - eine Meldung, dass die Webschnittstelle einen 4xx Http-Code zurückgegeben hat.
    • Und das HttpErrorResponse Objekt das im Code behandelt wird

Mit dem HttpErrorResponse wollen wir arbeiten. Klappe es in der Console auf und gucke dir dessen Inhalt an:

HttpErrorResponse

Innerhalb des Attributes error finden wir obige Daten wieder. Dies wollen wir nun umwandeln, da unser switch Block mit dem HttpErrorResponse nichts anfangen kann. Dies machen wir durch einen neuen catch-Block an der toPromise-Methode. Innerhalb des Blockes werfen wir einen neuen Fehler mittels throw new Error(msg) und ersetzen msg durch das Attribut message in unserem HttpErrorResponse.

Hilfestellung (auf den Pfeil klicken).
// home.page.ts
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

return this.http.get<{ data: ICovid19Response }>(url)
  .toPromise()
  .catch((err: HttpErrorResponse) => {
    throw new Error(err.error.error.message);
  });

Der neugeworfene Fehler (Error) hat nun dieselbe Struktur wie andere und wir können den switch-Block um einen neuen case mit der Nachricht Position could not be identified. erweitern. Als Toast-Nachricht kannst du zum Beispiel “Keine Covid-19-Daten zur Position ermittelbar.” setzen.

case 'Position could not be identified.':
  break;

Schließen des Toasts beim Verlassen der Seite

Ist ein Toast offen und wechselt der Nutzer die Seite über das Menü (zur Karte), so wird der Toast bestehen bleiben. Das wollen wir nicht, denn auf der Kartenansicht hat dessen Meldung keinerlei Relevanz mehr. Zum Schließen nutzen wir die LifeCycleHooks vom letzten Mal (ionViewDidEnter) - nur diesmal nutzen wir ionViewWillLeave. Diese Methode wird ausgeführt, sobald der Nutzer eine Navigation zu einer anderen Seite startet. Innerhalb der Methode geben wir den Wert this.toastCtrl.dismiss(); zurück, das alle offenen Toasts schließt.

Hilfestellung (auf den Pfeil klicken).
// home.page.ts
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

export class HomePage {
  ionViewWillLeave() {
    return this.toastCtrl.dismiss();
  }
}

(optional) Fehlerbehandlung, wenn die App offline ist

Zu guter Letzt wollen wir noch den Fall behandeln, falls die App keine Internetverbindung herstellen kann. In diesem Fall zeigen wir keinen Toast an, sondern eine Nachricht anstelle der Ladeanimation. Dazu wenden wir folgende Punkte an, die wir in den vorherigen Sessions gelernt haben:

  • eine Klassenvariable isOnline: boolean
  • *ngIf in der HTML-Datei, um einen Text und einen Neuladen-Button anzuzeigen, falls die App offline ist
  • einen ion-button und ein ion-icon, mit dem (click) Handler, um dem Nutzer die Möglichkeit des Neuladens zugeben.

Zusätzlich benötigen wir navigator.onLine, dass uns mitteilt, ob die Anwendung derzeit eine Internetverbindung hat (true) oder nicht (false). Nutze diesen Wert, um deine Programmlogik aufzubauen.

Das Ergebnis kann in etwa so aussehem:

Error Handling Offline

Zum Testen der offline Funktionalität, muss du kurzzeitig die Internetverbindung von deinem Gerät ausschalten.

Hilfestellung (auf den Pfeil klicken).
<!-- home.page.html -->
  <ion-grid *ngIf="!covidData">
    <ion-row class="ion-justify-content-center">
      <ion-spinner *ngIf="isOnline"></ion-spinner>
      <div *ngIf="!isOnline">
        <ion-row>
          <h3>
            <ion-text color="danger">Die App kann keine Verbindung zum Internet herstellen. Überprüfe deine
              Einstellungen.
            </ion-text>
          </h3>
        </ion-row>
        <ion-row>
          <ion-button (click)="loadCovidData()">
            <ion-icon slot="start" name="reload-outline">
            </ion-icon> Neuladen
          </ion-button>
        </ion-row>
      </div>
    </ion-row>
  </ion-grid>
// home.page.ts
export class HomePage {
  public isOnline = true;

  public loadCovidData() {
    this.isOnline = navigator.onLine;
    if (!navigator.onLine) {
      return;
    }
   ....
  }
}

Aufgabe: Füge dieselbe Methodik in der Kartenansicht hinzu.

App Refresh mittels Pulldown (“Pull to Refresh”)

Im folgenden wollen wir einen Pulldown-Refresher einbauen, d.h. der Nutzer zieht die Oberfläche von oben nach unten und Daten werden nachgeladen. Sollte bekannt sein von großen Social-Media-Plattformen. Hier gibt es ein Beispiel aus den Apple-Richtlinien (Video abspielen). Ionic bietet so eine Komponente bereits an mit dem ion-refresher- Diesen wollen wir in home.page.ts und home.page.html einbauen, sodass die Nutzer manuell Daten neuladen können. Gründe hierfür gibt es verschiedene. Beispielweise können die Nutzer die App in den Hintergrund schieben - dies geschieht über den HomeButton (ältere Modelle) oder einen Swipe von unten nach oben (neuere Modelle). In diesem Fall wird ionViewDidEnter nicht ausgeführt im Lifecycle.

Zur Umsetzung schauen wir uns das ion-refresher aus der Ionic-Dokumentation an:

<!-- Default Refresher -->
<ion-content>
  <ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
    <ion-refresher-content></ion-refresher-content>
  </ion-refresher>
</ion-content>

In der HTML-Datei sehen wir zwei neue Komponenten: ion-refresher und den ion-refresher-content. Am ion-refresher registrieren wir ein Event (ionRefresh) das ausgeführt wird, sobald der Nutzer die Ansicht von oben nach unten zieht. Der ion-refresher-content enthält Texte, Icons und Animationen während des Vorgangs. Für uns von Interesse ist vor allem das (ionRefresh)-Event, das in der folgenden TypeScript-Datei erklärt wird:

import { Component } from '@angular/core';

@Component({
  selector: 'refresher-example',
  templateUrl: 'refresher-example.html',
  styleUrls: ['./refresher-example.css'],
})
export class RefresherExample {
  constructor() {}

  doRefresh(event) {
    console.log('Begin async operation');

    setTimeout(() => {
      console.log('Async operation has ended');
      event.target.complete();
    }, 2000);
  }
}

Die Methode doRefresh erhält ein Argument event, das in der HTML-Datei mittels $event übergeben wird. Innerhalb der doRefresh-Methode wird nach zwei Sekunden (setTimeout) event.target.complete() ausgeführt und damit der Refresher geschlossen.

Etwas ähnliches wollen wir auch in unserer App haben. Nur schließen wir den Refresher nicht nach willkürlichen zwei Sekunden, sondern sobald der Lademechanismus (loadCovidData) entweder erfolgreich ist oder fehlschlägt. Dazu sind folgende Änderungen in der home.page.ts notwendig:

  • Füge ein return Statement vor getCurrentPosition ein und gibt den gesamten Block zurück. Dadurch ist der return-Wert von loadCovidData nun ein Promise.
  • Füge eine neue Methode hinzu, z.B. doRefresh(event). Führe in dieser loadCovidData aus und nutze das Promise um im Erfolgs- wie auch Fehlerfall event.target.complete() auszuführen.

Vergiss nicht beide Refresher-Komponent zur home.page.html hinzuzufügen und deine neue Methode beim (ionRefresh) zu registrieren.

Hilfestellung (auf den Pfeil klicken).
// home.page.ts
import { HttpClient, HttpErrorResponse } from '@angular/common/http';

export class HomePage {
  public refreshData(event) {   
    this.loadCovidData()
      .then(() => event.target.complete())
      .catch(() => event.target.complete());
  }
  
  public loadCovidData() {
    this.isOnline = navigator.onLine;
    if (!navigator.onLine) {
      return;
    }
  

    const baseUrl = `https://covid-api-rki.vercel.app/api/v1/county-data-by-position`;

    return this.geolocation.getCurrentPosition()
      ....
  }
}
<ion-content>
  <!-- Ladeanimation und Offline-Fehler -->
  ...
  <ion-refresher slot="fixed" (ionRefresh)="refreshData($event)">
    <ion-refresher-content>
    </ion-refresher-content>
  </ion-refresher>
  <ion-grid *ngIf="covidData">
  ...
  </ion-grid>
</ion-content>

Bauen der Anwendung für Android und Ausprobieren auf dem Smartphone.

Als Vorbereitung nehmen wir noch zwei kleine Änderungen vor, da unsere App derzeit einen sehr generischen Namen hat. Öffne die Datei config.xml und ändere die Werte im Element <name> (MyApp) und die id im widget Element. Der <name> gibt an wie die Anwendung auf deinem HomeScreen heißt. Nutze etwas kurzes, prägnantes, da viele Geräte die Zeichenzahl stark begrenzen. Ein Beispiel ist “Corona Ampel”. Die id (derzeitiger Wert ist io.ionic.starter) muss im gesamten App-Store einzigartig sein und sollte nie verändert werden nachdem die App einmal veröffentlich wurde. Ansonsten können keine Updates mehr bereitgestellt werden. Ändere den Wert beispielsweise auf de.schulcampus-evershagen.corona-ampel.DeinVorname (und ersetze DeinVorname mit deinem Vorname oder etwas anderem willkürlichem).

Hier ist mein Beispiel:

 <!--config.xml  -->
 <?xml version='1.0' encoding='utf-8'?>
<widget id="de.schulcampusevershagen.coronaampel.philipp" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>Corona Ampel</name>
    ....

Zusätzlich wollen wir noch in der app.component.ts die Zeile

this.statusBar.styleDefault();

zu

this.statusBar.styleBlackTranslucent();

ändern. Das habe ich bei der Vorbereitung vergessen und ohne diese Zeile, wird auf Android-Geräten die Statusbar nicht angezeigt.. 😅

Als Voraussetzung zum Bauen der Anwendung benötigst du:

  • Die Ionic und Cordova CLI
  • Android Studio und das Android SDK
  • Ein (emuliertes) Android-Geröt

Die ersten beiden Punkte sollten vorbereitet sein. Überprüfe dies indem du eine Kommandozeile öffnest, dort ionic -v und danach cordova -v eintippst. zusätzlich tippst du adb.exe devices ein. In allen Fällen sollte eine Ausgabe erfolgen, wobei adb devices voraussichtlich nur “List of devices attached” ausgibt.

Nun haben wir zwei Optionen:

  1. Das Installieren der Anwendung auf deinem eigenen Android-Smartphone
  2. Das Testen der Anwendung in einem emulierten Android Gerät

Hast du ein USB-Kabel für dein Gerät dabei? Wenn ja, dann folge den kommenden Anweisungen. Falls nicht, kannst du mit einem emulierten Gerät weitermachen.

Installieren auf einem echten Android-Gerät

Bevor wir die App auf dem Gerät installieren können, musst du ein paar Dinge vorbereiten. Auf deinem Gerät muss der Entwicklermodus und USB-Debugging aktiviert werden. In der Regel geht dies wie folgt:

Zum Aktivieren des Entwicklermodus gehe in die Einstellungen deines Gerätes, wähle Telefoninfo. Gehe nun zu “Softwareinformationen” und suche den Eintrag “Buildnummer”. Tippe diesen mehrmals Mal an bis eine Meldung auftaucht, die sagt, dass der “der Entwicklermodus aktiviert wurde”.

Wechsle nun in das neue Menü. Meist ist der Entwicklermodus bzw. die Entwicklereinstellungen direkt als neuer Punkt in den Einstellungen, oder aber auch unter System zu finden. Suche innerhalb der Entwickleroptionen den Punkt “USB-Debugging” und aktiviere ihn.

Kommst du nicht weiter, suche im Internet nach deinem konkreten Modell.

Nachdem der Modus aktiviert ist, verbindest du dein Telefon mit dem Kabel und dem Computer. Möglicherweise musst du noch den USB-Modus auswählen. Tue dies. Auf dem PC solltest du jedenfalls das Gerät sehen und auch die Dateien. Auf deinem Telefon erscheint nun die folgende Meldung:

USB Debugging Dialog

Diese musst du Zulassen damit euer Rechner Zugriff auf das Telefon bekommt und die App installieren darf. Kommt die Meldung nicht, überprüfe die vorherigen Schritte. Zusätzlich solltest du in einer Kommandozeile den Befehl adb.exe devices ausführen. Dies startet den Android Daemon, der eine Verbindung herstellt. Die Ausgabe des Kommandos sollte wie folgt aussehen:

List of devices attached
993AY18ECA      device

Wobei die Zeichenfolge am Anfang eine andere sein sollte. Dabei handelt es sich um eine ID für dein Gerät.

Hat dies geklappt und adb.exe devices zeigt dein Gerät an, kannst du in die Kommandozeile der Corona App wechseln und dort das Kommando

ionic cordova run android

ausführen. Der Vorgang kann durchaus ein paar Minuten dauern. Die App wird gebaut und auf deinem Telefon installiert. Hat alles geklappt, wird die App auch direkt starten.

Alternativ kannst du auch eine APK-Datei erzeugen mit Hilfe von

ionic cordova build android

Achte auf das Kommando - es sagt dir wo die Datei am Ende liegt. Dies sollte

platforms/android/app/build/outputs/apk/debug/app-debug.apk

sein. Kopiere die app-debug.apk auf dein Telefon, wechsle in den Dateiexplorer deines Telefons und installiere die APK-Datei. Anschließend kannst du die App starten.

Installieren auf einem emulierten Android-Gerät

Vorweg: ich weiß nicht, ob dein PC dafür vorbereitet ist. Möglicherweise musst du im BIOS noch die Virtualisierung deiner CPU aktivieren. Dies kommt erst zum Tragen, falls die folgenden Schritte nicht funktionieren:

Hast du kein Kabel dabei oder willst die App auf einem anderen Android-Gerät testen, so kannst du auch ein emuliertes Gerät benutzen. Dies müssen wir zunöchst im Android Virtual Device Manager anlegen. Starte dazu Android Studio. Öffnet sich der Auswahldialog am Anfang, wähle “Mehr/More” und dann “AVD Manager”. Öffnet sich Android Studio komplett mit einem ganzen Projekt wählst du in der Menüleiste oben “Tools > AVD Manager”. Klicke im Fenster nun auf “Create Virtual Device”.

Wähle eines der vordefinierten Geräte aus und klicke dich durch den weiteren Dialog. Wähle eine (installierte) Android Version aus und wähle am Ende einen Namen für das Gerät. Ist dies abgeschlossen, kannst du das Gerät über den AVD Manager starten.

Ist das Gerät gestartet, öffnest du die Kommandozeile deiner App und führst das Kommando

ionic cordova run android

aus. Nachdem es fertig ist, kannst du zu deinem emulierten Gerät wechseln und die App starten und ausprobieren.

Das Bauen der Anwendung für iOS-Geräte

Apple Geräte decken wir hier nur grob ab. Um eine mobile App für ein Apple-Gerät zu bauen, ist zwingend ein Computer mit MacOS notwendig (iMac, Mac Mini, MacBook etc). Die Vorgehensweise fasse ich hier daher nur kurz zusammen:

  1. Installiere auf deinem Mac die Ionic CLI und Cordova CLI.
  2. Setze den Quellcode des Projektes auf und führe npm install aus.
  3. Führe das Kommando ionic cordova prepare ios aus.
  4. Öffne den erzeugten Ordner (platforms/ios) in XCode
  5. Baue die Anwendung in XCode

App Store Listings

Als letzten Schritt, vermutlich auch parallel mit den Design-Teams, wollen ein paar Dinge für die App-Store-Einträge vorbereiten. Dazu zählen vor allem Screenshots, aber auch Texte. Wir benötigen

  • mindestens einen Screenshot der App
  • einen Beschreibungstext

Du hast verschiedene Möglichkeiten: Mache einen Screenshot der App auf deinem Gerät, oder dem emulierten Gerät. Du kannst der Einfachheit halber aus, das “Snipping Tool” von Windows nehmen und einen Screenshot der Anwendung im Browser machen. Vergiss nicht in den Entwicklertools deines Browsers die Ansicht für mobile Geräte zu aktivieren.

Hsat du einen oder mehrere Screenshots, so brauchen wir noch einen Text. Beschreibe was die App macht, erwähne auch, dass Sie im Rahmen des Schulprojektes entstanden ist.

Und denk dran: alles was wir in den Store packen ist öffentlich zugänglich!

Natürlich ist dies noch nicht alles um eine App im Store zu veröffentlichen. Wir benötigen einen (Bezahl-)Account, ein App-Icon, müssen Zielgruppen festlegen und verschiedensten Richtlinien zustimmen und noch viel mehr. Das sprengt allerdings den Rahmen und wir übernehmen dies.

Zusammenfassung

Viel gelernt in der letzten Session. Wir haben uns um die Fehlerbehandlung gekümmert und auch das erste Mal die Anwendung auf einem Android-Gerät installiert. Zusätzlich haben wir ein paar der Notwendigkeiten für ein Store-Listing kennengelernt.

Zum Abschluss werden wir deinen Quellcode veröffentlichen. Dies wird ein paar Tage dauern.

Sonstiges

Der komplette Quellcode ist auf Gitlab - Branch step-4 zu finden.

Written on December 7, 2020
Source code on Gitlab: /covid19-app-school-project-part-4.md