Quadratisch codiert mit Android



Ähnliche Dokumente
ROFIN App Benutzerhandbuch. Version 1.0

QR Code. Christina Nemecek, Jessica Machrowiak

Über die Internetseite Hier werden unter Download/aktuelle Versionen die verschiedenen Module als zip-dateien bereitgestellt.

15 Arten von QR-Code-Inhalten!

Handbuch für die DailyDeal Entwertungs-App

Datensicherung. Beschreibung der Datensicherung

Berechtigungen im Kalender Anleitung für die Rechtevergabe im Outlook Kalender FHNW, Services, ICT

Lizenzen auschecken. Was ist zu tun?

Dokumentation PuSCH App. windows-phone

Urlaubsregel in David

Dokumentation PuSCH App. android phone

TechCommToGo (DE) conbody section title TechCommToGo - so einfach wie Kaffee machen. / title / section. section p image / p

Beispiel(unten ist der Spielfeldrand):

Sie werden sehen, dass Sie für uns nur noch den direkten PDF-Export benötigen. Warum?

RepCare für Android. Konfiguration und Installation André Weinert

4.1 Download der App über den Play Store

OP-LOG

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Installation einer C++ Entwicklungsumgebung unter Windows --- TDM-GCC und Eclipse installieren

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Dokumentation PuSCH App. android phone

2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE

INDEX. Öffentliche Ordner erstellen Seite 2. Offline verfügbar einrichten Seite 3. Berechtigungen setzen Seite 7. Öffentliche Ordner Offline

GeoPilot (Android) die App

1. Laptop: Benutzen Sie die Anleitung ab Seite 2 2. Tablet / Smartphone: Benutzen Sie die Anleitung ab Seite 4. Seite 2 Seite 4

2. Installation der minitek-app auf einem Smartphone. 3. Verbindung zwischen minitek-app und minitek herstellen

Benutzung der LS-Miniscanner

Online Newsletter III

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Kurzanleitung /Kompalitätstest Barcode. Sie haben zwei Möglichkeiten unsere Barcode/Strichcodes für Ihren eigenen stationären Einzelhandel zu nutzen.

Benutzerhandbuch. Leitfaden zur Benutzung der Anwendung für sicheren Dateitransfer.

Die Dateiablage Der Weg zur Dateiablage

Dokumentation PuSCH App. iphone

Anti-Botnet-Beratungszentrum. Windows XP in fünf Schritten absichern

Downloadfehler in DEHSt-VPSMail. Workaround zum Umgang mit einem Downloadfehler

AUF LETZTER SEITE DIESER ANLEITUNG!!!

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER

Kurzeinweisung. WinFoto Plus

2. Die eigenen Benutzerdaten aus orgamax müssen bekannt sein

Persönliches Adressbuch

Verwendung von QR-Codes zum Teilen von digitalen Rezepten in Printmedien mittels der Recipe Packaging Toolbox von My Own Cookbook

DOKUMENTATION VOGELZUCHT 2015 PLUS

TeamSpeak3 Einrichten

Steganos Secure Schritt für Schritt-Anleitung für den Gastzugang SCHRITT 1: AKTIVIERUNG IHRES GASTZUGANGS

Problem crazytrickler unter Windows 8:

FrontDoor/Monitor mehr sehen von FrontDoor

Installation von NetBeans inkl. Glassfish Anwendungs-Server

Logics App-Designer V3.1 Schnellstart

Der schnelle Weg zu Ihrer eigenen App

ARCO Software - Anleitung zur Umstellung der MWSt

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite.

Handbuch. timecard Connector Version: REINER SCT Kartengeräte GmbH & Co. KG Goethestr Furtwangen

Professionelle Seminare im Bereich MS-Office

EasyWk DAS Schwimmwettkampfprogramm

Updateanleitung für SFirm 3.1

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Kundenleitfaden Installation

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Was meinen die Leute eigentlich mit: Grexit?

Wissenswertes über LiveUpdate

Thema: Microsoft Project online Welche Version benötigen Sie?

- Zweimal Wöchentlich - Windows Update ausführen - Live Update im Norton Antivirusprogramm ausführen

Durchführung der Datenübernahme nach Reisekosten 2011

Der Kalender im ipad

Kleines Handbuch zur Fotogalerie der Pixel AG

Installation und Inbetriebnahme von Microsoft Visual C Express

40-Tage-Wunder- Kurs. Umarme, was Du nicht ändern kannst.

SCHRITT 1: Öffnen des Bildes und Auswahl der Option»Drucken«im Menü»Datei«...2. SCHRITT 2: Angeben des Papierformat im Dialog»Drucklayout«...

Mitarbeiter-Alarm. 1x Taster mit Kabel zum Anschluss an den seriellen Com-Port (optional) 1x Installationsprogramm auf CD 1x Lizenz

Leichte-Sprache-Bilder

DRM geschützte ebooks auf dem ipad

Installation und Test von Android Apps in der Entwicklungs- und Testphase

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Grundfunktionen und Bedienung

Barcodedatei importieren

Handbuch für Redakteure

Benutzerhandbuch MedHQ-App

Um eine fehlerfreie Installation zu gewährleisten sollte vor der Installation der Virenscanner deaktiviert werden.

Speichern. Speichern unter

WOT Skinsetter. Nun, erstens, was brauchen Sie für dieses Tool zu arbeiten:

Anleitung zur Webservice Entwicklung unter Eclipse

Zeiterfassung mit Aeonos. Bedienungsanleitung für die App

Installation der Konfigurationsdateien für alle Windows-Versionen bis einschließlich Microsoft Windows 7

Windows 10. Vortrag am Fleckenherbst Bürgertreff Neuhausen.

Einfügen von Bildern innerhalb eines Beitrages

FRILO-Aktuell Ausgabe 2/2013

Wordpress: Blogbeiträge richtig löschen, archivieren und weiterleiten

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Plugins. Stefan Salich Stand

Anleitung zur Installation des EPSON TM-m30 WLAN Moduls

Liferay 6.2. Open Source IT-Dienstleister. Ein modernes Open Source Portal System. forwerts solutions GmbH, Gabriele Maas

GS-Programme 2015 Allgemeines Zentralupdate

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

Erstellen einer Collage. Zuerst ein leeres Dokument erzeugen, auf dem alle anderen Bilder zusammengefügt werden sollen (über [Datei] > [Neu])

ABSENDUNGEN der BICS-REISEANMELDUNG CHECKEN

DER SELBST-CHECK FÜR IHR PROJEKT

Transkript:

Codieren und Decodieren von QR-Codes mit Android Quadratisch codiert mit Android Viele moderne Medien nutzen QR-Codes, um Daten über die Kamera an ein Smartphone zu übertragen. Dieser Artikel zeigt verschiedene Wege auf, wie die eigene App QR-Codes einlesen und erstellen kann. Von Janusz Leidgens AUTOR Januz Leidgens hat an der Universität Bielefeld den Masterstudiengang»Intelligente Systeme«absolviert. Er arbeitet als wissenschaftliche Hilfskraft im Bereich der Software-Entwicklung. Er entwickelt derzeit bei der Kupferwerk GmbH in Regensburg Android-Apps. janusz@leidgens.de QR-Codes sind eine maschinenlesbare Repräsentation von Daten. QR steht für Quick Response und bezieht sich auf die guten Ein lese-eigenschaften der Codes. Entwickelt wurden die Codes von Denso Wave Incorporated, die in den Vereinigten Staaten von Amerika, Japan und Europa auch die Markenrechte an dem Begriff QR Code hält. Den ersten Einsatz haben die Codes in der Autoindustrie gefunden. Hier dienen sie dazu, markierte Werkstücke oder Fahrzeuge automatisch zu erkennen. Wie im QR-Code in Bild 1 zu sehen, sind drei Ecken des Codes extra markiert. Diese Markierung ermöglicht ein Einlesen in einer beliebigen Ausrichtung. Diese Eigenschaft und die Fehlertoleranz von bis zu 30 Prozent schafft eine Robustheit, die den Einsatz von QR-Codes nicht nur in der Autoindustrie so beliebt macht. Die zweidimensionalen Codes können bis zu 4296 alphanumerische Zeichen codieren. Bei Verwendung im mobilen Bereich sollte die Kapazität jedoch auf rund 1000 Zeichen beschränkt werden, da die QR-Codes immer größer werden, und irgendwann tun sich die Handykameras dann doch schwer mit der Erkennung des Inhalts. Einsatz in der Werbung Ein Beispiel-QR-Code, in dem ein URL codiert ist (Bild 1) Inzwischen finden die QR-Codes auch immer mehr Verbreitung in anderen Anwendungsfeldern, zum Beispiel bei der Erstellung von Werbung. Die Werbetreibenden erwarten, dass sich durch das Bereitstellen eines maschinenlesbaren Codes auf dem Werbemittel der Aufwand für den Besuch einer bestimmten Webseite senken und so der Erfolg der Werbung erhöhen lässt. Statt einen URL abzutippen, können Smartphone-Besitzer den QR-Code mit ihrer Handykamera scannen und werden dann direkt auf die Webseite oder App der beworbenen Marke weitergeleitet. Weiterere Einsatzzwecke der Codes sind der Austausch von Daten zwischen Smartphones sowie die Indoor-Navigation. So werden etwa QR-Codes auf Messen eingesetzt, um den Standort des Nutzers festzustellen. Der User scannt an einem Stand oder einer Kreuzung einen Code und bekommt dann auf diese Position zugeschnittene Informationen. Auf diese Weise lässt sich der schlechte GPS-Empfang in Messehallen ausgleichen. Dieser Artikel soll zeigen, wie QR-Codes eingelesen und erzeugt werden können. Das meistverwendete Framework zum Einlesen und Erstellen von QR-Codes ist ZXing (http://code.google.com/p/zxing). ZXing ist eine Abkürzung für Zebra-Crossing und ist eine Anspielung auf die Ursprünge des Projekts als Barcode-Scanner. Neben QR-Codes scannt ZXing auch folgende Codes: UPC-A, UPC-E, EAN-8, EAN-13, Code 39, Code 93, Code 128, ITF, Codabar, RSS-14 und Data Matrix. Das ZXing Framework wird als Open Source mit der Apache-2.0- Lizenz angeboten. ZXing bietet zwei Möglichkeiten zur Integration in die eigene App: Einbinden der gesamten ZXing-Funktionalität als Sourcecode oder Interaktion der eigenen App mit der von ZXing im Android-Market bereitgestellten App Barcode Scanner (https://market.android.com/ details?id=com.google.zxing.client.android). Die Integration mit der Barcode-App über Intents ist auf jeden Fall die typische Android- LISTING 1: VERARBEITEN @Override public void onactivityresult(int requestcode, int resultcode, Intent intent) { final IntentResult scanresult = IntentIntegrator. parseactivityresult (requestcode, resultcode, intent); if (scanresult!= null) { Log.d(getClass().getSimpleName(), "Result is: " + scanresult.getcontents()); 2

Weg, das Codier- und Decodierproblem zu lösen. Die eigene App wird nicht durch zusätzliche Ressourcen vergrößert und Bugfixes in der ZXing-Bibliothek erfordern kein Update der eigenen App. Allerdings muss der Nutzer verstehen, dass er für die Barcode-Funktionalität eine weitere App benötigt. Der Scan-Prozess kann nicht gebrandet oder lokalisiert werden und die App ist abhängig davon, dass die Barcode-Scanner-App funktionsfähig bleibt. Scannen via Intent Zur Integration mit der Barcode-Scanner-App stellt ZXing die IntentIntegrator-Klasse (http:// code.google.com/pzxing/source/browse/ trunk/android-itegration/src/com/google/ zxing/integration/android/intentintegrator. java) zur Verfügung. Fügt man diese Klasse in das eigene Projekt ein, kann der Barcode Scanner wie folgt gestartet werden: Möchte man nun Daten in einem QR-Code codieren und auf dem Bildschirm des Telefons darstellen, kann dies über einen gewöhnlichen Share-Intent geschehen. Das folgende Listing zeigt, wie ein allgemeiner Intent erzeugt wird, der dem User alle Anwendungen anzeigt, die in der Lage sind, Text zu teilen: Intent sharetext = new Intent (Intent.ACTION_SEND); sharetext.settype("text/plain"); sharetext.putextra(android.content. Intent.EXTRA_TEXT, "Sharing a text as a QR-Code is simple."); startactivity(intent. createchooser(sharetext, "Title for chooser")); Ist die Barcode-Scanner-App installiert, taucht auch diese in der App-Auswahl auf. Sollen die Informationen explizit über die Barcode-Scanner-App geteilt werden, kann dies auch über IntentIntegrator integrator = new IntentIntegrator (InventurHelferActivity.this); integrator.initiatescan(); Listing 1 zeigt, wie das Scan-Ergebnis mit Hilfe der Klasse IntentResult (http://code.google.com/p/zxing/source/brose/trunk/android-integration/src/com/goole/zxing/integration/android/intentresult.java) im onactivityresult-callback verarbeitet werden kann. Im Optimalfall erscheint die in Bild 2 zu sehende Oberfläche der Barcode-Scanner-App, und nach dem erfolgreichen Einlesen des Codes kehrt der User direkt in die eigene App zurück. Hat der Benutzer die Barcode-App nicht installiert, wird der in Bild 3 zu sehende Dialog angezeigt, der dem User anbietet, die App aus dem Android-Market herunterzuladen. Dieser Dialog wird in der Methode showdownloaddialog erzeugt. Da die IntentIntegrator-Klasse als Quellcode vorliegt, kann diese auch nach Belieben angepasst werden. Hier lohnt es sich, den Dialog zu lokalisieren und vielleicht eine ausführlichere Erklärung zu liefern, warum der User eine weitere App herunterladen soll. Eine Beispielanwendung, die Daten über Intents einliest, ist auf www.mobile-developer.de in der Rubrik Aktuelles Heft zu finden. QR-Codes erstellen via Intent die IntentIntegrator-Klasse erreicht werden. Das folgende Listing zeigt, wie ein Text mit der von ZXing gelieferten Klasse geteilt werden kann: IntentIntegrator integrator = new IntentIntegrator (InventurHelferActivity.this); integrator.sharetext("sharing a Text through the IntentIntegrator is also simple"); Auch hier wird, wenn die Barcode-Scanner-App nicht installiert ist, der Benutzer auf den Android-Market zur Installation weitergeleitet. QR-Codes einlesen mit integriertem Scanner Benötigen Apps mehr Flexibilität, als die Nutzung einer Drittanbieter-App über Intents zulässt, kann der Sourcecode der Barcode-Scanner- App (http://code.google.com/p/zxing/down loads/detail?name=zxing-2.0.zip) so ange- Oberfläche der Barcode- Scanner-App (Bild 2) 3

KOMMUNIZIEREN Intents sind abstrakte Beschreibungen von Aktionen. Anstatt eine Aktion direkt auszuführen, wird dem System über ein Intent mitgeteilt, was der Benutzer machen möchte. Ein Beispiel ist das Weiterleiten eines Textes. Der Programmierer definiert das Format Text, wählt als Aktion Send aus und übergibt dies als Intent an das Betriebssystem. Dieses sucht nun alle installierten Apps zusammen, die angeben, dass sie eine Send-Aktion mit Daten im Format Text ausführen können, und lässt den User eine auswählen. Nach der Auswahl wird der Intent zur Ausführung an die gewählte App ausgeliefert. passt werden, dass die Capture- oder Encoding- Activity, die im ersten Teil des Artikels als externe Activity gestartet wurden, innerhalb der eigenen App aufgerufen werden. Die Programmierer der Barcode-Scanner-App raten allerdings dringend davon ab, dies zu tun. Im Großteil aller Fälle ist es sicherer, dem User sehr genau zu erklären, was der Start der Barcode-Anwendung bedeutet und wieso eine weitere Anwendung nötig ist, damit die eigene App funktioniert. Der größte Nachteil der Integration des Barcode-Scanner-Codes ist die Aktualität des Decodier-Codes. Die Barcode-App wird laufend aktualisiert, vor allem aufgrund der Ansprache von verschiedenen Kamerafunktionen auf verschiedenen Geräten. Die Kamerafunktionen sind ein Bereich, bei dem die Fragmentierung des Android-Marktes am stärksten zu spüren ist. Eine App, die auf möglichst vielen aktuellen Android-Geräten laufen soll, profitiert hier also von einer möglichst aktuellen Barcode-Scanner- App. In zwei Fällen ist jedoch eine Integration des Scanner-Codes unausweichlich: Auf dem Zielgerät ist kein Android-Market installiert. Die Barcode-Scanner-App kann somit nicht nachgeladen werden. Die Anzeige während des Scannens des QR- Codes muss zwingend individualisiert werden. Der Sourcecode der Scanner-App bringt nicht nur die Codier- und Decodier-Funktionalität für QR-Codes mit sich, sondern ergänzt auch nützliche Layout-Dateien und andere Ressourcen. Da all dies in einem Library-Projekt nicht nutzbar ist, muss der Code direkt in die eigene App integriert werden. Am einfachsten beginnen Sie, indem Sie eine Kopie der Barcode-Scanner- App erstellen und über Eclipse ein neues Projekt über File, New Android Project, Create Project from existing Source anlegen. In diesem Projekt müssen Sie nun die core.jar in den libs-ordner kopieren. Nun haben wir einen kompletten Klon der Barcode-Scanner-App. Damit unsere App und die Barcode-Scanner-App gleichzeitig auf einem Telefon installiert sein können, muss der Package-Name der App geändert werden. Dies geht am schnellsten über einen Rechtsklick auf das Projekt und Android Tools, Rename Application Package. Da wir auch das Manifest der Scanner-App übernommen haben, reagiert unsere App auch auf alle Intent-Filter, die die Barcode-Scanner- App definiert. Um Verwirrung beim Benutzer zu vermeiden, sollten Sie nun alle nicht benötigten Intent-Filter aus der Manifest.xml-Datei löschen. Die Barcode-Scanner-App definiert auch einige Permissions und Activities, die für eine Integration in eine eigene App eventuell nicht gebraucht werden, zum Beispiel den Zugriff auf das Adressbuch des Benutzers. Je nach Bedarf sollten dieses auch aufgeräumt werden. Das Projekt InventurHelper2 (Download von www. mobile-developer.de/aktuellesheft) enthält eine mögliche Version eines aufgeräumten Manifests. Da die angepassten Versionen der Capture- und Encoding-Activity weiterhin per Intent angesprochen werden, müssen zwei der Intent-Filter bestehen bleiben: der Intent-Filter für die Aktion com.google.zxing.client.android.scan und für die Aktion com.google.zxing.client.android.encode. Um hier Überschneidungen mit einer eventuellen Installation der Barcode-Scanner- App zu vermeiden, müssen die Aktionen umbenannt werden. Dazu ändern Sie den Aktionsteil von SCAN auf zum Beispiel READ_BARCO- DE und von ENCODE auf SHOW_BARCODE. Eine letzte Sicherheitsmaßnahme ist das Ändern des vorgestellten Packet-Namens zum Beispiel von com.google.zxing.client.android auf com. google.zxing.integrated.android. Der Einfachheit halber verwenden wir auch innerhalb unserer App den IntentIntegrator zum Initiieren des Scanners. Dieser prüft momentan aber noch, ob die Original-App installiert ist, und versucht, die alten Intent-Filter auszulösen. Daher müssen Sie die Konstante BS_PACKAGE auf das neue Scanning-Package umschreiben und in der Methode initiatescan den Endteil der Aktion auf den im Manifest eingestellten Wert ändern. Der IntentIntegrator überprüft allerdings noch immer, ob der Barcode Scanner installiert ist. Dies wird ausgelöst durch den folgenden Code: String targetapppackage = findtargetapppackage(intentscan); if (targetapppackage == null) { return showdownloaddialog(); Sie können einfach beim Erstellen der Intents in der Methode sharetext und der Methode initiate- Scan die Zeilen, die den Package-Namen betreffen, komplett entfernen. Wenn Sie nun mit dem IntentIntegrator eine integrierte CaptureActivity starten, werden Sie feststellen, dass diese sich sofort wieder beendet. Das liegt daran, dass in der Barcode-Scanner-App überprüft wird, ob die Activity mit der korrekten Aktion gestartet wurde. Dieser Test schlägt fehl, da wir die Aktion umbenannt haben. Um dies zu beheben, müssen Sie die Konstante Action in der Klasse com.google.zxing.client.android.intents.scan auf die im Manifest definierte Aktion umschreiben. Sollten Sie die Paketnamen der Original- ZXing-Klassen ändern, bedenken Sie, dass einige dieser Klassen Views oder Activities sind, deren Paketnamen Sie dann auch im Manifest oder den entsprechenden Layout-Dateien anpassen müssen. Nach diesen Anpassungen startet der modifizierte IntentIntegrator nun die Capture- 4

Activity, die in unserem Projekt definiert ist. Diese kann nun nach Ihren Wünschen angepasst und mit einem zur App passenden Layout versehen werden. QR-Codes erzeugen mit einem integriertem Encoder Soll auch die Anzeige von Barcodes innerhalb der eigenen App erfolgen, gehen wir ähnlich vor wie bei der Integration des Scanners. Die Definition der Encodierungsaktion im Manifest haben wir schon geändert, um Konflikte mit der Original-App zu vermeiden. Nun müssen wir noch die Aktion in der sharetext-methode des IntentIntegrators anpassen. Auch die EncodeActivity überprüft beim Start, ob eine korrekte Aktion übergeben wurde. Um diesen Check zu bestehen, muss in der Klasse com.google.zxing. client.android.intents.encode die Konstante Action ebenfalls auf den im Manifest eingestellten Wert umgeschrieben werden. Nun kann unsere App ohne Nutzung einer Dritt-App angezeigt wird, wenn die Barcode- Der Dialog, der vom IntentIntegrator QR-Codes decodieren und Scanner-App nicht auf dem Telefon codieren. Allerdings hat die installiert ist (Bild 3) App immer noch den Namen und das Icon der Barcode-Scanner-App und enthält auch noch sehr viel Code und einige Ressourcen, die wir vermutlich für unsere Zwecke nicht benötigen. Hier bleibt es Ihnen selbst überlassen, wie gründlich Sie die App aufräumen wollen. Bedenken Sie auch, dass viele Teile Ihrer App nun auf einem Open-Source-Projekt aufbauen. Sie sind also verpflichtet, die entsprechenden Lizenzbedingungen zu erfüllen. QR-Codes sind eine gute Methode, um Daten an verschiedene Smartphones zu übertragen. Sie folgen einem offenen Standard, der nicht von einem Telefonhersteller abhängig ist. Als Entwickler sollte man sich allerdings bewusst sein, dass die Art und Weise, wie QR-Codes genutzt werden, noch nicht jedem Smartphone-Benutzer klar sind. Wenn man die quadratischen Codes in der Praxis einsetzt, darf eine Erklärung nicht fehlen. Ebenso sollten die codierten Daten nicht nur über den QR-Code erreichbar sein, da ein QR-Code nicht im Kopf bleibt. Ein URL auf einem interessanten Plakat bleibt vielleicht hängen und bewegt den Nutzer zum späteren Nachlesen, auch wenn ein Einscannen des Codes gerade nicht möglich war. [mb] 5

Praxiswissen für Entwickler DD e v books Rückschau 2013 Vorschau 2014 Auf den Punkt! Jedes ebook liefert Praxiswissen in kompakter Form zu genau einem Thema. Geschrieben von den Experten der Branche. Auf jedem Gerät! Egal, ob ipad, Kindle oder PC Sie entscheiden, auf welchem Endgerät Sie ihr ebook lesen möchten. Aus der Praxis! Jedes ebook liefert Ihnen neben fundierter Theorie sofort anwendbares Praxiswissen mit Code für Ihr Projekt KOSTEN- FREI! Zu beziehen über www.developer-media.de/devbooks