Dies ist eine Lektion unseres alten Android App programmieren Tutorials. Sie wird von uns nicht mehr aktuell gehalten und wurde durch unser neues Android Apps Programmieren Tutorial abgelöst, das immer aktuell gehalten wird.
Mit folgenden Link gelangt ihr zur aktuellen Version dieser Lektion: Daten aus dem Internet abfragen in Android.
Hier geht es zu unserem Android Tutorial mit den aktuellen Inhalten.
Da dieser Beitrag für einige Leser trotz fehlender Aktualität dennoch sehr hilfreich ist, haben wir ihn nicht gelöscht. Wenn ihr aber unser aktuelles Android Tutorial machen wollt, dann könnt ihr über den oberen Link direkt zu den neuen Inhalten gelangen.
In diesem Tutorial lernt ihr:
- Aktiendaten online abfragen
- Erlaubnis für den Internetzugriff in Android einholen
- Aktiendaten in dem asynchronen Task HoleDatenTask online abfragen
- Android App ausführen
Ihr solltet auch lesen:
Hinweis: Der Service von Yahoo! Finance wurde scheinbar eingestellt. Das großen Android Tutorial wurde daher umgeschrieben, so dass nun simulierte Finanzdaten vom eigenen Web-Server verwendet werden.
Im achten Teil unseres großen Android™ Tutorials werden wir unsere App mit dem Internet verbinden.
Über die Internetverbindung fragen wir online Finanzdaten ab und speichern die erhaltenen Daten in einem String. Den Inhalt des Strings geben wir als Log-Meldung zur Kontrolle aus. Später werden wir Teile des Inhalts in der App anzeigen.
Die Abfrage über das Internet muss in einem asynchronen Task ausgeführt werden, dies wird vom Android System so verlangt.
Daher haben wir in dem vorherigen Tutorial-Teil den asynchronen Task HoleDatenTask implementiert. Er ist unser Hintergrund-Thread, der das HTTP-Request durchführt.
Bevor von unserer App aus auf das Internet zugegriffen werden kann, müssen wir von Android bzw. dem Benutzer die Erlaubnis für den Zugriff einholen. Dieser Schritt ist sehr einfach und erfordert nur eine kleine Änderung in der AndroidManifest.xml
Datei.
Unser Vorgehen in diesem Teil des Android Tutorials wird wie folgt sein:
- Vorstellen wie wir die Finanzdaten abfragen werden
- Erlaubnis für den Internetzugriff in Android einholen
- Online Anfrage nach den Aktiendaten in dem asynchronen Task HoleDatenTask
- Testen unserer Android App und Kontrollieren des Aktiendaten-Strings in der Log-Meldung
Nun wünschen wir euch viel Spaß bei dem achten Teil unseres großen Android Tutorials. Los geht’s!
1. Aktiendaten von einem Server online abfragen
Unsere Android App wird verschiedene Aktiendaten ausgeben. Die Daten werden wir von unserem eigenen Server herunterladen, der sie extra zu diesem Zweck generieren wird.
Bei den Daten handelt es sich nicht um echte Aktiendaten, sondern um simulierte, die wie reale Aktienkurse erscheinen. Die Daten werden von unserem Server im XML-Format generiert und an die App über das Internet gesendet.
Die empfangenen XML-Aktiendaten werden wir dann anschließend in unserer Android App auswerten und weiterverarbeiten.
Mit folgender Anfrage lassen wir von unserem Server simulierte Aktiendaten für die Unternehmen BMW (BMW.DE) und Daimler (DAI.DE) erzeugen:
https://www.programmierenlernenhq.de/tools/query.php?s=DAI.DE,BMW.DE
Als Antwort erhalten wir die angefragten Finanzdaten im XML-Format, siehe folgende Abbildung:
In unserer App werden wir die Anfrage-URL nachbauen, mit weiteren Symbolen (Kennungen von Unternehmen) ergänzen und anschließend mittels HttpURLConnection eine Verbindung zu unserem Server aufbauen.
2. Erlaubnis für den Internetzugriff in Android einholen
Ein wichtiger Designansatz der Sicherheitsarchitektur von Android ist, dass keine Anwendung die Erlaubnis besitzt, schadhafte Operationen auf andere Anwendungen, das Betriebssystem oder den Benutzer auszuführen. Dies beinhaltet Aktionen wie:
Jede Android App wird dadurch in einer Prozess Sandbox, ein isolierter Bereich, innerhalb dessen jede Maßnahme keinerlei Auswirkung auf die äußere Umgebung hat, ausgeführt. Möchte eine App zusätzliche Fähigkeiten erlangen, muss sie dafür um Erlaubnis fragen.
Android Apps erklären statisch welche Genehmigungen sie benötigen. Das Android System teilt dem Nutzer dies bei der Installation der App mit. Der Nutzer muss diese Genehmigungen erteilen, wenn er die Anwendung nutzen möchte.
Eine dynamische Erlaubnisvergabe zur Laufzeit ist in dem Android System nicht zu finden, da sie die Benutzererfahrung verschlechtern würde.
Eine sehr detaillierte Beschreibung dieses Sicherheitskonzepts findet ihr unter: http://developer.android.com/guide/topics/security/permissions.html.
Zur Info: Seit Android 6.0 erfolgt die Erlaubnisvergabe dynamisch. Detaillierte Informationen über den neuen Vergabeprozess könnt ihr hier finden.
2.1 Genehmigung (Erlaubnis) für geschützte Funktionen einholen
Eine einfache Android Anwendung besitzt standardmäßig keine mit ihr verbundenen Genehmigungen. Sie kann somit keinen Schaden auf das Benutzererlebnis oder die Gerätedaten verursachen. Um die geschützten Funktionen eines Android Geräts nutzen zu können, müssen diese einzeln in der AndroidManifest.xml
beantragt werden. Es muss um Erlaubnis gebeten werden, diese nutzen zu dürfen.
Mit Hilfe der <uses-permission>-Tags wird gezielt erklärt, welche geschützten Funktionen von der App genutzt werden müssen, damit die Anwendung ihre Arbeit verrichten kann.
Eine App, die eingehende SMS überwachen muss, würde um folgende Genehmigung bitten:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app.myapp" > <uses-permission android:name="android.permission.RECEIVE_SMS" /> ... </manifest>
Wenn eine App installiert wird, sorgt der Package Installer dafür, dass sie die benötigten Genehmigungen erhält. Dies geschieht nicht automatisch, sondern muss von dem Benutzer bestätigt werden. Werden die angefragten Genehmigungen nicht erteilt, kann die App nicht installiert werden.
Android stellt eine große Menge an Genehmigungen zur Verfügung, die in Manifest.permission
definiert sind. Eine Übersicht über die möglichen Genehmigungen des Android Systems, zusammen mit jeweils einer kurzen Erklärung, findet ihr hier: http://developer.android.com/reference/android/Manifest.permission.html
2.2 Genehmigung für den Internetzugriff anfordern
Unsere Android App soll Online-Aktiendaten abfragen, daher benötigt sie den Zugriff auf das Internet. Mit der folgenden Codezeile bitten wir um die Erlaubnis, auf das Internet zugreifen zu dürfen. Wird uns diese vom Anwender erteilt, erhält unsere App die Erlaubnis network sockets zu öffnen.
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Die obere Codezeile fügen wir in unser Android Projekt in die Datei AndroidManifest.xml
ein. In Android Studio sieht der gesamte Quellcode dann folgendermaßen aus:
Das war auch schon alles. Mit dieser kleinen Änderung haben wir um die Zugriffserlaubnis auf das Internet gebeten. Wenn bei der Installation unserer Anwendung der Benutzer die Erlaubnis erteilt, wird die App in der Lage sein auf das Internet zuzugreifen.
3. Aktiendaten in dem asynchronen Task online abfragen
Da wir jetzt die Zugriffserlaubnis für Internetabfragen besitzen, kann die online Anfrage an den Web-Server von unserer App heraus erfolgen.
Die Anfrage darf aber nicht im UI-Thread ausgeführt werden, sondern muss in einem Nebenthread stattfinden.
Daher muss der Quellcode, der die Anfrage ausführt, in die innere Klasse HoleDatenTask gelagert werden.
Die Klasse HoleDatenTask ist von der Klasse AsyncTask abgeleitet, wodurch alle Anweisungen, die in der überschriebenen Methode doInBackground angegeben sind, in einem eigenen Arbeitsthread ausgeführt werden. Daher muss unsere Abfrage der Online-Finanzdaten genau in dieser Methode stattfinden. Den Quellcode dazu haben wir unten angegeben.
Der unten angegebene Quellcode der doInBackground-Methode muss in die innere Klasse HoleDatenTask der Klasse AktienlisteFragment eingefügt werden. Und zwar muss durch ihn die bereits vorliegende Methode doInBackground ersetzt werden.
Zusätzlich müssen die folgenden Import-Anweisungen im Quellcode ganz oben in der Klasse AktienlisteFragment eingefügt werden:
AktienlisteFragment.java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;
Die folgende Datei enthält den gesamten Quellcode der Klasse AktienlisteFragment zur Übersicht:
AktienlisteFragment.java (als ZIP-Datei gepackt)Jetzt folgt der Quellcode der doInBackground-Methode, mit dem die Abfrage der Online-Aktiendaten erfolgt:
AktienlisteFragment.java
protected String[] doInBackground(String... strings) { if (strings.length == 0) { // Keine Eingangsparameter erhalten, daher Abbruch return null; } // Exakt so muss die Anfrage-URL an unseren Web-Server gesendet werden: // https://www.programmierenlernenhq.de/tools/query.php?s=DAI.DE,BMW.DE // Wir konstruieren die Anfrage-URL für unseren Web-Server final String URL_PARAMETER = "https://www.programmierenlernenhq.de/tools/query.php"; String symbols = "DAI.DE,BMW.DE"; String anfrageString = URL_PARAMETER; anfrageString += "?s=" + symbols; Log.v(LOG_TAG, "Zusammengesetzter Anfrage-String: " + anfrageString); // Die URL-Verbindung und der BufferedReader, werden im finally-Block geschlossen HttpURLConnection httpURLConnection = null; BufferedReader bufferedReader = null; // In diesen String speichern wir die Aktiendaten im XML-Format String aktiendatenXmlString = ""; try { URL url = new URL(anfrageString); // Aufbau der Verbindung zur YQL Platform httpURLConnection = (HttpURLConnection) url.openConnection(); InputStream inputStream = httpURLConnection.getInputStream(); if (inputStream == null) { // Keinen Aktiendaten-Stream erhalten, daher Abbruch return null; } bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = bufferedReader.readLine()) != null) { aktiendatenXmlString += line + "\n"; } if (aktiendatenXmlString.length() == 0) { // Keine Aktiendaten ausgelesen, Abbruch return null; } Log.v(LOG_TAG, "Aktiendaten XML-String: " + aktiendatenXmlString); publishProgress(1,1); } catch (IOException e) { // Beim Holen der Daten trat ein Fehler auf, daher Abbruch Log.e(LOG_TAG, "Error ", e); return null; } finally { if (httpURLConnection != null) { httpURLConnection.disconnect(); } if (bufferedReader != null) { try { bufferedReader.close(); } catch (final IOException e) { Log.e(LOG_TAG, "Error closing stream", e); } } } // Hier parsen wir später die XML Aktiendaten return null; }
Wir werden hier nur kurz auf den Quelltext eingehen und sehr einfach beschreiben, was die verschiedenen Anweisungen bewirken.
In Zeile 8 ist der Anfrage-String beispielhaft in seiner ursprünglichen Form angegeben. Diesen String werden wird nachbauen und an einer Stelle eine Variable einfügen, damit wir später gezielt Aktiendaten anfragen können.
Mit den Zeilen 11 bis 16 bauen wir den Anfrage-String anfrageString
zusammen. Dieser besteht aus statischen und dynamischen Teilstücken.
Das statische Teilstück:
- URL_PARAMETER: Die Basis-URL zu unserem Web-Server.
Das dynamische Teilstück:
- symbols – Enthält die Liste der Finanzinstrumente (Aktien, Indizes, …), für die wir die Finanzdaten abfragen möchten.
Mit der Zeile 18 loggen wir den zusammengesetzten Anfrage-String als verbose-Meldung. Somit können wir in Android Studio den String mittels Logging schnell überprüfen.
In dem äußeren try
-Block von Zeile 27 bis 64 führen wir den HTTP Request durch. Dazu erzeugen wir aus dem zusammengesetzten Anfrage-String eine URL und bauen anschließend eine HttpURLConnection darauf auf.
Die zurückgelieferten Aktiendaten lesen wir mittels InputStream und BufferedReader aus. Die Daten speichern wir in dem String aktiendatenXmlString ab. Sie sind in dem XML-Format abgelegt und müssen später von uns gezielt ausgelesen werden.
Das XML-Format (Extensible Markup Language) eignet sich hervorragend für den schnellen Datenaustausch zwischen Anwendungen.
In Zeile 47 loggen wir die erhaltenen XML-Aktiendaten als verbose-Meldung mit und geben in Zeile 48 den Arbeitsfortschritt bekannt. In den restlichen Zeilen Code wird Fehlerbehandlung betrieben, sowie die HttpURLConnection und der BufferedReader geschlossen.
4. Testen unserer Android App und Kontrollieren der erhaltenen Aktiendaten in der Log-Meldung
Jetzt ist es endlich soweit, wir greifen mit unserer Android App das erste Mal auf echte Aktiendaten über das Internet zu.
Damit wir unsere App auf dem Smartphone oder Tablet starten können, müssen alle Schritte von Teil 3 des Android Tutorials befolgt worden sein.
Zuerst schließen wir unser Android Gerät an den PC an und stellen eine Verbindung über die ADB (Android Debug Bridge) her. Danach klicken wir auf das Run 'app'
-Symbol. Unser Android Projekt wird dadurch neu erstellt und auf dem angeschlossenen Gerät ausgeführt.
Das Run 'app'
-Symbol befindet sich in der oberen Menüleiste, siehe folgende Abbildung:
Nach einigen Momenten öffnet sich der Select Deployment Target
-Dialog. In ihm nehmen wir die folgenden Einstellungen vor:
- Das angeschlossene Android Gerät unter
Connected Devices
auswählen. - Mit einem Klick auf den
OK
-Button die Installation unserer App auf das Gerät starten.
Der Dialog schließt sich und unsere Android App wird auf das angeschlossene Gerät übertragen und installiert. Die Installation dauert nur einen kurzen Augenblick und verläuft fast unbemerkt im Hintergrund. Danach wird unsere App automatisch gestartet.
4.1 Die Log-Meldungen mit LogCat im Terminal überwachen
Dazu öffnen wir den Terminal mit einem Klick auf den Text Terminal
in der unteren Leiste von Android Studio. In dem Terminal navigieren wir in das sdk\platform-tools
-Verzeichnis und geben den folgenden ADB-Befehl ein:
adb logcat AktienlisteFragment:v HoleDatenTask:v *:s
Mit dem oberen Befehl werden uns Log-Meldungen ab Stufe verbose angezeigt, die einen der beiden Tags AktienlisteFragment oder HoleDatenTask verwenden. Alle anderen Log-Meldungen werden durch den Filter *:s
geblockt, wobei s für silent steht.
Nachdem wir den Befehl (Markierung 1) eingegeben und mit Enter bestätigt haben, werden uns folgende Meldungen (Markierung A) im Terminal angezeigt:
Jetzt klicken wir in unserer App auf den Aktualisieren
-Button im Overflow Menu. Dadurch wird der asynchrone Task HoleDatenTask gestartet und die Methode doInBackground ausgeführt.
In der Methode wird zuerst der Anfrage-String zusammengesetzt und anschließend daraus eine URL erzeugt, über die eine HttpURLConnection aufgebaut wird. Als Ergebnis erhalten wir die angefragten Aktiendaten von unserem Web-Server zurück in Form eines XML-Strings.
Nachdem wir auf den Aktualisieren
-Button geklickt haben, erhalten wir folgende Log-Meldung:
Und wie wir sehen können, haben wir einen korrekten Anfrage-String zusammengesetzt (Markierung A) und erhalten die Finanzdaten für die Finanzinstrumente BMW.DE und DAI.DE als XML-String zurück.
Auf dem Display des Android Geräts bekommen wir die Finanzdaten noch nicht angezeigt. Diese Funktion werden wir erst in der nächsten Lektion des Android Tutorials implementieren, wenn wir den XML-String parsen (auslesen) und die erhaltenen Finanzinformationen auf dem Display ausgeben.
Nun möchten wir noch die Log-Meldungen mit dem Dalvik Debug Monitor Server (DDMS) überwachen.
4.2 Die Log-Meldungen mit dem Dalvik Debug Monitor Server (DDMS) überwachen
Wir starten den DDMS wie in Teil 5 des Android Tutorials beschrieben. Dabei ist unser Android Gerät angeschlossen und auch unsere App läuft bereits.
Jetzt klicken wir auf den Aktualisieren
-Button und fragen erneut Aktiendaten online ab. In dem DDMS erhalten wir folgende Log-Meldungen angezeigt:
Um die Log-Meldungen so wie in der Abbildung angezeigt zu bekommen, müssen folgende Schritte ausgeführt werden:
- Als Erstes klicken wir auf unsere App, um die Log-Meldungen für das angeschlossene Android Gerät betrachten zu können.
- In der Suchleiste
tag:AktienlisteFragment|HoleDatenTask
eingeben, um nur Log-Meldungen mit diesen beiden Tags anzuzeigen. - Einstellung des Prioritäts-Level. Wir lassen verbose ausgewählt, wodurch alle Log-Meldungen ab Stufe verbose ausgegeben werden.
Der grüne Rahmen (A) umschließen die Prozess-ID (10302). Der violette Rahmen (B) umschließen die Thread-ID (10302 bzw. 11148).
Wie zu erkennen ist, unterscheiden sich die beiden IDs zeitweise. Dies muss so sein, da der asynchrone Task in einem eigenen Arbeitsthread mit der ID (11148) ausgeführt wird. Der UI-Thread (Main-Thread) besitzt als Prozess- und Thread-ID jeweils die gleiche ID (10302).
Unseren zusammengesetzten Anfrage-String haben wir mit einem blauen Rahmen markiert (C) und direkt darunter sind die übertragenen XML-Aktiendaten von einem orangen Viereck umrahmt (D).
Außerdem können wir uns in DDMS auch die Netzwerkaktivitäten anzeigen lassen. Im oberen Diagramm ist der Netzwerkverkehr dargestellt. Er besteht aus gesendeten und empfangenen Datenpaketen.
Auch im DDMS konnten wir den Anfrage-String und die erhaltenen Aktiendaten mit Hilfe der Log-Meldungen schnell überprüfen. Unsere App funktioniert so, wie sie es soll, wobei bisher die Aktiendaten nur als Log-Meldungen ausgegeben werden.
Um dies zu ändern, werden wir in dem nächsten Teil des Android Tutorials die erhaltenen XML-Aktiendaten weiterverarbeiten und in dem bereits erstellten ListView anzeigen lassen.
Zusammenfassung
In diesem Teil unseres großen Android Tutorials haben wir simulierte Finanzdaten über einen Web-Server angefragt und anschließend in unserer App weiterverarbeitet.
Damit unsere Android Anwendung auf das Internet zugreifen durfte, mussten wir uns vom Android System und dem User vorher die Erlaubnis dafür einholen. Dies haben wir mit einer kleinen Änderung in der AndroidManifest.xml
-Datei getan und dabei die Sicherheitsarchitektur von Android kennengelernt.
Mit der Erlaubnis Internetzugriffe aus der App heraus auszuführen, konnten wir eine Verbindung unserem Web-Server aufbauen und uns mit einer speziellen Anfrage-URL die Finanzdaten für Aktien liefern lassen.
Die gelieferten Aktiendaten, ein XML-String, haben wir mit Hilfe des Logging-Systems von Android überprüft. Dafür wurde der Terminal (Konsole) von Android Studio und auch der Dalvik Debug Monitor Server (DDMS) verwendet.
In dem nächsten Teil unseres Android Tutorials werden wir die Aktiendaten weiterverarbeiten, indem wir den XML-String zerlegen und bestimmte Finanzinformationen in dem ListView unserer App und somit auch auf dem Display unseres Android Geräts anzeigen.