Komplette Kenntnisse der Android-Entwicklung in vier Banden: Band 1
Author: Artem Sinihin
Date: 2016-10-23T23:00:00+00:00
Keywords: Computer & Internet
Description: Alles, was Sie über Android-Entwicklung wissen wollte ** Kurzbeschreibung Alles, was Sie über Android-Entwicklung wissen wollte
Publisher: UNKNOWN

Table of Contents

• Key Android Konzepte

• Die Wahl Ihrer Entwicklungs-Werkzeugen

• Tutorial # 1- Installieren der Werkzeuge

• Android und Projekte

• Tutorial # 2 - Erstellen eines Stub-Projekt

• Unterwegs in Android Studio

• Inhalt von Android-Projekte

• Einführung in Gradle unddas Manifest

• Tutorial # 3- Offensichtliche Änderungen

• Ein paar Worte über Ressourcen

• Tutorial # 4- Einstellen Unsere Ressourcen

• DasDie Theorie von Widgets

• Die Android-Benutzeroberfläche

• Grund Widgets

• Debugging-App

• Die Classic-Container-Klassen

• Andere gebräuchliche Widgets und Container

• Tutorial # 5- Fortschritte machen

• GUI-Gebäude, Fortsetzung

• AdapterViews und Adapter

• Die WebView Widget

• definierenund Verwendung von Stilen

• JAR-Dateien und Bibliotheksprojekte

• Tutorial # 6Hinzufügen einer Bibliothek -

• Einführung in ConstraintLayout

• Die Aktionsleiste

• Vector Drawables

• Tutorial # 7- Einstellung der Aktionsleiste oben

• Android-Prozessmodell

• -Aktivitäten und deren Lifecycles

• Tutorial # 8- Einstellung eine Tätigkeit Up

• Die Taktik des Fragments

• Tutorial # 9- Start Unsere Fragmente

• Swiping mit ViewPager

• Tutorial # 10- Aufriggen ein ViewPager

• Ressourcen Sets und Konfigurationen

• Material Design Basics

• Der Umgang mit Themen

• Anfordern von Berechtigungen

• Tutorial: Runtime Permission Unterstützung

• Assets, Dateien und Daten-Parsing

• Tutorial # 11Hinzufügen einfacher Inhalt -

• Tutorial # 12- Anzeige der Buch

• Mit Voreinstellungen

• Tutorial # 13- Mit einigen Einstellungen

• SQLite-Datenbanken

• Tutorial # 14- Speichern Hinweise

• Internet Zugang

• Intents, Intent-Filter

• Broadcasts und Broadcast-Receiver

• Tutorial # 15- Gemeinsame Nutzung Ihre Notizen

• Dienstleistungen unddas Command-Muster

• Tutorial # 16- Aktualisierung des Buches

• Großbild-Strategien und Taktiken

• Tutorial # 17- Unterstützung einer großen Screens

• Rückwärtskompatibilität Strategien und Taktiken

• Systemdienste

• Google Play-Dienste

• Hilfe bekommen

• Arbeiten mit Bibliotheksprojekte

• Gradle und Legacy-Projekte

• Gradle und Aufgaben

• Gradle und das neue Projektstruktur

• Gradle und Abhängigkeiten

Key Android Konzepte

Kein Zweifel, Sie sind inEile mit Android-Anwendung Entwicklung zu beginnen. Immerhin lesen Sie dieses Buch, an stark frequentierten Programmierer richtet.

Doch bevor wir Werkzeuge in immer einrichten und starten in der tatsächlichen Programmierung tauchen, ist es wichtig,dass wir in Bezug auf mehrere hochrangige Android-Konzepte "auf der gleichen Seite zu bekommen". Dies wird weitere Gespräche vereinfachen später in dem Buch.

Android-Anwendungen

Dieses Buch wird auf das Schreiben Android-Anwendungen konzentriert. Eine Anwendung ist etwasdass ein Benutzer möglicherweise aus dem Play Store installieren oder anderweitig an ihr Gerät herunterladen. Dieser Antrag sollte eine Benutzeroberfläche haben, und es könnte ein anderer Code haben entworfen im Hintergrund (Multi-Tasking) zu arbeiten.

Dieses Buch istauf die Android-fi nicht auf Änderungen konzentriert

Ware, wie zum

Beispiel das Schreiben von Gerätetreibern. Fürdass, müssen Sie zu suchen,andereRessourcen.

Dieses Buch geht davondass Sie einige praktische Erfahrungen mit Android-Geräten, und deshalb sind Sie mit den Tasten wie zu Hause und zurück, die eingebauten Einstellungen Anwendung, das Konzept eines Home-Bildschirm und Werfer und so weiter bekannt. Wenn Sie noch nie ein Android-Gerät verwendet haben, werden Sie dringend empfohlen, eine (neu oder gebraucht) zu bekommen und einige Zeit mit ihm vor dem Start in das Lernen auf Android-Anwendung Entwicklung zu verbringen.

Programmiersprache

Die große Mehrheit der Android-Anwendungenausschließlich in Java geschrieben werden. Daher ist das, was in diesem Buch über die meiste Zeit verbringen werden und wird mit einer scheinbar unendlich viele Beispiele zeigen.

Es gibt jedoch auch andere Möglichkeiten:

• Sie können Teile schreibendie App in C / C ++, für Performance-Gewinne, die Portierung über Code-Basen, usw.

• Sie können eine ganze app in C / C ++, vor allem für Spiele mit OpenGL für 3D-

Animationen schreiben

• Du kannst schreibendie Eingeweide einer App in HTML, CSS und JavaScript, um die Verwendung von Tools, dass das Material in eine Android-Anwendung zu verpacken, die durch den Play Store und ähnlichen Orten verteilt werden können

• Und so weiter

Einigedies wird später in dem Buch, aber die überwiegende Mehrheit des Buches konzentriert sich auf die Java-basierte App-Entwicklung.

Der Autor übernimmtdass Sie Java an dieser Stelle wissen. Wenn Sie dies nicht tun, müssen Sie Java zu lernen, bevor Sie viel weiter gehen. Sie müssen nicht alles über Java zu wissen, wie Java groß ist.

Vielmehr konzentrieren sich auf:

• Sprache Grundlagen(Flusskontrolle, etc.)

• Klassen und Objekte

• MethodenundDatenelemente

• Öffentliche, private und geschützte

• Statische und Instanzbereich

• Ausnahmen

• Themen

• Sammlungen

• Generics

• Datei-I / O

• Betrachtung

• Schnittstellen

Die Links verweisen auf Wikibooks Material aufdiese Themen, aber es gibt unzählige andere Java-Ressourcen für Sie zu prüfen.

Komponenten

Wenn Sie fi
gelernt Java - Ob das war gestern oder zurück, als die Dinosaurier die Erde
bevölkerten - Sie wahrscheinlich mit so etwas wie dies begann:

Mit anderen Worten,der Einstieg in Ihre Anwendung war ein public static void Methode namens main (), die einen String Array von Argumenten nahm. Von dort waren sie verantwortlich für zu tun, was notwendig war.

Es gibt jedoch auch andere Muster an anderer Stelle in Java verwendet. Zum Beispiel, was Sie tunin der Regel nicht eine Methode main () schreiben, wenn ein Java-Servlet zu schreiben. Stattdessen erweitern Sie eine bestimmte Klasse von einem Rahmen geliefert (zB HttpServlet), eine Komponente zu erstellen, dann einige Metadaten schreiben, die Ihre Komponenten und erzählen den Rahmen aufzählt, wann und wie sie verwendet werden (zB Web.xml).

Android Apps sind näher im Geistedie Servlet-Ansatz. Sie werden kein public static void main () Methode schreiben. Stattdessen werden Sie Subklassen von einigen Android-gelieferten Basisklassen erstellen, die verschiedene Anwendungskomponenten definieren. Darüber hinaus werden Sie einige Metadaten erstellen, die Android über diese Subklassen erzählt.

Es gibt vierArten von Komponenten, von denen alle ausführlich in diesem Buch behandelt werden: Aktivitäten

Der BausteinDie Benutzerschnittstelle ist die Aktivität. Sie können einer Aktivität denke, das Android-Analogon für das Fenster oder Dialog in einer Desktop-Anwendung, oder die Seite in einem klassischen Web App als zu sein. Es stellt einen Teil Ihrer Benutzeroberfläche und in einigen Fällen eine diskrete Einstiegspunkt in Ihrer Anwendung (dh eine Art und Weise für andere Anwendungen, um Ihre Anwendung zu verknüpfen).

Normalerweise dauert eine Aktivität auf die meistender Bildschirm, Raum für einige "Chrom" Bits wie die Uhr zu verlassen, Signalstärke Indikatoren, und so weiter.

Jedoch beachtendass bei einigen Geräten, wird der Benutzer in der Lage sein zu zurzeit, wie Split-Screen-Modus auf einem Smartphone oder Tablet mit mehr als einer Aktivität zu arbeiten. So, während es leicht ist, an Aktivitäten zu denken, wie auf dem Bildschirm gleichwertig, nur nicht vergessen, dass dies ein simplifi ist
und dass die Realität ist komplizierter (wie die Realität
oft ist).

Dienstleistungen

Die Aktivitäten sind kurzlebig und können jederzeit abgeschaltet werdenZeit, wie zum Beispiel, wenn der Benutzer drückt die Taste BACK. Dienste, auf der anderen Seite sind so ausgelegt, am Laufen zu halten, falls erforderlich, unabhängig von irgendeiner Aktivität, für eine moderate Zeitraum. Sie könnten einen Dienst für die Überprüfung nach Updates zu einem RSS-Feed nutzen oder Musik wiedergeben, auch wenn die Steueraktivität wird nicht mehr in Betrieb. Sie werden auch Dienstleistungen für geplante Aufgaben (ähnlich zu Linux oder OS X "cron-Jobs") verwenden und benutzerdefinierte APIs für andere Anwendungen auf dem Gerät zum Belichten, obwohl letztere eine relativ fortgeschrittenen Fähigkeit ist.

Anbieter von Inhalten

Anbieter von Inhalten zu Verfügung stelleneine Abstraktionsebene für alle auf dem Gerät gespeicherten Daten, die von mehreren Anwendungen zugänglich ist. Das Android-Entwicklungsmodell
fordert Sie dazu auf Ihre eigenen Daten anderen Anwendungen zur Verfügung, als auch Ihre eigenen zu machen- Ein Content-Provider bauen können Sie das tun, während ein gewisses Maß an Kontrolle über die Aufrechterhaltung, wie Sie Ihre Daten zugegriffen wird.

So zum Beispiel, wenn Sieein PDF-fi
dass Sie im Namen des Benutzers heruntergeladen,
und Sie möchten dem Benutzer zu ermöglichen, dass die PDF-fi anzuzeigen

Sie könnten
erstellenein Content-Provider, die PDF-fi machen
zur Verfügung zu anderen

Anwendungen. Sie könnendann eine Aktivität starten, die diese PDF zu betrachten werden können, wo Android und der Benutzer wird feststellen, welche PDF-Betrachtungs Aktivität, die Anforderung verarbeitet.

Broadcast-Receiver

Das System oder Anwendungen werden Sendungen versenden vonZeit zu Zeit für alles von der Batterie schwach werden, um, wenn der Bildschirm ausgeschaltet wird, zu, wenn die Verbindung wechselt von WiFi für mobile Daten. Ein Rundfunkempfänger kann vorsehen, diese Sendungen zu hören und entsprechend reagieren.

Widgets, Container und Ressourcen
die meistender Fokus auf Android-Anwendung Entwicklung ist auf der UI-Ebene und Aktivitäten.

Die meisten Android-Aktivitäten verwenden, was als "Widget-Framework" bekannt ist für ihre Benutzeroberfläche Rendering, obwohl Sie willkommen sind, als auch die 2D (Canvas) und 3D

(OpenGL) APIs verwenden für speziellere GUIs.

In Android Bedingungen,ein Widget ist die "micro" Einheit der Benutzeroberfläche. Felder, Knöpfe, Etiketten, Listen und sind so auf alle Widgets. Ihre Aktivität UI daher besteht aus einem oder mehreren dieser Widgets gemacht. Zum Beispiel, hier sehen wir Etikett (Textview), fi (Text bearbeiten) Und Taster(Taste) Widgets:

Wenn Sie mehrals ein Widget - die ziemlich typisch ist - müssen Sie Android zu sagen, wie diese Widgets auf dem Bildschirm organisiert sind. Um das zu tun, werden Sie verschiedene Container-Klassen bezeichnet als Layout-Manager verwenden. Diese lassen Sie die Dinge in Zeilen, Spalten oder komplexere Anordnungen nach Bedarf.

Um zu beschreiben, wiedie Behälter und Widgets verbunden sind, Sie werden in der Regel ein LayoutRessource-Datei erstellen. Ressourcen in Android beziehen sich auf Dinge wie Bilder, Strings und andere Materialien, die Ihre Anwendung verwendet, sondern in Form einer bestimmten Programmiersprache Quellcode nicht. UI-Layouts sind eine andere Art von Ressource. Sie werden diese Layouts entweder mit Hilfe eines strukturierten Werkzeug, wie ein IDE-Drag-and-Drop GUI-Builder, oder mit der Hand in XML-Form erstellen.

Manchmal wird die Benutzeroberfläche in allen Arten von Geräten arbeiten: Smartphones, Tablets, Fernseher, etc. Manchmal, Ihre UImüssen für unterschiedliche Umgebungen zugeschnitten werden.

Sie können Ressourcen in Ressourcengruppen zu setzen, die unter angeben welchen Umständen diese Mittel verwendet werden können (zB verwenden diese für normal große Bildschirme, aber die für größere Bildschirme verwenden).

Wir werden die Prüfung all diese Konzepte, viel genauer, als wir tiefer in das Buch.

Apps und Pakete

Gegebeneinen Eimer mit Quellcode und ein Korb von Ressourcen, bauen die Android-Tools, die Sie eine Anwendung als Ergebnis geben wird. Die Anwendung kommt in Form einer APK-Datei. Es ist das, APK fi, die Sie auf den Play Store laden werden oder durch andere Mittel zu verteilen.

Jede Android-Anwendung hatein Paketname, auch bezeichnet als eine Anwendungs-ID. Ein Paketname muss drei Anforderungen fulfi:

1. Es muss seinein gültiger Java-Paketnamen, die als einige Java-Quellcode von

Android Build-Tools in diesem Paket erzeugt werden

2. Keine zwei Anwendungen kann mit dem gleichen Applikations-ID in der gleichen

Zeit auf einem Gerät existieren

3. Es können keine zwei Anwendungen hochgeladen werdenden Play Store die
gleiche Anwendungs-ID mit

Wenn Sie erstellen Ihr Android-Projekt- Das Repository des Quellcodes und diese Ressourcen - Sie werden erklären, welche Paketname für Ihre Anwendung verwendet werden soll. Normalerweise werden Sie den Namen eines Pakets nach dem Java-Paketnamen "Reverse Domain Name"

Konvention (zB com.commonsware.android.foo) wählen. Auf diese Weise wird sichergestellt, das Domain Name System, dass Ihr Paket Namensprefix (com.commonsware) einzigartig ist, und es ist an Ihnen, um sicherzustellen, dass der Rest des Pakets Namen eines Ihrer Apps von jedem anderen unterscheidet.

Android-Geräte

Es sind weit über eine Milliarde Android Geräte heute im Einsatz, wasTausende von verschiedenen Modellen aus Dutzenden von verschiedenen Herstellern. Android selbst ist seit Android 1.0 im Jahr 2008. Zwischen den verschiedenen Gerätetypen und unterschiedlichen Android-Versionen entwickelt, viele Medien Pandit den Begriff "Fragmentierung" im Android lobbed hat, was darauf hindeutet, dass der App-Entwicklung, die auf all diesen verschiedenen Umgebungen laufen, ist unmöglich.

In Wirklichkeit ist esnicht so schlecht. Einige Anwendungen haben erhebliche Schwierigkeiten, aber die meisten Anwendungen werden nur fi arbeiten
ob du folgst die Führung in diesem

Buch und in anderen Ressourcen vorgestellt.

Typen

Android-Geräte kommen in allen Formen, Größen und Farben. Allerdings gibt es zwei dominante

"Formfaktoren":

• das Telefon

• das Tablet

Darüber hinausDarüber hinaus gibt es mehrere weniger gebräuchlichen Formfaktoren

• das Fernsehen (TV)

• die tragbare (intelligente Uhren, Google Glass, etc.)

• das Notebook oder Netbook (Tablet-Größe Bildschirm mit einer angeschlossenen Tastatur)

• der Desktop (kleine Android-Gerät entwickelt, um in einem Monitor, eine Tastatur angeschlossen werden, und Maus)

Sie werden oft hören Entwickler und Experten beziehen sich aufdiese Formfaktoren, und dieses Buch wird auch so von Zeit zu Zeit tun. Es ist jedoch wichtig, dass Sie verstehen, dass Android keine Einbau-Konzept eines Gerätes hat eine "Telefon" oder eine "Tablette" oder ein "TV" zu sein.

Vielmehr Android unterscheidet auf Fähigkeiten und Funktionen basierte Geräte. Also, werden Sie keine isPhone () -Methode überall zu sehen, wenn Sie Android fragen:

• was istdie Bildschirmgröße?

• tutdas Gerät über Telefonie-Fähigkeit?

• etc.

In ähnlicher Weise, wie Sie Ihre Anwendungen zu erstellen, eherdieser Formfaktoren als zu denken, konzentrieren sich auf welche Fähigkeiten und Funktionen, die Sie benötigen. Nicht nur wird diese Hilfe, die Sie in einer Reihe aufstellen besser mit, wie Android möchte, dass Sie Ihre Anwendungen zu bauen, aber es wird es einfacher für Sie zu anderen Formfaktoren anzupassen, die etwa wie kommen:

• Flugzeugsitz-Rücken Entertainment-Center

• In-Car Navigation und Entertainment-Geräte

• und so weiter

Betriebssysteme

Sie können durch verwechselt werdendieser Position. Immerhin Android ist ein Betriebssystem.

Welche Betriebssysteme gibt es für Android, andere als Android?

Im Jahr 2016 hat Google Android Apps zur Verfügung zu viele Chrome OS-Geräte. Diese Notebooks und Desktopsnicht nur Chrome OS-Anwendungen laufen, aber Apps aus dem Play Store erhalten.

Daher laufen Ihre Anwendungen könnten auf Chrome OS als auch Geräte.

Der Emulator

Während es übereine Milliarde Android-Geräte Tausende von Modellen darstellen, wahrscheinlich haben Sie nicht ein jedes Modell. Sie können nur ein einziges Stück von Android-Hardware haben.

Und wenn Sie nicht einmal, dass Sie haben, Sie sicherlich wollen eine zu erwerben, bevor Sie eine Android-App zu veröffentlichen.

Damit fi in den Lücken zwischen den Geräten, die Sie und die Geräte haben, die möglich sind, liefern die Android-Entwickler-Tools einen Emulator. Der Emulator verhält sich wie ein Stück von Android-Hardware, aber es ist ein Programm, das Sie auf dem Entwicklungscomputer ausgeführt werden. Sie können diesen Emulator verwenden, um viele verschiedene Geräte mit
unterschiedlichen Bildschirmgrößen und Android OS Versionen emulieren, durch eine oder mehrere Android virtuelle Geräte zu schaffen, oder AVDS.

Imein kommender KapitelWerden wir diskutieren, wie Sie installierendie Android-Entwickler-Tools und wie werden Sie in der Lage sein,erstellendiese AVDS und führen Sie den Emulator.

OS-Versionen und API-Ebenen

Android ist gekommenein langer Weg seit den frühen Beta-Versionen von Ende 2007. Jede neue Android OS-Version mehr Funktionen auf der Plattform ergänzt und mehr Dinge, die Entwickler diese Fähigkeiten zu nutzen, tun können.

Außerdem,die Core-Android-Entwicklungsteam versucht, sehr hart vorwärts und rückwärts Kompatibilität zu gewährleisten. Eine App, die Sie heute schreiben sollte auf zukünftige Versionen von Android (vorwärts-Kompatibilität), wenn auch vielleicht fehlen einige Funktionen oder arbeiten in einer Art von "Kompatibilitätsmodus" unverändert funktionieren. Und es gibt gut trod Pfade, wie Anwendungen zu erstellen, die sowohl auf dem neuesten und früheren Versionen von Android (Abwärtskompatibilität) funktionieren wird.

Damit wir den Überblick über alledie verschiedenen OS-Versionen, die als Entwickler für uns wichtig, hat Android API-Ebenen. Eine neue API-Ebene ist, wenn eine Android-Version Schiffe definiert, die Änderungen enthält, die Entwickler beeinflussen. Wenn Sie einen Emulator erstellen AVD Ihre Anwendung zu testen, werden Sie, was API-Ebene zeigen, dass Emulator emulieren soll. Wenn Sie Ihre Anwendung verteilen, werden Sie die älteste API-Ebene Ihrer Anwendung unterstützt zeigen, so dass die App nicht auf älteren Geräten installiert ist.

Beimdie Zeit des Schreibens dieses Artikels sind die API-Ebenen von Bedeutung für die meisten Android-Entwickler:

• API Ebene 16 (Android 4.1)

• API Stufe 17 (Android 4.2)

• API Stufe 19 (Android 4.4)

• API Stufe 21 (Android 5.0)

• API Stufe 22 (Android 5.1)

• API Stufe 23 (Android6.0)

Hier ist "von Bedeutung" bezieht sich auf API-Ebenendass haben, eine angemessene Anzahl von Android-Geräten - 5% oder mehr, wie vondie "Plattform-Versionen" Armaturenbrett-Chart.

Die neueste Version von Android 7.0, API-Ebene 24.

Hinweisdass API Level 20 wurde für die Version von Android 4.4 auf dem fi verwendet

-

Generation Android Wear-Geräte. Sofern Sie nicht ausdrücklich Apps für Wear Entwicklung sind, werden Sie nicht viel Gedanken über API Level 20.

Dalvik und ART

In Bezug auf die Android, Dalvik und Kunst sind virtuelle Maschinen (VM) s. Virtuelle Maschinen werden von vielen Programmiersprachen, beispielsweise Java, Perl, und Smalltalk verwendet. Dalvik und ART sind so konzipiert, viel zu arbeiten, wieeine Java-VM, aber für Embedded-Linux-Umgebungen optimiert.

In erster Linie,der Unterschied zwischen den beiden ist, dass die Kunst auf Android 5.0 und höher verwendet wird, während Dalvik auf älteren Geräten verwendet wurde. In Wahrheit ist die Geschichte komplizierter als das, aber das wird jetzt tun.

Also, geht, was wirklich auf, wenn jemand schreibt eine Android-Anwendung ist:

1. Entwickler schreiben Java-Syntax-Quellcode, Klassenbibliotheken veröffentlicht die Nutzung vondas Android-Projekt und Dritten.

2. Entwickler kompilierender Quellcode in Java-VM-Bytecode, die javac mit

Compilerdas kommt mit dem Java SDK.

3. Entwickler übersetzender Java-Bytecode-VM in Dalvik VM-Bytecode, die mit anderen fi verpackt
in ein ZIP-Archiv mit der APK-Erweiterung (die APK fi

4. Ein Android-Gerät oder Emulator läuftdie APK fi

Verursachung der Bytecode
von einer Instanz eines Dalvik oder ART VM ausgeführt werden.

Von Ihrem Standpunkt, die meistendies wird durch die Build-Tools verborgen. Sie schütten Java-Quellcode in die Spitze, und die APK fi
kommt herausder Boden.

Allerdings wird es Orte, vonZeit zu Zeit, wo die Unterschiede zwischen der Dalvik VM und dem traditionellen Java VM-Anwendungsentwickler auswirken wird, und dieses Buch wird gegebenenfalls einige von ihnen hinweisen.

Prozesse und Themen

Wenn die Anwendung ausgeführt wird, wird es tun, so in einem eigenen Prozess. Das istnicht signifikant verschieden von jeder anderen herkömmlichen Betriebssystem. Ein Teil der Dalvik Magie macht es möglich, für viele Prozesse auf einmal laufen viele Android-Anwendungen werden ohne lächerliche Mengen an RAM verbrauchen.

Android wird auch einrichteneine Charge von Threads für Ihre Anwendung ausgeführt wird. Der Faden, der Code wird auf ausgeführt werden, die meiste Zeit ist verschiedentlich die

"Hauptanwendungsthread" oder das "UI-Thread" genannt. Sie müssen es nicht gesetzt, aber, wie wir später in dem Buch sehen werden, müssen Sie darauf achten, was Sie tun und nicht tun, in diesem Thread. Sie sind herzlich eingeladen, Ihre eigenen Threads zu gabeln Arbeit zu tun, und das ist ziemlich häufig, wenn auch in einigen Orten Android Griffe, die für Sie hinter die Kulissen.

Seien Sie nicht Angst

Ja,dieses Kapitel warf Ihnen eine Menge von Begriffen. Wir werden in diesem Buch auf alle von ihnen mehr ins Detail gehen. Allerdings ist Android wie ein Puzzle mit vielen ineinander greifenden Teile. Um der Lage sein, ein Konzept im Detail zu beschreiben, müssen wir zumindest einige der anderen verweisen. Daher wurde in diesem Kapitel soll Sie Bedingungen aussetzen, in der Hoffnung, dass sie vage vertraut klingen, wie wir in die Details tauchen.

Auswählen der Entwicklung

Toolchain

Bevor Sie viel weiter in Ihrem Android-Bemühungen gehen (oder möglicherweise bestrebt, je nach Ihrer bevorzugten Schreibweise), werden Siemüssen, um zu bestimmen, welche Toolchain verwenden Sie Ihre Android-Anwendungen zu erstellen.

Android Studio

Die aktuelle Google-backed Android IDE ist Android Studio. Basiert weg vonIntelliJ IDEE, Android Studiodie neue Grundlage der Google-Bemühungen Android-Entwickler-Tools
erstklassige Entwicklung zu geben.

Dasnächstes Kapitelenthältein Abschnitt mit Anweisungen, wie Android Studio einzurichten.

Beachten Sie jedoch,dass Android Studio erfordert eine ziemlich leistungsfähige Entwicklungs Maschine gut zu funktionieren: schnelle CPU, viel RAM und eine SSD sind alle sehr zu empfehlen.

Finsternis

Eclipse ist aucheine populäre IDE, vor allem für die Java-Entwicklung. Eclipse-war Googles ursprüngliche IDE für Android-Entwicklung, mit Hilfe der Android Developer Tools (ADT) Addin, die den Kern von Eclipse Bewusstsein für Android gibt. Die ADT Add- in im Wesentlichen vor, nimmt regelmäßig Eclipse-Operationen und erweitert sie mit Android Projekten zu arbeiten.

Beachten Sie jedoch,dass Google hat die Wartung von ADT eingestellt. Die Eclipse Foundation ist die Einrichtungdie "AndMore" Projektum zu versuchen, die Arbeit fortzusetzen, so dass Eclipse-Android-Apps zu bauen. Dieses Buch tutnicht decken zu diesem Zeitpunkt die AndMore Projekt und Entwickler dringend empfohlen, den ADT-fähigen Eclipse-von Google nicht zu verwenden ermutigt.

IntelliJ IDEA

Während Android Studio auf IntelliJ IDEA basiert, können Sie immer noch verwendendie ursprüngliche IntelliJ IDEA für Android-App-Entwicklung. Eine große Teilmenge der Android Studio-Funktionen sind im Android-Plugin für IDEA zur Verfügung. Plus, die kommerzielle IDEA Ultimate Edition wird über Android Studio in vielen Bereichen außerhalb der Android-Entwicklung gehen.

Insbesondere dann, wenn Sie auf der Suche nach "dem einenTrue IDE ", die Sie für Android und Nicht-Android-Projekte verwenden können, sollten Sie IntelliJ IDEA in Betracht ziehen. Android Studio ist schön, aber es ist nur für Android-Projekte.

Kommandozeilen-Builds über Gradlefür Android

Und natürlich, was Sie tunnicht brauchen überhaupt eine IDE zu verwenden. Während dies für einige sacrilegious klingen mag, IDEs sind nicht der einzige Weg, um Anwendungen zu bauen. Vieles von dem, was über eine IDE erreicht wird, kann durch Kommandozeilen-Äquivalenten erreicht werden, eine Shell Bedeutung und ein Editor ist alles, was Sie wirklich brauchen.

Der empfohlene Weg Android Apps außerhalb einer IDE zu bauen, ist durch Gradle. Google veröffentlichtein Gradle-Plugin, das Gradle wie zu bauen Android Apps lehrt. Android Studio selbst nutzt Gradle für seine baut, so dass eine einzelne Build-Konfiguration (zB build.gradle fi
kann beide von einer IDE verwendet werden und aus ein Build-Automatisierungstool wie ein Continuous-Integration-Server.

Einkommenden Kapitelwird in mehr darüber, was Gradle (unddas Android-Plugin für Gradle) sind alle über.

Noch andere Alternativen

Andere haben die IDEsihre Äquivalente des ADT, wenn auch mit minimaler Unterstützung von Google. Zum Beispiel hat NetBeans Support über das NBAndroid Add-on, und dem Vernehmen nach hat sich diese im wesentlichen in den letzten Jahren vorangetrieben.

Sie werden auch Bezug auf die Verwendung von Apache Ant dafür Befehlszeilen Builds von Android Apps hören. Dies wurde von Gradle für Android verdrängte beidieses Mal, und es gibt wenig

Unterstützung für Apache Ant mehr. Neuankömmlinge Android werden ermutigt, keine Zeit in neue Arbeit mit Apache Ant für Android Entwicklungsprojekte investieren.

IDEs ... Und dieses Buch

Sie werden ermutigt, Android Studio verwenden, wie Sie durch die Arbeitdieses Buch. Sie sind willkommen, eine andere IDE zu verwenden, wenn Sie es wünschen. Sie sind auch willkommen, um die IDE komplett zu überspringen und nur einen Editor benutzen.

Dieses Buch konzentriert sich in erster Linie Android-Fähigkeiten zu demonstrieren unddie APIs für diese Fähigkeiten zu nutzen. Daher wird der Beispielcode mit einer beliebigen IDE arbeiten.

Allerdings wird dieses Buch einige Android Studio-spezifische Anweisungen decken, denn das ist die vorherrschende Android IDE heute im Einsatz ist.

Was wir nicht decken

Imder Anfang (aka, 2007), hatten wir das Glück jedes Mittel haben eine Android-App zu erstellen.

Heutzutage scheint es zu sein,Ende nicht auf die Mittel, mit denen wir eine Android-App erstellen können.

There sind ein paar dieser "bedeutet" aber, dass für dieses Buch speziell außerhalb des Bereichs sind.

App Inventor

Sie können auch gehört haben vonein Tool App Inventor benannt und frage mich, wo es fi im

Mit all diesen.

App Inventor wurde ursprünglich von ein erstelltBildung Gruppe innerhalb von Google, als ein Mittel, die Schüler zu lehren, wie man über Programmierkonstrukte (Verzweigungen, Schleifen, etc.) zu denken und interessante Ausgabe (Android Apps) in Java oder andere Syntax-basierte Sprachen ohne klassische Programmierung erstellen. Inventor App ist rein Drag & Drop, die beide von Widgets und Anwendungslogik, die diese mittels "Blöcke", die zusammen reißen logische Ketten zu bilden.

App Inventor wurde von Google MIT gespendet, die sie vor kurzem wieder eröffnetnachdas Öffentlichkeit.

Allerdings ist App Inventorein geschlossenes System - in der heutigen Zeit, es erzeugt keine irgendwie Java-Code, den Sie später erweitern können. Das schränkt Sie, was auch immer App Inventor ist nativ dazu in der Lage, die zwar beeindruckend in seinem eigenen Recht, einen kleinen Teil der gesamten Android SDK-Funktionen bietet.

App-Generatoren

Es gibteine scheinbar unendliche Anzahl von "app-Generatoren" als Online-Dienste. Diese sind vor allem für Anwendungen für spezifi vertikalen Märkten, wie zum Beispiel Apps für Restaurants oder Apps für Lebensmittelgeschäft zu schaffen. Die daraus resultierenden Anwendungen sind meist "Broschüre-ware", mit wenigen Fähigkeiten, die über eine mobile Website, noch erfordert immer noch um den Benutzer zu fi

Herunterladen und installierendie App. Nur wenige
dieser Generatoren liefern den Quellcode der erzeugten App zu ermöglichen, die Anwendungen über individuell gestaltet werden können, was der Generator erzeugt.

Tutorial # 1- Installieren der Werkzeuge

Nun wollen wir uns erhalten Sie eingerichtet mitdie Stücke und Teile, die notwendig eine Android-App zu bauen.

HINWEIS: Die Anweisungen hier vorgestellten sind genau wiedie Zeit des Schreibens dieses Artikels. Allerdings ändern sich die Werkzeuge schnell, und so diese Anweisungen können durch die Zeit, die Sie dies lesen veraltet sein. Bitte wende dich an dieAndroid-Entwickler-WebsiteAktuelle Anweisungen, mitdies als Basis-Richtlinie von dem, was zu erwarten ist.

Aber zuerst, einige Hinweise zu Android Emulator

Die Android-Tools umfassen einen Emulator,ein Stück Software, die ein Android-Gerät zu sein vorgibt. Dies ist sehr nützlich für die Entwicklung - nicht nur, dass es bedeutet, können Sie ohne ein Gerät auf Android zu beginnen, aber der Emulator können Testgerätekonfigurationen helfen, die Sie nicht besitzen.

Es gibt zweiArten von Emulator: x86 und ARM. Dies sind die beiden wichtigsten Arten von CPUs für Android-Geräte verwendet. Sie wollen wirklich in der Lage sein, die x86-Emulator zu verwenden, da die ARM-Emulator extrem langsam ist.

Jedoch verwendendie x86-Emulator, muss der Entwicklungsmaschine Dinge richtig eingestellt haben bis fi

Linux Benutzer müssen KVM, während Mac und Windows-Benutzer die

"Intel Hardware Accelerated Execution Manager" müssen (aka, HAXM).

Ebenfalls,Dies funktioniert nur für bestimmte CPU-Architekturen, diejenigen, die Virtualisierung in Hardware unterstützen:

• Intel Virtualization Technology (VT, VT-x, VMX) Erweiterungen

• AMD Virtualization (AMD-V, SVM) Erweiterungen (nur Linux)

Diese Virtualisierungserweiterungen muss auch sein,im BIOS aktiviert Geräts und andere OS-spezifische Modifikationen erforderlich.

Auch zumindest für neuere API-Ebenen, die CPUUnterstützung SSSE3 Erweiterungen müssen, obwohldie Einzelheiten dieser Anforderung sind ab August 2016 nicht dokumentiert.

Teil vondas Android-Studio Installation wird versuchen Sie einrichten zu können, die x86-Emulator zu verwenden. Notieren Sie alle Nachrichten, die Sie im Installationsassistenten finden Sie in Bezug auf "HAXM" (oder, wenn Sie Linux laufen, KVM), wie die später wichtig sein wird.

Schritt 1: Überprüfen Sie Ihre Hardware

Kompilieren und den Aufbau einer Android-Anwendung, auf seine eigene, istnicht besonders hardwareintensiv, außer für sehr große Projekte. Allerdings gibt es zwei häufig verwendete Werkzeuge, die mehr von Ihrer Entwicklungsmaschine fordern: Ihre IDE und die Android-Emulator.

Von den beiden stellt der Emulator das größere Problem.

Je mehr RAM Sie haben,desto besser. 8 GB oder höher ist eine sehr gute Idee, wenn Sie beabsichtigen, gemeinsam eine IDE und den Emulator zu verwenden.

Eine schnellere CPU ist auch eine gute Idee. Allerdings nutzt das Android-Emulator nur einen einzigen Kern aus Ihrer Entwicklungsmaschine. Daher ist es die Single-Core-Geschwindigkeit, was zählt. Die beste CPU zu verwenden, ist eine, die mehrere Kerne nutzen können, zu geben, was zu einer schnelleren Single-Core-Mengen, wie Intels Core i7 mit Turbo-Boost.

Jedoch verwendendie x86-Emulator - der Emulator, der gut läuft - benötigen Sie eine CPU mit bestimmten Eigenschaften:

Entwicklung

CPU-Anforderungen

OS

Windows-
eine Intel-CPU mit Unterstützung für VT-x, EM64T und "Execute Disable"

(XD)

Mac
irgendein

Linux
eine Intel-CPU mit Unterstützung für VT-x, EM64T und "Execute Disable"

(XD), oder eine AMD CPU mit Unterstützung fürAMD-V

Wenn Ihre CPU tutnicht diesen Anforderungen gerecht zu werden, werden Sie 1+ Android-Geräte zur Verfügung zu haben, so dass Sie auf Hardware testen können.

Auch, wenn Sie Windows oder Linux laufen, Siemüssen sicherstellen, dass das BIOS Ihres Computers eingerichtet ist Intels Virtualisierungserweiterungen zu unterstützen.

Leider sind viele PC-Hersteller deaktivierendies standardmäßig. Die Details, wie in die BIOS-Einstellungen zu bekommen von PC, variieren aber in der Regel geht es um Ihren Computer neu zu starten und eine Funktionstaste auf der ersten Ladebildschirm drücken. In den BIOS-Einstellungen, suchen Sie Verweise auf "Virtualisierung" oder "VT-x". Aktivieren Sie sie, wenn sie nicht bereits aktiviert sind.

Schritt 2: Einrichten von Java und 32-Bit-Linux-Support

Wenn Sie Android-Anwendungen schreiben, schreiben Sie in der Regelsie in Java-Quellcode. Das Java-Quellcode wandte sich dann in die Sachen, die Android tatsächlich läuft (Dalvik Bytecode in einer APK fi

Android Studio, beginnend mit Version 2.2, Schiffe mit seinem eigenen privaten Kopie von OpenJDK 8, und es wird verwendendass in der Standardeinstellung. Sie sind herzlich eingeladen, Ihre eigenen JDK zu installieren und zu verwenden, wenn Sie es wünschen, obwohl ideal für Java 8 ist.

Wenn Ihre Entwicklung OS Linux ist, stellen Sie sicher,dass Sie 32-Bit-Linux-Binaries laufen kann.

Dies kann oder kann nicht bereits in Ihrem Linux-Distribution freigegeben werden. Zum Beispiel auf Ubuntu 14.10, müssen Sie die folgende laufen die 32-Bit-Binär-Unterstützung zu erhalten installiert, dass die Android Build-Tools benötigt wird:

Du könntest auchmüssen lib32bz2-1.0, je nach Ihrer Version von Linux.

Schritt 3: Installieren Android Studio

Wie bereits inIm vorigen Kapitel gibt es ein paar Entwickler-Tools, die Sie wählen können.

Dieses Buch des Tutorials konzentrieren sich auf Android Studio. Sie sind willkommen, um zu versuchen, Eclipse verwenden, einen anderen IDE oderkeine IDE auf alle für den Bau von Android-Apps. Allerdings müssen Sie einige der Tutorials 'IDE-spezifi Anweisungen zu übersetzen zu sein, was für die Entwicklung Toolchain der Wahl erforderlich ist.

Beim2.1.x die Zeit des Schreibens dieses Artikels ist die aktuelle Produktionsversion von Android Studio, und dieses Buch deckt diese Version. Wenn Sie dies in der Zukunft lesen, können Sie sein aufeine neuere Version von Android Studio, und es kann einige Unterschiede zwischen dem, was Sie haben und was hier präsentiert wird.

Sie haben zwei große Download-Optionen. Du kannst bekommendie neueste ausgelieferte Version von Android Studio ausdas Android-Studio Download-Seite.

Oder Sie können Android Studio 2.2.0 herunterladen- Die Version in dieser Ausgabe dieses Buches verwendet - vondas Android-Studio-Projekt-Site. Diese Option ist wichtig, wenneine neuere Android Studio ist zu der Zeit zur Verfügung, die Sie dies lesen.

Windows-Benutzer können herunterladenein selbst installierendes EXE, die für Sie geeignete Start-Optionen hinzufügen, werden in der Lage sein, die IDE zu starten.

Mac-Benutzer können herunterladenein Disk-Image DMG und installieren Sie sie auf andere Mac-Software verwandt.

Alle Benutzer, einschließlich Linux-Benutzer können herunterladenein ZIP fi entpacken Sie es bis zu einem gewissen wahrscheinlich Stelle dann auf Ihrer Festplatte. Android Studio kann dann aus dem Studio Batch fi oder Shell-Skript von Ihrem Android-Studio-Installation des bin /

Verzeichnis ausgeführt werden.

Schritt 4: Installierendie SDKs und Add-Ons

Nächsten wirmüssen überprüfen, welche Teile des Android SDK haben wir bereits und vielleicht einige neue Elemente zu installieren. Um das zu tun, müssen Sie den SDK-Manager zugreifen.

Wenn Sie fi

Lauf Android Studio, können Sie gefragt, ob Sie die Einstellungen von einem
anderen vor der Installation von Android Studio importieren möchten:

Für die meisten Anwender, insbesonderediejenigen mit Android Studio für die fi

Zeit, die

"ich habe nicht ..." Option ist die richtige Wahl zu treffen.

Dann danacheinen kurzen Splash-Screen, werden Sie auf dem Android-Studio-Setup-Assistenten getroffen werden:

klicken Sie auf "Weiter" Gerade Vorausdie zweite Seite des Assistenten:

Hier hast dueine Wahl zwischen "Standard" und "Custom" Setup-Modi. Wahrscheinlich, gerade jetzt, wird die "Standard" Route fi sein
für Ihre Umgebung.

ichf Sie gehen, um die "Standard" Route und klicken Sie auf "Weiter", dann sollten Sie auf eine Seite des Assistenten getroffen werden, um zu überprüfen, was heruntergeladen und installiert werden:

nehmen Sie auf Weiter klicken könnenein Assistent Seite einige Informationen über die Android-Emulator zu erklären:

Was erklärt aufDiese Seite kann nicht viel Sinn machen. Das ist vollkommen normal, und wir werden bekommen in das, was diese Seite versucht, später in dem Buch zu sagen. Klicken Sie einfach auf "Fertig stellen", um den Setup-Prozess beginnen. Dazu gehört auch eine Kopie des Android SDK herunterladen und in ein Verzeichnis neben dem Android Studio selbst installiert Installation ist.

Wenn Sie Linux ausführen und die Installation von Abstürzen mit einem Fehler "Kann nicht mksdcard SDK-Tool ausführen", gehen Sie zurück zuSchritt 2und Einrichten von 32-Bit-Unterstützung auf Ihrem Linux-Umgebung.

When das geschehen ist, nach einem Klick auf "Fertig stellen", wird Android Studio eifrig beginnen Sachen Entwicklungscomputer herunterzuladen. Sie können mit einem Ergebnisdialog präsentiert werden, wenn die Arbeit abgeschlossen ist:

Durch Klicken auf "Fertig stellen" wirddann nehmen Sie zum Android Studio Willkommen-Dialog: Dann indas Willkommen-Dialog, klicken Sie auf Konfigurieren, eine Konfiguration Dropdown-Liste aufzurufen:

Dort,Tippen Sie auf SDK Manager, um das SDK-Manager aufzurufen.

Mit SDK-Manager und Aktualisieren der Umwelt

Sie sollten jetzt habendas SDK-Manager als Teil der allgemeinen Standardeinstellungen für Android Studio geöffnet,:

Die "SDK-Plattformen"Reiter listet die Versionen von Android, die Sie gegen kompilieren können.

Die neueste Version von Android ist in der Regel bei der Installation von Android Studio zunächst einrichten. Doch für die Tutorials, bitte auch überprüfen "Android 7.0 (Nougat)" in der Liste, wenn es nicht bereits aktiviert ist, und klicken Sie dann auf die Schaltfläche "Apply" zum Herunterladen

und diese Versionen zu installieren. Möglicherweise müssen Sie eine Lizenz Konfi zu akzeptieren

Dialog als Teildieser Prozess:

Wanndass abgeschlossen ist, können Sie auf "Fertig stellen" klicken Sie auf den Download-Dialog zu schließen, und dann werden Sie auf die SDK-Manager zurückgegeben werden.

Klicken Sie auf das "SDK Tools" tab:

Hier werden Werkzeuge und verwandte Materialien für Android Entwicklung, andereals der Emulator (die nach oben und konfiguriert separat eingestellt ist). Android Studio hat in der Regel das Recht auf Sachen einrichten geprüft und installiert bereits für Sie. Sie können installieren möchten:

• die "Dokumentation für Android SDK", was zu einer offl beträgt

Polizisty der
das meiste Material gefunden aufhttp://developer.android.com

• die beiden ConstraintLayout Elemente in der "Support Repository" Kategorie (

"ConstraintLayout für Android" und "Solver für ConstraintLayout") Die anderen Elemente in hier sindein bisschen mehr esoterisch, und Sie werden sie nicht für die meisten dieses Buches werden müssen.

Einige dieser Dinge können markiert werdenein Zustand, der anzeigt, dass ein Update verfügbar, die Updates anzuwenden, in dem Fall können Sie es wünschen. Umgekehrt, wenn irgendetwas mit

"Vorschau" oder "RC" aktiviert ist, deaktivieren und es deinstallieren. Diese Elemente würden zu einem hervorragenden Entwickler-Vorschau von einer neuen Version von Android in Beziehung gesetzt werden. Während Entwickler Previews nützlich sind, fügen sie Komplexität für Einsteiger in Android.

Sobald Sie haben geprüft und ungeprüftdie Änderungen, die Sie vornehmen möchten, klicken Sie auf "Übernehmen", um die neue Dinge zum Download und die unerwünschten Dinge zu entfernen.

Wenn Sie machen getanDiese Anpassungen können Sie den SDK-Manager, indem Sie auf die Schaltfläche OK aus nächster Nähe.

In unserer nächsten Folge ...

… wir werdenein Android-Projekt erstellendas wird als Grundlage für alle unsere zukünftigen Tutorials sowie einrichten unsere Emulator und Gerät dienen.

Android und Projekte

Wenn Sie zum Erstellen einer App für Android arbeiten, tun Sie dies durch die Arbeit inein Projekt". Das Projekt ist ein Verzeichnis des Quellcodes und andere fi enthält,

. like Bilder
und UI-Definitionen. Ihre IDE oder andere Build-Tools nehmen, was in Ihrem Projekt und erzeugen eine Android-App (APK) als Ausgabe.

Die Details, wie Sie mit Einstiegein Projekt, hängen davon ab, welche IDE Sie verwenden, so dass dieses Kapitel die verschiedenen Möglichkeiten geht.

Gemeinsame Konzepte

Die verschiedenen Möglichkeiten, wie wir Android-Projekte eingerichtet haben einige gemeinsame Elemente.

Die "Application Name" istder ursprüngliche Name des Projekts, wie vom Benutzer, an Orten wie dem Home-Bildschirm Launcher-Symbol und die Liste der installierten Anwendungen zu sehen.

Die "Projektname" istder Name des Projekts, da es innerhalb der IDE dargestellt wird. Wie Sie in einem Anwendungsnamen eingeben, werden der Projektname automatisch fi sein
im
passen der Name der Anwendung, mit Leerzeichen und andere ungültige Zeichen entfernt.

Natürlich können Sie diese ändern, wie Sie fi sehen

Im der Fall von Android Studio bildet
das Projektnamen auch den Namen des Verzeichnisses, das das Projekt halten wird.

Die "Paketname" bezieht sich aufein Java-Paketnamen (zB com.commonsware.empublite). Dieser Paketname wird zur Erzeugung einige Java-Quellcode verwendet werden, und es wird auch als eindeutige Kennung dieses Pakets verwendet wird, wie bereits erwähnt wurde,früherdieses Buch.

Die "Minimum RequiredSDK "bezieht sich auf, wie in Android-Version der Geschichte weit zurück Sie bereit sind, zu unterstützen. Je niedriger der Wert, den Sie hier angeben, desto mehr Android-Geräte die App laufen können, aber je mehr Arbeit, die Sie tun müssen, um zu testen, ob die App wirklich diese Geräte nicht unterstützt. Heute für die Entwicklung neuer, benötigt ein Minimum SDK von 15 sinnvoll ist, und Sie können später auf den gewünschten Wert zu ändern, wenn nötig.

the "Target SDK", grob gesprochen, ist die Version von Android Sie dachten, wenn Sie den Code für diese Anwendung geschrieben haben. Normalerweise werden Sie diese setzen die neueste Versand Android API-Ebene zu sein, ist es dann im Laufe der Zeit ändern, wenn neue Versionen von Android
veröffentlicht werden und Sie entscheiden, dass Sie für einige dieser Änderungen bereit sind. Wir werden die Erkundung der ramifi

Ziel SDK-Versionen im gesamtendas Buch.

Die "Compile Mit" (auch bekannt als "bauen SDK" odercompileSdkVersion) ist die Version von Android, deren Klassen und Methoden, die Sie gegen kompilieren wollen. Dies kann sein, neuer als die minimal erforderliche SDK, und es ist oft höher. Bei neueren Geräten neueren Versionen von Android läuft, möchten Sie vielleicht nutzen einige neue Funktionen zu übernehmen, und Sie werden

"Route um" diesen Code auf älteren Geräten Kompatibilität zu halten rückwärts. Daher, in der Regel ist, wird Ihr Build-SDK auf eine ziemlich neue Version von Android setzen, sicherlich eine neue genug alle Klassen und Methoden aus dem Android SDK zu unterstützen, die Sie verwenden möchten. Beachten Sie, dass dies auf API-Ebene zu setzen 21 oder höher, müssen Sie für Ihr Java-Compiler Java 7 oder höher werden.

Das "Thema" isteine allgemeine Aussage des Look and Feel Ihrer Anwendung, insbesondere in Bezug auf die Farbgebung. Der aktuelle Standard ( "Holo-Licht mit dunklen Action-Bar") bedeutet, dass der Körper Ihres UI dunkle Schrift auf hellem Hintergrund sein wird, mit Ausnahme des

"Aktionsleiste" über die Spitze, die hellen Text auf dunklem Hintergrund sein wird. Sie können Ihre eigenen Themen zu erstellen, überschreiben verschiedene Eigenschaften aus einem dieser Lager Themen, Ihr eigenes Farbschema einzurichten und dergleichen. Wir werden diesen Prozess erforschenspäter imdas Buch.

Projekte und Android Studio

Sie haben gewählt zu verwendenAndroid Studio als IDE.

Mit Android Studio, arbeiten aufein Projekt, können Sie entweder ein neues Projekt von Grund auf neu erstellen, können Sie eine vorhandene Android Studio-Projekt auf eine neue kopieren, oder Sie können eine bestehende Android-Projekt in Android Studio importieren. In den folgenden Abschnitten werden die erforderlichen Schritte für jede dieser überprüfen.

Erstellen Neues Projekt

Sie können erstellenein Projekt von einem von zwei Orten:

• Wenn Sie andie anfängliche Dialog, die Sie fi
die auftreten, wenn Sie Android

Studio geöffnet, wählen Siedie "ein neues Android-Studio-Projekt starten ..." Menüpunkt

• Wenn Sie innendas Android-Studio-IDE selbst, wählen Sie Datei> Projekt anlegen ... aus dem Hauptmenü

Dies bringtdas neue Projekt-Assistent:

Der fi

Seite vonDer Assistent ist, wo Sie angeben können:

• Die AnwendungName

• Das PaketName

• Das Verzeichnis, wo Sie wollendas Projekt fi
gehen

• Ob Sie nun wissen, ob Sie C ++ verwenden werden odernicht als Teil des Kit Android native Entwicklung (NDK)

In der Standardeinstellungder Paketname wird aus zwei Teilen bestehen:

1. Die DomainName, den Sie in der "Gesellschaft Domain" fi angeben

2. Die Anwendungnennen, umgewandelt in Kleinbuchstaben, ohne Leerzeichen oder
andere Interpunktions

Obdas ist nicht das, was Sie wollen, klicken Sie auf den kleinen Link "Bearbeiten" auf der rechten Seite des Paketnamen vorgeschlagen, die jetzt können Sie den Paketnamen direkt zu bearbeiten:

Ein Klick auf "Weiter" wird voran Sieeine Seite des Assistenten in dem Sie angeben, welche Art von Projekt, das Sie erstellen, in Bezug auf die beabsichtigte Gerätetyp (Telefone / Tabletten, Fernseher, etc.) und SDK-Ebene Mindestanforderungen erfüllt:

Entwickler gerade erst auf Android sollten nur "Phone und Tablet" überprüfen, wieder Gerätetyp. Der Standard "Minimum SDK" Wert auch in der Regel ist eine gute Wahl, und es kann leicht in Ihrem Projekt geändert werden, wie wir später im Buch sehen.

Ein Klick auf "Weiter" rückt Siedie dritte Seite des Assistenten, in dem Sie können wählen, ob Android Studio eine erste Aktivität für Sie erstellen sollten, und wenn ja, basierend auf welcher Vorlage:

Keiner vonDiese Vorlagen sind besonders gut, da sie eine Menge Beispiel Material hinzufügen, die Sie ersetzen eingereicht werden. "Empty Activity" ist die beste der verfügbaren Optionen für fi

-Zeit Android-Entwickler, einfach weil es fügt die geringste Menge dieser "cruft".

ichf wählen Sie eine andere Option als "Keine Aktivität hinzufügen", klicken Sie auf "Weiter"

werden Sie auf eine Seite des Assistenten vorrücken, wo Sie weitere Details zu den Aktivitäten zur Verfügung stellen können erstellt werden:

Welche Optionen erscheinen hier wirdvariieren Sie auf der vorherigen Seite auf der Vorlage gewählt haben. Gemeinsame Optionen gehören "Activity Name" (der Name der Java-Klasse für Ihre Aktivität) und "Layoutname" (der Basisname eines XML-fi
das wird ein UI-Definition Ihrer

Aktivität enthalten).

Die "Rückwärtskompatibilität (AppCompat)" Kontrollkästchen zeigt an, ob Sie verwenden möchteneine Bibliothek bekannt alsAppCompat. Wir werden diskutieren, Bibliothekenspäter imdas BuchSowie, wasDieses "AppCompat" ist. Es sei denn, Sie sicher wissen, dass Sie AppCompat verwenden möchten - und nur wenige von diesem Beispiel apps Buch tun - diese Checkbox deaktivieren.

Durch Klicken auf "Fertig stellen" wird Ihr Projekt fi generieren

.

Kopierenein Projekt

Android Studio-Projekte sind einfach Verzeichnisse von fi

, Ohne spezielle Metadaten an
anderer Stelle statt. Daher ein Projekt zu kopieren, kopieren Sie einfach sein Verzeichnis.

Einfuhrein Projekt

Sie können importierenein Projekt von einem von zwei Orten:

• Wenn Sie andie anfängliche Dialog, die Sie fi
die auftreten, wenn Sie Android

Studio geöffnet, wählen Siedas "Projekt importieren ..." Menüpunkt

• Wenn Sie innendas Android-Studio-IDE selbst, Datei> Neu ...> Projekt importieren ...

aus dem Hauptmenü wählen

Dann wählen Siedas Verzeichnis, das Projekt enthält, importiert werden.

Was hängt geschieht jetzt aufdie Art des Projekts. Falls das Projekt bereits für die Verwendung mit Android Studio eingerichtet wurde, oder zumindest mit Gradle für Android, das Android-Studio-spezifische fi
werden erstellt (oder aktualisiert) werden in das Projektverzeichnis.

Wenn jedochdas Projekt wurde nicht für Android Studio oder Gradle für Android eingerichtet, aber nicht Eclipse-Projekt fi (oder zumindest ein project.properties fi Sie durch eine Eclipse-Import-Assistenten geführt wird.

Der fi

Seite vondass Assistenten können Sie angeben, wo Android Studio eine Kopie
des Projekts machen sollte, so dass es nichts mit dem ursprünglichen Verzeichnis zu ändern: Durch Klicken auf "Next" wird bringeneine Seite, wo Sie einige automatische fi es konfigurieren können, dass der Import-Assistenten auf die importierte Projektcode gelten. Die Details von dem, was vor sich geht hier weit über, was wir bisher in dem Buch haben. Normalerweise sind die Standardwerte fi

Durch Klicken auf "Fertig stellen" wird durchführendie Projektkonvertierung. Android Studio wird eine Import-Summary.txt fi eröffnen

Skizzierung einige Details, wie Die

Umwandlung wurde durchgeführt. An diesem Punkt wird die kopierte-and-modifi

Projekt
ist einsatzbereit.

Starter Projekt Generatoren

Neben Projekten über eine IDE-neue-Projekt-Assistenten erstellen, gibt es verschiedene Web-Sitesdass Angebot Online-Projekt-Generatoren:

• Android Bootstrap

• Android Kickstartr

Aufdiese Websites bieten Sie grundlegende Konfigurationsdaten, wie zum Beispiel die Anwendung des Paketnamen, und sie erzeugen ein komplettes Starter-Projekt für Sie. Diese Projekte sind in der Regel wesentlich weiter fortgeschritten zu seinals das, was Sie von den IDE-Assistenten erhalten. Auf der positiven Seite, erhalten Sie eine aufwändigere "Gerüst", auf dem Sie Ihre eigene Business-Logik "hängen". Allerdings verstehen, was diese Generatoren erzeugen und wie Sie den generierten Code zu ändern, erfordert ein gutes Stück von Android-Entwicklung Erfahrung.

Tutorial # 2- Erstellen eines Stub-Projekt

CrEssen eine Android-Anwendung fi
involves ein Android "Projekt" zu schaffen. Wie bei
vielen anderen Entwicklungsumgebungen, ist das Projekt, in dem Sie Ihren Quellcode und sonstige Vermögenswerte (zB Icons) befinden. Und enthält das Projekt die Anweisungen für Ihre Werkzeuge, wie diesen Quellcode zu konvertieren und sonstige Vermögenswerte in einem Android-APK fi für die Verwendung mit einem Emulator oder Gerät, in dem die APK Android ausführbare fi-Format ist.

Daher wird inIn diesem Tutorial, treten wir die Entwicklung einer Probe Android-Anwendung ab, Ihnen die Möglichkeit zu geben, einige zu setzen, was Sie in diesem Buch in der Praxis lernen.

Über unser Tutorial-Projekt

Die Anwendungwir werden in diesen Tutorials bauen wird EmPubLite genannt. EmPubLite wird ein digitaler Buchleser sein, so dass Anwender ein digitales Buch wie das zu lesen, die Sie gerade lesen.

EmPubLite wird eine teilweise Umsetzung sein,das EmPubLeserbenutzt fürdie APK-Version dieses Buches. EmPub selbst ist eine recht umfangreiche Anwendung, so EmPubLite nur einen Teil seiner Funktionen haben wird.

the "Em" von EmPub und EmPubLite steht für "embedded". Diese Leser sind nicht zu lesen, eine beliebige EPUB oder MOBI formatiert Buch mit dem Sie von irgendwo herunterladen könnten.

Vielmehr wird der Inhalt des Buches (weitgehend eine entpackte EPUB fi
werden werden

"gebacken in" der Leser APK selbst, so dass durch die APK zu verteilen, verteilen Sie das Buch.

überDer Rest des Tutorials

Natürlich können Sie wenig Interesse am Schreiben habeneine digitale Book-Reader App.

Die Tutorials präsentiert indieses Buch sicherlich optional. Es gibt keine Erwartung, dass Sie einen Code, um zu schreiben, um Wert aus dem Buch zu bekommen. Diese Tutorials sind hier einfach als eine Möglichkeit, die von Ihnen zu helfen, die "learning by doing" haben die Möglichkeit, genau das zu tun.

Daher gibt es irgendwelcheAnzahl von Möglichkeiten, wie Sie diese Tutorials verwenden können:

• Sie können ignorierensie vollständig. Das ist nicht die beste Antwort, aber Sie sind herzlich eingeladen, es zu tun.

• Du kannst lesendie Tutorials, aber nicht tatsächlich eine der Arbeit zu tun. Dies ist die beste Low-Aufwand Antwort, wie es wahrscheinlich ist, dass man die Dinge aus den Übungen lernen, die Sie durch einfaches Lesen der nicht-Tutorial Kapitel verpasst haben könnte.

• Sie können folgen zusammendie Schritte und bauen tatsächlich die EmPubLite App.

• Yodu kannstherunterladendie AntwortenfroM die GitHub-Repository des Buches. Dort finden Sie fi
eins Verzeichnis pro Tutorial zeigt die Ergebnisse mit den Schritten in
diesem Tutorial getan. Zum Beispiel werden Sie fi
ein T2-Projekt / Verzeichnis
eine Kopie der EmPubLite Beispielanwendung nach in diesem Tutorial enthält gefunden

Schritte abgeschlossen haben. Sie können diese Projekte in die IDE importieren, prüfen, was sie enthalten, Querverweis sie zu den Tutorials selbst zurück, und sie laufen.

Irgendein vondiese sind gültige Optionen - Sie für sich selbst entscheiden müssen, was Sie tun wollen.

Über unsere Werkzeuge

Die Anweisungen indie restlichen Übungen sollten für Android Studio genau sein

2.1.x.

Die Anweisungen können Arbeit für andere Versionen vonDiese IDE, aber es kann auch einige Unterschiede.

Schritt 1: ErstellenProjekt

Wirmüssen das Android-Projekt für EmPubLite zu erstellen.

Von Willkommen-Dialog die Android Studio, klicken Sie auf "Starten Sie ein neues Android-Studio-Projekt", die das neue Projekt-Assistent bringen, wie beschrieben indas vorigen Kapitel.

Imdieses fi

Zauberer Seite, fi im:

• EmPubLitefürdie "Application Name"

• com.commonswarefürdas "Unternehmen Domain"

• com.commonsware.empublitefürdie "Paketname"

Auch lassenDie C ++ Unterstützung Checkbox deaktiviert, und wählen Sie eine sichere Stelle auf Ihrer Entwicklungsmaschine in das Projekt zu speichern. Klicken Sie dann auf "Weiter", um zur nächsten Seite des Assistenten zu gelangen.

On der zweiten Seite des Assistenten klicken Sie auf "Telefon und Tablet", und wählen Sie "API 15" im "Minimum SDK" drop-down:

Klicken Sie dann auf "Weiter", um VorausAuf der nächsten Seite des

Assistenten. Dort klicken Sie auf "Empty Activity", und klicken Sie dann auf "Weiter".

Aufdass letzte Seite des Assistenten, ändern Sie die "Aktivitätsname" zu EmPubLiteActivity, die

"Layoutname" zur Haupt ändern, und deaktivieren Sie "Rückwärtskompatibilität (AppCompat)":

Klicken Sie abschließend auf "Fertig stellen" Android Studio erstellen, um Ihreneues Projekt für Sie.

Android Studio hat zwei Möglichkeiten der Betrachtungder Inhalt von Android-Projekten. Der Standard ein, die Sie sind mit, wenn Sie das Projekt erstellen, wird als "Android Ansicht" bekannt: Während Sie willkommen zu navigieren Ihrem Projekt sind es,die Tutorial Kapitel in diesem Buch, wo sie Screenshots von Android Studio haben, werden die Projektansicht zeigen:

Zum Umschalten aufdiese Ansicht - und damit übereinstimmen, was die Tutorials zeigen Ihnen -
auf der rechten Seite der "Android" und "Projektdateien" Laschen an den Pfeilspitzen klicken und wählen Sie "Projekt".

Schritt # 2: Get Readyfür die x86-Emulator

Ihre fi

Entscheidung zu machen ist, ob nicht, dass Sie jetzt einen Emulator Bild Einrichtung zu stören. Wenn Sie ein Android-Gerät haben, können Sie es vorziehen, auf das Testen der App zu starten, und kommen zurück, um den Emulator zu einem späteren Zeitpunkt einrichten. In diesem Fall fahren Sie mitSchritt # 4.

Ansonsten ist hier, was können Sietun müssen, um, basierend auf dem Betriebssystem auf Ihrer Entwicklungsmaschine.

Windows-

Wenn Ihre CPU erfülltdie Anforderungen, und Sie aktiviert erfolgreich die richtigen Dinge im BIOS

Ihres Systems sollte die Android Studio-Installation HAXM installiert haben, und Sie sollten zu gehen bereit sein.

Wenn aufAuf der anderen Seite, können Sie einige Fehlermeldungen im Installationsassistenten in Bezug auf HAXM bekam, müssten Sie diejenigen fi zu adressieren

Mac

Die Zauberer von Cupertino einrichtenihre Mac-Hardware die Android-x86-Emulator laufen, die furchtbar nett von ihnen ist in der Lage sein, wenn man bedenkt, dass Android mit iOS
konkurriert. Die Android-Studio-Installationsassistent HAXM sollte erfolgreich installiert, und Sie sollten mit dem nächsten Schritt des Tutorials fortsetzen können.

Linux

Die Android-x86-Emulator auf Linux tutverwenden HAXM nicht. Stattdessen verwendet es KVM, eine gemeinsame Linux-Virtualisierungs-Engine.

Wenn währenddas Android-Studio Installation zeigte der Assistent eine Seite, die sagt, dass man KVM konfigurieren benötigt, müssen Sie genau das zu tun, bevor Sie den x86-Emulator einrichten und nutzen. Die Details, wie KVM einrichten wird von Linux-Distribution variieren (zBUbuntu).

Schritt 3: Einrichtendie AVD

Der Android-Emulator kann eine oder mehrere Android-Geräte emulieren. Jeder configuration Sie wollen in einer "Android virtuelles Gerät" gespeichert oder AVD. Der AVD Manager ist, wo Sie diese AVDS erstellen.

Hinweisdass Android Studio hat jetzt eine eigene Implementierung des AVD-Manager, der von der einen Android-Entwickler traditionell getrennt verwendet haben. Sie können Screenshots der älteren AVD-Manager in Blog-Posts, Stack-Überlauf Antworten und dergleichen zu sehen. Der AVDManager noch fi
die gleiche Rolle, aber es hat einen anderen Look and Feel.

Öffnender AVD-Manager in Android Studio, Tools> Android> AVD-Manager aus dem Hauptmenü wählen.

Sie sollten ergriffen werden, um -Typs Bildschirm "Willkommen":

Klicken"Create Virtual Device" -Taste, die eine "Virtual Device Configuration" Assistent bringt:

Der fi

Seite vonDer Assistent ermöglicht es Ihnen, ein Gerät Profi zu wählen
zu
verwenden, wie Ausgangspunkt für Ihre AVD. Die "Neue Hardware-Profil" Taste können Sie neue Profile zu definieren, wenn es keine vorhandenen profi ist
dass Ihren Bedürfnissen
entspricht.

Da Emulator Geschwindigkeitengebunden etwas auf die Auflösung ihrer (virtuellen) Bildschirme wollen Sie in der Regel für ein Gerät Profi
das ist am unteren Ende aber ist nicht völlig
lächerlich. Zum Beispiel würde ein 800x480 oder 1280x768 Telefon von vielen Menschen betrachtet werden ziemlich niedriger Auflösung zu sein. Allerdings gibt es viele Geräte gibt, mit dieser Auflösung (oder niedriger), und es macht für einen angemessenen Start Emulator.

Wenn Sie möchten, erstellenein neues Gerät Profi auf der Grundlage einer vorhandenen - einige Parameter zu ändern, aber sonst verwenden, was die ursprüngliche Profi hatte - klicken Sie auf die

"Clone Device" -Taste, sobald Sie Ihr Starter-Profil ausgewählt haben.

Jedoch im allgemeinen beiBeginn an eine bestehende Profi mit
ist perfekt fi Ein

Klick auf "Weiter" können Sie einen Emulator Bild zu wählen, zu verwenden:

Die Emulator Bilder sind verteilt auf dreiRegisterkarten:

• "Empfehlenswert"

• "X86 Images"

• "Weitere Bilder"

FürIm Sinne der Tutorials, die Sie nicht einen Emulator Bild mit den "Google-APIs" müssen - das sind für Emulatoren, die Google in ihnen und verwandte Anwendungen wie Google Maps Play-Dienste haben. Allerdings Ebene in Bezug auf die API, können Sie alles von API-Level 15

(Android 4.0.3) auf bis zu wählen. Sie sollten ein oder mehrere geeignete Bilder haben bereits für Sie eingerichtet, mit freundlicher Genehmigung von Android Studio installiert zu haben.

Der Emulator Bilder mit "Download"neben ihnen löst eine einmalige Download der fi notwendig AVDS für diese bestimmte API-Ebene und CPU-Architektur Kombination, nach einer weiteren Lizenz-Dialog und progess Dialog zu erstellen:

Sobald Sie heruntergeladendas Bild (n), die Sie wollen, klicken Sie auf einen von ihnen im Assistenten:

Durch Klicken auf "Weiter" können Sie fi
e die Konfiguration Ihres AVD:

Ein Standardname für die AVD wird vorgeschlagen, obwohl Sie willkommen sind, diese mit Ihrem eigenen Wert zu ersetzen.

Veränderungder AVD-Name, falls notwendig, um etwas gilt: nur Buchstaben, Zahlen, Leerzeichen und wählen Sie Interpunktion (zB, _, -, (,).) werden unterstützt.

Der Rest vondie Standardwerte sollten fi sein
für jetzt.

Durch Klicken auf "Fertig stellen" kehren Sie zumdie Haupt AVD Manager Ihre neue AVD zeigt. Sie können dann die AVD-Manager-Fenster zu schließen.

Schritt 4: Einrichtendas Gerät

Sie machennicht ein Android-Gerät müssen in Android-Anwendung Entwicklung zu beginnen. eine ist eine gute Idee, bevor Sie versuchen, eine Anwendung zu versenden (zB an die Play Store laden).

Und vielleicht haben Sie bereits ein Gerät - vielleicht ist das, was Ihr Interesse für Android in der Entwicklung beflügelt.

Wenn Sie tunnicht haben ein Android-Gerät, das Sie für die Entwicklung einrichten wollen, diesen Schritt überspringen.

Der fi

Schritt Ihr Gerät bereit für den Einsatz mit der Entwicklung zu machen, ist zu gehen in die Anwendung Einstellungen auf dem Gerät. Was hängt passiert jetzt ein bisschen auf Ihrem Android-Version:

• Auf Android 1.x / 2.x, gehen Sie in Anwendungen,dann in die Entwicklungs

• Auf Android 3.0 bis 4.1, gehen Sie in "Entwickleroptionen" ausdie wichtigsten Einstellungen Bildschirm

• Auf Android 4.2 und höher, gehen Sie in über,tippen Sie auf die Build-Nummer sieben Mal, und drücken Sie dann zurück und gehen in die "Entwickleroptionen" (was früher verborgen war)

Du darfstbenötigen einen Schalter in der oberen rechten Ecke des Bildschirms auf die "ON" Position zu schieben Sie die Werte auf diesem Bildschirm zu ändern.

Im Allgemeinen werden Sie nach unten scrollen undAktivieren USB-Debugging, so dass Sie Ihr Gerät mit dem Android-Build-Tools verwenden können:

Du kannst gehendie anderen Einstellungen allein für jetzt, wenn Sie wollen, wenn Sie fi nden können
das"Bleib wach" Option handlich zu sein, wie es Sie davon ab, speichert Ihr Telefon entsperren alledie Zeit, während es in den USB angeschlossen.

Hinweisdass auf Android 4.2.2 und höher Geräte, bevor Sie tatsächlich die Einstellung, die Sie gerade umschalten können, werden Sie aufgefordert USB-Debugging mit Ihrem spezifischen Entwicklungsmaschine über ein Dialogfeld zu ermöglichen:

Dies geschieht, wenn Sie steckendas Gerät über das USB-Kabel und haben die Fahrer entsprechend eingerichtet. Dieser Prozess ändert sich durch das Betriebssystem Ihrer Entwicklungsmaschine, wie in den folgenden Abschnitten behandelt wird.

Windows-

Wenn Sie fi

Stecker in Ihrem Android-Gerät, versucht Windows zu fi nden
einen

Treiber dafür. Es ist möglich, dass aufgrund anderer Software, die Sie installiert haben, dass der Treiber für den Einsatz bereit ist. Wenn es fi
ein Fahrer, sind Sie wahrscheinlich bereit zu
gehen.

Obder Fahrer nicht, hier sind einige Möglichkeiten, um einen gefunden.

Windows Update

Einige Versionen von Windows (zB Vista) fordert Sie Windows Update nach Treibern zu suchen.

Dies ist sicherlich wertein Schuss, wenn auch nicht jedes Gerät wird seine Fahrer zu Microsoft geliefert.

Standard-Android-Treiber

In Ihrem Android-SDK-Installation, wenn Sie gewählt haben zu installierendie "Google USB

Driver" Paket aus dem SDK-Manager, werden Sie fi
ein Extras / google / usb_driver /

Verzeichnis enthältein normaler Windows-Treiber für Android-Geräte. Sie können versuchen, den Treiber-Assistenten in diesem Verzeichnis verweist, um zu sehen, ob es diese Fahrer denkt, für das Gerät geeignet ist. Dies wird oft für Nexus-Geräte arbeiten.

Hersteller bereitgestellte Treiber

Wenn Sie noch tunkeinen Treiber haben, dieTreiber OEM USBimdie Entwickler-Dokumentation hilft Ihnen fi kann
einszum Download von Ihrem Gerätehersteller. Hinweisdass Sie die

Modellnummer für Ihr Gerät, anstatt den Modellnamen für Marketing-Zwecke (zB GT-P3113
anstelle von "Samsung Galaxy Tab 2 7.0") verwendet werden, können müssen.

OSX und Linux

Ungerades sind in Ordnung, die einfach in Ihrem Gerät eingesteckt wird "einfach funktionieren". Sie können sehen, ob Android Ihr Gerät über Lauf adb Geräte in einer Shell erkennt (zB OS X-Terminal), wo adb in Ihrer Plattform-Tools / Verzeichnis Ihres SDK ist. Wenn Sie eine Ausgabe ähnlich der folgenden erhalten, erfasst die Build-Tools Ihr Gerät:

Wenn Sie mit Ubuntu (oder vielleicht auch andere Linux-Varianten),und dieser Befehl nicht funktioniert, müssen Sie möglicherweise einige udev-Regeln hinzuzufügen. Zum Beispiel, hier ist ein

51- android.rules fi
das wird die Geräte von einer Handvoll Hersteller Griff:

Fallendass in Ihrem/etc/udev/rules.dVerzeichnis auf Ubuntu,dann entweder den Computer neu starten oder auf andere Weise die neu zu ladenudevRegeln (zBsudo Service udev reload).

Dann ziehen und wieder einsteckensiehe das Gerät und wenn es erkannt wird.

Das CyanogenMod-Projekt betreuteine Seite auf ihrer Wikimit mehr aufdiese udev

Regeln, einschließlich der Regeln auseine Vielzahl von Herstellern und Geräten.

Schritt # 4: LaufenProjekt

Jetzt können wir Konfi
dass unser Projekt richtig läuft, indem es auf einem Gerät oder

Emulator einrichten.

Tundass in Android Studio, drücken Sie einfach die Run Symbolleiste auf die Schaltfläche (in der Regel als grüner nach rechts zeigendes Dreieck dargestellt).

Du wirstdann ein Dialogfenster angezeigt werden, die angibt, wo Sie die App ausgeführt werden soll: auf einige bestehende Gerät oder Emulator oder auf einige neu eingeführte Emulator: Wenn Sie tunhaben nicht einen Emulator läuft, wählen Sie eine aus der Liste aus, und klicken Sie auf OK. Android Studio wird Ihren Emulator für Sie starten.

Und, ob Sie beginnenein neuer Emulator-Instanz oder Wiederverwendung eines bestehenden, Ihre App sollte es erscheinen:

Hinweisdass müssen Sie möglicherweise Ihr Gerät oder Emulator entsperren, um tatsächlich die App laufen zu sehen. Es wird nicht automatisch für Sie, mit Ausnahme der sehr fi entsperren

Zeit, dass Sie den Emulator laufen.

In unserer nächsten Folge ...

… wir werdenändern die AndroidManifest.xmlfi unserer Tutorial-Projekt.

Unterwegs in Android Studio

Eclipse-hat sich füreine sehr lange Zeit und ist ein sehr beliebtes IDE erwiesen. Als Ergebnis ist es ziemlich viel Material darüber geschrieben, von Bücher und Blogs Überlauf Fragen und offi zu Stack

Projektdokumentation.

Android Studio Aktieneine Vielzahl von Funktionen, mit seinen Eltern, IDEA IntelliJ. Allerdings IDEA selbst wurde nicht von Eclipse Niveau der Popularität erreicht, auch wenn es lange die IDE
der Wahl für viele "Power-Entwickler" gewesen ist. Und Änderungen Android Studio zu IDEA weitgehend undokumentiert.

Daher,In diesem Kapitel wird als eine schnelle Tour durch die Android Studio IDE, dienen Sie in. Andere Android-spezifi-Funktionen von Android Studio in den Kapiteln erkundet werden Eingewöhnung zu helfen, die folgen.

Navigation im Projekt-Explorer

Nachder Hauptbereich Bearbeitung - wo Sie Ihre Java-Quellcode ändern wird, Ihre Ressourcen und so weiter - das Stück Android Studio Sie die meiste Zeit mit verbringen ist die Projekt-Explorer, in der Regel auf der linken Seite des IDE-Fensters zur Verfügung:

Diese Explorer-Fenster hat zwei Haupt "Projektansichten"das Android-Projektansicht und die klassische Projektansicht: dass ein Android-Entwickler verwenden.

Android-Projekt-Ansicht

In der Standardeinstellung, wenn Sie erstellen oder importierenein Projekt, werden Sie in der Android-Projektansicht eingereicht.

In der Theorie,das Android-Projektansicht ist so konzipiert, mit Android-Projekt fi zur Vereinfachung der Arbeit

. In der Praxis kann es tun, aber nur für einige fortgeschrittene

Entwickler. Im Großen und Ganzen ist es die IDE wesentlich komplizierter für Einsteiger in Android, da es ziemlich schwierig ist, zu sehen, wo die Dinge sind und was bezieht sich auf das, was.

Wir werden aufdas Android-Projekt ein wenig später in dem Buch sehen und seine Vorteile in Bezug erklärenRessourcenundGradle des sourcesets.

Jedoch ist für die meistendas Buch - was am wichtigsten ist, für die Tutorials - werden wir das klassische Projektansicht verwenden.

Klassische Projektansicht

Zum Umschalten aufdas klassische Projektansicht, klicken Sie auf das Paar von Pfeilen auf der rechten Seite des "Projektdateien" Tab direkt über dem Baum im Explorer, und wählen Sie Projekt:

Dies wird sich ändernder Inhalt des Baumes Sie alle der fi zeigen

, In ihren
zugehörigen Verzeichnissen:

Dieses Projekt Ansicht ist ähnlich wie sein Äquivalent in anderen IDEs, so dass Sie fi alle von
die Stücke von Ihrem Android-Projekt. Wir erforschen, was diese Stücke sind, und wie sie ihre fi
sind in unseren Projekten organisiert, in das nächste Kapitel.

KontextMenüs im Explorer

Ein Rechtsklick aufein Verzeichnis oder fi
im der Forscher werden Sie mit einer Vielzahl von

Optionen, um ein Kontextmenü geben. Einige davon werden typisch für jede Art von fi sein Manager, such als "Schnitt", "Kopieren" und / oder "Paste" Optionen. Einige von ihnen organisiert werden nach wie IntelliJ IDEA verwaltet Anwendungsentwicklung, wie die "Umgestalten"

Untermenü, in dem Sie umbenennen oder fi bewegen
um. Und doch werden andere spezifi

sein Android Studio, wie die Fähigkeit, Assistenten aufrufen bestimmte Arten von Android-Komponenten oder andere Java-Klassen zu erstellen.

Öffnen von Dateienaus dem Explorer

Ein Doppelklick aufeine fi
gewöhnlich öffnet dass fi
im ein Register, das Sie
bearbeiten, die fi mit irgendeiner Art von Editor ermöglicht.

Einige fi

Typen, wie Bilder, geöffnet werden kann, aber nicht bearbeitet, als Android Studio für alle fi nicht Redakteuren

Typen.

Laufende Projekte

Natürlich, wie Sie Ihre Anwendung zu ändern, werden Sie wollen, es zu versuchen und sehen, ob es funktioniert, ob aufein Gerät oder ein Emulator.

Die Grundlagen

Wie bereits inLernprogramm# 2, Um das Projekt auszuführen, drücken Sie einfach die Run Symbolleiste auf die Schaltfläche:

Du wirstdann ein Dialogfenster angezeigt werden, die angibt, wo Sie die App ausgeführt werden soll: Die "Connected Devices" Kategorie listet alle Geräte oder Emulatoren laufendass die Build-Tools können fi

Einige können deaktiviert werden aufgrund von Kompatibilitätsproblemen, wie
zum Beispiel einen Emulator für eine alte Version von Android mit denen Ihre Anwendung erfordert eine neuere Version von Android.

Die "Available Emulators" Kategorie listet alle AVDSdass Sie in der AVD-Manager definiert, die nicht bereits ausgeführt werden. Auch hier können Sie fi nden, dass einige aus Kompatibilitätsgründen deaktiviert sind.

Die "Create New Emulator" Button öffnetder Assistent eine neue AVD, genau wie die, zu erstellen Sie aus dem AVD-Manager starten.

"Instant Run"

Sobald Sie laufendas Projekt auf dem Emulator, wenn Sie Änderungen vornehmen, standardmäßig werden Sie in "Instant Run" Modus. Anstatt die ganze App neu zu erstellen, wird Android versuchen, die bestehende Anwendung auf dem Gerät oder Emulator zu flicken, um die Änderungen zu reflektieren.

Die Lauf Kontrollen indie Android-Studio-Symbolleiste wird an diesem Punkt zu ändern: Speziell:

• Der grüne Punkt indie "App" drop-down zeigt, dass dies läuft

• Das Blitzneben dem Run-Button zeigt an, dass Instant-Run-Modus aktiviert ist, und wird verwendet, wenn Sie versuchen, die App wieder zu laufen

• Die "Rerun App" -Taste (grauer Kasten mit grünemgeschwungenen Pfeil) werden sich fragen aktiviert ist, die App wieder von Anfang an zu laufen

• Die rote "Stopp" -Taste wirdaktiviert, so dass Sie die laufende App vollständig durch die Beendigung der Prozess zu stoppen

Instant-Run Anwendungeneine Vielzahl von Tricks seine Leistungen der Magie zu ziehen aus. Als Ergebnis kann es Fehler haben, die gepatchte App verursacht laufen anders als würde eine völlig neue zu bauen. Sie können bei der Suche nach "Instant Run" in das Such fi Instant-Run vollständig über Einstellungen deaktivieren

Anzeigen der Ausgabe

Jenseits der App selbst, wird Android Studio andere Arten von Diagnoseausgang erzeugen, indie Form der "Konsole" -Stil Transkripte von Dingen, die aufgetreten sind. Die zwei von ihnen, die wahrscheinlich am meisten für Sie wichtig sind die Gradle Konsole und LogCat.

Gradle Console

Standardmäßig ankern indie untere rechte Ecke des Android Studio-Fenster ist ein "Gradle Console"

aus. auf das Tippen auf eine Scheibe, welche die Ausgabe von Versuchen, Ihre Anwendung zu erstellen, öffnen:

Dies kann automatisch erscheinen ausZeit zu Zeit, wenn spezifi Build-Probleme erkannt werden, und Sie können immer es gehen untersuchen, wann immer Sie brauchen.

Klicke aufdie "Gradle Console" Artikel wieder die Ansicht zu kollabieren und es aus dem Weg zu bekommen.

LogCat

Nachrichtendie zur Laufzeit erscheinen - einschließlich der alle wichtigen Java Stack-Traces durch Fehler in Ihrem Code ausgelöst - sind sichtbar in LogCat. Der "Android Monitor" Artikel in Richtung der unteren linken Ecke Ihres Android Studio-Fensters verankert wird LogCat angezeigt wird, wenn angezapft:

LogCat wird detaillierter erklärtein bisschen später in diesem Buch.

Der Zugriff auf Android Tools

Nicht alles, was auf Android bezogen ist direkt Teil des Android Studio selbst. In einigen Fällen, Werkzeugemüssen zwischen den Nutzern von Android Studio, Nutzer von Eclipse und Nutzer von

"keine der oben genannten" geteilt werden. In einigen Fällen, während die langfristige Richtung der Werkzeug Funktionalität direkt in Android Studio, dass die Arbeit einfach sein kann, hat sich zu übernehmen bisher nicht abgeschlossen ist.

Hier sind einige bemerkenswerte Android-bezogene Werkzeugedass Sie über die Tools> Android-Hauptmenü-Option zu gelangen.

SDK und AVDManager

Wie wir gesehen haben inLernprogramm# 1, Das SDK Manager Tool Android für Teile des Android SDK herunterzuladen, einschließlich:

• "SDK-Plattform" Ausgaben, so dass wir gegen kompiliereneine bestimmte API-Ebene

• ARM und (manchmal) x86-Emulator Bilder

• Dokumentation

• Aktualisierungendie Kern Build-Tools

• Etc.

Sie können startendas SDK Manager über Tools> Android> SDK-Manager aus dem Android Studio Hauptmenü oder durch Symbolleiste auf die Schaltfläche auf der "in einer Box Droiden"

klicken:

Der AVD Manager istdas Werkzeug für Emulatoren, die emulieren bestimmte Android-

Umgebungen, basierend auf API-Ebene, Bildschirmgröße und andere Eigenschaften zu schaffen.

Sie können startender AVD Manager über Tools> Android> AVD Manager aus dem Android Studio Hauptmenü oder durch die "Droiden und einen Bildschirm" Symbolleiste auf die Schaltfläche klicken:

Android-GerätMonitor
an anderer Stelle indieses Buch finden Sie Verweise auf Tools im Zusammenhang mit der Dalvik Debug Monitor Server (DDMS), wie die Verwendung von es sehen inspizieren apps Ihre Lauf für Speicher oder Threadingprobleme zu helfen. Sie werden auch Verweise auf Tools wie Hierarchieansicht zu sehen, für den Versuch, Sinn für die Benutzeroberfläche zu machen, wie es zur Laufzeit angezeigt wird, nachdem Sie programmatisch viele Änderungen daran vorgenommen haben.

ichn Eclipse DDMS und Hierarchieansicht sind "Perspektiven", über das ADT-Plugin für Eclipse hinzugefügt.

Für jedennicht mit Eclipse - einschließlich der Nutzer Android Studio - DDMS und Hierarchieansicht über den Android Device Monitor Standalone-Tool zur Verfügung stehen.

Android Studio Benutzer können den Monitor über Tools> Android> Android Device Monitor aus dem Hauptmenü starten.

Dies fi
bringen oben ein Splash-Screen:

gefolgt vonder Monitor selbst:

Wenn Sie lesen überDinge online von DDMS oder Hierarchieansicht, wie in Blog-Posts oder Antworten Stack-Überlauf, die meisten dieser Funktionen sollten über den Android Device Monitor zur Verfügung stehen.

Android Studio und Update-Versionen

Wenn Sie Android Studio installieren fürdie fi

Zeit, wird Ihre Installation Updates zu erhalten
eingerichtet werden auf dem "stabil" Release-Kanal. Hier wird ein "Release-Kanal" ist ein spezifi Satz möglicher Upgrades. Die "stabil" Release-Kanal bedeutet, dass Sie die volle produktionsfertige Updates bekommen. Android Studio wird nach Updates suchen, wenn gestartet, und Sie können für Updates über das Hauptmenü manuell überprüfen (zB Hilfe> Nach Updates suchen ... unter Windows und Linux).

Wenn ein Update verfügbar ist, wird Ihnen präsentiert mitein Dialogfeld Sie Details der Aktualisierung zeigt:

"Release Notes" sind dabei die entscheidenden bringeneine Webseite mit Release Notes für das neue Release. Durch Klicken auf "Update und Neustart" macht ziemlich genau, wie die Schaltfläche Name schon sagt: es lädt das Update und startet die IDE, auf dem Weg das Update installieren.

Ein Klickdie "Updates" Hyperlink im Dialog bringt noch einen weiteren Dialog auf, so dass Sie die Release-Version Sie abonnieren möchten, wählen:

Sie haben vier Kanäle zur Auswahl:

• Stabile, die für die meisten Entwickler geeignet ist

• Beta, welche Updates erhaltenDas sind knapp vor stabil

• Dev, die vor uns noch mehr istals die Beta-Kanal

• Kanarische, die sehr früh aktualisiert (undder Name, was auf eine "Kanarienvogel in einer Kohlengrube", zeigt an, dass Sie hier zu helfen Debuggen der IDE)

Besuchdie Spuren!

Android Studio Projektstruktur Dialog und Übersetzungen Editor abgedecktspäter im dieses Buch.

Inhalt von Android-Projekte

Das Android-Build-System ist organisiert umein spezifi Verzeichnisstruktur für Ihr Android-Projekt, ähnlich wie jedes andere Java-Projekt. Die Besonderheiten, sind aber ziemlich einzigartig für Android - die Android-Build-Tools ein paar zusätzliche Dinge tun, um die tatsächliche Anwendung vorzubereiten, die auf dem Gerät oder Emulator ausgeführt wird.

HerstellungDinge komplizierter ist, dass die Standardstruktur für die aktuellen Tools unterscheidet (zB Android Studio) und die Legacy-Tools (zB mit dem ADT-Plugin Eclipse).

Hier isteine schnelle Grundierung auf der Projektstruktur, Sie Sinn des Ganzen, vor allem für den Beispielcode in diesem Buch verwiesen zu helfen.

Was Sie erhalten in der Regel

Die Einzelheiten genau das, was fi sind in Ihrem Projekt hängen von Ihrer Wahl der IDE. Doch unabhängig davon, ob Sie gehen mit Android Studio oder etwasda sonst sind viele Elemente gemeinsam.

DasManifest

AndroidManifest.xml ist ein XML-fi
beschreiben wobei die Anwendung aufgebaut und
welche Komponenten - Aktivitäten, Dienstleistungen usw. - werden von dieser Anwendung zugeführt wird. Sie können daran denken, wie die "Inhaltsverzeichnis" zu sein, was Ihre Anwendung ist etwa, wie viel ein Buch ein "Inhaltsverzeichnis" hat die verschiedenen Teile, Kapitel Auflistung und Anhänge, die im Buch erscheinen.

Wir werden prüfen,das Manifest ein bisschen mehr Ausgangs eng indas nächste Kapitel.

die Java

Wenn Sie erstelltdas Projekt lieferte Sie den vollständig qualifizierten Klassennamen der "main"

Aktivität für die Anwendung (zB com.commonsware.android.SomeDemo). Sie werden dann fi
dass Ihr Projektbaum Java-Quellcode hat bereits den Verzeichnisbaum des Pakets an Ort und Stelle sowie eine Stub Aktivität Unterklasse Ihre Haupttätigkeit darstellt (zB src / com /
commonsware / android / SomeDemoActivity.java). Sie sind herzlich eingeladen, diese fi ändern
und hinzufügen Java-Klassen als benötigt, um Ihre Anwendung zu
implementieren, und wir werden, dass unzählige Male zeigen, wie wir durch dieses Buch Fortschritte.

Anderswo- In Verzeichnisse, die Sie normalerweise mit nicht funktionieren - die Android Build-Tools werden auch für Sie jedes Mal, wenn Sie Ihre Anwendung bauen Code-Generierung einige Quellcode sein. Einer der Code-generierten Java-Klassen (R.java) wird zur Steuerung unserer User Interfaces aus der eigenen Java-Code wichtig sein, und wir werden viele Verweise auf diese RKlasse, wie wir die Erstellung von Anwendungen im Ernst beginnen.

Die Ressourcen

Sie werden auch fi
dass Ihr Projekt hat eine res / Verzeichnisbaum. Dies gilt "Ressourcen"

—
statisch fi

Das sind zusammen mit der Anwendung verpackt, entweder in ihrer
ursprünglichen Form oder gelegentlich in einer vorverarbeiteten Form. Einige der Unterverzeichnisse Sie fi nden
oder erstellen Sie unter res / umfassen:

1. res / ziehbar /für Bilder (PNG, JPEG, etc.)

2. res / Layout /für XML-basierte UI-Layout-Vorgaben

3. res / Menü /für XML-basierte Menü Spezifikationen

4. res / raw / für allgemeine Zwecke fi

(Beispielsweise ein Audio-Clip,eine CSV-
fi
von Kontoinformationen)

5. res / Werte /für Streicher, Dimensionen undähnliches

6. res / xml / für andere allgemeine Zwecke XML fi

Sie möchten zu versenden

Einigedie Verzeichnisnamen können Suffixe, wie res / ziehbar-hdpi /. Dies zeigt an, dass das Verzeichnis von Ressourcen nur unter bestimmten Umständen verwendet werden soll - in diesem Fall sind die ziehbaren Mittel nur auf Geräten mit hoher Dichte Bildschirme verwendet werden sollen.

Wir decken allediese und weitere, später in diesem Buch.

Die Build-Anleitung

Die IDEmuss wissen, wie all dieses Zeug zu nehmen und mit einem Android-APK fi
kommen

Etwas von dies ist bereits "bekannt" zu der IDE basiert auf, wie die IDE
geschrieben wurde. Aber einige Details sind Dinge, die Sie benötigen, können von Zeit zu Zeit zu konfigurieren, und so werden diese Details in fi gespeichert
dass Sie, auf die eine oder
andere, von Ihrer IDE bearbeiten.

In Android Studio, die meistenDieses Wissen wird in einer oder mehreren fi gehalten genannt build.gradle. Diese sind für eine Build-Engine bekannt alsGradle.dass Android Studio verwendet APKs und andere Android-Ausgänge zu bauen.

Im Legacy-Eclipse-Projekte im StilDieses Wissen wird unter mehreren fi verstreut

, Von
denen einige Sie können manuell (zB project.properties) bearbeiten und von denen einige würden Sie nur durch Eclipse-selbst (zB .classpath) ändern.

Der Inhalt eines Android Studio-Projekt

Allediese Elemente in einem bestimmten Verzeichnisstruktur in einem Android-Studio-Projekt ...

zumindest standardmäßig gespeichert. Android Studio und Gradle sind leistungsfähig und kann so konfiguriert werden, um andere Strukturen zu handhaben. So zum Beispiel, werden Sie fi etwas Projekte mit das Erbe von Eclipse-Stil Struktur, die anders ist als das, was Android Studio normalerweise verwendet.

Davon abgesehen, die meisten Projektedass Sie begegnen - fast alle der Beispielanwendungen in diesem Buch - werden mit dem Android Studio Standard-Struktur bleiben.

Das Stammverzeichnis

Imdas Stammverzeichnis Ihres Projekts, der wichtigste Punkt ist die app / Verzeichnis, in dem Anwendungscode befindet. Wir werden das betrachtenimder nächste Abschnitt.

Darüber hinausdie app / Verzeichnis, das andere bemerkenswerte fi
im die Wurzel des

Projekts sind:

• build.gradle, die einen Teil der Build-Anweisungen für Ihr Projekt ist, wie oben beschrieben,

• Verschiedene andere Gradle bezogenen fi

(settings.gradle.gradle.properties, und
so weiter)

• local.properties, Die angibt, wo Ihr Android-SDK-Tools befinden

• Ein.iml fi
wo Android Studio hält einige zusätzliche Metadaten über Ihr Projekt

Schließlich haben Sie:

• Ein Build / Verzeichnis, die kompilierte Ausgabe Ihrer Anwendung enthält, sowie verschiedene Berichte und andere fi
verbunden nach der Build-Prozess und App-

Tests

• Ein .gradle / Verzeichnis enthält Gradle ausführbaren Code

• Ein.idea / Verzeichnis - dies, zusammen mit dem .iml fi
darstellen Daten benötigt
von IntelliJ IDEA, auf denen Android Studio basiert

Die App-Verzeichnis

Dasapp / Verzeichnis und dessen Inhalt sind, wo Sie die meiste Zeit als Entwickler verbringen.

Selten müssen Sie die fi zu manipulieren
im die Projektwurzel.

Das wichtigstewas in der app / Verzeichnis ist das src / Verzeichnis, das die Wurzel Ihres Projekts sourcesets ist, die in beschrieben wirdder nächste Abschnitt.

Darüber hinausdas src / Verzeichnis, gibt es ein paar andere Gegenstände der Anmerkung in app /:

• Ein Build / Verzeichnis, das die Ausgaben der Aufbau Ihrer App halten,
einschließlich Ihrer APK fi

• Ein build.gradle fi
wo die meisten Ihrer projektspezifischen Gradle

Konfiguration gehen, Android Studio zu lehren, wie Ihre Anwendung zu erstellen

• Einapp.iml fi
mit mehr Android Studio Metadaten

Die Sourcesets

Sourcesets sind, wodie "Quelle" des Projekts organisiert. Hier ist "Quelle" nicht bezieht sich nur auf Programmiersprache Quellcode (zB Java), aber auch andere Arten von Eingaben an den Build, wie Sie Ihre Ressourcen.

sourceSetdass Sie die meiste Zeit verbringen in ist main /. Sie haben auch einen Stub sourceSet namens androidTest, für den Einsatz in Unit-Tests zu schaffen, als abgedeckt wirdspäter imdas Buch.

Innenein sourceSet, können Sie haben:

• Java-Code, inein java /

• Ressourcen, ina res / Verzeichnis

• Vermögenswerte, in einVermögenswerte / Verzeichnis, was andere statische
fi

Sie wünschen, verpackt mitdie Anwendung für den Einsatz auf das Gerät

• IhreAndroidManifest.xmlfi

Der Inhalt eines Eclipse-Art-Projekt

Ein Vermächtnis von Eclipse-Stil-Projekt hat eine andere Struktur, mit den folgenden Elementen im Projektstammverzeichnis:

1. AndroidManifest.xmlWird, wie oben beschrieben wurde

2. bin /, die die Anwendung hält, sobald es kompiliert wird (Anmerkung: Dieses

Verzeichnis wird, wenn Sie fi erstellt werden
bauen Ihre Bewerbung)

3. res /, die Ihre Ressourcen hält, wie oben beschrieben

4. src /, die den Java-Quellcode für die Anwendung hält

In Ergänzung zur fi
und Verzeichnisse oben dargestellt sind, können Sie fi
irgendein vondie folgenden in Android-Projekten:

1. Aktiva /, die andere statische fi hält

Sie wünschen verpackt mit die

Anwendung für den Einsatz auf das Gerät

2. gen /, wo Android Build-Tools Quellcode platzieren wird, dass sie erzeugen

3. libs /, die von Drittanbietern Java JAR-Dateien Ihre Anwendung hält erfordert 4. pROPERTIES, Die Daten enthalten, Konfiguration für Ihre Builds

5. proguard.cfgoderproguard-project.txt, Die sich für die Integration verwendet, um mitProGuardfür Ihr Android-Code Verschleiern

6. Versteckte Eclipse-Projekt fi

(z.B,.classpath)

What You Get Out Of It

Als Teil Ihrer Anwendung laufen aufein Gerät oder Emulator, wird die IDE eine APK fi erzeugen

Sie fi

Dies:

• imdie Build / Ausgänge / apk-Verzeichnis Ihres Android Studio-Projekt, wenn das Projekt keine Module hat (zB kein app / Verzeichnis) oder

• imdasAufbau / Ausgänge / apkVerzeichnis Ihres Moduls Verzeichnis (zBapp / build /

Ausgänge / apkfürein traditionelles Android Studio-Projekt) oder

• imdas bin / Verzeichnis Ihres Projekts Eclipse-Stil

Die APK fi
ist ein ZIP-Archiv kompilierten Java-Klassen, die kompilierte Ausgabe Ihrer

Ressourcen (resources.arsc), jegliche nicht-kompilierten Ressourcen enthält (wie zum Beispiel, was Sie in res / raw / put) und die AndroidManifest.xml fi

Ob Sie bauen eine Debug-Version der

Anwendung - dies ist die Standardeinstellung - Sie haben
yourapp-debug.apkals APK, für eine Appgenanntyourapp.

Einführung in Gradle unddas Manifest

Imdie Diskussion über Android Studio, hat dieses Buch etwas namens "Gradle" erwähnt, ohne viel Erklärung.

ImIn diesem Kapitel werden die Geheimnisse der Gradle dir offenbart
werden. (Na ja, OK, einige der Geheimnisse ...)

We auch im Vorbeigehen im vorigen Kapitel das Konzept der "manifestieren", als eine besondere fi erwähnt
im unsere Android-Projekte.

Aufdie einerseits Gradle und das Manifest nicht streng verwandt. Auf der anderen Seite, einige (aber bei weitem nicht alle) der Dinge, die wir im Manifest einrichten kann, kann in Gradle außer Kraft gesetzt werden.

Also, inIn diesem Kapitel wird überprüfen wir beide, was Gradle ist, was das Manifest ist, was jeder ihrer Rollen sind, und die Grundlagen, wie sie zusammen zu binden.

Gradle: Die großen Fragen

Lassen Sie uns zuerst "gesetztdie Bühne "durch die Untersuchung, was das alles ist, durch eine Reihe von fi
y-gestellte Fragen (FAQs).

Was ist Gradle?

Gradleist eine Software für die Entwicklung von Software, die auch als "Build-Automatisierungssoftware bekannt"Oder" Build-Systeme ". Sie haben möglicherweise andere Build-Systeme, bevor sie in anderen Umgebungen, wie make (C / C ++), Harke (Rubin), Ant (Java), Maven (Java), etc. verwendet

Diese Werkzeuge kennen- Über intrinsische Fähigkeiten und Regeln, die Sie ihnen beibringen - wie das, was zu bestimmen, muss erstellt werden (zB basierend auf fi

Änderungen) und wie zu
schaffen Sie. Ein Build-System lässt sich nicht kompilieren, Link, Paket, usw. Anwendungen direkt, sondern leitet stattdessen getrennte Compiler, Linker und Verpacker, dass die Arbeit zu tun.

Gradle verwendeteine domänenspezifische Sprache (DSL) auf der Groovy gebaut, um diese Aufgaben zu erfüllen.

Was ist Groovy?

Es gibt viele Programmiersprachendass sind so konzipiert, auf der Java-VM zu laufen. Einige davon, wie JRuby und Jython, sind Implementierungen von anderen gängigen Programmiersprachen (Ruby und Python, beziehungsweise). Andere Sprachen sind einzigartig, undtollist einer vonjene.

Groovy-Skripte aussehenein bisschen wie ein Mashup von Java und Ruby. Wie bei Java unterstützt Groovy:

• Defi

Klassen mitdie Klasse Schlüsselwort

• Erstellen von Unterklassen miterweitert

• Importieren von Klassen von externen JAR-Dateien verwendeneinführen

• Defi

Methodenrümpfe Zahnspangen({ und })

• Die Objekte werden erstellt überder neue

Betreiber Wie bei Rubin, aber:

• Statements kann Teil seineine Klasse, oder einfach nur in einem imperativen Stil, wie eine Skriptsprache geschrieben

• Parameter und lokale Variablen nicht eingegeben

• Die Werte können automatisch in Strings gepatcht werden, wenn auch etwas andere Syntax("Hallo,$ Name "für Groovy statt"Hallo,#{Name}"für Ruby)

Groovy ist eine interpretierte Sprache, wie Ruby und im Gegensatz zu Java. Groovy-Skripte ausführen, indem die Ausführungein groovy Befehl, es das Skript vorbei zu laufen. Die Groovy-Laufzeit, obwohl, ist ein Java-JAR und erfordert eine JVM, um zu funktionieren.

Eine der Stärken von Groovy ist bei der Schaffung voneindomänenspezifische Sprache(Oder DSL).

Gradle, ist beispielsweiseein starkes DSL für Software tun baut. Gradle spezifischen Funktionen erscheinen fi sein

-Klasse Sprachkonstrukte, in der Regel nicht zu unterscheiden
von Fähigkeiten eigen Groovy. Noch,die Groovy DSL ist weitgehend deklarativen, wie ein XML-fi Bis zu einem gewissen Grad, erhalten wirdas Beste aus beiden Welten: XML-Style-Definitionen (in der Regel mit weniger Interpunktion), aber mit der Fähigkeit, "in Groovy erreichen" und benutzerdefinierte Skripts zu tun, wie gebraucht.

Was macht Android haben mit Gradle zu tun?

Google veröffentlichtdas Android-Plugin für Gradle, die die Möglichkeit gibt, Gradle Android-Projekte zu bauen. Google ist auch mit Gradle und Gradle für Android als Build-System hinter Android Studio.

Warum haben wirUmzug nach Gradle?

Ursprünglich, als würden wir eine App bauen,diese Builds wurden mit Eclipse und Ant getan.

Eclipse-war die IDE, während Ant das Kommandozeilen-Tool war. Eclipse-nicht verwendet Ant nicht für Android Projekte an, sondern hat seine eigene Build-System. Und wir waren erfolgreich den Aufbau einer Millionen-plus-Anwendungen mit diesen Werkzeugen. Diese Werkzeuge heute noch arbeiten, wenn Ant-Unterstützung schnell verblasst.

Also, warum ändern?

Es gab mehrere Faktoren, einschließlich:

• Beibehaltung von zwei separaten Build-Systeme (Ant und nativen Ansatz der Eclipse) wurde immer zeitaufwändig und würde schlimmer werden mit das Aufkommen von Android Studio und noch ein Build-System. Daher wollte Google auf einem einzigen Build-System zu standardisieren, basierend auf Gradle, für IDE und Befehlszeilen Szenarien.

• Ant-Skripts, alles zu tundass Google benötigt für Builds wurde ein bisschen
knarrende bekommen.

• Ant hatkeine fi

-Klasse Unterstützung für "externe Artefakte" (zB Bibliotheken) und

Abhängigkeitsmanagement von diese Bibliotheken. Zwar gibt es Möglichkeiten, zu
pfropfenMaven auf Ant oder eigene Build-System von Maven verwenden, Google niediesen Ansatz unterstützt. Gradle bietet viel bessere Unterstützung in diesem Bereich als Sie Eclipse oder Ant, und es einfacher machen, wird dazu beitragen, für Entwickler, um zuverlässig verbrauchen Bibliotheken aus einer Vielzahl von Autoren.

• Gradle ist so konzipiert, in IDEs integriert werden als eine Bibliothek, viel mehr als Ant ist.

Wie funktioniert Gradle Relateauf Android Studio?

Wie oben erwähnt, verwendet Android Studiodie neue Gradle-basierten Build-System als seine native Ansatz für Android Projekte an. Während die IntelliJ IDEA IDE, die auch als Android Studio Kern dient seinen eigenen Build-System hat (viel wie Eclipse man hat), ist IDEA zugänglicher Systeme tauschbare bauen.

Zu EndeZeit, dies ermöglicht es Google auf einem einzigen Build-System (Gradle) für alle unterstützten Szenarien zu konzentrieren, anstatt mit einer Sammlung von unabhängigen Build-Systeme beschäftigen.

Beziehen Gradle

Wie bei jedem Build-System, es zu benutzen, Siemüssen das Build-System des Motors selbst.

Wenn Sie nur Gradle verwenden werden inder Zusammenhang von Android Studio, wird die IDE

Pflege Gradle für Sie bekommen. Wenn jedoch planen Sie Gradle über die Verwendung außerhalb von Android Studio (zB Kommandozeilen-Builds), werden Sie zu prüfen, wo Ihr Gradle herkommt.

Dies ist besonders wichtig für Situationen, in denen Sie die App ohne IDE in Sicht, wie die Verwendung einer kontinuierlichen Integration (CI) Server, wie Jenkins aufbauen wollen.

Direkte Installation

Was suchen die meisten Entwickler Gradle verwenden außerhalb von Android Studio wird dabei aufzuwickeln ist Gradle direkt installieren.

DasGradle Download-Seiteenthält Links zu ZIP-Archiven für Gradle selbst: Binaries, Quellcode, oder beides.

Sie können UNZIPdieses Archiv an die gewünschte Position auf Ihrer Entwicklungsmaschine.

Linux-Pakete

Sie kann in der Lage sein Gradle zu erhalten überein Paket-Manager auf Linux-Umgebungen. Zum Beispiel gibt esein Ubuntu PPA für Gradle.

Der gradlew Wrapper

Wenn Sie abein Projekt, das jemand anderes veröffentlicht hat, können Sie fi
ein
gradlewundgradlew.batfi
im das Projekt Wurzel, zusammen mit einemgradle

/Verzeichnis. Dies entsprichtdie "Gradle Wrapper".

Die Gradle Wrapper besteht aus drei Teilen:

• die Charge fi

(gradlew.bat) Oder Shell-Skript (gradlew)

• die JAR-fi
benutzt durch die Charge fi
und Shell-Skript (in dasgradle /

Wrapper /

Verzeichnis)

• dasgradle-wrapper.propertiesfi

(ebenfalls im dasgradle / Wrapper /Verzeichnis)

Android Studio Anwendungendasgradle-wrapper.propertiesfi
um zu bestimmen, wo von

Gradle zum Herunterladen von für den Einsatz in Ihrem Projekt,dasdistributionUrlImmobilien indass fi

(von

Basic / Knopf / gradle / Wrapper / gradle-
wrapper.properties)

Wenn Sie erstellen oder importierenein Projekt, oder wenn Sie die Version von Gradle ändern, auf die im Eigenschaften fi
androide Studio wird heruntergeladen die Gradle, auf die der
distributionUrl Eigenschaft und installieren Sie es zu einem .gradle / Verzeichnis (die führende beachten.) in Ihrem Projekt. Diese Version von Gradle sein wird, was Android Studio verwendet.

REGEL # 1: Verwenden Sie nureindistributionUrldass Sie vertrauen.

Wenn Sie ein Android-Projekt importieren auseine dritte Partei - wie die Proben für dieses Buch - und sie enthalten diegradle / Wrapper / gradle-wrapper.properties
fi
untersuchen, um zu sehen, wodie distributionUrl zeigt auf. Wenn es von
services.gradle.org geladen wird, oder von einem internen Enterprise-Server, ist es wahrscheinlich vertrauenswürdig. Wenn es auf eine URL verweist woanders befindet, zu prüfen, ob Sie wirklich, dass die Version von Gradle verwenden möchten, wenn man bedenkt, dass es manipuliert worden sein.

Die Batch-fi

Schale Skript, und JAR-fi
gibt es Befehlszeilen baut zu unterstützen.

Wenn Sie gradlew verwenden, wird es eine lokale Kopie von Gradle verwenden in .gradle / im Projekt installiert. Wenn es keine solche Kopie von Gradle ist, wird gradlew Gradle Download von der
distributionUrl, wie auch Android Studio. Beachten Sie, dass Android Studio nicht verwenden gradlew für diese Rolle - diese Logik in Android Studio selbst gebaut.

Regel 2: Nur Verwendungeingradlewdass man wirklich vertrauen.

Es ist relativ einfach, eine .properties fi zu untersuchen
überprüfeneine URL zu sehen, ob es
gültig zu sein scheint. Sinnvoll einer Charge fi
oderShell-Skript kann mühsam sein.

Decompilingeine JAR-fi
undmacht Sinn für sie kann ziemlich schwierig sein. Doch wenn Sie
verwendengradlew, die Sie von jemandem erhalten, das Skript und JAR laufen auf Ihrer

Entwicklungsmaschine, wie die Kopie von Gradle ist, dass sie zu installieren. Wenn dieser Code manipuliert wurde, hat sich die Malware vollständigen Zugriff auf Ihre Entwicklungsmaschine und alles, was sie, wie Server in Ihrem Unternehmen erreichen können.

Hinweisdass Sie müssen nicht alle Gradle Wrapper verwenden. Wenn Sie lieber nicht darum kümmern, eine Version von Gradle auf Ihrer Entwicklungsmaschine selbst installieren und die Gradle Wrapper fi entfernen

. Sie können die gradle Befehl verwenden, um Ihre

Anwendung zu erstellen (wenn Ihr Gradle das bin / Verzeichnis in PATH ist) und Android Studio Ihre Gradle Installation verwenden (wenn Sie lehren sie, wo zu fi nden
es, wie über die

GRADLE_HOME Umgebungsvariable).

Versionen von Gradle unddas Android-Plugin für Gradle

Das Android-Plugin für Gradledass wir Gradle verwenden zu geben "Super Android Kräfte!" in regelmäßigen Abständen aktualisiert. Jedes Update hat seine entsprechende erforderliche Version von Gradle.

Die Regeln, nach Google, sind:

• Android Studio 1.x funktioniert mit jedem Android-Plugin für Gradle Version 1.x, wodie Werte für "x" müssen nicht übereinstimmen

• Android Studio 2.x funktioniert mit jedem Android-Plugin für Gradle Version 2.x, wo wiederDie Werte für "x" müssen nicht übereinstimmen

• Das Android-Plugin für Gradle hat seinen eigenen Satz von Anforderungen fürdie zugrunde liegende Gradle Version:

Android Plugin für Gradle Versionen Unterstützte Gradle

Versionen

1.0.0- 1.1.3

2.2.1- 2.3

1.2.0- 1.3.1

2.2.1 - 2.9

1.5.x

2.2.1 oder höher

Android Plugin für Gradle Versionen Unterstützte Gradle

Versionen

2.x

2.10 oder höher

Wenn Sie mitdie Gradle Wrapper, verwenden Sie eine Installation von Gradle, die dem Projekt lokal ist. Solange die Version von Gradle im Projekt entspricht der Version von Gradle für Android beantragt im build.gradle fi

- Wie es im nächsten Kapitel behandelt werden -
sollten Sie in fi sein
gestalten.

Wenn du bistnicht die Gradle Wrapper verwenden, müssen Sie entscheiden, wann für Android Version auf einem neuen Gradle zu nehmen und Ihre Gradle Installation und fi aktualisieren planen build.gradle
im Tandem an diesem Punkt.

Gradle Umgebungsvariablen

Wenn Sie Gradle selbst installiert haben, werden Sie definierenein GRADLE_HOME

Umgebungsvariable und zeigt auf, wo Sie Gradle installiert, und das bin / Verzeichnis innerhalb von Gradle zu Ihrer Umgebungsvariable PATH hinzuzufügen.

Sie können auch prüfen, Einrichtenein GRADLE_USER_HOME Umgebungsvariable, indem er auf ein Verzeichnis, in dem Gradle ein .gradle Unterverzeichnis erstellen können, für per- Benutzer-Caches und verwandten Materialien. Standardmäßig wird Gradle Ihr Standard-Home-Verzeichnis verwenden.

untersuchendie Gradle Dateien

Ein Android-Studio-Projekt hat in der Regel zweibuild.gradle fi

, Auf Projektebene eins
und eins auf der "Modul" Ebene (zB im app / Verzeichnis).

Das Projekt-Level-Datei

Dasbuild.gradle fi
im das Projektverzeichnis steuert die Gradle Konfiguration für alle

Module in Ihrem Projekt. Gerade jetzt, höchstwahrscheinlich nur Sie ein Modul, und viele Anwendungen immer nur ein Modul verwenden. Es ist jedoch möglich, dass Sie andere Module zu diesem Projekt hinzuzufügen, und wir werden Gründe erforschen für so später in diesem Buch zu tun.

Hier ist ein typisches Top-Levelbuild.gradlefi

(vonBasic / Knopf / build.gradle)

buildscript

Dasbuildscript Verschluss (dh Codeabschnitt in Klammern eingeschlossen) in Gradle ist, wo Sie die JAR-Dateien konfigurieren und so, dass Gradle sich für die Auslegung der Rest der fi

verwenden

Daher hier sind Sienicht Konfi

Ihr Projekt so viel wie Sie den Build selbst
konfigurieren.

DasRepositorys Verschluss innerhalb des buildscript Schließung zeigt an, wo Abhängigkeiten von, in der Regel in Form von Maven-Repositories Stil kommen kann. Hier jcenter () ist eine integrierte Methode, die die Repository-Informationen für Maven Zentrale eingerichtet hat, ein beliebter Ort für Open-Source-Abhängigkeiten zu erhalten.

DasAbhängigkeitenVerschluss zeigt an, was ist notwendig, um zu laufender Rest des Build-Skript.classpath'Com.android.tools.build:gradle:2.1.2'istnicht besonders durch die Gradle Team gut dokumentiert. Doch die'Com.android.tools.build:gradle:2.1.2'Teil bedeutet:

• Findendascom.android.tools.buildGruppe von Artefakten inein Repository

• Findendie gradle Artefakt in dieser Gruppe

• Dafür sorgendass wir haben Version 2.1.2 des Artefakts

Der fi

Zeit, die Sie Ihren Build, mit dem buildscript Verschluss laufen, wie oben gezeigt, wird Gradle feststellen, dass Sie diese Abhängigkeit nicht haben. Es wird dann herunterladen, das Artefakt aus der jcenter () Repository.

Manchmal,das letzte Segment der Version ist mit einem + Zeichen ersetzt (zB 2.1. +). Dies sagt Gradle die neueste Version herunterladen, damit automatisch auf die neueste Patch-Level-Upgrade (zB 1.0.3 an einem gewissen Punkt).

allprojects
the allprojects Schließung sagt "für alle Module in diesem Projekt, diese Einstellungen zu übernehmen". Hier setzen wir auf jcenter () als Repository für fi verwenden benutzten

Bibliotheken in einem derdie Module in unserem Projekt.

DasModul-Ebene Gradle Datei

In deinemapp / Modul, Sie fi auch eine build.gradle fi Diese Einstellungen einzigartig für dieses Modul hat, unabhängig von einem anderen Modul, das Projekt in der Zukunft haben kann.

Hier ist ein typisches Modul-Ebenebuild.gradlefi

(vonBasic / Knopf / app / build.gradle)

Abhängigkeiten

Diesbuild.gradlefi
ebenfalls hat einAbhängigkeitenSchließung.

WohingegendasAbhängigkeitenVerschlussdasbuildscriptVerschluss die Top-

Levelbuild.gradlefi
ist für Bibliotheken von der Build-Prozess,
derAbhängigkeitenVerschlussDie Höhe des Modulsbuild.gradlefi
ist durch Verwendung im

Code-Bibliotheken indieses Modul. Wir werden in das Konzept dieser Bibliotheken erhaltenspäter imdas Buch.

Diese besonderebuild.gradle fi hat eine leere Abhängigkeiten Schließung, was bedeutet, dass es nicht auf irgendwelchen Bibliotheken abhängt. Die Abhängigkeiten Verschluss ist in diesem Fall nicht erforderlich - es hier nur zu Demonstrationszwecken ist.

androide

Dasandroid Schließung enthält alle Android-spezifi-Konfigurationsinformationen. Dieser Verschluss ist das, was das Android-Plugin ermöglicht.

Aber bevor wir in das, was erhalten ist, inDieser Verschluss, wir sollten "Schaltanlagen" und über das Manifest fi sprechen
wie was geht in das Android-Verschluss ist ähnlich zu dem, was im

Manifest fi geht

Einbringendas Manifest

Die Grundlage für jede Android-Anwendung istdas Manifest fi AndroidManifest.xml. Dies wird in der App-Moduls src / main / Verzeichnis für klassische Android Studio-Projekte sein.

Hier ist, wo Sie erklären, was in Ihrer Anwendung- Die Tätigkeiten, Leistungen, und so weiter. Sie zeigen auch, wie diese Stücke selbst Android-System auf das Gesamt befestigen; zum Beispiel, geben Sie an, welche Aktivität (oder Aktivitäten) auf das Hauptmenü des Geräts (aka, launcher) erscheinen soll.

Wenn Sie Ihre Anwendung erstellen, erhalten Sieein Starter-Manifest für Sie generiert. Für eine einfache Anwendung, eine einzelne Aktivität und nichts anderes anbieten, erzeugt die auto-manifest wird wahrscheinlich fi trainieren
oder vielleicht erfordern ein paar kleinere

Änderungen. Am anderen Ende des Spektrums, das Manifest fi
für die Android API Demo-

Suite ist mehr als 1000 Zeilen lang. Ihre Produktion Android-Anwendungen werden
wahrscheinlich irgendwo in der Mitte liegen.

Wie bereits erwähnt, können einige Elemente in beiden definiert werdendas Manifest und in einem build.gradle fi

Das Ansatz des Setzens das Zeug im Manifest noch funktioniert. Für Android

Studio-Anwender, werden Sie wahrscheinlich die Gradle fi verwenden
und haben werden,
diese gemeinsamen Elemente nicht im Manifest definiert.

Dinge gemeinsam Zwischendas Manifest und Gradle

Es gibtein paar wichtige Elemente, die im Manifest definiert werden kann und in build.gradle Aussagen außer Kraft gesetzt werden. Diese Elemente sind ziemlich wichtig für die Entwicklung und den Betrieb unserer Android Apps auch.

Paketname und Anwendungs-ID

Die Wurzel allen offensichtlichen fi
ist, nicht überraschend, dass ein offensichtlicher Element:

HinweisdasandroideNamespace-Deklaration. Sie werden nur verwendender Namensraum auf viele der Attribute, nicht die Elemente (zB<Manifest>nicht<Android: Manifest>).

Der größte Teil der Informationen Siemüssen auf dem <Manifest> Element zu liefern ist das PaketAttribut.

DasPaket-Attribut immer brauchen im Manifest zu sein, auch für Android Studio-Projekte. Das Paket Attribut steuern, wo einige Quellcode für uns erzeugt wird, vor allem einige R und BuildConfig Klassen, die wir später in diesem Buch begegnen werden.

Schon seitder Paketwert für Java Code-Generierung verwendet wird, hat es eine gültige Java-Paket-Namen. Java-Konvention besagt, dass der Name des Pakets auf einem Reverse Domain-Namen (zB
com.commonsware.empublite) basieren sollte, in dem Sie die betreffende Domäne besitzen. Auf diese Weise ist es unwahrscheinlich, dass jemand anderes aus Versehen mit dem gleichen Namen kollidiert.

the-Paket dient auch als unsere App-default "Anwendungs-ID". Dies muss eine eindeutige Kennung zu sein, so dass:

• keine zwei Anwendungen können mit dem gleichen Applikations-ID in der gleichen Zeit auf dem gleichen Gerät installiert werden

• keine zwei Anwendungen können mit derselben Anwendungs-ID (und andere

Vertriebskanäle können die gleiche Einschränkung) im Play Store geladen werden

In der Standardeinstellungdie Anwendungs-ID ist das Paket Wert, aber Android Studio Benutzer es in ihrem Gradle bauen fi außer Kraft setzen können

. Insbesondere kann im Inneren des

Android-Verschluss ein DefaultConfig Verschluss sein, und im Inneren von dort kann eine applicationId Aussage sein:

Nicht nur kann Studio-Nutzer Android Überschreibungdie Anwendungs-ID in der DefaultConfig Schließung, aber es gibt Möglichkeiten der verschiedenen Anwendungs-ID-Werte für verschiedene Szenarien, die, wie eine Debug im Vergleich zu einem Release-Build bauen. Wir werden entdecken, dass mehrspäter imdas Buch.

minSdkVersion undtargetSdkVersion

Ihr Manifest kann auchein<Verwendet-sdk>Element als Kind von der<Manifest>Element, um festzulegen, welche Versionen von Android unterstützen Sie. Es kann enthalten, unter anderem,android: minSdkVersionundandroid: targetSdkVersionAttribute.Legacy-Eclipse-Projekte im Stil wird immer dieses Element haben. Android Studio-Projekte kann dieses Element nicht haben, da die Werte definiert werden alsminSdkVersionundtargetSdkVersionImmobilien dasdefaultConfigSchließung, woapplicationIdkann definiert werden.

Vondie beiden, desto kritischer ist minSdkVersion. Dies zeigt an, was die älteste Version von Android ist, dass Sie mit Ihrer Anwendung zu testen sind. Der Wert des Attributs ist eine ganze Zahl, die die AndroidAPI-Ebene. Also, wenn Sie Ihre Anwendung testen auf Android 4.1 und neueren Versionen von Android, würden Sie setzen IhreminSdkVersion sein 16.

Du kannst auchgeben Sie eine targetSdkVersion. Dies zeigt an, welche Version von Android Sie denken an, wie Sie Ihren Code schreiben. Wenn Ihre Anwendung auf eine neuere Version von Android laufen wird, kann Android einige Dinge tun, um zu versuchen, die Kompatibilität Ihres Codes in Bezug auf Änderungen in den neueren Android gemacht zu verbessern. Heutzutage sind die meisten Android-Entwickler sollten ein Ziel SDK-Version 15 oder höher angeben. Wir werden beginnen, mehr über die targetSdkVersion zu erkunden, wie wir tiefer in das Buch zu bekommen; für den Augenblick, was auch immer Ihre IDE Sie als Standardwert gibt, ist wahrscheinlich eine fi
beginnend Punkt.

Die XMLElement wie folgt aussieht:

Die entsprechendeEinträge inbuild.gradlehineingehen dasdefaultConfigSchließung:

Versionscode und Version Name

Ihr Manifest kann auchangebenandroid: versionundandroid: versionAttribute, bis aufder Ursprung<Manifest>Element. Ein Projekt Android Studio, obwohl, springt häufig diejenigen, und definiert sieüberversionundversionImmobiliendasdefaultConfigSchließung.

Diese beiden Werte stellendie Versionen Ihrer Anwendung. Der Wert ist version, was der Benutzer für einen Versionsindikator in den Anwendungen sehen die Details für Ihre App auf ihrer Anwendung Einstellungen Bildschirm:

Ebenfalls,der Versionsname wird von der Play Store-Eintrag verwendet, wenn Sie Ihre Anwendung auf diese Weise verteilen. Der Versionsname kann ein beliebiger Zeichenfolgenwert sein Sie wollen.

Dasversion, auf der anderen Seite, muss eine ganze Zahl sein, und neuere Versionen müssen höhere Codes Version haben alsältere Versionen zu tun. wenn die neue APK Android und das Play Store wird die Versionscode einer neuen APK zur Versionscode eines installierten Programms vergleichen, um zu bestimmen, ist in der Tat ein Update. Der typische Ansatz ist es, den Versionscode bei 1 zu beginnen und es mit jedem Produktionsfreigabe Ihrer Anwendung erhöhen, wenn Sie eine andere Konvention können wählen, ob Sie es wünschen. Während

Entwicklung, können Sie verlassendiese allein, aber wenn man die Produktion bewegen, werden diese Attribute sehr wichtig.

Andere Gradle Artikel von Note

Sie werden immer mindestens zwei Aussagen haben direkt indas Android-Verschluss: compileSdkVersionund buildToolsVersion.

(vonGradle / HelloNew / build.gradle)

compileSdkVersion spezifi
die API-Ebene als eine einfache API-Ebene ganze Zahl (zB

19) kompiliert gegen, in der Regel zu werden. Ein Vermächtnis von Eclipse-Stil-Projekt würde dies ziehen aus dem project.properties fi
im die Wurzel des Projektverzeichnis.

buildToolsVersion gibt die Version des Android SDK Build-Tools, die Sie wollen mit diesem Projekt zu verwenden. Während des Downloads der Android-Plugin von Maven Zentrale gibt uns Teile, was notwendig ist, ist es nicht vollständig. Der Rest stammt aus dem "Android SDK Errichten-Tools" im SDK-Manager:

Hinweisdass die SDK-Manager ermöglicht es Ihnen, die neueste Version der Build-Tools von Gradle (erscheint als 20 im obigen Screenshot) sowie früheren Versionen (zB 18.0.1 und 17 im obigen Screenshot) verwendet zum Download bereit. Dies entspricht der buildToolsVersion in Ihrem build.gradle fi

Also deinandroid Schließung könnte wie folgt aussehen:

eclipse-tatnicht haben wirklich die Vorstellung von einem konfigurierbaren Build-Tools Version, so gibt es kein Analogon für buildToolsVersion in einem Legacy-Eclipse-Stil-Projekt.

Wo istdie GUI?

Sie fragen sich vielleicht, warum wir durch alle slog habendiese Groovy-Code und Wunder, wenn es einige GUI für Gradle Einstellungen zu beeinflussen.

Die Antwort ist ja ... und nein.

Es gibtdie Projektstruktur Dialog.dass können Sie etwas über dieses Thema zu erhalten. Und Sie sind herzlich eingeladen, es zu versuchen. Allerdings desto komplexer Build wird, desto wahrscheinlicher ist es, dass die GUI wird nicht ausreichen, und Sie werden mit dem Gradle arbeiten müssen fi bauen

Mehrdirekt. Daher,Dieses Buch wird dazu neigen, auf dem Build
zu konzentrieren
fi

.

Der Rest vondas Manifest

Nicht alles, was indas Manifest in der Gradle bauen fi außer Kraft gesetzt werden

. Hier sind
ein paar wichtige Elemente, die immer im Manifest erscheinen wird, unabhängig davon, ob dieses Projekts ist es, durch Android Studio oder anderen Mitteln gebaut werden.

Eine Anwendung für Ihre Anwendung

In Ihrem ersten Projekt Manifest,das primäre Kind des <manifest> Element ist ein

<Application>Element.

In der Standardeinstellung beim Erstellenein neues Android-Projekt können Sie eine einzelne

<Aktivität> get

Element innerhalb des<Application>Element:

(von Skeleton / Now / AndroidManifest.xml)

DiesElement liefert android: für den Klassennamen, die Aktivität der Umsetzung,
android: label für den Anzeigenamen der Aktivität, und (manchmal) ein

<Intent-Filter> Kind-Element beschreibt, unter welchen Bedingungen wird diese Aktivität angezeigt.

Die Aktie <Aktivität> Element richtet Ihre Aktivität im Launcher erscheinen, so dass die Benutzer es ausführen wählen können. Wie wir später in diesem Buch sehen werden, können Sie mehrere Aktivitäten in einem Projekt haben, wenn Sie so wählen.

Dasandroid: nameAttribut, inIm vorliegenden Fall hat eine kahle Java-Klassennamen (Jetzt).

Manchmal werden Sie sehen,android: namemiteine voll qualifizierten Klassennamen

(zBcom.commonsware.android.skeleton.Now). Manchmal werden Sie sehen,ein Java-Klassennamen mit einem einzigen Punkt als Präfix (zB.Jetzt). BeideJetztund.Jetztbeziehen aufeine Java-Klasse, die in Ihrem Projekt-Paket sein wird - die, die Sie in der erklärtPaketAttributdas<Manifest>Element.

UnterstützungMehrere Bildschirme

Android-Geräte kommen miteine große Auswahl an Bildschirmgrößen von 2,8 "kleinen Smartphones bis 46" TV. Android teilt diese in vier Eimer, basierend auf physikalischen Größe und der Abstand, in dem sie in der Regel betrachtet werden:

1. Klein (unter 3 ")

2. Normal (3 "bis etwa 4,5")

3. Groß (4.5 "bis etwa 10")

4. Extra große (über 10 ")

Standardmäßig wird Ihre Anwendung unterstützen kleine undnormale Bildschirme. Es wird auch groß und extra-großen Bildschirmen über einige automatische Konvertierung Code eingebaut in Android unterstützen.

Um wirklich zu unterstützen alledie Bildschirmgrößen Sie wollen, sollten Sie überlegen, ein Hinzufügen

<Träger-Bildschirme> Element zu Ihrem Manifest. Dies zählt die Bildschirmgrößen Sie für explizite Unterstützung. Zum Beispiel, wenn Sie benutzerdefinierte UI-Unterstützung für große oder extra große Bildschirme bieten, werden Sie die <Träger-Bildschirme> Element zu haben. So, während die

Ausgangs manifestieren fi

Arbeiten ist es, mehrere Bildschirmgrößen Umgang mit etwas, was

Sie wollennachdenken über.

Sie winden sich mit einemElement ähnlich:

Viel mehr Informationen über solide Unterstützung für alle Bildschirmgrößen, einschliesslich Probendie <Stützen-Bildschirme> -Element, wird später in diesem Buch zu finden, wie wir großen Bildschirm-Strategien decken.

Andere Sachen

Wie wir gehen durchdas Buch, werden Sie fi
andere Elemente werden mit dem
offensichtlichen hinzugefügt, wie zum Beispiel:

• <Verwendet-permission>, um den Benutzer zu sagen, dass Sie die Erlaubnis benötigen bestimmte Gerätefunktionen zu verwenden, wie zum Beispiel das Internet zugreifen

• <Verwendet-Funktion>, Android zu sagen, dass Sie das Gerät müssen bestimmte Merkmale aufweisen (zB eine Kamera), und damit Ihre App sollte nicht auf Geräten installiert werden solche Merkmale fehlen

• <Meta-data>, für die Bits von Informationen, die von bestimmten Erweiterungen Android benötigt, wie zum Beispiel die Google Play-Services-Bibliothek.

Diese und andereElemente werden an anderer Stelle in dem Buch vorgestellt.

LernenMehr über Gradle

Dieses Buch geht in mehr über Gradle, sowohl indie Kernkapitel und in den Spuren. Aber, wird der Fokus auf Gradle für Android sein und Gradle selbst bietet viel mehr als das. Die Gradle Website-HostsDokumentationLinks zuGradle spezifische BücherUnd Links zuandere

GradleBildungsressourcen.

Gegenwärtig,die Gradle für Android Dokumentation ist begrenzt und meist erscheintdie Android-Tools-Website. Bemerkenswert istdie Top-Level-Seite über das neue Build-System, und die Gradle Plugin Benutzerhandbuch, Beide können jedoch veraltet sein im Vergleich zudie eigentlichen Werkzeuge selbst.

Besuchdie Spuren!

Es gibtnoch ein paar Kapitel in diesem Buch in mehr Einzelheiten über die Verwendung von Gradle und Gradle für Android bekommen.

• Gradle und Legacy-Projekteist für Entwickler, die mit Legacy-Eclipse-Projekte im Stil zu verwenden Gradle suchen

• Gradle und Aufgabenerklärt, wie wir Gradle fragen zu tunDinge in unserem Namen (

"Aufgaben"), wie zum Beispiel unsere APK kompilieren für uns

• Gradle unddas neue Projektstrukturwird in das, was Fähigkeiten, die wir erhalten ausdie Gradle Projektstruktur, einschließlich der Fähigkeit, "Build-Typen" und "Produkt Aromen"

zu konfigurieren

• Gradle und Abhängigkeitenumfasst mehr über die "Artefakte" erwähnt oben in diesem Kapitel, wie Möglichkeiten können wir verpackt Bibliotheken automatisch über nur ein paar Zeilen in unserer build.gradle fi in unsere Projekte hinzukommen

Es gibt auchdas"Advanced Gradle für Android Tips"Kapitel für andere Gradle Themen unddas Kapitel über die offensichtlichen Zusammenführung in Gradle.

Tutorial # 3- Offensichtliche Änderungen

Wie wir bauenEmPubLite, werden wir eine Reihe von Änderungen an unserem Projekt zu manifestieren müssen. In diesem Tutorial werden wir ein paar dieser Änderungen kümmern, um Ihnen zu zeigen, wie man die AndroidManifest.xml fi zu manipulieren

Künftige Tutorials
werden noch weitere Änderungen vornehmen.

Android Studio Nutzer auch bekommen ihre fi

Chance für die Arbeit mitdie build.gradle
fi

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository des Buches.

Einige Anmerkungen über relative Pfade

ImDiese Tutorials finden Sie Verweise auf relative Pfade zu sehen, wie

AndroidManifest.xml.res / Layout /, und so weiter.

Android Studio-Nutzer sollten interpretierendiese Wege als in Bezug auf die app / src / main /

Verzeichnis innerhalb des Projekts ist, sofern nichts anderes angegeben ist. So zum Beispiel Schritt

# 1 unten fragen Sie öffnenAndroidManifest.xml- Dass fi
kann sein gefundenimapp / src /
main / AndroidManifest.xmlvondie Projektwurzel.

Schritt # 1: Unterstützung Screens

Unsere Anwendung wird die unterstützten Bildschirmgrößen beschränken. Tabletten machen für idealebook Leser. Telefone können auch verwendet werden, aber je kleiner die Telefon, desto schwieriger

wird es sein, kommen miteine Benutzeroberfläche, die der Benutzer alles tun lassen, die benötigt wird, aber immer noch Zimmer in einer Zeit für mehr als ein oder zwei Sätze des Buches haben.

Wir werden Bildschirmgröße Strategien kommen in undihre Detailsspäter imdieses Buch. Fürobwohl der Moment, werden wir eine <Träger-Bildschirme> Element hinzufügen, um unsere Anwendung zu halten off "kleine" Screen-Geräte (unter 3 "Bilddiagonale).

Android StudioBenutzer können einen Doppelklick aufAndroidManifest.xmlimder Projekt-Explorer.

Wieein Kind der Wurzel<Manifest>Element, fügen Sie ein<Träger-Bildschirme>Element wie folgt: Schritt # 2: Sperren Backups

Wenn man sichdas Element <application>, werden Sie sehen, dass es ein paar Attribute, darunter Android: allowBackup = "true". Dieses Attribut gibt an, dass EmPubLite in Android automatische Backup-System teilnehmen.

Das istkeine gute Idee, bis Sie die technischen und rechtlichen ramifi dieser Wahl verstehen, die wir erforschenviel später indieses Buch.

Imdie kurzfristigändernandroid: allowBackupseinfalsch.

Schritt 3: Das Ignorieren Lint

Selbst nachdiese Änderung kann die Anwendung Elementname einen beigen Hintergrund haben.

Wenn Sie die Maus über sie und Blick auf die erklärenden Tooltip schweben, werden Sie sehen, dass es beschwert sich, dass diese App nicht indexierbar ist, und dass Sie eine ACTION_VIEW

Aktivität der App hinzuzufügen.

Das ist lächerlich.

Zuerst,Diese App (hoffentlich) nie im Play Store eingereicht und so Googles "App-Indexierung"

Fähigkeit wird nie relevant sein.

Zweitens sollten Entwicklersein Hinzufügen zufälliger Aktivitäten ihrer App nicht nur aus der Basis einiger Tooltip.

Setzen Sie Ihren Text-Cursor irgendwo indie Anwendung Elementnamen und drücken

Sie (oder das Äquivalent auf macOS). Dies sollte ein Popup-Fenster, in
einige "Quick fi zeigtes "für das Problem:

Wählendie "Unterdrückung Lint" -Option. Dann drücken

(oderdas Äquivalent auf
macOS) umformatierendie fi

Sie werden sich wie mit etwas Wind-up:

(von

EmPubLite-Android Studio / T3-Manifest / EmPubLite / app /
src / main / AndroidManifest.xml)

Das<Application>Element hat jetzt einWerkzeuge: ignore =

"GoogleAppIndexingWarning"Attribut, undder Ursprung<Manifest>Element definiert dieWerkzeugeXML-Namespace. DasNettoeffekt ist, dass wir die Build-Tools sagen - speziell die Lint-Dienstprogramm -, dass es dieses besondere Problem ignorieren sollte.

In unserer nächsten Folge ...

… wir werdenmachen einige Änderungen andie Ressourcenunserer Tutorial-Projekt

Ein paar Worte über Ressourcen

Es ist sehr wahrscheinlichvon diesem Zeitpunkt, dass Sie "auf der Zunge zergehen" tatsächlich, um in einen Code zu schreiben. Das ist verständlich. Davon abgesehen, bevor wir in die Java-Quellcode für unser Stub Projekt tauchen, sollten wir wirklich kurz über Ressourcen halten.

Die Ressourcen sind statische Bits von Informationen außerhalb gehaltendie Java-Quellcode. Die Ressourcen werden als fi gespeichert
unter die res / Verzeichnis in Ihrem Android-Projekt-

Layout (ob das in der Projektwurzel für Eclipse oder im Haupt / sourceSet für Android Studio ist).

Hier ist, wo Sie fi
alle Ihre Symbole und andere Bilder, Ihre externalisiert Saiten für

Internationalisierung und vieles mehr.

Diese sind getrennt vondie Java-Quellcode nicht nur, weil sie im Format unterschiedlich sind. Sie sind getrennt, weil Sie mehrere Definitionen einer Ressource haben kann, in anderen Umständen zu verwenden. Zum Beispiel bei der Internationalisierung, werden Sie Strings für verschiedene Sprachen haben. Ihr Java-Code wird in der Lage sein, weitgehend ohne auf diese zu bleiben, wie Android wird die richtige Ressource wählen aus allen Kandidaten zu verwenden, in einem bestimmten Umstand (zB die spanische Zeichenfolge wählen, ob das Gebietsschema des Gerätes ist auf Spanisch festgelegt).

Wir werden alle deckendie Details dieser Ressourcengruppenspäter imdas Buch. Gerade jetzt, wirmüssen die Ressourcen in die Nutzung durch unsere Stub Projekt zu besprechen, plus eins mehr.

In diesem Kapitel beziehen sich aufdie res / Verzeichnis. Android Studio Benutzer fi dass
in der app / src / main / Verzeichnis ihres Projekts.

Stringtheorie

Halten Sie Ihre Etiketten und anderen BitsText außerhalb des Haupt Quellcode Ihrer Anwendung ist in der Regel eine sehr gute Idee zu sein, betrachtet. Insbesondere hilft es bei der Internationalisierung (I18N) und Lokalisierung (L10N). Auch wenn Sie nicht Ihre Strings in anderen Sprachen gehen zu übersetzen, ist es einfacher, Korrekturen vorzunehmen, wenn alle Saiten an einem Ort sind, anstatt im gesamten Quellcode verstreut.

Plain Strings

Im Allgemeinen alles, was Sietun müssen, ist haben eine XML-fi
im die res / Werte-

Verzeichnis (in der Regel genannt res / Werte / strings.xml), mit einem Element Ressourcen Wurzel, und ein Kind String-Element für jede Zeichenfolge, die Sie als eine Ressource zu kodieren möchten. Der String-Element nimmt einen Namen Attribut, das der eindeutige Name für diesen String ist, und ein einziges Textelement den Text der Zeichenfolge enthält:

Einsschwierige Teil ist, wenn der String-Wert ein Angebot oder einen Apostroph enthält. In diesen Fällen werden Sie wollen, um diese Werte zu entkommen, indem sie mit einem Schrägstrich voran (zBDies sind die Zeiten, die Männer versuchen, \ 's Seelen). Oder, wenn es nur ein Apostroph ist, könnten Siesetzen Sie den Wert in Anführungszeichen (zB,"Dies sind die Zeiten, die versuchen,die Seelen der Menschen. ").

Beispielsweise,ein strings.xml fi des Projekts
aussehen könnteDies:

(von

EmPubLite-Android Studio / T3-Manifest / EmPubLite / app /
src / main / res / Werte / strings.xml)

Wir können verweisendiese String-Ressourcen von verschiedenen Standorten, in unserer Java-Quellcode und anderswo. Zum Beispiel wird die app_name String-Ressource oft in der AndroidManifest.xml fi verwendet

(von

EmPubLite-Android Studio / T3-Manifest / EmPubLite / app /
src / main / AndroidManifest.xml)

Hier,das android: label-Attribut des <application> -Element bezieht sich auf die app_name String-Ressource. Dies wird an einigen Stellen in der Anwendung angezeigt werden, vor allem in der Liste der installierten Anwendungen in den Einstellungen. Also, wenn Sie ändern möchten, wie Ihre Anwendung den Namen in diesen Orten erscheint, stellen Sie einfach den app_name String-Ressource zu entsprechen.

Die Syntax@ Zeichenfolge / app_namesagt fi Android "

die Zeichenfolge Ressource mit
dem NamenApp Name". Dies bewirkt, dass Android die entsprechende
scannenstrings.xmlfich

(Or jede andere fi
enthält String-Ressourcen in Ihremres

/ Werte /Verzeichnis) zu fi versuchenApp Name.

styled Text

VieleDinge in Android können Rich-Text-Anzeigen, wo der Text einige leichte HTML-Markup mit formatiert wurde: <b>, <i> und <u>. Ihre String-Ressourcen unterstützen dies, indem Sie einfach mit den HTML-Tags, wie Sie es in einer Web-Seite:

CDATA. CDATA Run. Führen Sie, DATEN, Ausführen.

Schon seitein Zeichenketten Ressource XML fi
ist eine XML-fi
obIhre Nachricht
enthält<,> Oder & Zeichen (andere als die Formatierungs-Tags oben aufgeführten), müssen Sie einen CDATA-Abschnitt zu verwenden:

Der Verzeichnisname

Unsere Zeichenfolge Ressourcen in unseren Stub-Projekt in der res / Werte / strings.xml fi sind Da diese Verzeichnisnamen (Werte) keine Suffixe hat, werden die String-Ressourcen in diesem Verzeichnis für jede Art von Situation, einschließlich der Gebietsschema für das Gerät gültig.

Wir werdenmüssen zusätzliche Verzeichnisse mit deutlichen strings.xml fi

, In andere

Sprachen unterstützen. Wir decken, wie das zu tunspäter imdieses Buch.

Bearbeiten von String-Ressourcen

Wenn Sie einen Doppelklick aufeine String-Ressource fi
mögenres / Werte / strings.xml, in

Android Studio, haben Sie die XML und bearbeiten Sie sie auf diese Weise dargestellt. Es gibt eine Option für eine eigene String-Übersetzungs Ansicht Eingabe,überdachtespäter imdieses Buch.

Bekamdas Bild?

Android unterstützt Bilder indie PNG, JPEG und GIF-Formate. GIF ist offiziell entmutigt, aber; PNG
ist das Gesamt bevorzugte Format. Android unterstützt auch einige proprietäre XML-basierte Bildformate, obwohl wir nicht diejenigen, erst später im Buch ausführlich diskutieren. Viele neuere Versionen von Android unterstützt auch WebP Bildformat von Google, obwohl dies nicht besonders beliebt ist.

Es gibt zweiArten von Ressourcen, die Bilder wie diese verwenden: Drawables und mipmaps. In Wahrheit sind sie nahezu identisch. Mipmaps sind vor allem für "Launcher Icons" verwendet -
die Symbole in Home-Bildschirm Werfer gesehen, die Aktivitäten zu identifizieren, die der Benutzer beginnen kann. Drawables halten alles andere.

(wenn du bistein erfahrener Android-Entwickler und diesen Abschnitt lesen: während drawable Ressourcen entfernt werden könnten, wenn eine APK-Verpackung, wie für die Gradle für Android Split-System für die Dichtespezifische Ausgaben einer App zu machen, MipMap Ressourcen allein gelassen, scheinbar)

Es ist möglich, zu haben,res / ziehbar /undres / MipMap /Verzeichnisse in einem Android-Modul.

Allerdings werden Sienicht fi

Bitmapses in der Regel. Stattdessen,diejenigen, befinden sich
in Verzeichnissen wieres / ziehbar-MDPI /undres / ziehbar-hdpi /.

Diese beziehen sich auf verschiedene Ressourcengruppen. Die Suffixe (zB-mdpi, -hdpi) sind gatoren, was darauf hinweist, unter welchen Umständen die in diesen Verzeichnissen gespeicherten Bilder verwendet werden soll. Insbesondere zeigt -ldpi Bilder, die auf Geräten mit niedriger Dichte Bildschirme verwendet werden sollen (etwa 120 Punkten pro Zoll oder "dpi"). Die -mdpi ausrei zeigt Ressourcen für mitteldichte Bildschirme (ca. 160dpi), -hdpi zeigt an Ressourcen für High-Density-Bildschirme (ca. 240dpi). -xhdpi zeigt an Ressourcen für extrahochdichte Bildschirme (ca. 320dpi), -
xxhdpi zeigt an Extra-Extra-High-Density-Bildschirme (ca. 480dpi), -xxxhdpi zeigt Extra-extra-extra-High-Density-Bildschirme (ca. 640dpi), und so weiter.

Imdas EmPubLite Tutorial-Projekt, werden Sie fi
eine Reihe von MipMap Verzeichnisse mit
den gleichen Arten von Endungen (zB ,. res / Mipmap-hdpi). Innerhalb jedes dieser Verzeichnisse erhalten Sie eine ic_launcher.png fi sehen

Dies ist der Aktiensymbol, das für Ihre Anwendung
im Home-Bildschirm Launcher verwendet wird. Jedes der Bilder ist die gleiche Symbol, aber die höhere Dichte Symbole haben mehr Pixel. Ziel ist es für das Bild auf jedem Gerät in etwa die gleiche physikalische Größe zu sein, höhere Dichten mit detailliertere Bilder zu haben.

UnserAndroidManifest.xmlfi
dann verweist unsereic_launcherSymbol indas

<Application>Element:

(von

EmPubLite-Android Studio / T3-Manifest / EmPubLite / app /
src / main / AndroidManifest.xml)

Hinweiseinfach, dass das Manifest bezieht sich auf @ MipMap / ic_launcher, Android zu fi sagen
eine Mipmap Ressource namens ic_launcher. Die Ressource-Referenz zeigt nicht
die fi

Typ der Ressource - es gibt keine .png in der Ressource-Kennung. Dies bedeutet,
dass Sie nicht ic_launcher.png und ic_launcher.jpg im selben Projekt haben kann, da sie beide von der gleichen Kennung identifiziert werden würde. Sie müssen die "Basisnamen" (fi zu halten
sans Erweiterung) verschieden für alle Ihre Bilder.

Ebenfalls,das @ MipMap / ic_launcher Referenz erwähnt nicht, welche Rasterdichte zu verwenden.

Das liegt daran, dass Android die richtige Rasterdichte wählen, zu verwenden, basierend auf dem Gerät, das Ihre Anwendung ausgeführt wird. Sie müssen darüber ausdrücklich keine Sorge, über mehrere Kopien Ihrer Symbol haben. Wenn Android erkennt, dass das Gerät eine Rasterdichte hat, für die Sie ein Symbol fehlt, wird Android nehmen Sie die nächsten nächstgelegene und skalieren.

Erste Android Drawables

Du darfst seinGrafiker. Oder Sie können einen Grafikdesigner kennen. In diesen Fällen können Sie Ihre eigenen Icons erstellen, idealerweise folgende GoogleDesign-Richtlinien für Ikonographie.

Wenn du bistkein Grafikdesigner und verfügen nicht über einen leichten Zugang zu einem, müssen Sie mit Ihrem drawable Ressourcen durch andere Mittel zu kommen. Es gibt eine Vielzahl von

Symbolbibliotheken von Drittherstellern verfügbar, aber die folgenden Abschnitte für die Umsetzung Symbole in der App einige der Google-Lösungen skizzieren.

Android Image-Asset-Assistent

Android Studio bietet ein Image-Asset-Assistenten. Dieser Assistent ist so konzipiert, zu nehmenein Starter-Bild, das Sie Icons und geben, in einer Vielzahl von Dichten, die das Bild für ein bestimmtes Bild Rolle, wie Ihr Home-Bildschirm Launcher-Symbol (die ic_launcher.png verwenden fi wir sahen früher indieses Kapitel). Der Image-Asset-Assistent führt Sie MipMap Ressourcen geben, wenn Sie wählen Launcher Icons zu erstellen, und es wird Ihnen drawable Ressourcen geben, wenn Sie andere Arten von Symbolen wählen zu erstellen.

Es gibt aucheinem separaten Vektor Asset-Assistent, diskutiertspäter imdieses Buch.

Android Asset-Studio

Die gleiche Grundfunktionalität gefunden inder Image-Asset-Assistent ist außerhalb jeder IDE (aber in einem Chrome-Browser) in Form der zur Verfügung stehendenAndroid Asset-Studio. Wie beider Image-Asset-Assistenten können Sie eine Art Symbol (zB Launcher Icons) wählen:

Dann kannst dugeben die Quelle des Grundbild (hochgeladen fi

Dosen-Cliparts oder

Freitext) und andere Konfigurationsdaten. Die resultierenden Bilder in verschiedenen Dichten, kann heruntergeladen werden unterdie unten auf der Seite:

Bearbeiten vorhandener Ressourcen Drawable

Android Studio tutnicht mit jeder Art von Bild-Editor versenden, die Sie für PNG und JPEG-fi verwenden könnte

. Daher werden Sie fi
sichBearbeitung dieser Bilder außerhalb

Ihrer IDE mit anderen Werkzeugen.

Maße

Maßesind an mehreren Stellen im Android benutzt, um Entfernungen, wie ein Widget Größe zu beschreiben. Es gibt verschiedene Maßeinheiten für Sie da:

1. px bedeutet Hardware Pixel, deren Größe je nach Gerät unterschiedlich werden, da nicht alle Geräte die gleiche Rasterdichte

2. in und mm für Zoll und Millimeter, die jeweils auf die tatsächliche Größe des Bildschirms basiert

3. pt für Punkte, die publizistisch ist 1/72. von einem Zoll (wiederum auf der Grundlage der tatsächlichen physikalischen Größe des Bildschirms)

4. Dip (oder dp) für dichteunabhängige Pixel - ein Dip entspricht einer Hardware-Pixel für eine ~ 160dpi Auflösung Bildschirm, sondern ein Dip gleich zwei Hardware-Pixel auf einem Bildschirm ~ 320dpi

5. sp für skalierte Pixeln, wobei ein sp einer Dip für normale Schriftskalenniveaus entspricht, Vergrößern und Verkleinern wie in den Einstellungen auf die Benutzer-gewählten Schriftart Skalenniveau basierend brauchte

Dimension Ressourcen, sind standardmäßig gehalten ineindimens.xmlfi
im dasres / Werte /

Verzeichnisdas gilt auch die Saiten.

Um kodiereneine Dimension als eine Ressource, ein Dimen Element dimens.xml, mit einem Namensattribut für Ihren eindeutigen Namen für diese Ressource, und ein einzelnes Kind Textelement, die den Wert hinzu:

Imein Layout können Sie Referenz Abmessungen wie@dimen / ..., Wo die Ellipsen ein Platzhalter für Ihren eindeutigen Namen für die Ressource (zBdünnundFettvondie Probe oben).

In Java verweisen Sie Dimension Ressourcen durch den eindeutigen Namen mit dem

PräfixR.dimen.(z.B,Resources.getDimension (R.dimen.thin)).

Während unser Stub-Projekt tutverwenden Dimension Ressourcen nicht, wir werden sie bald genug sehen.

Bearbeiten Dimension Ressourcen

Wie bei den meistenTypen von XML-Ressourcen, nur Android Studio hat die XML direkt bearbeiten, wenn Sie einen Doppelklick auf die Ressource im Projekt-Explorer.

Die Ressource, die werden nicht namentlich genannt ... Doch

Ihr Stub-Projekt hat auchres / layout / Verzeichnis, zusätzlich zu den oben beschriebenen,. Das ist für die UI-Layouts, die beschreiben, was Ihre Benutzeroberfläche aussehen sollte.

Wir werden uns inbeginnen die Details dieser Art der Ressource, wie wir unsere Benutzeroberflächen Prüfung inein kommender Kapitel.

Tutorial # 4- Einstellen Unsere Ressourcen

UnserEmPubLite Projekt hat einige erste Ressourcen. Allerdings sind die Standardeinstellungen nicht das, was wir für langfristig wollen. So, zusätzlich zu das Hinzufügen neuer Ressourcen in Zukunft Tutorials, werden wir diejenigen, fi nden wir bereits in diesem Tutorial haben.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Ändernder Name

Unsere Anwendung zeigt überall als "EmPubLite" up:

• Imdie Titelleiste unserer Tätigkeit

• Wiedie Beschriftung unter unserem Symbol im Startbildschirm Launcher

• Imdie Anwendungsliste in der App Einstellungen

• Und so weiter

We sollte das ändern "EmPub Lite" und fügte hinzu, einen Raum zum leichteren Lesen zu sein, und zu zeigen, dass dies eine "lite" Version des vollen EmPub Anwendung ist.

Doppelklicken Sie aufdasres / Werte / strings.xmlfi
im Ihre Projekt-Explorer.

Imder XML-Editor für die String-Ressourcen, werden Sie fi
ein Element, das wie folgt
aussieht:

Veränderungder Textknoten in diesem Element zu EmPub Lite. Dann speichern Sie die Änderungen, so dass Sie so etwas wie:

Schritt 2: Änderndas Symbol

Die Build-Tools liefern unsein Aktiensymbol für den Launcher zu verwenden - die tatsächlich verwendete Bild variiert von Android Tools Release. Allerdings können wir sie auf etwas anderes zu ändern. Zum Beispiel könnten wir das Symbol Teil des CommonsWare Logo verwenden: Herunterladendas Molekül PNG fi
von die CommonsWare Websiteund speichern Sie
es irgendwo auf Ihrer Entwicklungsmaschine.

Dann mit der rechten Maustaste aufdie res / Verzeichnis in Ihrem Haupt-sourceSet im Projekt-Explorer, und wählen Sie Neu> Image-Asset aus dem Kontextmenü. Das wird die Asset-Studio-Assistenten bringen:

Klickendie "Bild" Radio-Button in der "Nutzungsart" Reihe. Klicken Sie dann auf die "..." auf der rechten Seite des "Path" fi
und wählen die molecule.png fi
dass Sie heruntergeladen
haben. Außerdem sicher, dass "Skalierung" wird auf "Shrink to Fit", und wählen Sie "Keine" aus dem "Shape" drop-down. Dies sollte Ihnen eine Vorschau von dem, was die Symbole aussehen wird:

Verlassender Rest des Assistenten allein, dann klicken Sie auf Weiter, um zur nächsten Seite zu gelangen:

Du solltest bekommeneine rote Warn nach unten, was darauf hinweist, dass, wenn Sie fi der

Assistent, werden Sie bestehende fi überschreiben

. Dies wird erwartet, da wir versuchen,
die alte ic_launcher.png fi ersetzen
mit neue. So gehen Sie vor und klicken Sie auf Fertig
stellen.

Schritt # 3: Laufendas Ergebnis

Wenn Sie laufendie resultierende App, werden Sie sehen, dass es mit dem neuen Namen und das Symbol zeigt sich, wie im Launcher:

In unserer nächsten Folge ...

… wir werdenhinzufügeneine Fortschrittsanzeigenachdie Benutzeroberfläche unserer Tutorial-Projekt.

Die Theorie des Widgets

Es gibteine gute Chance, dass Sie bereits mit der Arbeit mit Widget-basierte UI-Frameworks getan haben. In diesem Fall wird ein großer Teil dieses Kapitels überprüft werden kann, obwohl der Abschnitt Check-out auf derabsolute Positionierung Anti-Mustersollten auf jeden Fall lohnen.

Es gibtobwohl eine Chance, dass Ihr UI Hintergrund hat sich von Orten kommen, wo Sie haben nicht ein traditionelles Widget Rahmen verwendet haben, wo entweder Sie wurden alle von der Zeichnung selbst (zum Beispiel Spiel-Frameworks) tun oder wo die Benutzeroberfläche definiert ist mehr in der Form eines Dokuments (zB klassische Web-Entwicklung). In diesem Kapitel wird auf Sie, richtet Ihnen eine Vorstellung davon zu geben, was wir reden, wenn die Vorstellung von Widgets und Containern zu diskutieren.

Was sind Widgets?

Wikipedia hateine schöne Definition eines Widgets:

In der Computerprogrammierung,ein Widget (oder Kontrolle) ist ein Element einer
grafischen Benutzeroberfläche (GUI), die eine Informationsanordnung veränderbar durch den Benutzer, beispielsweise einem Fenster oder einem Textfeld anzeigt. Das
bestimmende Merkmal eines Widgets ist eine einzige Interaktionspunkt für die direkte

Manipulation einer bestimmten Art von Daten zur Verfügung zu stellen. Mit anderen Worten, sind Widgets grundlegende visuelle Bausteine, die in einer Anwendung
kombiniert, halten alle von der Anwendung verarbeiteten Daten und die zur Verfügung stehenden Interaktionen auf diese Daten.

(Zitat ausNehmen Sie die 7. März 2014 Version der Seite), zum

Beispiel, diese Android Bildschirm:

Hier sehen wir:

• ein Text, wie "Phone-only, nicht synchronisierten co ..." und "TELEFON"

• eine Ikone derein Kontakt "Rolodex" Karte

• einige DatenEintrag fi
mit Hinweise wie "Name" und "Unternehmen"

• einige "Spinner" Drop-Down-Listen (die Elemente mitDie Pfeilspitzen zeigen Südosten)

• einige graue Trennlinien

Alles oben aufgeführt istein Widget. Die Benutzeroberfläche für die meisten Android-Bildschirme ( "Aktivitäten") besteht aus einem oder mehreren Widgets gemacht.

Dies giltnicht bedeuten, dass Sie Ihre eigene Zeichnung nicht tun kann. In der Tat sind alle vorhandenen Widgets werden über Low-Level-Zeichenroutinen implementiert, die Sie für alles von Ihrer eigenen benutzerdefinierten Widgets für Spiele verwenden können.

Dies tut auchbedeutet nicht, dass Sie nicht Web-Technologien nutzen können. In der Tat werden wir später in diesem Buch sehenein Widget konzipiert, dass Sie Web-Inhalte einbindenin ein Android Aktivität.

Doch für die meistenNicht-Spiel-Anwendungen, Android-Benutzeroberfläche wird aus mehreren Widgets werden.

Größe,Ränder und Padding

Widgets haben eine Art von Größe, daein Null-Pixel hohe, Null-Pixel breiten Widget ist nicht besonders benutzerfreundlich. Manchmal wird diese Größe durch diktieren, was im Inneren des Widgets ist selbst, wie ein Etikett (Textview) mit einer Größe durch den Text in dem Etikett diktiert hat. Manchmal wird diese Größe durch die Größe diktiert werden von was auch immer das Widget hält ( "Container", die im nächsten Abschnitt beschrieben), wo das Widget will alle verbleibende Breite aufzunehmen und / oder Höhe. Manchmal wird diese Größe ein spezifi Satz von Dimensionen sein.

Widgets können die Margen auswirken. Wie bei CSS, bieten Margen Trennung zwischenein Widget und etwas daneben (zB andere Widgets, Ränder des Bildschirms). Die Margen sind wirklich Widgets bis hin nebeneinander um zu verhindern, entworfen vom Laufen, so dass sie visuell deutlich. Einige Entwickler jedoch versuchen, die Margen als eine Möglichkeit zu nutzen "absolute Positionierung"

in Android zu hacken, das ist ein Anti-Muster, das wir untersuchen werdenspäter imdieses Kapitel.

Widgets können Polster haben. Wie bei CSS, bietet Polsterung Trennung zwischender Inhalt eines Widgets und die Kanten des Widget. Dies ist vor allem mit Widgets verwendet, die irgendeine Art von Hintergrund haben, wie eine Taste, so dass der Inhalt des Widgets (zB Taste Beschriftung) nicht richtig in die Ränder der Schaltfläche ausführen, erneut zur visuellen Unterscheidung.

Was sind Container?

Container sind Möglichkeiten, mehrere Widgets in eine Art von Struktur zu organisieren. Widgets tunnicht selbst natürlich in einem gewissen spezifi Muster ausrichten - wir haben uns dieses Muster zu definieren.

In den meisten GUI-Toolkits,ein Behälter gilt als eine Gruppe von Kindern zu haben. Diese Kinder sind Widgets, oder manchmal auch andere Behälter. Jeder Behälter hat seine Grundregel, wie sie ihre Kinder auf dem Bildschirm legt, möglicherweise angepasst durch Anfragen von den Kindern selbst.

Gemeinsame Behälter Muster umfassen:

• setzen alle Kinder ineine Reihe, eine nach der anderen

• setzen alle Kinder ineine Säule, eine unterhalb der nächste

• arrangierendie Kinder in eine Tabelle oder ein Gitter mit einer gewissen Anzahl von Zeilen und Spalten,

• Ankerdie Kinder an den Seiten des Behälters, entsprechend den Anforderungen von den Kindern gemacht

• Ankerdie Kinder zu anderen Kindern in den Behälter, entsprechend den Anforderungen von den Kindern gemacht

• stapeln alle Kinder, ein auf der Spitzeder nächste

• und so weiter

Imdie Probe Aktivität über die dominante Muster ist eine Spalte, mit Dingen von oben nach unten angelegt. Einige dieser Dinge sind Zeilen, mit Inhalt von links nach rechts angeordnet. Jedoch, wie sich herausstellt, die Fläche mit den meisten dieser widgets ist scrollbar.

Android lieferteine Handvoll von Containern, häufigsten Szenarien zu behandeln entworfen, oben in der Liste darunter alles. Sie sind auch willkommen, Ihre eigenen Container zu erstellen, um Geschäftsregeln implementieren, die von den bestehenden Behälter nicht direkt unterstützt werden.

Hinweisdass Behälter haben eine Größe auch, Polsterung und Margen, wie Widgets tun.

Die absolute Positionierung Anti-Pattern

You könnte sich fragen, warum alle diese Behälter und so notwendig sind. Schließlich kann nicht sagen, dass Sie nur, dass so und so Widget an diesem Pixel geht koordinieren, und das andere Widget geht an diesem Pixel zu koordinieren und so weiter?

Viele Entwickler haben genommenDieser Ansatz - bekannt als absolute Positionierung - im Laufe der Jahre bis zu ihrem endgültigen Bedauern.

Zum Beispiel Windows-Anwendungen viele von Ihnen haben, verwendet zurück inIn den 1990er Jahren, wo, wenn Sie die Anwendung Fenstergröße ändern würde, würde die App reagieren nicht wirklich alles, was viel. Sie würden das Fenster zu erweitern, und die Benutzeroberfläche nicht ändern würde, außer große leere Bereiche des Fensters auf der rechten Seite und am Boden zu haben. Dies liegt daran, die Entwickler einfach gesagt, dass so und so Widget geht an dieses Pixel koordinieren, und das andere Widget geht an die Pixel-Koordinate, unabhängig von der tatsächlichen Fenstergröße.

In der modernen Web-Entwicklung, sehen Siedies in der Debatte überfied gegen fl

Netz

Entwurf. Der Konsens scheint zu sein,dass fl

Designs obwohl häufig besser sind, sie sind
schwieriger einzurichten. Fluid-Web-Designs lassen sich besser verarbeiten Browser Fenstergrößen unterscheiden, ob diese Fenstergrößen sind, weil der Benutzer manuell ihre Browser-Fenster der Größe verändert, oder weil die Fenstergrößen sind durch die diktiert

Bildschirmauflösung vondas Gerät die Webseite anzeigen. Feste Web-Designs - sagen effektiv, dass so und so Element geht bei so und so Pixel koordinieren und so weiter - sind in der Regel einfacher zu bauen, aber mehr schlecht an unterschiedliche Browser Fenstergrößen anzupassen.

Bei mobilen, insbesondere mit Android, wir habeneine breite Palette von möglichen Bildschirmauflösungen, von QVGA (320x240) bis über 1080p (1920x1080) und viele Werte dazwischen. Darüber hinaus ist jeder Gerätehersteller willkommen ein Gerät mit dem, was Auflösung zu schaffen sie es wünschen - es gibt keine Regeln Hersteller bestimmte Auflösungen zu begrenzen. Daher wird, wie Entwickler, ist das Android-Äquivalent von Flüssigkeit Web-Designs, die kritisch, und die Art und Weise, dass durch sinnvolle Nutzung von Containern erreichen wird, die absolute Positionierung zu vermeiden. Die Behälter (und, in geringerem Maße, die widgets) wird bestimmen, wie zusätzlicher Raum verwendet wird, wie die Bildschirme größer und größer werden.

Das Thema dieser Rubrik: Themen

In Web-Entwicklung haben wir Sheets für recht gehabteine Weile. Durch eine solche Cascading Style Sheets (CSS) fi

Können wir verschiedene Regeln darüber, wie unsere Web-Seiten aussehen
sollte festgelegt. Das beinhaltet:

• Festlegungein Standardaussehen für bestimmte HTML-Tags von Tag-Namen (zum

Beispiel die Schriftart und Größe für alle <h1> Einstellung und <h2> Elemente)

• Festlegungein Blick für spezifi HTML-Elemente von Klasse oder ID (zB die Breite einer bestimmten <div> auf eine bestimmte Anzahl von CSS-Pixel Einstellung) In Android,die entsprechenden Konzepte in Stile und Themen zu finden. Arten sind eine Sammlung von Werten für die Eigenschaften (beispielsweise haben eine Vordergrundfarbe rot). Diese können sich auf spezifi Widgets angewendet werden (zum Beispiel das Etikett sollte diese Art annehmen), oder sie können von "Themen" verwendet werden, die die Standard-Look für alle Arten von Widgets und andere Elemente unserer Benutzeroberfläche zur Verfügung stellen.

Natürlich tust dukein Thema für Ihre App erklären müssen. Android finden Sie eine Standard-Look-and-Feel geben ohne spezifi Thema. Das Look-and-Feel hat sich im Laufe der Jahre verändert, aber die visuellen Grundlagen der verschiedenen Android-Widgets zu beeinflussen. Diese Themen haben Namen, mit denen wir auf sie verweisen: Thema, Theme.Holo und Theme.Material.

ImAm Anfang war "Theme" Es, und es war Meh

Weg zurück in Android 1.0,das Standard-Theme wurde einfach als Thema bekannt. Technisch gesehen, erben alle Themen von Themen, wie viel, wie später CSS-Stylesheets "erben" die Einstellungen einzurichtende durch vorherige Sheets.

DasTheme UI hatte einen besonderen Blick auf sie:

Beispielsweise:

• Beimdie oben auf dem Bildschirm, wir hatten einen dünnen grauen "Titelleiste" mit dem Namen unserer App

• Der fokussierte fi

(ein EditText Widget) hatte eine leuchtend orange Umriss,
während es normalerweise ein einfaches weißes Rechteck war

• Die Tasten ( "OK" und "Abbrechen") waren ... na ja ... buttons Holo, dort!

Android 3.0 (API Stufe 11) eingeführtein neues Standard-Theme, Theme.Holo, mit dem so genannten

"holographische Widget Thema" genannt. Dies änderte sich das Aussehen unserer UI etwas:

Jetzt:

• EINt die oben auf dem Bildschirm, haben wir einen "Aktionsleiste", unsere App-Logo und den Namen enthält,

• the konzentriert fi

Hasa blau "underbracket", während normalerweise ist es grau

• Die Tasten sind etwas anders gestylt, miteine größere Schrift, alternative

Hintergründe usw.

In Anbetrachtdas Material

Android 5.0 geändertdas Standard-Theme noch einmal zuTheme.Material:

Jetzt:

• In der Aktionsleiste andie oben auf dem Bildschirm nicht mehr zeigt das App-Symbol

• Unsere fi
ist durch einen Unter angegeben, die teal wenn fokussiert oder grau ist,
wenn unkonzentriert

• Die Tasten sind nun in allen Caps Schriftart gezwungen, miteine etwas kleinere Schriftgröße und auf subtile Weise anders Hintergrund, als wir mit Theme.Holo hatte TunMehr mit Themen

Natürlich können wir tun,viel mehr als nur diese verwenden. Es gibt noch andere Lager Themen, mit unterschiedlichen Merkmalen. Darüber hinaus können wir die Themen, die von der Definition unserer eigenen (abgeleitet von einem Lager Thema) und können einige der Eigenschaften (zB

Austausch der blaugrüne Farbe mit etwas anderem) anpassen.

Wir werden uns viel mehr in kundenspezifische Designs zu schaffen undThemenspäter imdas Buch.

Aber wir werden sehen,die Effekte vonThema.Theme.Holo, undTheme.Materialauf Lager Widgetsein kommender Kapitel.

Die Android-Benutzeroberfläche

Das Projekt, das Sie erstellt ineine frühere Tutorialwar nur die Standard-fi von den Android Build-Tools erzeugt - Sie nicht schreiben, jeder Java-Code selbst. In diesem Kapitel werden wir die grundlegenden Java-Code und Ressourcen untersuchen, die ein Android-Aktivität bilden.

Die Aktivität

Der Java-Quellcodedass Sie in einem Standard-Java-Stil Baum von Verzeichnissen auf dem Java-Paket basiert wird beibehalten Sie ausgewählt haben, als Sie das Projekt erstellt (zBcom.commonsware.androidErgebnisse incom / commonsware / android /). Android Studio habendiese Quelle, die standardmäßig inapp / src / main / java /aus derdie Top-Level-Projekt Wurzel.

Wenn Sie überprüftdie Checkbox in Ihrem IDE-Assistenten neue Projekt eine Aktivität zu erstellen, werden Sie, im innersten Verzeichnis haben, eine Java-Quelle fi eine Aktivitätsklasse darstellt.

Eine sehr einfache Tätigkeit wie folgt aussieht:

(von

EmPubLite-Android Studio / T2-Projekt / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Sezieren die Aktivität

Lassen Sie uns untersuchenDiese Java-Code Stück für Stück:

(von

EmPubLite-Android Studio / T2-Projekt / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

In der Standardeinstellungdie Paketdeklaration ist die gleiche wie die, die Sie bei der Erstellung des Projekts. Und wie jedes andere Java-Projekt, müssen Sie alle Klassen zu importieren, die Sie verweisen. Die meisten der Android-spezifi-Klassen sind in der Android-Paket.

Merkendass nicht jede Java SE Klasse Android-Programme zur Verfügung! Besuche denAndroid Klassenreferenzum zu sehen, was ist undNicht verfügbar.

(von

EmPubLite-Android Studio / T2-Projekt / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Die Aktivitäten sind öffentliche Klassen, abgeleitet vondie android.app.Activity Basisklasse (oder möglicherweise von einer anderen Klasse, die sich von Aktivität erbt). Sie können alle Daten, Mitglieder, die Sie entscheiden, dass Sie benötigen, wenn der Anfangscode keine hat.

(von

EmPubLite-Android Studio / T2-Projekt / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

DasonCreate () Methode aufgerufen wird, wenn die Aktivität gestartet wird. Wir werden die Bundle-Parameter auf onCreate () diskutierenimein späteres Kapitel. Fürder Moment, halten es für eine undurchsichtige Griff, dass alle Aktivitäten bei der Erstellung erhalten.

Der fi
was man normalerweise in onCreate () ist Kette nach oben zu der übergeordneten

Klasse, so dass die Lager Android Aktivität Initialisierung getan werden kann, tun sollten. Die einzige andere Erklärung in unseren Stub Projekt onCreate () ist ein Aufruf an setContentView ().

Dies ist, wo wir Android sagen, was die Benutzeroberfläche soll für unsere Tätigkeit.

Dies wirftdie Frage: Was bedeutet R.layout.main bedeuten? Woher kam diese R gekommen?

ErklärenDazu brauchen wir denken über das Layout Ressourcen zu beginnen und wie Ressourcen aus Java-Code verwiesen wird.

Mit XML-basierte Layouts

Wie bereits inIm vorigen Kapitel verwendet Android eine Reihe von Widgets und Behälter Ihre typische Benutzeroberfläche zu beschreiben. Diese alle erben von einer android.view.View Basisklasse, für Dinge, die in einem Standard-Widget-basierte Aktivität wiedergegeben werden kann.

Auch wenn es technisch möglich ist, Widgets und Behälter zu unserer Tätigkeit rein durch Java-Code zu erstellen und zu befestigen,die häufiger Ansatz ist ein XML-basiertes Layout fi verwenden

Dynamische Instantiierung der Widgets ist für kompliziertere Szenarien reserviert, wo Die Widgets sind nicht zur Compile-Zeit (zB bevölkern eine Spalte von Radiobuttons basierend auf abgerufenen Daten aus dem Internet) bekannt.

Mitin diesem Sinne, ist es Zeit, die XML-auszubrechen und lernen, wie man Android Aktivität Inhalte zu legen, auf diese Weise.

Was ist ein XML-basiertes Layout?

Wieder Name schon sagt, ein XML-basiertes Layout ist ein spezifi
von seine Widgets

'Beziehungen zu jeweils anderen - und Container - im XML-Format codiert. Insbesondere hält Android XML-basierte Layouts Ressourcen, und als solche Layout fi sein
sind gespeichert in
die res / Layout / Verzeichnisses im Android-Projekt (oder, wie wir später andere Layout-RessourceSets, wie res / Layout-Land sehen werden / für Layouts zu verwenden, wenn das Gerät im Querformat gehalten wird). Wie in diesem Buch festgestellt, an anderer Stelle, so ist die anfängliche Lage der res / in app / src / main / für Android Studio.

Jede XML-fi
enthältein Baum von Elementen ein Layout von Widgets und Container
angeben, die eine Ansicht bilden. Die Attribute der XML-Elemente sind Eigenschaften, die beschreiben, wie ein Widget aussehen soll oder wie ein Container verhalten soll. Zum Beispiel, wenn ein Button-Element ein Attribut-Wert von Android hat: Textart = "bold", das bedeutet, dass der Text auf dem Gesicht der Taste erscheinen soll in einem Fettdruck Schriftstil gemacht werden.

Zum Beispiel, hier isteinres / Layout / main.xmlfi
das könnte mit der oben
erwähnten Aktivität verwendet werden:

(von

EmPubLite-Android Studio / T2-Projekt / EmPubLite / app /
src / main / res / Layout / main.xml)

Die KlasseName eines Widgets oder Container - wieRelativeLayoutoderTextview- Bildet den Namen des XML-Elements. Schon seitTextviewWidget Android-versorgt ein, können wir nur nutzendie nackten Klassennamen. Wenn Sie Ihre eigenen Widgets als Subklassen
erstellenandroid.view.View, Müssten Sie auch ein komplettes Paket Erklärung zur Verfügung zu stellen (zBcom.commonsware.android.MyWidget).

Der UrsprungElement muss das Android-XML-Namespace zu deklarieren (xmlns: android =

"http://schemas.android.com/apk/res/android"). Alle anderen Elemente werden die Kinder der Wurzel sein und wird diese Namespace-Deklaration erben.

Die Attribute sind Eigenschaften vondas Widget oder Behälter, die beschreiben, was es aussehen und funktionieren sollte. Beispielsweise dieAndroid: layout_centerHorizontal = "true"Attribut

aufdasTextviewElement
anzeigt,
dass
dieTextviewsollte
in
seiner
zentriert
werdenRelativeLayoutElternteil.

Wir werden in die Details erhalten überDiese Attribute, ihre möglichen Werte und ihre Verwendung in den folgenden Kapiteln. Beachten Sie, dass diese Attribute im Tools-Namensraum (zB Werkzeuge: Kontext) gibt es nur die Android Build-Tools zu unterstützen und wirken sich nicht auf die Laufzeit der Ausführung des Projekts.

Android SDK Schiffe mitein Werkzeug (aapt), die die Layouts verwendet. Dieses Tool wird automatisch von Ihrem Android-Werkzeugkette (zB Android Studio) aufgerufen. Von besonderer Bedeutung für Sie als Entwickler ist, dass aapt eine fi R.java Quelle erzeugt
so dass Sie

Layouts und Widgets zuzugreifen innerhalbdiese Layouts direkt aus Java-Code. Mit anderen Worten, das ist, wo die Magie R-Wert in setContentView verwendet () kommt. Wir werden diskutieren, dass ein bisschen mehrspäter imdieses Kapitel.

XML-Layouts und Ihre IDE

Wenn Sie Android Studio verwenden und Sie einen Doppelklick aufdie res / Layout / main.xml fi in Ihrem Projekt werden Sie nicht von Anfang an, dass die XML zu sehen. Stattdessen werden Sie in den grafischen Layout-Editor gezogen werden:

Wir werden viel mehr ins Detail gehen über die Verwendung vondie grafischen Layout-Editor inein kommenden Kapitelbeginnen, wie wir mehr mit spezifi arbeiten Widgets und Containern.

Gründe für die Verwendung von XML-basierten Layouts?

Fast alles, was Sie XML-Layout fi Sie mit
kannerreicht durch Java-Code werden. Zum

Beispiel könnten Sie verwendensetText () eine Taste, um eine bestimmte Beschriftung anzuzeigen, anstatt eine Eigenschaft in einem XML-Layout verwenden. Da XML-Layouts noch eine andere fi sind für Sie im Auge zu behalten, brauchen wir gute Gründe für eine solche fi mit

.

Vielleichtder wichtigste Grund dafür liegt in der Schaffung von Werkzeugen für die View-Definition, wie die bereits erwähnten grafischen Layout-Editoren in Android Studio zu unterstützen. Solche GUI-Builder im Prinzip könnte, erzeugen Java-Code anstelle von XML. Die Herausforderung Forschung ist die Definition um Unterstützung Änderungen zu lesen - das ist viel einfacher, wenn die Daten in a
strukturierten Format wie XMLals in einer Programmiersprache. Darüber hinaus ist aus handgeschriebenen Code ausgesondert die erzeugten Bits zu halten macht es weniger wahrscheinlich, dass jemand individuell gestaltete Quelle zufällig verprügelt wird erhalten, wenn die erzeugten Bits neu generiert erhalten. XML-Formulare ein schöner Mittelweg zwischen etwas, das einfach ist, für Werkzeug-Autoren und einfach zu bedienen für Programmierer mit je nach Bedarf von Hand zu arbeiten.

Auch XML alsein GUI-Definition-Format wird immer üblicher.

MicrosoftsXAMLAdobesBiegenGooglesGWTUnd MozillaXULalle nehmenein ähnlicher Ansatz wie von Android: Layout Details in einem XML-fi setzen
und setzen Programmierung smarts
in Quelle fi

(ZB JavaScript für XUL). Viele weniger bekannte GUI-Frameworks, wieZK,

Auch XML für View-Definition verwenden. Während "folgendedie Herde "ist nicht unbedingt die beste Politik, hat es den Vorteil, zu helfen haben, den Übergang in Android von jedem anderen XML-zentrierten Sicht Beschreibungssprache zu erleichtern.

Die Verwendung von Layoutsvon Java

Gegebensorgfältig die Widgets und Container für Ihre Ansicht in einem XML-Layout fi einrichten, dass Sie
genannt main.xml in res / Layout gespeichert / alles, was Sie brauchen, ist eine Aussage in Ihrer Tätigkeit des onCreate () Rückruf, der das Layout zu verwenden, wie wir in unseren Stub Projektaktivität sah:

Hier,R.layout.mainladen in erzählt Androiddas Layout (Layout) Ressource (R) Mit dem Namen main.xml (Main).

Grund Widgets

Jedes GUI-Toolkit hat einige grundlegende Widgets: fi

, Etiketten, Buttons, etc.

Android Toolkit ist nicht anders als in den Umfang und die grundlegenden Widgets wird eine gute Einführung, wie Widgets arbeiten in Android Aktivitäten. Wir werden eine Anzahl von diesen in diesem Kapitel untersuchen.

Gemeinsame Konzepte

Es gibteinige Kernfunktionen von Widgets, die wir von Anfang an zu diskutieren müssen, bevor wir in die Details auf spezifi Arten von Widgets tauchen.

Widgets und Attribute

Wie bereits erwähnt inein vorheriges Kapitel, Widgets haben Attributedie beschreiben, wie sie sich verhalten sollten. In einem XML-Layout fi
diese sind buchstäblich XML-Attribute auf das

Element des Widgets in der fi

Normalerweise gibt es entsprechende Getter und Setter-

Methoden für die Manipulationdieses Attribut zur Laufzeit von Java-Code.

Wenn Sie besuchendie JavaDocs für ein Widget, wiedie JavaDocs für Textview, Erhalten Sie eine

"XML-Attribute" Tisch in der Nähe der Spitze zu sehen. Diese listet alle der eindeutig auf diese Klasse definiert Attribute und die "Inherited XML-Attribute" Tabelle, die Listen alle jene folgt, dass das Widget von Oberklassen, wie zum Beispiel anzeigen erbt. Natürlich listen die JavaDocs auch die fi

, Konstanten, Konstrukteure und öffentliche / geschützte Methoden, die Sie auf das Widget selbst verwenden können.

Dieses Buch tutnicht versuchen, jedes einzelne Attribut auf jedem Widget zu erklären. Wir werden jedoch decken die beliebtesten Widgets und die meistgenutzten Attribute auf diese Widgets.

Referenzierung Widgets von ID

Viele Widgets und Behälter nurmüssen in der XML-Layout fi erscheinen
und machen nicht
brauchen in Ihrem Java-Code referenziert werden. Zum Beispiel kann ein statischer Etikett (Textview) braucht oft nur in dem Layout fi sein
um anzuzeigen, wo es angezeigt werden
soll.

Alles, was Sie in Ihrer Java-Quelle verwenden wollen, obwohl,braucht ein Android: id.

Die Konvention ist, zu verwenden,@ + Id / ... als der ID-Wert, wo die ... Ihre lokal eindeutigen Namen für das Widget in Frage stellt, für die fi
das Auftreten voneine bestimmte ID-Wert in

Ihrem Layout fi

Das zweite und die folgenden Ereignisse in das gleiche Layout fi
sollte fallendas Zeichen +.

Android bietetein paar spezielle Android: id-Werte, von der Form @android: id / ... - wir werden einige von ihnen in den verschiedenen Kapiteln dieses Buches zu sehen.

Für den Zugriff auf unsere identifiziert Widgets, VerwendungfindViewById (), ist es die numerische Kennung des Widgets in Frage vorbei. Diese numerische Kennung wurde von Android in der RKlasse als R.id.something erzeugt (wo etwas ist, das spezifi-Widget Sie suchen).

Dieses Konzept wird wichtig werden, wenn wir versuchen, die Zuhörer zu unserer Widgets zu befestigen (zB fi
aus, wenneine Checkbox aktiviert ist), oder wenn wir Referenzierung

Widgets von anderen Widgets in einem Layout XML fi versuchen

(Beispielsweise mit

RelativeLayout). Alledies wird später in diesem Kapitel behandelt.

Größe
die meistendie Zeit, müssen wir Android zu sagen, wie groß wir unsere Widgets sein wollen.

Gelegentlich wird dies für uns behandelt werden - wir werden ein Beispiel, dass mit Tablelayout sehen inein kommender Kapitel. Aber wir in der Regelbenötigen diese Informationen selbst zur Verfügung zu stellen.

Tundass, müssen Sie liefernandroid: layout_widthundandroid: layout_heightAttribute auf Ihre Widgets indas XML-Layout fi

Diese Attribute 'Werte haben drei Geschmacksrichtungen:

1. Sie können zur Verfügung stelleneine spezifi Dimension, wie 125dip das Widget, um anzuzeigen, sollte genau eine bestimmte Größe (hier: 125 dichteunabhängige Pixel) aufnehmen

2. Sie können zur Verfügung stellenwrap_content, was bedeutet, das Widget so viel Platz in Anspruch nehmen sollte, wie sein Inhalt erfordern (zB ein Textview-Label-Widget Inhalt ist der Text angezeigt werden soll)

3. Sie können zur Verfügung stellenmatch_parent, die das Widget bedeutet sollten sich alle noch verfügbaren Raum in seiner umschließenden Behälter fi

Die beiden letztgenannten Varianten sinddie häufigste, wie sie von Bildschirmgröße unabhängig sind, so dass Android Ihre Ansicht einzustellen, um den verfügbaren Platz fi nden.

Hinweisdass Sie werden auch sehen,fill_parent. Dies ist einälteres Synonym
fürmatch_parent.match_parentistder empfohlene Wert geht nach vorn, aberfill_parentwird sicherlich funktionieren.

Dieses Kapitel konzentriert sich auf die einzelnen Widgets. Größe wird viel wichtiger, wenn wir mehrere Widgets starten Kombination aufder Bildschirm auf einmal, und so werden wir mehr Zeit verbringen Szenarien in späteren Kapiteln auf Sizing.

Daslayout_ Präfix zu diesen Attributen bedeutet, dass diese Attribute Anforderungen durch das Widget in seine umschließenden Behälter darstellen. Ob diese Anforderungen wirklich geehrt werden wird ein bisschen davon abhängen, welche andere Widgets gibt es in dem Behälter und dem, was ihre Wünsche sind.

Einbringendas grafische Layout Editor

Wenn Sie öffneneine Layout-Ressource in Android Studio, standardmäßig werden Sie den grafischen Layout-Editor finden Sie unter:

Diese Angeboteeine Drag-and-Drop bedeutet den Inhalt dieses Layoutressource zu definieren.

Android IDEs haben Drag-and-Drop-GUI Gebäude Fähigkeit hattemehrere Jahre, zurückgehend auf, wenn Eclipse-war der offi

IDE. Allerdings Android Studio 2.2 machte einige
signifi

Änderungen im die Art, wie die Drag-and-Drop-GUI-Builder aussieht und
funktioniert. Dieses Buch behandelt diese neuere Look-and-Feel, aber ältere Blog-Posts, Stack Overflow Antworten und ähnliche Ressourcen auf Aspekte der früheren GUI-Builder beziehen.

Mit allenschauen, schauen wir uns die verschiedenen Teile des grafischen Layout-Editor, dass im Auge behalten.

Palette
dominierend die linke Seite des grafischen Layout-Editor ist die Palette-Tool:

Hier werden alle Arten von Widgets und Containerndass Sie ziehen können. Sie sind in Kategorien unterteilt ( "Widgets", "Text Ansichten", "Layouts", etc.) mit vielen Optionen in jedem. Einige sind nicht streng Widgets oder Container, sondern andere Arten von XML-Elemente, die Sie in einem Layout-Ressource haben können (zB <Fragment>, <request>).

Wie wir decken, wie zu benutzendie grafischen Layout-Editor, werden wir sehen, wie einige dieser Widgets, Container und andere Elemente zu erstellen und zu konfigurieren.

Vorschau

Die wichtigsten zentralen Bereichdie grafischen Layout-Editor besteht aus zwei Perspektiven auf Ihrem Layout Ressource Inhalt. Die auf der linken Seite ist eine Vorschau von dem, was Ihre UI ähneln sollte, wenn dieses Layout für die Benutzeroberfläche einer Aktivität verwendet wurden:

Dies gießt Ihr Layout Ressource Inhalt inein Vorschaufenster, die Aspekte eines normalen Android-Gerät, wie die Navigationsleiste am unteren Rand und der Statusleiste am oberen Rand hat.

Wenn Sie ziehen Sie die Elemente ausdie Palette und sie in den Vorschaubereich fallen, werden sie zu Ihrem Layout Ressource hinzugefügt werden.

Entwurf

Nachdas Recht der Vorschaubereich ist der Entwurf Ansicht. Dies auch optisch stellt Ihr Layout Ressource. Anstatt jedoch zeigt Ihnen eine Vorschau von dem, was Ihre UI aussehen könnte, stellt es visuell, was Widget und Container-Klassen Sie verwenden.

Und für einigeArten von Behältern, wird sich zeigen, wie einige der Dimensionierung und Positionierung Regeln, die Sie für die Kinder dieses Containers verwenden:

Fürtriviale Layout Ressource wie dieses - was Sie aus dem Android Studio "Empty Activity" Vorlage erhalten - der Bauplan Ansicht nicht zeigen Ihnen viel. Es wird mit komplexeren Layout Ressourcen nützlicher werden. Insbesondere ist es sehr hilfreich, wenn Sie einige Widgets oder Container bezeichnet haben als unsichtbar zu sein, wie sie im Entwurf angezeigt wird, aber nicht in der Vorschau:

Vorschau Toolbar

Überdie Vorschau und Entwurf ist ein Bi-Level-Symbolleiste, die Sie verschiedene Aspekte der Vorschau und Plan Aussehen und Verhalten konfigurieren können.

Symbolleiste am oberen Rand Ebene

Von links nach rechts,die obere Ebene der Symbolleiste enthält:

• Drei Tasten zum Umschalten, ob Sie sehendie Vorschau, der Bauplan oder beides

• Ein Umschalten zu steuern, ob Sie das Layout Hoch- oder Quer Perspektiven
angewendet sehen

• Ein Drop-down zu wählen, was Gerätegröße und Auflösung sollte für die Vorschau, gekeult von Ihrem Emulator Bilder und die zur Verfügung stehenden Gerätedefinitionen verwendet werden

• Ein Drop-down zu wählen, was API-Ebene sollte für die simulierte UI der Vorschau verwendet werden

• Eine Schaltfläche zu wählen, wasThemazu verwenden, für die Präsentationdie

Benutzeroberfläche der Vorschau

• Eine Schaltfläche zu wählen, welche Sprache für die Bestimmung zu verwenden,
welche Ihrer String-Ressourcen in der Vorschau verwendet wird

• Ein Dropdown-Menü automatisch Klone Ihrer Layouts erstellen füranders

Konfigurationen

Ein paar von denen - vor allem das Thema Wähler und der Begriff der "unterschiedlichen Konfigurationen" - beziehen sich auf Themen, die wir später in diesem Buch erkunden.

Symbolleiste am unteren Rand Ebene

Aufdie rechte Seite der unteren Symbolleiste Ebene sind:

• Zoomsteuerung

• Eine Taste, um den Zoom zum Zurücksetzen den Bereich für die Vorschau und / oder Entwurf zu fi nden

• A-Taste zu aktivieren "Pan und Zoom" Modus (mehr dazu in Kürze)

• Ein "Klingel" Symbol, das anzeigt, ob es irgendwelche Warnungen oder Fehler mit Ihrem Layout Ressource zugeordnet

Die linke Seite vondie untere Ebene der Vorschauleiste ändert sich, basierend auf dem ausgewählten Widget oder Container, Optionen bieten für Sie einfache Änderungen an machen zu können, was auch immer gewählt wird. Wir werden Beispiele dafür in den nächsten Kapiteln sehen Pan und ZoomModus

Die "Pan und Zoom" Modus ermöglicht es Ihnen, zu navigiereneine gezoomte in Version Ihrer Vorschau und / oder ein Muster. Während die Hauptansichten in gezoomt wird, öffnet die "Pan und Zoom" Symbolleiste auf die Schaltfläche Abgreifen eines fl up

Fenster zeigt die
gesamte Vorschau und / oder ein Muster, mit einem roten Feld angibt, welcher Anteil, dass Sie in der Hauptansichten sehen:

Sie können per Dragder rote Rahmen um den fl

Fenster zu ändern, welcher Teil von die
gesamte Zoom-In Ansicht können Sie in der Hauptansicht zu sehen.

Komponentenbaum
zuder unteren linken Ecke ist die Komponentenbaum:

Dies gibt Ihneneine vollständige Baum aller der Widgets und Container innerhalb dieses Layouts Ressource. Er entspricht dem Baum der XML-Elemente in der Layout-Ressource selbst.

Ein Klick auf ein beliebiges Element inKomponentenbaum Highlights es sowohl in der Vorschau und Bauplan Blick sowie schaltet er auf diesem Widget oder Behälter für den Eigenschaftenbereich.

Eigenschaften

Wannein Widget oder Container gewählt - ob über den Komponentenbaum, auf sie in der Vorschau klicken, oder in dem Entwurf darauf klicken - der Bereich Eigenschaften auf der rechten Seite ermöglicht es Ihnen, wie das Widget oder Container Aussehen zu manipulieren und sich verhält.

Standardmäßig wird es bringeneine verkürzte Liste von den wichtigsten Eigenschaften:

Ein Klickdie "Alle Objekte" Link oder auf die grüne Pfeile Symbolleiste auf die Schaltfläche, wechselt auf eine Liste aller Eigenschaften:

Wir werden sehen, was viele vonDiese Eigenschaften sind und wie mit ihnen im Laufe der nächsten Kapiteln zu arbeiten.

Registerkarte Text
zuder Boden des grafischen Layout-Tool, werden Sie sehen, dass es zwei Unterregister enthält.

Ein "Design" umfasst alles oben beschrieben. Die andere, "Text", können Sie die XML-Rohdaten zu bearbeiten, die den eigentlichen Inhalt des Layouts Ressource ist:

In der Standardeinstellungder gesamte Bereich ist mit dem Texteditor gewidmet. Wenn jedoch der Text Unterregister aktiv ist, wird ein "Preview" Werkzeug auf der rechten Seite des angedockten erscheinen

Android Studio-Fenster. Ein Klickdas wird die Vorschau von der Registerkarte Unter entwerfen:

Klicken auf ein Element inDie Vorschau wird das entsprechende XML-Element im Texteditor markieren.

Zuweisen von Labels

Die einfachste Widget istdas Etikett, auf die in Android als Textview. Wie in den meisten GUI-Toolkits, Etiketten sind Bits von Text nicht bearbeitet werden direkt von den Nutzern.

Typischerweise werden sie verwendet, um benachbarte widgets (beispielsweise ein "Name:"

identifizieren Etikett vor einem fi
wo man fi inein Name).

In Java können Sie erstellenein Etikett durch eine Textview-Instanz erstellen. Häufiger jedoch werden Sie Etiketten im XML-Layout fi erstellen
durch Hinzufügen ein Textview-Element
in das Layout, mit einem Android: Text-Eigenschaft den Wert des Etiketts selbst einzustellen.

Wenn Sie Etiketten müssen nach bestimmten Kriterien zu tauschen, wie Internationalisierung, können Sie einen String-Ressource-Referenz in Android verwenden: Text statt (zB @ String /
label).

Beispielsweise inunsere letzten Tutorial, Wir sind immer noch mitdie automatisch generierte res /

Layout / main.xml fi
enthält, unter anderem,ein Textview:

(von

EmPubLite-Android Studio / T4-Ressourcen / EmPubLite / app /
src / main / res / Layout / main.xml)

Android Studio grafische Layout Editor

DasTextview-Widget ist in der "Widgets" Kategorie der Palette im Android Studio grafischen Layout-Editor zur Verfügung:

Sie können per Dragdass Textview aus der Palette in ein Layout fi
im die

Hauptbearbeitungsbereich das Widget, um das Layout hinzuzufügen. Oder ziehen Sie es über den oberen Teil einige Container, die Sie im Komponentenbaum Bereich des Editors sehen es als Kind dieses speziellen Container hinzuzufügen.

Durch Klicken aufdie neue Textview wird stellen Sie den Bereich Eigenschaften mit den verschiedenen Eigenschaften des Widgets aus, die Sie bis nach Bedarf ändern.

Bearbeitungder Text

Die Eigenschaft "Text" ermöglicht es Ihnen, zu wählen oder definiereneine String-Ressource als Text zu dienen angezeigt werden:

Der "Text" mitein Schraubenschlüssel-Symbol ermöglicht es Ihnen, ein separates Stück Text zu schaffen, die in der Vorschau angezeigt wird, aber nicht von Ihrer Anwendung zur Laufzeit verwendet werden.

Sie könnengeben Sie entweder eine wörtliche Zeichenfolge rechts im Fenster Reihe Eigenschaften, oder Sie können klicken Sie auf die Schaltfläche "..." auf der rechten Seite des fi nach
pflücken eine String-Ressource:

Sie können eine der Highlightdiese Ressourcen und klicken Sie auf "OK", es zu benutzen. Oder in Richtung der oberen rechten dieser Dialog gibt es eine "Neue Ressource" drop-down. Wann Betrachten String-Ressourcen,dass Drop-down einen einzigen Befehl enthalten: "Neue Zeichenfolge Value ...". Die Wahl es erlaubt Ihnen eine neue String-Ressource über einen weiteren Dialog zu definieren:

Sie können geben Sie Ihremneue String-Ressource ein Name, der eigentliche Text der Zeichenfolge selbst, die fi
in welchemdie String-Ressource sollte (strings.xml Standardeinstellung)

befinden, und welche Werte / Verzeichnis die Zeichenfolge sollte in (Werte von Standard) gehen. Sie werden auch die "Quelle-Set" wählen - für jetzt, die nur Haupt sein wird. Sobald Sie den Dialog, Ihrem neuen String-Ressource akzeptieren werden Ihrem Textview angewendet werden.

Bearbeitungdie ID

Die "id" Eigenschaft ermöglicht es Ihnen, zu änderndas Android: id-Wert des Widgets:

Der Wert, den Sie fi hier ist das, was nach dem @ geht + id / Teil (zB textView2).

Bemerkenswerte Textview Attribute

Textview hat zahlreiche andere Eigenschaften von Bedeutung für Etiketten, wie zum Beispiel: 1. android: Schrifteinstellendie Schrift für die Beschriftung zu verwenden (zBMonospace) 2. android: Textartum anzuzeigendass die Schrift fett gemacht werden soll (Fett
gedruckt), Kursiv(kursiv) Oder fett und kursiv (Fett Kursiv)

3. android: textcoloreinstellendie Farbe des Textes der Bezeichnung, im RGB-Hex-Format (zB# FF0000für rot) oder ARGB Hex-Format (zB# 88FF0000fürein lichtdurchlässiges rot) Diese Attribute, wie die meisten anderen, kann geändert werden durchder Bereich Eigenschaften.

Beispielsweise indasGrund / LabelBeispielprojekt, werden Sie fi
das folgende Layout fi

(von Grund / Label / app / src / main /
res / Layout / main.xml)

Geradedass das Layout allein, mit dem Stummel Java-Quellcode, um Ihre Anwendung zur Verfügung gestellt, zusammen mit den entsprechenden String-Ressourcen, gibt Ihnen:

Ein Kommandierender Knopf

Android hat ein Button-Widget, das der klassische Druckknopf "me klicken und etwas kühl passieren wird" Widget. Wie sich herausstellt, Knopf ist eine Unterklasse von Textview, so im vorhergehenden Abschnitt diskutiert alles in Bezug auf die Formatierung der Fläche der Taste hält immer noch.

Beispielsweise indasBasic / KnopfBeispielprojekt, werden Sie fi
das folgende Layout fi

(von

Basic / Knopf / app / src / main / res

/ Layout / main.xml)

Geradedass das Layout allein, mit dem Stummel Java-Quellcode, um Ihre Anwendung zur Verfügung gestellt, zusammen mit den entsprechenden String-Ressourcen, gibt Ihnen:

Android Studio grafische Layout Editor

Wie beidas Textview-Widget, das Button-Widget ist in der "Widgets" Teil der Palette im Android Studio grafischen Layout-Editor zur Verfügung:

Sie können per Dragdass Knopf aus der Palette in ein Layout fi
im die

Hauptbearbeitungsbereich das Widget, um das Layout hinzuzufügen. Im Bereich Eigenschaften können Sie dann die verschiedenen Attribute dieser Taste einstellen. Da Knopf Abgeleitet von Textview, sind die meisten Optionen gleich sind (zB "Text").

Tracking-Knopf Klicks

Die Tasten sind Befehls Widgets- Wenn der Benutzer eine Taste drückt, erwarten sie etwas passiert.

Um festzulegen, was passiert, wenn Sie klickenein Knopf, können Sie:

1. Defi
einige Verfahren aufAktivität, die die Schaltfläche enthält, die einen
einzelnen View-Parameter nimmt, hat eine Lücke Rückgabewert, und istöffentlich

2. In Ihrem Layout XML, aufdasTasteElement umfassen dieandroid: onClick

Attribut mitder Name der Methode, die Sie zum Beispiel im vorherigen Schritt definiert, könnten wir eine Methode auf unserer Aktivität haben, die wie folgt aussieht:

Dann könnten wir verwendenDiese XML-Deklaration für das Button selbst, einschließlich android: onClick:

Dies reicht für Android auf "Draht zusammen"Der Button mit dem Click-Handler. Wenn der Benutzer auf die Schaltfläche klickt, wird somemethod () aufgerufen werden.

Ein weiterer Ansatz ist zu überspringenandroid: onClickStatt AufrufsetOnClickListener ()aufdasTasteObjekt in Java-Code. WanneinTastedirekt durch eine Aktivität verwendet wird,Dies wird normalerweise nicht verwendet -android: onClickistein bisschen sauberer. Wenn wir jedoch beginnen,reden über Fragmente, du wirst sehendassandroid: onClicktutnicht funktionieren, dass auch mit Fragmenten, und so werden wir verwendensetOnClickListener ()beimdieser Punkt.

flüchtige Bilder

Android hat zwei Widgets, Ihnen zu helfenBilder einbetten in Ihre Aktivitäten: Image und Image. Wie die Namen vermuten lassen, sind sie bildbasierten Analoga Textview und Button sind.

Jedes Widget nimmt einAndroid: src-Attribut (in einem XML-Layout) angeben, welches Bild zu verwenden. Diese Referenz in der Regel eine drawable Ressource (zB @ ziehbar / Symbol).

Image, Eine Unterklasse vonImageMischt sich in der StandardTasteVerhaltensweisen, für die Klicks und so weiter reagieren.

Nehmen wir zum Beispieleinen Blick auf diemain.xmlLayout aus dasBasic / ImageBeispielprojekt:

(von

Basic / Image / app / src / main / res /

Layout / main.xml)

Das Ergebnis, nur mitder Code-generierte Aktivität, ist einfach das Bild:

Android Studio grafische Layout Editor

DasImage Widget kann in den "Images & Medien" Teil der Palette im Android Studio grafischen Layout-Editor zu finden:

Imageerscheint nebenImageimdass die Werkzeugpalette.

Ziehen Sie an einer derdiese in der Vorschau oder Plan, werden Sie sofort von einem Dialog begrüßt eine drawable Ressource oder Farbe zu wählen, für das Bild zu verwenden: Leider haben Siekeine andere Wahl, als eine von ihnen zu wählen, da aufgrundein Käferwenn Sie, klicken Sie auf Abbrechen, umden Dialog zu verlassen, es verlässt auch die gesamte Drag-and-Drop-Vorgang.

Sie können per Dragdiese in einem Layout fi

Verwenden Sie dann den Bereich

Eigenschaften ihre Attribute zu setzen. Wie alle Widgets, erhalten Sie eine "id" Option haben, um die Android-Set: id-Wert für das Widget. Zwei andere von Bedeutung, obwohl, sind einzigartig und Imageimage:

• "Src" können Sie auswählen,eine drawable Ressource als Bild zu verwenden angezeigt werden, die fi in durch sein wird, was Sie in der Ressource-Dialog gewählt

• "Content" bietetder Text, das Bild zu Benutzern verwendet werden zu beschreiben, die Zugänglichkeit Dienste aktiviert (zB Talkback), wie zum Beispiel sehbehinderte Benutzer haben

• "Scaletype" eröffnetein Drop-down-Menü, in dem Sie auswählen können, wie das Bild skaliert werden soll:

Wir werden prüfen,diese Waagentypen mehr im nächsten Abschnitt.

Skalieren von Bildern

Es ist möglich, vielleicht sogar wahrscheinlich,dass unsere Image Größe nicht genau die Größe der Bilder entsprechen, die wir zeigen wollen. Image unterstützt eine Vielzahl von "Waagentypen", die angeben, wie Android sollte mit der Diskrepanz zwischen der Größe / Seitenverhältnis des Bildes zu tun versuchen, und die Größe / Seitenverhältnis des Image selbst.

Diese Werte können gesehen werden indie JavaDocs indas ImageView.ScaleTypeKlasse. Der Standard(Fitcenter) skaliert einfach das Bild nach oben zu besten den verfügbaren Platz fi nden.

Zu beachten ist,eine Auswahl von "Mitte" wird das Bild in den verfügbaren Raum zentrieren, sondern wird das Bild nicht vergrößern:

Eine Auswahl an centerCrop skaliert das Bild so, dass seine kürzeste Dimension fi dasPlatzangebot und Kulturender Rest:

Eine Auswahl an fitXY skaliert das Bild um den Raum zu fi nden, um das Seitenverhältnis zu ignorieren:

Fields of Green. Oder andere Farben.

Zusammen mit den Tasten und Etiketten, fi
sind die dritte "Anker" der meisten GUI-

Toolkits. In Android, werden sie über das EditText Widget implementiert, die eine Unterklasse der Textview für Etiketten verwendet wird.

Zusammen mitdie Standard-Textview-Attribute (zB Android: Textart), hat EditText andere, die bei der Konstruktion von fi für Sie nützlich sein wird

, Insbesondere android: input, zu
beschreiben, welche Art von Eingabe Ihrer EditText erwartet (Zahlen E-Mail-Adressen Telefonnummern??). Eine ausführliche Erklärung von Android: input und seine Interaktion mit Eingabemethoden-Editoren (auch bekannt als "Soft-Tastaturen") wird in ein diskutiertkommenden Kapitel.

Beispielsweise ausdasBasic / FeldBeispielprojekt, hier ist ein XML-Layout fi eine zeigtText bearbeiten:

(von Basic / Feld / app / src / main / res /

Layout / main.xml)

Hinweisdass wir habenAndroid: input = "textMultiLine", So können die Benutzer in mehreren Zeilen Text einzugeben. Wir haben auch den ursprünglichen Text zu sein, der Wert von a
definiertLizenzString-Ressource.

Das Ergebnis, einmal gebaut und installiert inDer Emulator ist:

Android Studio grafische Layout Editor

Die Android Studio grafische Layout der Palette hatein ganzer Abschnitt in erster Linie auf EditText Widgets, mit dem Namen "Textfelder (EditText)" gewidmet:

Der fi

Eintrag ist ein Allzweck-EditText. Der Rest kommt vorkonfiguriert für
verschiedene Szenarien, wie zum Beispiel den Namen einer Person oder einem Passwort.

Sie können alle ziehendiese in das Layout, verwenden Sie dann den Bereich Eigenschaften relevanten Attribute zu konfigurieren. Die "ID" und "Text" Attribute sind die gleichen wie auf Textview gefunden, wie viele andere Eigenschaften, wie EditText von Textview erbt.

Bemerkenswerte EditText Attribute

Der "Hinweis" Artikel inder Bereich Eigenschaften können Sie einen "Hinweis" für diese EditText einzustellen. Der "Hinweis" Text wird in hellgrau im EditText Widget angezeigt werden, wenn der Benutzer noch nichts eingegeben hat. Sobald der Benutzer beginnt in den EditText eingeben, verschwindet der "Hinweis". Dies ermöglicht Ihnen, auf dem Bildschirm Platz zu sparen, ein separates Etikett Textview zu ersetzen.

Der "Input Type" Artikel inder Bereich Eigenschaften können Sie, welche Art von Input zu beschreiben, die Sie in diesem EditText erhalten erwarten, mit vielen der Arten von fi bis Auskleiden

Sie können per Drag ausdie Palette in das Layout:

Dasinput Attribut wird in größerem Detail in einem abgedeckt werdenkommenden Kapitel.

Weitere gemeinsame Konzepte

Alle Widgets, einschließlichdie, die oben gezeigt, erstrecken sich ansehen. Die Ansicht der Basisklasse gibt allen Widgets eine Reihe von nützlichen Eigenschaften und Methoden über die bereits beschrieben.

Polsterung

Widgets habeneine Mindestgröße, eine, die durch beeinflusst werden können, was in ihnen ist. So zum Beispiel wird ein Knopf erweitern die Größe der Beschriftung aufzunehmen. Sie können diese Größe mit Polsterung steuern. Hinzufügen Polsterung wird der Raum zwischen den Inhalten erhöhen (zB die Beschriftung einer Schaltfläche) und die Ränder des Widgets.

Padding kann für alle vier Seiten in XML einmal gesetzt werden(android: padding) Oder auf einer per- Seitenbasis (android: paddingLeft, etc.). Padding kann auch in Javaüber die eingestellt werdensetPadding ()Methode.

Der Wert einesdiese ist eine Dimension - eine Kombination aus einer Maßeinheit und einer Zählung.

Also, 10dip 10 dichteunabhängige Pixel, 2 mm beträgt 2 Millimeter, usw.

Die Margen

Standardmäßig werden die Widgets dicht gepackt, einneben dem anderen. Sie können über die Verwendung von Pannen steuern diese, ein Konzept, das zuvor beschrieben erinnert an die Polsterung ist.

Der Unterschied zwischen Polsterung und Margen kommt in Bezug aufder Hintergrund. Für Widgets mit transparentem Hintergrund - wie die Standarddarstellung eines Textview - Polsterung und Margen haben ähnliche visuelle Effekt, den Raum zwischen dem Widget und den angrenzenden Widgets zu erhöhen. Doch für die Widgets mit einem nicht transparenten Hintergrund - wie ein Button -

Polsterung im Inneren der Hintergrund betrachtet, während die Margen außerhalb sind. Mit anderen Worten, Polsterung wird das Hinzufügen der Abstand zwischen dem Inhalt (zum Beispiel die Beschriftung einer Schaltfläche) und die Ränder zu erhöhen, während das Hinzufügen Marge erhöht den leeren Raum zwischen den Rändern und den angrenzenden Widgets.

Die Margen können in XML gesetzt werden,entweder auf einer Pro-Seite-Basis (zB Android: layout_marginTop) oder auf allen Seiten über Android: layout_margin. Wiederum wird der Wert von beliebigen von diesen ist eine Dimension, - eine Kombination aus einer Messeinheit und einer Zählung, wie 5DP 5 dichteunabhängige Pixel.

Farben

Es gibt zweiArten von Farbattributen in Android Widgets. Einige wieandroid: Hintergrundnehmen, nur eine einzige Farbe (oder eine drawable als Hintergrund zu dienen). Andere, wieandroid: textcoloraufTextview(Und Unterklassen) können nehmeneinColorStateListÜber die Java setter einschließlich (in diesem Fall,SetTextColor ()).

Ein ColorStateList können Sie verschiedene Farben für verschiedene Bedingungen zu spezifizieren.

Zum Beispiel, wenn Sie in die Auswahl von Widgets in einem der nächsten Kapitel bekommen, werden Sie sehen, wie ein Textview eine andere Textfarbe hat, wenn es das ausgewählte Element in einer Liste im Vergleich zu, wenn es in der Liste ist aber nicht ausgewählt. Dies erfolgt über die Standard ColorStateList im Zusammenhang mit Textview behandelt.

Wenn Sie ändern möchtendie Farbe eines Textview-Widget in Java-Code, haben Sie zwei Hauptwahlen:

• BenutzenColorStateList.valueOf ()Werden, welches einColorStateListin dem alle

Zustände betrachtet habendie gleiche Farbe, die Sie als die Versorgung

ParameterdasWert von()Methode. Das istdie Java-Äquivalent desandroid:

textcolorAnsatz zu machen,dasTextviewsei immereine bestimmte Farbe unabhängig von den Umständen.

• Erstellenein ColorStateList mit unterschiedlichen Werten für verschiedene Zustände, entweder über den Konstruktor oder über eine XML-ziehbar Ressource. Dies wird
abgedecktviel später imdas Buch.

Weitere nützliche Attribute

Einige zusätzliche Attribute auf Ansicht am ehesten verwendet werden, umfassen:

1. android: Sichtbarkeit, Das anzeigt, ob das Widget steuert zunächst sichtbar

2. android: nextFocusDown.android: nextFocusLeft.android: nextFocusRight,
undandroid: nextFocusUp, Die Steuerung des Fokus-Reihenfolge, wenn der Benutzer
das D-Pad, einen Trackball verwendet, oderähnliches Zeigegerät

3. android: content, die auf einer HTML-Tag <img> entspricht in etwa dem alt-Attribut ist, und durch Eingabehilfen verwendet wird, um Menschen zu helfen, die nicht auf dem Bildschirm navigieren, um die Anwendung zu sehen - das ist sehr wichtig für

Widgets wie Image

Wir werden sehen, mehr überdie Fokus-Attribute und Android: content indas Kapitel über die Fokusverwaltung und Zugänglichkeit, später imdieses Buch.

SinnvollMethoden

Sie können umschalten, obnicht ein Widgetüber aktiviertsetEnabled ()und sehen, ob esaktiviertüberaktiviert(). Eine häufige Verwendung Muster dafür ist, einige Widgets zu deaktivieren basiert auf einem SystemCheckBoxoderRadio knopfÜberprüfungsstatus. Wir
erkundenCheckBox.Radio knopfUndähnliche Arten von Widgetsein bisschen später in dem Buch.

Du kannst Gebenein Widget Fokus über request () und sehen, ob es über isFocused () fokussiert ist. Man könnte dies mit Deaktivierung Widgets im Konzert verwenden, wie oben erwähnt, ist das richtige Widget, um sicherzustellen, hat den Fokus, sobald Ihre Deaktivierung Vorgang abgeschlossen ist.

Um zu helfen navigierender Baum von Widgets und Container, die eine Aktivität des Gesamtansicht bilden, können Sie:

1. getParent ()zu fi
dasübergeordnete Widget oder Container

2. findViewById ()zu fi
ein Kind-Widget mit einer bestimmten ID

3. getRootView ()bekommendie Wurzel des Baumes (zum Beispiel, was Sie für die

Aktivität vorgesehen,übersetContentView ())

Besuchdie Spuren!

Sie können mehr über Android Eingabemethode Rahmen lernen- Was man als Soft-Tastaturen vielleicht denken -imein späteres Kapitel.

Ein weiteres Kapitel indie Wege Abdeckungendie Verwendung von Schriften, nachpassen Sie Ihr Textview-Widgets (und diejenigen, die von ihnen, wie Button erben).

Noch ein weiteres Kapitel indie Wege AbdeckungenRich-Text-FormatierungSowohl für die formatierten Text präsentiert inein Textview (zB Inline fett gedruckt) und für über eine kundenspezifische EditText formatierten Text von dem Benutzer zu sammeln.

Debugging-App

Jetztdass wir beginnen, mehr Layouts und Java-Code deutlich zu manipulieren, erhöhen Sie die Chancen, dass wir irgendwie gehen, um es falsch machen, und unsere App zum Absturz bringen.

ImIn diesem Kapitel werden wir ein paar Tipps abdecken, wie man diese Art von Fragen zu debuggen.

Holen dicheinen Stack-Trace

Wenn Sie sehen, eine derdiese "Force Close" oder "Hat Stopped" Dialoge, die fi was Sie tun
wollen ist, die Java-Stack-Trace untersuchen, die mit diesem Absturz verbunden ist. Diese werden zu einer Einrichtung angemeldet als LogCat bekannt, auf dem Gerät oder Emulator.

So zeigen LogCat, haben Sie drei Möglichkeiten:

1. BenutzenBefehl der adb logcat in der Befehlszeile (oder etwas, das verwendet
adb logcat, wie verschiedene colorizing Skripte online verfügbar)

2. Benutzendie LogCat Registerkarte in der Standalone-Android Device Monitor-

Dienstprogramm (run

Monitorvondie Kommandozeile)

3. Benutzendie LogCat Ansicht

Es gibt auchLogCat Apps im Play Store, wie aLogCat, die den Inhalt von LogCat angezeigt wird.

Doch für die Sicherheit und die Privatsphäre, auf Android 4.1 und höher Geräte, wie Anwendungen werden nur in der Lage sein, Ihnen ihre LogCat Einträge zu zeigen, nicht die aus dem System, Ihre

Anwendung oder sonst jemand. Daher ist für Entwicklungszwecke, ist es besser, eine der anderen oben skizzierten Alternativen zu verwenden.

LogCat in Android Studio

Die LogCat Ansicht ist an jeder verfügbarenZeit, von so ziemlich überall in Android Studio, mit Hilfe von auf dem Android-Tool-Fenster Eintrag klicken, in der Regel am unteren Rand des IDE-Fensters verankert:

Das Tippen aufdas wird einige Android-spezifi-Protokolle in einem "Android DDMS" Tool-Fenster mit einem Register für "Geräte bringen | logcat ":

LogCat zeigt Ihren Stack-Traces, Diagnoseinformationen ausdas Betriebssystem, und alles, was Sie wollen über Anrufe zu den statischen Methoden auf der android.util.Log Klasse aufzunehmen. Zum Beispiel Log.e () eine Meldung bei Fehlerschwere einzuloggen, so dass es in rot angezeigt werden.

Wenn Sie etwas von LogCat an jemanden senden möchtenandere, wie zum Beispiel über einen issue tracker, markieren Sie einfach den Text und kopieren Sie ihn in die Zwischenablage, wie Sie mit einem beliebigen Texteditor würde.

Der "Papierkorb" -Symbol oben aufder Werkzeugleiste auf der rechten Seite ist das "Protokoll löschen" -Tool. Ein Klick darauf erscheint LogCat zu löschen. Es klärt auf jeden Fall Ihre LogCat Ansicht, so dass Sie nur angemeldet sehen werden Nachrichten, nachdem Sie es gelöscht. Beachten Sie jedoch, dass dies nicht gelöscht tatsächlich die Protokolle aus dem Gerät oder Emulator.

In Ergänzung, Sie können:

• Benutzendie "Log Level" drop-down zu fi er Anschlüssen auf Basis der Schwere, in denen Nachrichten für den gewünschten Schweregrad oder höher
angezeigt

• Benutzendie Suche fi
nachdas Recht des "Log Level" drop-down, um Elemente
fi er auf einem Suchbegriff basiert

• Richten Sie dauerhaftere fi ers über das Drop-down auf der rechten Seite der Such fi

Der Fall vonzuschanden Klasse Guss

Wenn Sie abstürzen,die Stack-Trace könnte darauf hindeuten, dass es ein Problem auf Ihre Ressourcen gebunden ist. Ein gemeinsames Geschmack dieser ist einClasscastwenn Sie anrufenfindViewById (). Zum Beispiel könnten Sie rufen(Button) findViewById

(R.id.button)erhalten, noch einClasscast:android.widget.LinearLayoutwieein Ergebnis, was darauf hinweist, dass, während Sie dachten, dass IhrfindViewById ()Anruf zurückkehren würdeeinTaste, Kehrte er wirklich einLinearlayout.

Oft,das ist nicht deine Schuld. Manchmal bekommen die R-Werte nicht mehr synchron mit Pre-kompilierten Klassen aus früheren Builds. Das am häufigsten auftritt, kurz nachdem Sie Ihre Mischung von Ressourcen ändern (zB ein neues Layout hinzufügen).

Um dieses Problem zu beheben, Siemüssen Sie Ihr Projekt zu reinigen. Um dies zu tun, in Android Studio, wählen Sie "Build> Sauber-Projekt" aus dem Hauptmenü.

Also, wenn Sie bekommenein eigenartiger Sturz, der wie es scheint, auf Ressourcen in Zusammenhang stehen könnten, reinigen Sie Ihr Projekt. Wenn das Problem verschwindet, werden Sie setzen - wenn das Problem weiterhin besteht, müssen Sie ein bisschen mehr Debugging zu tun.

Point Break

Einer vondie Markenzeichen von Java IDEs ist die Fähigkeit, Echtzeit-Debugging, mit Haltepunkten und dergleichen zu tun. In dieser Hinsicht arbeitet Android Studio für Android-Anwendungen auf die gleiche Weise, dass IntelliJ IDEA und Eclipse Arbeit für Java-Anwendungen. Sie können auf einem Emulator debuggen oder jedem Android-Gerät, für das Sie USB-Debugging aktiviert ist (wie Sie in Tutorial # getan haben 1).

Ohne jede Android Studio spezifische Dokumentation, werden Sie wind up mit Bezug auf die Dokumentation für IntelliJ IDEAzu lernen, wie man seine Debugger zu verwenden.

Mit Android Studio,die Lauf Kontrollen in der Symbolleiste Sie einige Optionen geben für das Debuggen Ihrer Anwendung:

Der Bug-förmige Tastedas Recht der "run" grüne Dreieck wird die App starten und den Debugger anhängen, so Stützpunkte geehrt werden. Wenn Ihre Anwendung bereits ausgeführt wird, und Sie wollen den laufenden Prozess zu debuggen, können Sie tun, dass über die Symbolleiste auf die Schaltfläche, die mit einem kleinen Fehler in der unteren rechten Ecke wie ein Telefon aussieht.

Die Classic-Container-Klassen

Behälter- Manchmal als Layout-Manager - organisieren Widgets auf dem Bildschirm. Container Position und Größe von Widgets, basierend auf Regeln, die Sie zusammen mit den wichtigsten Geräteeigenschaften liefern, wie verfügbare Bildschirmgröße.

Drei Container haben dominiert Android App-Entwicklung seit Android Einführung Ende 2007:Linearlayout.RelativeLayout, undTablelayout. Dieses Kapitel konzentriert sich auf diejenigen. In späteren Kapiteln werden andere Container-Klassen, wie zum Beispiel 2016
suchenConstraintLayout.

Einbringendie Sampler App

DasContainer / SamplerBeispielprojekt hateine Reihe von Layout-Ressourcen, die in diesem Kapitel illustrieren verwenden, wie diese Behälter arbeiten.

Wenn Sie waren zu laufenDiese Beispielanwendung, würden Sie eine Reihe von Registerkarten, mit einem Layout pro Tab angezeigt sehen:

Wir sindin Gang zu bringen in den Java-Code nicht mit dieser Beispielanwendung in diesem Kapitel zugeordnet ist. Dieser Code stützt sich auf andere Themen, wieFragmenteunddas ViewPager Widget.dass wir nicht noch bekommen. Wir werden auf diese Beispiel-App zurückkommen und sehen, wie die Laschen dann umgesetzt wurden. Denn jetzt ist der Fokus auf das Layout fi zeigt spezifi Techniken für diese klassischen Behälter verwenden.

RTL und Ihre Layouts

die meistenSprachen der Welt sind von links nach rechts geschrieben. Also, in diesem Absatz, lesen Sie die Buchstaben und Wörter aus dem linken Rand einer Linie quer zum rechten Rand beginnen.

Arabisch und Hebräisch,unter anderenWerden von rechts nach links geschrieben. Die Abkürzung

"RTL" bezieht sich aufdiese Sprachen.

Ursprünglich wurde Android rein auf links-nach-rechts (LTR) Sprachen konzentriert. Wieein Ergebnis sehen Sie Attribute, um die Dinge in Bezug beziehen und von rechts nach links (zB Android: paddingLeft).

Langsam verbessert Android seine RTL-Unterstützung. Insbesondere mit API-Ebene ab 17. (Android 4.2), analog Attribute wurden hinzugefügt, "links" mit "Start" wieder anbringen und

"Recht"Mit" Ende ". Bei der Verwendung von "Start" / "Ende" Attribute (zB Android: paddingStart), "Start" bezieht sich auf, wo Sie eine Textzeile zu lesen beginnen, und "Ende" bezieht sich auf, wo Sie eine Textzeile am Ende zu lesen:

Sprachrichtung

"Start"

"Ende"

bedeutet ...

bedeutet ...

LTR

Links

Recht

RTL

Recht

Links

Im Allgemeinen wollen wirdie GUI mit der Sprachrichtung zu fließen. Dinge, die Sie auf der linken Seite mit einem LTR Sprache in der Regel auf der rechten Seite mit einer RTL-Sprache und so weiter gehen könnte.

Da jedochdiese "Start" und "Ende" Attribute neu auf API-Ebene 17, man kann sie nicht auf älteren Geräten verwenden. Manchmal wird wickeln wir oben entweder mit dem alten "links" / "Recht"

Attribute oder mit beiden Arten von Attributen, um alle Gerätevarianten abzudecken.

Wir werden RTL Sprachunterstützung erneutein bisschen später in diesem Kapitel.

Linearlayout undDas Box-Modell

Linearlayout stellt Android Annäherung an eine Box-Modell - Widgets oder Kind Container werden in einer Spalte oder Zeile, eine nach der anderen aufgereiht.

Konzepte und Eigenschaften

So konfigurierenein Linearlayout, haben Sie vier Hauptbereiche der Steuerung neben den Inhalt des Behälters: die Orientierung, das fi-Modell, das Gewicht, die Schwerkraft.

Orientierung

Orientierung gibt an, obdasLinearlayoutrepräsentierteine Zeile oder eine Spalte. Fügen Sie einfach dieandroid: OrientierungImmobilien auf IhreLinearlayoutElement in Ihrem XML-Layout, das Setzen Sie den Wert auf seinhorizontalfüreine Zeile odervertikalfüreine Kolumne.

Die Orientierung kann zur Laufzeit geändert werdendurch den AufrufsetOrientation ()aufdas LinearlayoutUnd liefert sie entwederHORIZONTALoderVERTIKAL.

FüllenModell

Der Punkt hinterein Linearlayout - oder einen der Android Container-Klassen - ist mehrere Widgets zu organisieren. Ein Teil dieser Widgets Organisation ist die Bestimmung, wie viel Platz jeder bekommt.

Linearlayout nimmt eine "älteste Kind gewinnt" Ansatz gegenüber dem Raum zugeordnet werden.

Also, wenn wir ein Linearlayout mit drei Kindern haben, die fi

Kindwird seine
angeforderte Raum bekommen. Das zweite Kind wird seinen Wunsch-Raum erhalten, wenn es genügend Platz bleibt, und ebenfalls für das dritte Kind. Also, wenn die fi

Kind fragt für
alle dem Raum (beispielsweise ist dies eine horizontale Linearlayout und die fi

Kind

Android hat: layout_width = "match_parent"), die zweite und dritte Kinder mit einer Breite von Null eingereicht werden.

Gewicht

Aber was passiert, wenn wir zwei oder mehr Widgetsdas sollte den freien Speicherplatz aufgeteilt?

Zum Beispiel, nehmen wir an zwei mehrzeiligen fi in einer Spalte haben, und wir wollen, dass sie den verbleibenden Platz in der Kolonne zu übernehmen, nachdem alle anderen Widgets ihren Platz zugewiesen worden sind.

Um sicherzustellen,diese Arbeit, zusätzlich zu Einstellung android: layout_width (für Zeilen) oder android: layout_height (für Spalten), müssen Sie auch Android gesetzt: layout_weight. Diese Eigenschaft gibt an, welcher Anteil des freien Raumes zu diesem Widget gehen sollte. Wenn Sie android gesetzt: layout_weight der gleiche Wert ungleich Null für ein Paar von Widgets zu sein (zum Beispiel 1), wird der freie Raum gleichmäßig zwischen ihnen aufgeteilt werden. Wenn Sie es Set 1
für ein Widget und 2 für ein anderes Widget zu sein, wird das zweite Widget zweimal den freien Raum, der fi aufbrauchen

Widget tut. Und so weiter.

Das Gewicht fürein Widget ist auf Null gesetzt.

Ein weiteres Muster für Gewichte, wenn Sie Größen wollen zuweisenprozentualer Basis. Zur Nutzung dieser Technik für, sagen wir, eine horizontale Layout:

1. Stellen Sie alledasandroid: layout_widthWerte sein,0fürdie Widgets im Layout

2. Setdasandroid: layout_weightWerte sein,die gewünschte prozentuale Größe für jedes Widget im Layout

3. Stellen Sie sicher, dass allediese Gewichte summieren sich zu 100

Wenn Sie wollen Raum über halten können,nicht auf ein Widget zugeordnet, können Sie eine hinzufügen
android: weightSumzuschreibendasLinearlayoutUnd sicherzustellen, dass die Summe der android: layout_weight Attribute der Kinder sind weniger als diese Summe. Die Kinder werden jeweils erhalten Platz auf dem Verhältnis ihrer android zugeordnet basiert: layout_weight im Vergleich zu dem Android: weightSum, nicht im Vergleich zur Summe der Gewichte. Und es wird leerer Raum sein, der den Rest des Raumes nimmt nicht an die Kinder verteilt.

Schwerkraft

Standardmäßig alles inein Linearlayout ist Start- und top-ausgerichtet sind. Also, wenn Sie eine Reihe von Widgets über eine horizontale Linearlayout zu erstellen, wird die Reihe fl auf
die Start Seite des Bildschirms (zB links in einer LTR-Sprache).

Obdas ist nicht das, was Sie wollen, müssen Sie eine Schwerkraft angeben. Im Gegensatz zu der physischen Welt hat Android zwei Arten von Schwerkraft: die Schwere eines Widgets in einem Linearlayout und die Schwere des Inhalts eines Widgets oder Behälter.

Dasandroid: SchwerkraftEigenschaft einiger Widgets und Containern- Die auch über definiert werdenSetGravity ()in Java- Weist Android den Inhalt des Widgets oder Behälter in einer bestimmten Richtung zu gleiten. Beispielsweise,android: Schwerkraft = "right"sagt gleitender Inhalt des Widgets nach rechts;android: Schwerkraft = "right | bottom"sagt gleitender Inhalt des Widget auf der rechten Seite und der Unterseite.

Hier "Inhalt" variiert.TextviewStützenandroid: SchwerkraftUnd die "Inhalte" ist der Text innerhalb der gehalteneTextview.LinearlayoutStützenandroid: SchwerkraftUnd die "Inhalte" sind die Widgets im Inneren des Behälters. Und so weiter.

Kinder voneinLinearlayouthabe auchdie Möglichkeit der Angabeandroid: layout_gravity. Dabei wird das Kind sagen, dieLinearlayout"Wenn es RaumSchieben Sie mir bitte (und mich allein) in diese Richtung ". Dies funktioniert jedoch nur in der Richtung entgegengesetzt der Ausrichtung desLinearlayout- Die Kinder einvertikale LinearlayoutKann benutzenandroid:

layout_gravitykontrollieren ihre Positionierung horizontal (AnfangOrEnde), Aber nicht in vertikaler Richtung.

Füreine Reihe von Widgets, ist die Standardeinstellung für sie so ihre Texte auf der Basislinie (die unsichtbare Linie, die Buchstaben scheinen zu "sitzen auf") ausgerichtet sind, ausgerichtet werden, wenn Sie die Widgets zum Zentrum entlang einer Dichte von center_vertical zu spezifizieren wünschen die vertikalen Mittelpunkt der Reihe.

Android Studio grafische Layout Editor

DasLinearlayout Behälter kann in der "Layouts" Teil der Palette des Android-Studio grafischen Layout-Editor zu finden:

Sie können per Dragentweder die "Linearlayout (vertikal)" oder "Linearlayout (horizontal)" in ein Layout XML Ressource, dann starten Sie in Kinder ziehen in den Behälter zu gehen.

Wenn deinLinearlayout wird das ausgewählte Widget, ein paar neue Schaltflächen der Symbolleiste wirdüber die Vorschau angezeigt werden:

Die linke Taste schaltet schaltetdasLinearlayoutzwischenvertikalundhorizontalOrientierung. Die beiden rechten Tasten umschaltendie Breite und die Höhe
zwischenmatch_parentundwrap_content, Während die dritte Tasteändert sich der Schwere derLinearlayout. Die zweite Taste von links scheint zu diesem Zeitpunkt keine Wirkung zu haben.

Wenn eines vonDie Kinder derLinearlayoutistdas ausgewählte Widget, die

SymbolleisteÄnderungen:

Von links nach rechts,die Knöpfe:

• Umschaltendie Mutterlinearlayout zwischen horizontalen und vertikalen

Orientierungen

• Ausrichtendie Kind-Widgets Basislinien (wo ein "Baseline" ist die unsichtbare Linie, die Text auf zu sitzen scheint)

• Gibtdas Widget einandroid: layout_weightvon1

• entferntdasandroid: layout_weightAttribut, wenn es hat man

• Umschaltendie Breite zwischenmatch_parentund wrap_content

• Umschaltendie Höhe zwischenmatch_parentundwrap_content

Im Bereich Eigenschaften fürdas ausgewählte Widget können Sie auch auf das zu bekommen Linearlayout Container Anpassungen ihrer Attribute, die Art und Weise zu machen: Beispiel: Bottom-then-Top

Diese Regeln werden mehr Sinn machen, wenn wir durch einige Beispiele zu arbeiten.

Der fi

Beispielist, wo wir zwei Widgets haben. Ein Widget sollte seine "natürliche" Menge Platz in Anspruch nehmen, verankertder Boden des Bildschirms. Das andere Widget sollten alle den verbleibenden Platz fi nden:

Die XML

Das Layout XMLdass erzeugt wird, dass Screenshot aus avertikale Linearlayoutund
zweiTasteWidgets:

(von

Container / Sampler / app / src / main / res / Layout

/ bottom_then_top_ll.xml)

DasLinearlayouthat seine Größen(android: layout_width.android: layout_heightSet), die jeweils zumatch_parent, So wird es den ganzen Raum zur Verfügung, um es fi auf. In dieser Beispielanwendung wird, dass alles unterhalb der Registerkarten sein.

BeideTasteWidgets habenihrandroid: layout_widthAttribute auch auf
match_parent, so werden sie horizontal alle verfügbaren Platz auf dem Bildschirm fi auf.

Der BodenTastehat seineandroid: layout_heighteinstellenwrap_content, So wird es nur so viel Platz in Anspruch nehmen, wie benötigt wird, seine Beschriftung und Hintergrund um es zu machen.

Die SpitzeTastehatandroid: layout_heighteinstellen0DP. Wenn wir nichts anderes tun haben, zur Folge haben, dass würde in einem unglaublich kurzen Taste. Allerdings haben wir auchAndroid: layout_weight = "1".

Wanndies auf dem Bildschirm gerendert wird, werden Linearlayout machen zwei Durchgänge durch ihre Kinder. Auf der fi
bestehen, es fragt nach, wie viel Platz Jedes Kind will, basierend auf
dem Android: layout_height Werte (da dies eine vertikale Linearlayout ist). Der fi Knopf für

0 Pixel Raum fragen, während die untere Taste für so sehr fragen wird es für seinen Inhalt muss.

Dann fragt der zweite Durchlauf des Linearlayout durch ihre Kinder für ihre Gewichte. Der fi

Knopf hat ein Gewicht von 1, während die untere Taste, um das Standardgewicht von 0.

Als Folge hat, die obere Taste, bekommt 1/1 = 100% aller Pixel von dem, was der fiübrig bestehenbenutzt. Dies bewirktden obersten Knopf zu werden groß, die untere Taste auf der Unterseite des Bildschirms schubsen.

Android Studio grafische Layout Editor

Sie können erstellenein neues Layout Ressource durch einen Rechtsklick auf das res / Layout /

Verzeichnis und "Neu> Layout Ressource fi" mit der rechten Mauskontextmenü wählen. Sie erhalten dann einen Dialog, in dem Sie die neue Ressource einen Namen geben und den Stammcontainer für das Layout wählen:

Standardmäßig erhalten Sieeinvertikale Linearlayout, Obwohl man könnte es wechseln zu horizontalüber die Schaltfläche in der Symbolleiste oder im Fensterbereich Eigenschaften: Während Sie ziehenButton widgets in das Layout, werden sie zunächst mit einer Breite von gegebenen match_parentundeine Höhe vonwrap_content:

Ein Klickdie obere Taste, und klicken Sie auf die "Weisen Sie alle Gewicht" Symbolleiste auf die Schaltfläche (sieht aus wie ein griechisches Sigma), gibt es ein Gewicht von 1 und das gewünschte Aussehen:

Beispiel: Stacked-Prozent

Gewichte können aufwändigere bekommenals nur alle zusätzlichen Raum zu einem Widget geben.

Die gestapelten Prozent-Szenario reserviert Speicherplatz aufprozentual auf alle Kinder des Linearlayout. In der Beispielanwendung haben wir ein Layout fi
mit drei Tasten,

Aufnahme 50%, 30% und 20% des Raumes in einer vertikalen Linearlayout:

Die XML

DiesZeit, das Layout Ressource XML hat alle drei Button-Widgets mit Höhen von 0:

(von

Container / Sampler / app / src / main / res /

Layout / stacked_percent_ll.xml)

Damit,die fi
bestehen dass die Linearlayout durch seine Kinder macht, fragt jedes Kind für

0 Pixel Höhe bedeutet, dass alle von der Linearlayout Platz für den zweiten Durchgang zur Verfügung steht.

On der zweite Durchgang, können die Kinder Gewichten von 50, 30 bzw. 20. 50 + 30 + 20 = 100, so dass die obere Taste 50/100 (50%) des Raumes wird, bekommt der mittlere Knopf 30/100 (30%) des Raumes und der untere Knopf bekommt 20/100 (20% ) des Raumes.

Hinweisdass Sie sich um die gleichen Ergebnisse mit Gewichten von 5, 3 und 2. Wirklich erhalten, ist es die Verhältnisse der Gewichte, die Materie. Wenn Sie jedoch in Bezug auf die Prozentsätze zu denken verwendet werden - vielleicht aufgrund früherer Erfahrungen mit anderen GUI-Toolkits -
können Sie integer Prozent verwenden, wenn Sie möchten.

Android Studio grafische Layout Editor

Constructingdies den grafischen Layout-Editor ist ähnlich dem vorherigen Beispiel:

• Erstellendas neue Layout Ressource, ein Linearlayout als Root-Container
wählen.

• Ziehen Sie dreiTasteWidgets indasLinearlayout.

• Mitder Bereich Eigenschaften, stellen dieandroid: layout_heightWerte aufdie

DreiTasteWidgets0DP:

• Mitder Bereich Eigenschaften, stellen Sie die Android-Version: layout_weight

Werte zu den drei Button-Widgets. Beachten Sie jedoch, dass das Gewicht nicht auf der kondensierten Eigenschaften Liste sein kann. Sie müssen möglicherweise alle

Eigenschaften anzuzeigen Zugang zu ihm zu haben:

Beispiel: URL-Dialog

Natürlich bist dunicht auf eine Achse beschränkt. Sie können Nest Linearlayout Widgets Dinge zu strukturieren sowohl entlang der X- und der Y-Achse.

Zum Beispiel könnte sein Streben Sieein Dialog-Stil Form wie folgt aus:

Die XML

Dieses Layout Ressource istein bisschen komplizierter, als wir jetzt bis zu vier Widgets plus drei Linearlayout Container sind:

(from

Container / Sampler / app / src / main / res /

Layout / url_dialog_ll.xml)

dieäußereLinearlayoutistvertikal, Dazu dient, die beiden zu stapelnhorizontale LinearlayoutReihen.

jeweilsjenehorizontale LinearlayoutBehälter hateine Höhe vonwrap_contentundeine Breite vonmatch_parent, So dass sie die Breite des Bildschirms erstrecken, aber nur so viel Höhe benötigen, wie erforderlich ist, ihre Widget Inhalt zu rendern.

Der fi
von unsere vier Widgets ist dasTextview. Da es in der fi
horizontale

Linearlayout, Wird es fl
auf die eine Seite (in einer LTR-Sprache wie Englisch links).

Allerdings haben wir4DPvon Marge, wobei sowohldieälterenandroid: layout_marginLeftunddie neuere, RTL-fähigandroid: layout_marginStartAttribute. Damit,Das Widget ist Einschub ein wenig von der Kante.

Das zweite Widget istdasText bearbeiten. Es hat eine Breite vonmatch_parent, So wird es alle verbleibenden Platzüber, nachdem die nehmenTextview.

Der BodenLinearlayouthatAndroid: Dichte = "Ende", Das seinen Inhalt verursacht Richtung der Stirnseite des zu gleitenLinearlayout(Rechts ineine LTR Sprache wie Englisch). Es enthält die beidenTasteWidgets unddeshalb ist die beidenTasteWidgets werden geschoben zudas
entgegengesetzte Ende des Formulars.

Android Studio grafische Layout Editor

Nicht überraschend,Je komplexer das Layout, das Sie ist erstellen möchten, desto mehr Arbeit erforderlich, um es zu schaffen. Die IDE hilft nur bis zu einem Punkt.

So zu konstruieren,dieses Layout, müssten Sie:

• Erstellendas neue Layout Ressource, ein Linearlayout als Root-Container
wählen.

• Ziehenein "Linearlayout (horizontal)" Artikel aus der Palette in die vertikale Linearlayout. Dies führt leider in der neuen Linearlayout den gesamten Raum des
übergeordneten raubend, da seine Höhe und Breite sind beide match_parent
standardmäßig:

• Mitder Bereich Eigenschaften, stellen Sie die Polsterung an allen Seiten 8DP zu sein:

• ZieheneinTextviewin dashorizontale Linearlayoutund stellen ihreTextnach

URL:Seine Breitewrap_contentUnd entfernen Sie sein Gewicht:

• Ziehenein "Nur-Text" EditText in die horizontale Linearlayout, seine Breite Einstellung match_parent werden, dessen Text leer zu sein, seine input etwas angemessen (zB zu sein, textUri, diese fi da in der Theorie
sollte halten eine URL), und sein Gewicht zu
entfernen. Beachten Sie, dass Sie fi nden können
es leichter das Widget in ihre

Behälter über den Komponentenbaum Werkzeug zu ziehen, besser, wenn Sie die

Reihenfolge der Kinder, die Art und Weise steuern können:

• Ziehen Sie eine weitere "Linearlayout (horizontal)" Artikel ausdie Palette, aber diesmal ist es auf der "Linearlayout (vertikal)" im Komponentenbaum fallen, dann die Kinder Nachbestellung im Komponentenbaum des neuen Linearlayout am Boden zu
setzen:

• Einstellendie Höhe der beidenLinearlayoutWidgets zu seinwrap_content.

• Ziehen Sie zweiTasteWidgets indass niedrigereLinearlayoutimKomponentenbaum:

• Entfernendie Gewichte von beiden Button-Widgets über den Bereich Eigenschaften:

• VeränderungdasSchwerkraftvonder niedrigerehorizontale LinearlayoutseinEnde, Das Fenster Eigenschaften mit:

• Veränderungdie Beschriftungen auf den Tasten "OK" und "Abbrechen": Nun, alle getan zu habendass die Glocke Symbolleiste auf die Schaltfläche über der Vorschau und Entwurf wird nun ein rotes Quadrat mit einer Reihe drin sein, was auf einige Warnungen über das Layout, die wir gebaut. dass Square tippen, wird ein Fenster mit den Nachrichten zu erklären, was Android Studio nicht wie Pop-up:

jeweilsdie Warnungen in der Liste hat in der Regel eine Erklärung, einige vorgeschlagen fi es, und anderen erläuternden Informationen. Ein Klick auf den Link für einen empfohlenen fi werden, dass die fi anwenden und aufklären, dass

Einigedie Warnungen können von den Beschriftungen für die Textview und Button-Widgets kommen. Wenn Sie nur eine Zeichenfolge in das Eigenschaftenfenster eingeben, dass fi im wörtlichen Zeichenfolge in das Layout, und im Idealfall verwenden wir String-Ressourcen. Für diejenigen, schlug die "Extract String-Ressource" fi ermöglicht es Ihnen, diejenigen, die als String-Ressourcen zu definieren.

Einigediese Warnungen werden über bestimmte Dinge über Stile (zB "Buttons in Symbolleisten sollten randlos"). Während auf lange Sicht Sie über diese Warnungen, die kurzfristig kümmern könnte, während Sie Android lernen, ignorieren die Warnungen, die vorgeschlagene fi ist eine gute Idee.

Beispiel:A Bigger Formular

Nicht alles, was ineine Form hat im Inneren eine zu seinhorizontale Linearlayoutdie selbst im Inneren einvertikale Linearlayout. Sie brauchen nur einhorizontale Linearlayoutwenn du. .. hasteine Zeile, die zwei oder mehr Widgets enthält. Für Single-Widget Reihen, können sie sein, nur einfache Kindervertikale Linearlayout.

Zum Beispiel, vielleicht haben Sieeine aufwendigere Form im Auge, mit mehreren fi und andere Widgets, wie dieser:

Die XML

Die Layout-Ressource Form ähneltdie URL-Dialog Szenario aus früheren:

(from

Container / Sampler / app / src / main /
res / Layout / form_ll.xml)

Beachten Sie jedoch,dass dieCheckBoxunddasTastesindnicht selbst eingewickelt inhorizontale LinearlayoutBehälter. Sie sind lediglich direkte Kinderdasvertikale Linearlayout. In diesem Fall werden beide setzen eine Breite zu haben,match_parentist jedoch, dass nicht erforderlich - Sie konnten sie aufwrap_contentwenn Sie es vorziehen.

Wir werden uns auf CheckBox näher ein kommender Kapitel.

Android Studio grafische Layout Editor

Einrichtendiese Form folgt dem gleichen Grundrezept wie für die einfachere Dialogform von oben in diesem Kapitel verwendet wurde:

• Konfigurationeine Layout-Ressource in eine verwurzeltvertikale Linearlayout

• Zieheneinhorizontale Linearlayoutin dasvertikale Linearlayout

• Ziehen einTextviewund einText bearbeitenin dashorizontale Linearlayoutund
konfigurierenerforderlich

• Wiederholendie letzten beiden Schritte für jede der anderen fünf Reihen

Das Problem

Wenn Sie zurückblicken aufDer Screenshot, werden Sie feststellen, dass die markierten EditText Widgets zackig sind, in Bezug auf deren Anordnung. Jede EditText folgt unmittelbar auf das Textview-Label, ohne Rücksicht auf jede Art von "Spalten". Das ist, weil jeder Linearlayout weitgehend unabhängig ist. Sie können nicht ohne weiteres eine Zeile haben, hängt von den anderen Reihen.

EIN Tablelayoutwäre eine bessere Wahl für diese Art von Formular, dort können wir verschiedene Spalten von Etiketten und Fi

. Wir werden sehen, wie Tablelayout diese Struktur Griffe
später in diesem Kapitel.

Alle Sachen sind Relative

RelativeLayout, wie der Name schon vermuten lässt, legt Widgets basierend auf ihrer Beziehung zu anderen Widgets in dem Behälter und dem übergeordneten Container. Sie können Widget X
unten und nach links von Widget Y platzieren, oder haben Widget Z unteren Rand ausgerichtet mit dem Boden des Behälters, und so weiter.

Konzepte und Eigenschaften

Um allediese Arbeit, müssen wir Wege andere Widgets innerhalb eines XML-Layout fi verweisen

Plus Wege, um anzuzeigen, die relativen Positionen dieser Widgets.

Relative PositionenIn den Container

Dasam einfachsten Beziehungen einzurichten sind ein Widget die Position, dass der Behälter zu binden:

1. android: layout_alignParentTopsagtdie Top-Widget sollte mit dem oberen Ende des Behälters ausrichten

2. android: layout_alignParentBottomsagtder Unterseite des Widget sollte mit dem Boden des Behälters ausrichten

3. android: layout_alignParentStartsagtder Startseite des Widgets sollte mit der Startseite des Behälters ausrichten

4. android: layout_alignParentEndsagtdie Stirnseite des Widgets sollte mit der

Stirnseite des Behälters auszurichten,

5. android: layout_centerHorizontalsagtDas Widget sollte horizontal in der Mitte des Behälters angeordnet sein,

6. android: layout_centerVerticalsagtdas Widget sollte vertikal in der Mitte des Behälters positioniert werden

7. android: layout_centerInParentsagtDas Widget sollte sowohl horizontal als auch vertikal in der Mitte des Behälters angeordnet sein,

AlleDiese Eigenschaften nehmen einen einfachen Booleschen Wert (wahroderfalsch). Auch gibt esandroid: layout_alignParentLeftund android: layout_alignParentRightAttribute, denn wo Sie pre-Android 4.2-Geräte oder für Fälle wollen unabhängig von Sprachrichtung zu positionieren.

Hinweisdass die Polsterung des Widgets wird berücksichtigt, wenn diese verschiedenen Ausrichtungen durchzuführen. Die Ausrichtungen sind bezogen auf die gesamte Zelle des Widgets (Kombination aus seinem natürlichen Raum sowie die Polsterung).

Relative Notation in Immobilien

Die übrigen Eigenschaften von Bedeutung sindRelativeLayout nehmen Sie die Identität eines Widgets in dem Behälter als Wert. Um dies zu tun:

• Setzen Sie Kennungen(Android: id Attribute) auf alle Elemente, die Sie ansprechen müssen

• Adressediese Widgets von anderen Widgets die Identifikatoren

Der fi

Auftreten eines id-Wert solltedas Plus-Zeichen (@ + id / widget_a); die zweite und die folgenden Zeiten, dass id-Wert im Layout fi verwendet wird
sollte fallen das Plus-Zeichen

(@ id / widget_a). Auf diese Weise können die Build-Tools, um besser helfen Sie Fehler in Ihrer Widget-ID-Werte zu fangen - wenn Sie nicht ein Pluszeichen für ein Widget-ID Wert haben, der vorher noch nicht gesehen hat, die zum Zeitpunkt der Kompilierung gefangen werden. Zum Beispiel wird, wenn Widget A in der RelativeLayout vor Widget B angezeigt wird, und Widget A als @ + id

/ widget_a identifiziert, kann Widget B beziehen sich A in einem seiner eigenen Eigenschaften über die Kennung @ id / widget_a zu Widget.

Relative Positionenzu anderen Widgets

Es gibt vier Eigenschaftendass Steuer Position eines Widgets gegenüber anderen Widgets:

1. android: layout_above zeigt an, dass das Widget sollte in der Eigenschaft
verweistüber das Widget platziert werden

2. android: layout_below zeigt an, dass das Widget sollte in der Eigenschaft verweist unter dem Widget platziert werden

3. android: layout_toStartOfzeigt andass das Widget sollte der Beginn der in der Eigenschaft verwiesen Widget platziert werden

4. android: layout_toEndOf zeigt an, dass das Widget sollte in der Eigenschaft verweist auf das Ende des Widgets platziert werden

Es gibt auchandroid: layout_toLeftOfundandroid: layout_toRightOf

Attribute für die Verwendung mit älteren Geräten.

Darüber hinausjene vier, gibt es fünf zusätzliche Eigenschaften, die man widget Ausrichtung relativ zur anderen steuern kann:

1. android: layout_alignTop zeigt an, dass die Top-Widget sollte mit der Spitze des in der Eigenschaft verwiesen Widget ausgerichtet werden

2. android: layout_alignBottom zeigt an, dass die Unterseite des Widget sollte mit dem Boden des in der Eigenschaft verwiesen Widget ausgerichtet werden

3. android: layout_alignStart zeigt an, dass die Anfangskante des Widgets sollte mit der Anfangskante des in der Eigenschaft verwiesen Widget ausgerichtet werden

4. android: layout_alignEnd zeigt an, dass die Abschlusskante des Widgets sollte mit der Abschlusskante des in der Eigenschaft verwiesen Widget ausgerichtet werden

5. android: layout_alignBaseline zeigt an, dass die Grundlinien der beiden Widgets ausgerichtet werden sollen (wobei das "Baseline" ist, dass unsichtbare Linie, die Text zu sitzen scheint)

the letzte ist nützlich zum Ausrichten von Etiketten und fi
so dass der Text "natürliche"

erscheint. da fi
habenein Feld um sie herum und Etiketten nicht, android: layout_alignTop
würde die Spitze des fi ausrichten
s Box mit dem oberen Rand des Etiketts, die den Text des

Etiketts verursachen wird auf dem Bildschirm höher zu sein, als der Text in die fi eingegeben Android Studio grafische Layout Editor

Sie fi

RelativeLayout im "Layouts" der Palette im Android Studio grafische Layout-Editor.

Sie können, dass in Ihr Layout XML Ressource ziehen.

Während Sie ziehen andere Widgets in IhreRelativeLayout, werden Pfeile man sich den Regeln anspielend, die angewendet werden, wenn Sie das Widget an der aktuellen Mausposition fallen: Bekommendie Regeln, die Sie vielleicht möglich sein, oder auch nicht rein durch Drag & Drop.

Unter Umständen müssen Sie einfach das Widget in die RelativeLayout fallen und manuell die Regeln anzupassen, sei es durch die Fenster Eigenschaften oder durch die XML direkt bearbeiten.

Beispiel: Bottom-then-Top

Zuvordas Kapitel sahen wir, wie die Bottom-dann-Top-Muster zu implementierenVerwendung ein Linearlayout, Wo wir einen kleinen Knopf auf der Unterseite und eine große Taste auf der Oberseite

hatte. Die große Taste eingestellt wurde den ganzen Raum zu nehmen, die nicht durch die kleine Taste erforderlich war.

Wir können erreichendas gleiche Ergebnis ein mitRelativeLayout.

Die XML

Wie beidasLinearlayoutSzenario, haben wir einen Container Plusdie ZweiTaste

Widgets. Imdiesem Fall ist der Behälter einRelativeLayout:

(von

Container / Sampler / app / src / main / res / Layout /
bottom_then_top_rl.xml)

Der BodenTastehatdie gleiche Größe wie zuvor, mitandroid:

layout_widtheinstellenmatch_parentundandroid: layout_heighteinstellenwrap_content. Aber auch sie hatAndroid: layout_alignParentBottom = "true"Es an der Unterseite des VerankerungsRelativeLayout. Seit derRelativeLayoutfi
alleverfügbarer Platz, der

BodenTastewird zu verankerndender Unterseite des Bildschirms, in Wirkung.

Die SpitzeTastehat zweiRelativeLayoutPositionierung Attribute:

• Android: layout_above = "@ + id / another_button", So wird sieüber dem Boden platziertTaste

• Android: layout_alignParentTop = "true", So wird es an die Spitze des verankertenRelativeLayout

GegebenDiese Regeln, ist es egal, was dieandroid: layout_heightAttributwert ist. DasTastewird gestreckt zwischendie beiden Ankerpunkte: die Spitze derRelativeLayoutunddie Oberseite des unterenTaste.

Android Studio grafische Layout Editor

In der Standardeinstellung beim Erstellenein neues Layout Ressource fi
du
erhältsteine vertikale Linearlayout als Stammelement. Sie können das ändern, die "Root-Element" Wert mit einem anderen Widget oder Container-Klassennamen, wie RelativeLayout durch Ersetzen:

Jedoch von dort unter Verwendungdie Drag-and-Drop-Funktionen beginnen mehr Schmerz zu sein, als sie wert sind.

Sie können per DrageinTasteindasRelativeLayout, beispielsweise:

Aber Sie bekommenkein visuelles Feedback, nachdem Sie fallen das Widget von dem, was die Regeln sind, dass die IDE gewählt haben, auf der Grundlage Ihrer Drag-and-Drop-Standort. Wenn Sie durch das Fenster Eigenschaften kramen, werden Sie sehen, dass die Regeln in einigen Checkbox Eigenschaften für die boolean RelativeLayout android reflektiert werden: layout_

Attribute sowie Margen je nachdem, wie weit von der RelativeLayout Kanten Sie das Widget platziert:

Festsetzungdiejenigen, die durch das Fenster Eigenschaften ist nicht leichter als fi sie
durch den XML-Editor. Argumentieren, ist die Eigenschaftsleiste mit langsamer.

Beispiel: URL-Dialog

Wir auchbenutzt Linearlayouterschaffendie "URL-Dialog" UI, Wo wir hatten die markierten fi
entlang mit "OK" und "Abbrechen" Tasten. Das gleiche Struktur kann auch mit einem RelativeLayout gebaut werden.

MitLinearlayoutBrauchten wir drei Behälter: einvertikale Linearlayoutgewickelt um zweihorizontal LinearLayouts.RelativeLayoutEinfacher ist ausdass Standpunkt, da wir nur eine
brauchenRelativeLayout. Die Komplexität bewegt sich in den Widgets statt:

(von

Container / Sampler / app / src / main / res /

Layout / url_dialog_rl.xml)

AlledasRelativeLayoutselbstmuss seine Größe festgelegt, die gleiche wie beivertikale Linearlayoutimdie frühere Version dieses Beispiels - eine Breite vonmatch_parentundeine Höhe vonwrap_content.

Anderealsandroid: layout_widthundandroid: layout_height, Die alle die Widget-Attribute mitLayout_sind Regeln, die von Kindern benutzt einRelativeLayoutfür die Positionierung. Also haben wir:

Widget

Horizontal Anchor

Vertikal Anchor
links / Start-SeitedasRelativeLayoutmit4DP

Basisliniedas

Textview
der Marge

Text bearbeiten
rechts / StirnseitedasTextview

Seitenanfangdas

Text

RelativeLayout
bearbeiten

"OK" Taste
rechts / EndkantedasText bearbeiten

Bodendas

Text bearbeiten

"Stornieren"

links / Startrand die "OK"Taste

Seitenanfangdie "OK"

Taste

Taste

Schon seitdasText bearbeitenBreite wird aufmatch_parent, Wird es den ganzen Raum in der "Reihe", nachdem die fiTextview. Da die "OK"Tastehorizontale Position istan die gebundenText bearbeiten, dasTastegleitet aufder Rand des Bildschirms entlang der angeschlossenen Ziehen "Abbrechen"Taste.

Wieein Ergebnis erhalten wir die gleiche grundlegende UI:

Beispiel: Overlap

RelativeLayout hat auch eine Funktion, die Linearlayout fehlt - die Möglichkeit, Widgets, einander überlappen zu lassen. Später Kinder eines RelativeLayout sind "höher in der Z-Achse" als früher Kinder sind, was bedeutet, dass später Kinder früher Kinder überlappen, wenn sie eingerichtet sind, den gleichen Platz im Layout zu besetzen.

Hier haben wir zwei Tasten, wodas "Ich bin klein", um Überschneidungen der "Ich bin groß"

Button:

Das Layout ist ziemlich einfach:

(von

Container / Sampler / app / src / main / res /

Layout / overlap_rl.xml)

Der fi

Taste eingestellt, um den Bildschirm zu fi nden. Der zweite Knopf wird
innerhalb des übergeordneten zentriert werden, aber nur so viel Platz in Anspruch nehmen, wie für seine Beschriftung benötigt wird. Daher wird die zweite Taste, um "fl erscheinen
zu Endedie fi

Taste.

BeideButton-Widgets können noch angeklickt werden, wenn auch auf dem kleineren Knopf klicken nicht auch den größeren Knopf klicken. Ihre Klicks werden durch das Widget an der Spitze im Falle einerÜberlappung wie diese behandelt werden.

Auf Android 5.0 und höher ist es möglich, zu erreichen,ein ähnlicher Effekt mit Linearlayout durch den Androiden mit: Höhen Attribut der Z-Achse zu steuern, wo höhere Höhenwerte höher auf der Z-Achse bedeuten, fl
zu EndeDiejenigen, die niedriger sind auf der Z-Achse.

Tabula Rasa

Wenn du möchtestHTML-Tabellen, werden Sie Android Tablelayout mögen. Es ermöglicht Ihnen, Ihre Widgets in einem Raster Ihren Vorgaben zu positionieren. Sie steuern die Anzahl der Zeilen und Spalten, die Spalten schrumpfen könnte oder strecken ihre Inhalte gerecht zu werden, und so weiter.

Tablelayout arbeitet in Verbindung mit TableRow. Tablelayout steuert das Gesamtverhalten des Behälters mit den Widgets selbst gegossen in eine oder mehrere TableRow Container, eine pro Zeile im Raster.

Konzepte und Eigenschaften

Für alledies funktioniert, müssen wir fi nden
e, wie Widgets mit Zeilen und Spalten arbeiten,
und wie Widgets zu handhaben, die außerhalb der Reihen leben.

Putting-Zellen in den Reihen

Die Zeilen werden von Ihnen erklärt,der Entwickler, indem Sie Widgets als Kinder eines TableRow innerhalb des Gesamttablelayout setzen. Sie deshalb direkt steuern, wie viele Zeilen in der Tabelle angezeigt werden.

DasAnzahl der Spalten von Android bestimmt werden; Sie steuern die Anzahl der Spalten in einer indirekten Art und Weise.

Erstens wird es mindestens eine Spalte pro Widget in Ihrer längste Zeile sein. Also, wenn Sie drei Reihen haben, eines mit zwei Widgets, eines mit drei Widgets und eine mit vier Widgets, wird es mindestens vier Spalten sein.

Aber,layout_span Eigenschaft, die die Anzahl der Spalten der Widget umfasst: ein Widget kann durch die Einbeziehung der Android mehr als eine Spalte in Anspruch nehmen. Das ist vergleichbar mit dem colspan Attribut ein fi
im Tabellenzellen in HTML:

Imdas obige XML-Layout-Fragment, das fi

Spannweiten drei Spalten.

Normalerweise werden Widgets setzen indie fi
verfügbar Spalte. Imgehen die obige Fragment,
würde das Etikett in der fi

Spalte (Spalte0, die als Spalten gezählt ausgehend von 0), und die
fi
würde inEin übergreifendes Set von drei Spalten (Spalten 1 bis 3). Sie können jedoch ein Widget in eine andere Spalte über den Android setzen: layout_column Eigenschaft, die 0-basierte Spalte angibt das Widget gehört:

Imdas vorhergehende XML-Layout-Fragment, geht die Abbrechen-Taste in der dritten Spalte (Spalte 2). Die OK-Taste geht dann in die nächste verfügbare Spalte, die die vierte Spalte ist.

Nicht-Reihe Kinder von Tablelayout

Normalerweise,Tablelayout enthält nur TableRow Elemente als unmittelbare Kinder. Allerdings ist es möglich, andere Widgets in zwischen den Reihen zu setzen. Für diese Widgets, verhält sich Tablelayout ein bisschen wie Linearlayout mit vertikaler Ausrichtung. Die Widgets haben automatisch ihre Breite zu match_parent gesetzt, so dass sie den gleichen Platz fi nden, dass die längste Zeile tut.

Stretch, Shrink, und Collapse

In der Standardeinstellungjede Spalte wird nach dem "natürlichen" Größe des größten Widget in dieser Spalte (unter aufgespannten Spalten berücksichtigt) bemessen sein. Manchmal allerdings funktioniert das nicht sehr gut aus, und Sie mehr Kontrolle über die Spalte Verhalten benötigen.

Sie können ein PlatzAndroid: stretchColumns Eigenschaft auf dem Tablelayout. Diese listet die Spalte oder Spalten, die jeden zusätzlichen Platz auf der Reihe aufnehmen sollte, wenn die natürliche Breite der Spalten gemeinsam schmaler als die verfügbaren horizontalen Raum ist.

Sie können:

• Listeeine einzelne Spalte gestreckt (zum Beispiel werden,Android: stretchColumns =

"0"Streckendie fi

Spalte)

• Zu Verfügung stelleneine durch Kommata getrennte Liste von Spalten gestreckt (zum Beispiel werden,

Android: stretchColumns = "0,1"Streckendie fi
zwei Spalten)

• Benutzen*um anzuzeigendass alle Spalten sollten mit gleich gestreckt, verwandt werdenandroid: layout_weightWerte ineine horizontaleLinearlayout(z.B,Android:

stretchColumns = "*")

Umgekehrt können Sie ein PlatzAndroid: shrinkColumns Eigenschaft auf dem Tablelayout. Auch dies sollte eine einzelne Spaltennummer, eine durch Kommata getrennte Liste von Spaltennummern sein,

oder * als Abkürzung für alle Spalten für die Vermittlung. Die Spalten in dieser Eigenschaft aufgeführt werden, um zu versuchen, ihre Inhalte Wort-wickeln die effektive Breite der Spalte zu reduzieren - standardmäßig Widgets sind nicht wort gewickelt. Dies hilft, wenn Sie Spalten mit potenziell wortreich Inhalt haben, dass einige Spalten auf der rechten Seite des Bildschirms geschoben werden könnten dazu führen.

Sie können auch eine HebelwirkungAndroid: collapseColumns Eigenschaft auf dem Tablelayout, wieder mit einer Spaltennummer oder durch Kommata getrennte Liste von Spaltennummern (* nicht als verfügbare Option dokumentiert). Diese Spalten werden beginnen "kollabiert", was bedeutet, werden sie Teil der Tabelle Informationen sein wird, aber unsichtbar sein.

Programmatisch können Sie kollabieren und un-Zusammenbruch Spalten durch den Aufruf() Auf dem Tablelayout setColumnCollapsed. Sie könnten diese Benutzer zu ermöglichen, verwenden, welche Spalten steuern, um sie von Bedeutung und sollte im Vergleich zu denen diejenigen weniger wichtig sind angezeigt und ausgeblendet werden können.

Sie können auch steuern, Stretching und zur Laufzeit schrumpfen über
setColumnStretchable ()und setColumnShrinkable ().

Android Studio grafische Layout Editor

Sie fi

Tablelayout und TableRow im "Layouts" der Palette im Android Studio grafischen Layout-Editor:

Gegebenein Tablelayout, können Sie einen oder mehrere TableRow Behälter hinein ziehen, dann starten Sie Widgets in die Zeilen ziehen, so wie Sie verschachtelte Linearlayout Container einrichten könnten.

Beispiel:A Bigger Formular

Ein Bereich, woTablelayoutzeichnet sich mit Formen, vor allem, wenn Sie mitdie klassische Zwei-Säulen "Label und Widget" Struktur für das Formular. Das ist weilTablelayoutkönnen Sie echte Spalten geben, währendLinearlayoutundRelativeLayoutkann nicht.

Wie bei den meistenTablelayout Nutzungen, sind die unmittelbaren Kinder von uns meist TableRow Containern und bietet jeweils den Inhalt der Spalten:

(from

Container / Sampler / app / src / main / res

/ Layout / form_tl.xml)

DasTablelayoutselbst hatAndroid: stretchColumns = "1", So dass alleübrig gebliebenen Platz in den Zeilen in der zweiten Spalte gehen (mit dem fi

Säule mit einem Index von 0) gewonnen.

Der fi
zweite und vierteTischreihehaben jeweils die gleiche Struktur auf, mit
einemTextviewEtikett vorhergehendendasText bearbeitenwoher der Benutzer kann in den Daten fi nden. Der dritteTischreiheHat allerdings nur ein Kind: dieCheckBox. Und unserTasteliegt außerhalb jederTischreiheAls direkte Kind der WurzelTablelayout. BeideCheckBoxunddasTastewerdengibt es auf einer Reihe von ihrer eigenen. Der Unterschied ist, dass dieCheckBoxgeht indie zweite Spalte, mit freundlicher Genehmigung vonAndroid: layout_column = "1", während
dieTastewirdüberspannendie gesamte Zeile (die Art und WeiseTischreiheBehälter erstrecken die gesamte Breite derTablelayout).

So, im Vergleich zudas Original LinearlayoutVersion vondiese Probe, unser

TablelayoutSpalten ordentlich und ausgerichtet:

Beispiel: URL-Dialog

Die

"URL-Dialog"

Layout
implementiert
zuvor
gesehen
mitLinearlayoutund

RelativeLayoutKann auch ein implementiert werdenTablelayout. Dies ist nicht die natürliche Verwendung einesTablelayout, Aber Sie können es tun, wenn man wollte.

Wie beidie Form Probe oben, beginnen wir mit einer Wurzel Tablelayout android mit: stretchColumns = "1" alle zusätzlichen Platz auf der zweiten Spalte zu geben ... obwohl wir mit insgesamt vier Spalten dieses Mal eingereicht werden:

(from

Container / Sampler / app / src / main / res /

Layout / url_dialog_tl.xml)

DasText bearbeitenimdie fi

TischreihehatAndroid: layout_span = "3", Was darauf hinweist,
dass es sollte drei Spalten fiüberspannen. Das, plus unserenTextview, Bedeutet, dass die fi Zeile für vier Spalten insgesamt eingerichtet.

Der fi

Knopf in der zweiten TableRow hat android: layout_column = "2", was darauf hinweist, dass es in der dritten Spalte zu gehen. Die andere Taste geht in die nächste Spalte (die vierte Spalte in diesem Fall), und die fi
zweiSpalten werden übersprungen. Damit,auch diese

Zeile für vier Säulen aufgebaut ist.

Also, wennAndroid: stretchColumns = "1"wird angewandt,der zusätzliche Raum wird auf den

"Inhalt" der zweiten Spalte angegeben werden:

• dasText bearbeitenimdie fi

Reihe

• der leere Raum, um die zwei Button-Widgets in der zweiten Reihe vorhergehenden Hey, was ConstraintLayout?

Im Jahr 2016 Google eingeführtConstraintLayout, mit einer Vision der es die vierte große Behälter zu werden und vielleicht der Standard ein, die Sie wählen würden.

ConstraintLayout hat seine Vorteile, sicher zu sein. Es erfordert jedoch die Verwendung einer Bibliothek, und wir sind noch nicht gedecktWie man anbringt Bibliotheken auf einem Android-Modul.

Also, wir diskutierenConstraintLayoutein bisschen später in dem Buch.

Umkehrenauf RTL

Damitdas / "Ende" "Start" Attribute zu arbeiten, müssen Sie haben android: supportsRtl = "true" in der <application> -Element in Ihrem Manifest. Die meisten neu erstellte Projekte werden dieses Attribut für Sie durch die neuen- Projekt-Assistenten haben bereits festgelegt.

Um zu sehen, wie Sie Ihre App mit RTL verhält- Ohne Arabisch oder Hebräisch zu lernen, wenn man nicht lesen und in diesen Sprachen sind - Sie Android zwingen kann RTL Layout-Regeln mit einer beliebigen Sprache auf Android 4.2+ Geräte zu verwenden. Um dies zu tun, gehen Sie in die Einstellungen App des Gerätes oder Emulator und wählen Sie "Entwickleroptionen". Dort, blättern Sie zu der "Kraft RTL Layout Richtung" Element nach unten. Standardmäßig ist dies ausgeschaltet und so das Layout Richtung wird durch die Benutzer-gewählte Sprache bestimmt:

Tappingdass der Schalter verwendet RTL Layout-Regeln - mit "Start", die sich auf der rechten Seite und "Ende", die sich auf der linken Seite - für alle Sprachen:

Wieeine Erinnerung, wenn "Entwickleroptionen" nicht in der Liste der Einstellungskategorien ist, gehen Sie in die "Info zu Gerät" Kategorie, fi nden die Build-Nummer Element, und tippen Sie auf es siebenmal. Dies wird "Entwickleroptionen" zurück auf die Hauptliste der Einstellungskategorien ermöglichen.

Andere gebräuchliche Widgets und

Behälter

Imdas Kapitel über grundlegende WidgetsVerließen wir alle ausdie klassischen "Zwei-Staaten"

Widgets, wie Checkboxen und Radio-Buttons. Wir werden diese und andere damit
zusammenhängende Widgets in diesem Kapitel untersuchen.

Darüber hinausdie klassischen Allzweckcontainer (Linearlayout.RelativeLayout.Tablelayout), Gibt es andere spezielle Behälter, wieFrameLayoutundRadiogroup, Dass Sie von Zeit zu Zeit nutzen werden. Wir werden auch diejenigen, die in diesem Kapitel untersuchen.

Geradeeine Box zu prüfen

Die klassische Kontrollkästchen hat zwei Zustände: geprüft und ungeprüft. Ein Klickdas Kontrollkästchen schaltet zwischen diesen Staaten eine Wahl zu zeigen (zB "rush Lieferung zu meiner Bestellung hinzufügen").

In Android gibt eseinCheckBoxWidget treffendiese Notwendigkeit. Es hatTextviewals Vorfahren, verwenden Sie können soTextviewEigenschaften wieandroid: textcolorformatierendas Widget.

Innerhalb von Java können Sie aufrufen:

1. wird geprüft()zu bestimmen, obdie Checkbox wurde geprüft

2. setChecked () das Kontrollkästchen in einem aktiviert oder deaktiviert Zustand zu zwingen,

3. Knebel (), um das Kontrollkästchen zu wechseln, als ob der Benutzer auf sie geklickt Außerdem können Sie sich registrierenein Listener-Objekt (in diesem Fall eine Instanz OnCheckedChangeListener) Benachrichtigt werden, wenn der Zustand der Checkboxändert.

Beispielsweise ausdas Basic / CheckBoxBeispielprojekt, hier istein einfaches Kontrollkästchen Layout:

(von

Basic / CheckBox / app / src / main /
res / Layout / main.xml)

Die entsprechendeCheckBoxDemo.java abruft und konfiguriert das Verhalten der Checkbox:

(von

Basic / CheckBox / app / src / main / java / com / commonsware /
android / Checkbox / CheckBoxDemo.java)

Hinweisdass die Aktivität dient als seine eigene Listener fürÄnderungen Checkbox Zustand, da es die implementiertOnCheckedChangeListenerSchnittstelle

(einstellbarübercb.setOnCheckedChangeListener (this)). Der Rückruf fürder Hörer ist (OnCheckedChanged), die das Kontrollkästchen empfängt, dessen Zustand geändert hat und was der neue Zustand ist. In diesem Fall haben wir den Text der Checkbox zu aktualisieren, um nachzudenken, was das eigentliche Feld enthält.

Das Ergebnis? Ein Klickdie Checkbox sofort aktualisiert seinen Text, wie unten dargestellt:

Android Studio grafische Layout Editor

DasCheckBox-Widget kann in der "Widgets" Teil der Palette im Android Studio grafische Layout-Editor zu finden:

Sie können es ziehen indas Layout und konfigurieren Sie es wie mit Hilfe der Fenster Eigenschaften erwünscht. Als CheckBox von Textview erbt, sind die meisten Einstellungen die gleichen wie diejenigen, die Sie fi nden würden
auf eine regelmäßige Textview.

Nicht mögen Ankreuzfelder? Wie über Schaltet oder Schalter?

Einähnliches WidgetCheckBoxistUmschaltknopf. MögenCheckBox.Umschaltknopfisteine Zwei-Staaten-Widget, das entweder aktiviert oder deaktiviert ist. Aber,Umschaltknopfhateine deutliche visuelle Erscheinungsbild:

Andernfalls,Umschaltknopfverhält sichähnlich wieCheckBox. Sie können es in einem Layout fi setzen, wie indas Basic / ToggleButtonSample:

(von

Basic / ToggleButton / app / src / main /
res / Layout / main.xml)

Sie können auch eine einrichtenOnCheckedChangeListenerseinbenachrichtigt, wenn der Benutzer den Zustand derÄnderungenUmschaltknopf.

Ebenso Android hatein Schalter-Widget, um den Zustand über einen kleinen "ON / OFF"

Schieber zeigt:

Schalter, mögenCheckBoxundUmschaltknopf, Erbt vonCompoundButtonUnd teilt daher eine gemeinsame API für Methoden wieUmschalten().wird geprüft(), undsetChecked (). Und wie bei den anderen, können Sie es in einem Layout fi setzen
wie gesehen in das Basic / Schalter

Sample:

(von

Basic / Switch / app / src / main /
res / Layout / main.xml)

Die größte Einschränkungmit Schalter ist, dass es nur auf das Android SDK in API-Ebene 14. Wenn Ihr minSdkVersion auf 14 oder höher eingestellt ist hinzugefügt wurde, sind Sie willkommen Schalter zu verwenden. Wenn Ihr minSdkVersion allerdings etwas niedriger als 14 ist, gesetzt ist, müssen Sie entweder etwas anderes zu wählen oder in komplizierteren Szenarien erhalten, wie eine Bibliothek, die eine Rückportierung von Switch bietet. Wir werden diese komplizierteren Szenarien später im Buch decken; jetzt ist es nur einfachste Schalter zu verwenden, wenn Ihr minSdkVersion auf 14 oder höher eingestellt ist.

Android Studio grafische Layout Editor

DasToggleButton und Switch-Widgets können in der "Widgets" Teil der Palette im Android Studio grafische Layout Editor, direkt unterhalb der CheckBox-Widget zu finden:

Sie können per Dragentweder Widget in das Layout und konfigurieren Sie es wie mit Hilfe der Fenster Eigenschaften erwünscht.

Wendedie Radio-Up

Wie bei anderen Implementierungen von Radio-Buttons in anderen Toolkits, Android Radiobuttons sind mit zwei Zuständen, wie Kontrollkästchen, kann aber so gruppiert werden,dass nur ein Optionsfeld in der Gruppe kann jederzeit überprüft werden.

CheckBox.Umschaltknopf.Schalter, undRadio knopfalle erben vonCompoundButton, Die wiederum erbt vonTextview. Daher sind alle die StandardTextviewEigenschaften für Schriftart, Stil, Farbe, etc.

sind für die Steuerung verfügbarder Blick von Radio-Buttons. Inähnlicher Weise können Sie anrufenwird geprüft()aufeinRadio knopfzu sehen, ob es aktiviert
ist,Umschalten()seineÜberprüfungsstatus zuändern, und so weiter, wie Sie können miteinCheckBox.

Die meiste Zeit werden Sie wollen, setzen Sie IhreRadioButton- Widgets innerhalb eines Radiogroup. Die Radiogroup ist ein Linearlayout, das eine Reihe von Radio-Buttons, dessen Zustand anzeigt, gebunden, das heißt, nur eine Taste aus der Gruppe kann jederzeit ausgewählt werden. Wenn Sie ein Android zuweisen: id zu Ihrem Radiogroup in Ihrem XML-Layout, können Sie die Gruppe von Java-Code zugreifen und rufen:

1. überprüfen () eine spezifi Optionsfeldüber seine ID zuüberprüfen (zB
group.check (R.id.radio1))

2. (ClearCheck) zu löschen alle Radio-Buttons, so dass keiner in der Gruppe geprüft 3. getCheckedRadioButtonId ()bekommendie ID des aktuellüberprüft Radio-Button

(oder-1obkeine geprüft)

Hinweisdass die gegenseitige AusschlussmerkmalRadiogroupgilt nur fürRadio knopfWidgets, die unmittelbare Kinder desRadiogroup. Sie können nicht haben andere Behälter zwischen derRadiogroupund seinRadio knopfWidgets.

Beispielsweise ausdas Basic / RadioButton-Beispielanwendung, Hier ist ein XML-

LayouteinRadiogroupVerpackung eine Menge vonRadio knopfWidgets:

(von

Basic / RadioButton- / app / src / main /
res / Layout / main.xml)

Mitdie Aktie Android-generierte Java für das Projekt und dieses Layout erhalten Sie:

Hinweisdass das Optionsfeld Gruppe wird zunächst am Anfang zu sein, völlig unkontrolliert gesetzt.

Um einen der Radio-Buttons voreingestellt werden geprüft, entwedersetChecked ()aufdasRadio knopfoderprüfen()aufdasRadiogroupaus IhreronCreate ()Rückruf in Ihrer Tätigkeit. Alternativ können Sie verwendendasandroid: geprüftAttribut auf einerdasRadio knopfWidgets indas Layout fi

Android Studio grafische Layout Editor

DasRadiogroup Behälter kann in der "Container" Teil der Palette im Android Studio grafische Layout-Editor zu finden:

Schleppen eine Radiogroup in die Vorschau funktioniert ähnlich wie ein Linearlayout in der Vorschau verschieben. Sie erhalten eine Box, in die Sie andere Widgets, wie der Radiobutton im

"Widgets" auf der Palette gefunden ziehen.

Ranken

Telefon-Bildschirme neigen dazu, klein zu sein, die Entwickler erfordert einige zu verwendenTricks eine Menge Informationen in der begrenzten verfügbaren Raum zu präsentieren. Ein Trick, dies zu tun ist Scrollen zu verwenden, so dass nur ein Teil der Informationen sichtbar zu einem Zeitpunkt, der Rest zur Verfügung über Scrollen nach oben oder unten.

Scroll ist ein Behälter, der für seinen Inhalt liefert scrollen. Sie können ein Layoutübernehmen, die für einige Bildschirme zu groß sein könnte, wickeln Sie es in einem Scrollview, und weiterhin Ihre vorhandenen Layoutlogik verwendet werden. Es passiert einfach so, dass der Benutzer nur einen Teil Ihres Layouts zu einem Zeitpunkt, der Rest zur Verfügungüber eine Rolle zu sehen.

Zum Beispiel, hier isteinScrollin einem XML-Layout fi verwendet

(vondas Behälter/ Scrollen

Demo):

(von

Container / Scroll / app / src / main /
res / Layout / main.xml)

Ohnedie Scrollview, würde die Tabelle mindestens 560 dichteunabhängige Pixel (7 Reihen bei 80

Dips, jeweils bezogen auf die Ansicht Erklärungen) in Anspruch nehmen. Möglicherweise gibt es einige Geräte mit Bildschirmen der Lage sein, so viel Informationen zeigen, aber viele werden kleiner sein. Die Scroll lässt uns die Tabelle halten, wie sie ist, aber nur vorhanden, ein Teil davon zu einem Zeitpunkt.

Aufdie Aktie Android-Emulator, wenn die Aktivität fi
gesehen, Sie sehen:

Beachten Sie, wie nur fünf Zeilen und Teilder sechste sichtbar. Sie können bis blättern und nach unten die restlichen Zeilen zu sehen. Beachten Sie auch, wie die rechte Seite des Inhalts durch den Scrollbar abgeschnitten wird - sicher sein, auf dieser Seite etwas Padding zu setzen oder auf andere Weise sicherzustellen, dass Ihre eigenen Inhalte nicht in dieser Art und Weise abgeschnitten wurde.

Android hat auchHorizontalScrollView, Die funktioniert wieScroll... Nur horizontal. Dies wäre gut für die Formen, die zu breit sein könnte und nicht zu groß. Beachten Sie, dassScrollnur scrollt vertikal undHorizontalScrollViewnur blätterns horizontal.

Beachten Sie auch,dass Sie rollbaren Elemente in eine Scroll nicht setzen können. Zum Beispiel kann ein Listview-Widget - das werden wir sehen, inein kommender Kapitel- Schon weiß, wie zu blättern.

Sie brauchen nicht ein Listview in einem Scroll zu setzen, und wenn man versuchen würde, wäre es nicht sehr gut funktionieren.

Und,einScrolloderHorizontalScrollViewkann nur ein Kind haben- Wenn Sie mehr als einen wollen, wickeln Sie die Kinder in einem geeigneten Behälter Klasse (zB einLinearlayout) Und setzen im Inneren der, dassScrolloderHorizontalScrollView.

Android Studio grafische Layout Editor

DasScroll und HorizontalScrollView Widgets erscheinen in der "Container" der Palette in der grafischen Layout-Editor. Sie können eine von diesen in Ihr Layout XML Ressource ziehen, dann ziehen eins Kind hinein.

Macht Fortschritte mit Progress

Wenn Sie Hintergrund-Threads auf den Tisch gehen zu tun Arbeit im Namen derder Benutzer, werden Sie den Benutzer über das Halten informiert zu denken, dass die Arbeit vor sich geht.

Dies gilt insbesondere, wenn der Benutzer effektiv für diesen Hintergrund Arbeit warten zu vervollständigen.

Dastypische Ansatz Benutzer zu halten Fortschritte informiert ist eine Form von Fortschrittsbalken, wie Sie sehen, wenn Sie ein Bündel fi von Platz kopieren in vielen Desktop-Betriebssysteme zu platzieren. Android unterstützt dies durch die ProgressBar-Widget.

Eine ProgressBar verfolgt die Spuren des Fortschritts, als eine ganze Zahl definiert, wobei 0 keine Fortschritte erzielt wurden. Sie können die maximale Ende des Bereichs definieren - welchen Wert zeigt den Fortschritt abgeschlossen ist - über setMax (). Standardmäßig wird eine ProgressBar beginnt mitein Fortschritt von 0, obwohl können Sie von einem anderen Startposition über setProgress ().

Wenn Sie Ihren Fortschrittsbalken bevorzugen unbestimmt zu sein- Was bedeutet, dass es eine allgemeine animierten Effekt, anstatt eine spezifi Menge Fortschritte zeigen wird - Verwendung setIndeterminate (), es auf true setzen.

In Java-Code, können Sieentweder setzen sich positiv auf die Menge des Fortschritts, die (über setProgress ()) oder erhöhen Sie den Fortschritt von der aktuellen Menge vorgenommen wurde (via incrementProgressBy ()). Sie können fi
auswie viel Fortschritt ist gemacht worden,
übergetProgress ().

Wir werden sehenein ProgressBar in Aktion indas nächste Kapitelein anderer einer unserer Tutorials.

Einrahmungdie Szene

Android
hat
einFrameLayoutKlasse.

MögenLinearlayout.RelativeLayout,
undTablelayout.FrameLayoutexistiert, um Größe und seiner Kinder positionieren.

Aber,FrameLayouthatein sehr einfaches Paar Layout-Regeln:

1. Alle Kinder gehen indie obere Start Ecke (zB links oben für LTR Sprachen), es sei denn, android: Schwerkraft, die Kinder zu positionieren zeigt an anderer Stelle 2. Später Kinder sind höher aufdie Z-Achse als früher sind Kinder, wie mit

RelativeLayoutüberlappen, so können Kinder

Das Ergebnis istdass alle Widgets sind übereinander gestapelt.

Dies kann nutzlos zu sein scheinen. Und,die Wahrheit zu sagen, ist es nicht annähernd so häufig verwendet wird, wie andere Behälter.

In erster Linie,FrameLayout wird dort eingesetzt, wo wir wollen Raum für etwas zu behalten, aber wir wissen nicht, was das "etwas" bei der Kompilierung ist. Die Entscheidung, was die "etwas" ist, wird zur Laufzeit vorgenommen werden, wo wir Java-Code verwenden, wird etwas in der FrameLayout zu setzen. Wir werden diese Muster mit Fragmenten verwendet sehen,später imdas Buch.

Gelegentlich, FrameLayout ist wörtlich für "Framing" verwendet, wo wir eine Art eines Rahmens um ein Kind wollen. In diesem Fall ist der Hintergrund des FrameLayout (zB

Android: Hintergrund) definiert, was der Rahmen aussehen sollte. Wir werden diesen Ansatz in einigen Orten gebraucht, wie indas Kapitel über das Hinzufügen von Drag-and-Drop Ihre App.

Besuchdie Spuren!

Die Routen TeilDas Buch enthältein Widget-Katalog, Bereitstellung Kapsel Beschreibung und Musterfür eine Reihe von Widgets nicht an anderer Stelle in diesem Buch beschrieben.

Das könnte Sie auch interessierenGitterstruktur, Die eine Alternative zu den klassischen Linearlayout.RelativeLayout, undTablelayoutBehälter.

Tutorial # 5- Fortschritte machen

Später imDiese Tutorials werden wir den Benutzer zu notieren Notizen zu dem Buch mit Bezug zu ermöglichen. Diese Hinweise werden in einer Datenbank gespeichert und können angezeigt, geändert oder gelöscht werden, wenn der Benutzer fi sieht

ImIn diesem Tutorial werden wir das Layout Ressource einzurichten, damit der Benutzer in diesen Notizen zu fi nden.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Erstellenein neues Layout Ressourcen

Rechtsklicken Sie aufdie res / Layout / Verzeichnis und Neu> "Layout Ressource fi" aus dem Kontextmenü wählen. Dies bringt das neue Layout Resource File Dialog auf:

Fill im Editor als das "Layout Dateiname", lassen Sie den Rest des Dialogs allein, und klicken Sie auf die Schaltfläche "OK".

Schritt 2: Definierendie UI

Das hätte eröffnetdie grafischen Layout-Editor für diesen neuen Editor Layout-Ressource:

Ziehenein "Mehrzeiliger Text" Widget aus der Palette in den Vorschaubereich. Im Eigenschaftenfenster ändern dieandroid: layout_widthundandroid: layout_heightjeder seinmatch_parentund Veränderungdie ID zuHerausgeber:

Als nächstes wird inEigenschaftenbereich klicken Sie auf den "Hinweis" Eintrag, klicken Sie auf die Schaltfläche "..." auf der rechten Seite davon. Es öffnet sich ein String-Ressource-Picker Dialog auf:

zuoben rechts auf die Schaltfläche "Hinzufügen neuer Ressourcen" Drop-Down und wählen Sie

"New String Value ..." von ihm, die String-Ressource-Editor Dialog zu öffnen: Ergänzeein Ressourcenname von Tip und ein Wert von Notizen hier eingeben. Lassen Sie den Rest des Dialogs allein, und klicken Sie auf OK.

Dann zurück inEigenschaftenbereich wechseln alle Eigenschaften, anstatt nur die Teilmenge zu sehen. Blättern Sie zu der Schwerkraft nach unten Eigenschaft, falten sie zu öffnen, und ändern Sie die markierten Werte auf "oben" und "Start":

Wenn man sichdas Layout XML in der Textunterregister, sollten Sie etwas davon haben: (von

EmPubLite-Android Studio / T5-Layout / EmPubLite / app /
src / main / res / Layout / editor.xml)

In unserer nächsten Folge ...

… wir werdenanfügeneine Drittanbieter-Bibliothekin unserem Tutorial-Projekt.

GUI-Gebäude, Fortsetzung

Wenn Sie ein IDE verwenden, und Sie haben experimentiert mitdie grafischen Layout-Editor und Drag-and-Drop-GUI Gebäude, in diesem Kapitel einige andere allgemeine Funktionen dieses Editors abdecken, dass Sie fi nden kann
sinnvoll.

Auch wenn Sienicht mit einem IDE, können Sie zumindest dieses Kapitel zu überfliegen, wie Sie fi nden
ein paar Tricks, die für Sie relevant sein, wie gut wird.

Machen Sie Ihre Auswahl

Durch Klicken aufein Widget macht es das ausgewählte Widget, was bedeutet, dass die Schaltflächen der Symbolleiste, dass Widget beeinflussen (oder manchmal sein Behälter, auf die Schaltfläche abhängig).

Ausgewählte Widgets habeneine dünne blaue Grenze mit blauen Quadrat "Haltegriffe" für seine Größe und Position anpassen.

Durch Klicken aufein Behälter wählt es auch. Allerdings kann es oder auch nicht eine blaue Grenze sein - insbesondere Behälter, die den Bildschirm (match_parent für Breite und Höhe) fi nicht die Grenze zu kommen scheinen.

Manchmal, wenn Sie auswählen möchtenein Container, der Sie nicht erreichen können, weil der Inhalt vollständig fi sind
mitWidgets. Imdiese Fälle, klicken Sie auf das Widget oder

Container im Komponentenbaum Fenster, um sie auszuwählen.

Inklusive Inklusive

Manchmal haben Sieein Widget oder eine Sammlung von Widgets, die Sie über mehrere Layout-XML-Ressourcen wiederverwendet werden soll. Android unterstützt die Vorstellung eines

"umfassen", dass dies erlaubt. Einfach ein spezielles Layout-XML-Ressource erstellen, die das Widget (n) wieder zu verwenden enthält, dann zu Ihrem Haupt-Layouts über eine fügen Sie

<include> Element:

Sie können sogar zuweisendie <include> Element eine Breite oder Höhe, wenn nötig, als ob es nur ein Widget oder Behälter waren.

Die IDE macht eseinfach für Sie Widgets aus einem bestehenden Layout-XML-Ressource zu nehmen und sie in eine separate Layout XML Ressource zu extrahieren, so dass sie mit einem Ersatz

<Include>Element.

In Android Studio, wählen Siedas Widget (n), die Sie wiederverwenden möchten, dann wählen Sie Refactor

> Extrahieren Sie Layout aus dem Kontextmenü. Dadurch wird ein Dialog angezeigt, in dem Sie in der fi fi können

Name des resultierenden Ressource:

Wenn Sie mehrere Widgets extrahierendas in ihrem eigenen Behälter nicht eingewickelt werden, wird die IDE automatisch wickeln Sie sie in einem <merge> -Element:

Dies ist notwendig, rein aus einer XML-Sicht- Sie können nicht mehrere Wurzelelemente in einer XML-Fi

Wann die <merge> ist mit einem anderen Layout hinzugefügt über

<Include>, das<Merge>Element selbst verdampft, hinter seinen Kindern zu verlassen.

Morphing Widgets

Gelegentlich kann man konfigurierennur ein Widget, später zu entscheiden, dass Sie es wirklich wollen eine andere Art von Widgets zu sein. Zum Beispiel, vielleicht starten Sie mit einem CheckBox und später eingeschaltet werden soll ein ToggleButton zu sein.

Tundies im Android Studio mit der rechten Maustaste auf das Widget (im Vorschaufenster oder im Komponenten-Strukturbereich) und wählen Sie aus dem Kontextmenü Morphing. Dies bringt ein Flyout-Menü von möglichen alternativen Klassen nach oben; die Wahl wird man das Widget in den ausgewählten Typ automatisch konvertieren.

Vorschau von Coming Attractions

Beimdie Spitze des grafischen Layout-Editor, werden Sie fi
eine Reihe von Dropdown-

Menüs, die Sie anpassen lassen, was die Vorschau sieht so aus:

Ihre IDE wird einige wahrscheinlich Standardwerte basierend auf den Projekteinstellungen wählen, aber Sie sind herzlich eingeladen, zu ändernsie, wie Sie fi sehen
bemerkenswert Änderungen sind:

• Welche Version von Android wird verwendet fürdie Vorschau (als Widget Styling ändert sich von Zeit zu Zeit in Android Versionen)

• Welche Sprache wird für Ihre String-Ressourcen genutzt?

• Welche Größe und Auflösung des Bildschirms verwendet wird?

• Ist es im Hoch- oder Quer angezeigt?

Diese wirken sich nur aufdie Vorschau, so dass sie Ihnen zeigen (ungefähr), was Ihr Layout wie unter diesen Bedingungen aussehen, aber sie ändern nichts über Ihr Layout XML selbst.

AdapterViews und Adapter
wenn du willstder Benutzer etwas aus einer Sammlung von Somethings zu wählen, können Sie eine Reihe von Radiobutton-Widgets. Allerdings hat Android eine Reihe von mehr fl widgdiejenigen ets als das, dass dieses Buch wird als "Auswahl-Widgets" beziehen sich auf.

Diese beinhalten:

• Listview, das ist der typische "Listenfeld"

• Spinner, die (mehr oder weniger) ist eine Dropdown-Liste

• Gridview bietet eine zweidimensionale Liste von Entscheidungen

• ExpandableListViewEine begrenzte "Baum" Widget, Unterstützung von zwei Ebenen in der Hierarchie
und viele mehr.

Beimderen Kern sind diese gewöhnlichen Widgets. Sie fi
sie in der Werkzeugpalette Ihrer

IDE grafischen Layout-Editor, und kann sie ziehen und positionieren sie, wie Sie fi sehen Der Schlüssel ist,dass diese alle eine gemeinsame übergeordnete Klasse haben: AdapterView, so genannt, weil sie Partner mit Objekten, die Adapter-Schnittstelle zu bestimmen, welche Möglichkeiten stehen zur Verfügung für den Benutzer zur Auswahl der Umsetzung.

Die Anpassungden Umständen

EinAdapter ist Ihre Brücke zwischen Ihrem Modelldaten und die Daten der visuellen Darstellung in der AdapterView:

• einAdapterkönnte "anpassen" ein RechnungineinAussichtdas würde als eine Zeile in einem dienenListenansicht

• einAdapterkönnte "anpassen"einBuchin einAussichtdas würde als eine Zelle in einem dienen

Rasteransicht

• und so weiter

Android wird mit mehrerenAdapterklassen bereit für Ihren Einsatz, wo die verschiedenen Adapterklassen sind entworfen, um verschiedene Arten von Sammlungen "anpassen" (zB Arrays im Vergleich Ergebnisse von Datenbankabfragen). Android hat auch eine BaseAdapter Klasse, die als Grundlage für Ihre eigenen Adapter Implementierung dienen können, wenn Sie auf

"anpassen", um eine Sammlung von Daten, die keine der Adapterklassen von Android geliefert wird fi.

Mit ArrayAdapter

Daseinfachste Adapter zu verwenden ist ArrayAdapter - alles, was Sie tun müssen, ist eine dieser Verpackung um eine Java-Array oder java.util.List Instanz, und Sie haben eine voll funktionsfähige Adapter:

Ein Geschmack vonder ArrayAdapter nimmt drei Parameter:

1. DasKontext zu verwenden (in der Regel wird dies Ihre Aktivitätsinstanz)

2. Die Ressourcen-IDeine Ansicht (beispielsweise ein eingebautes System Ressourcen-ID, wie oben gezeigt) zu verwenden,

3. Die tatsächliche Array oder eine Liste der Objekte zu zeigen,

In der StandardeinstellungdasArrayAdapteraufrufttoString ()aufund die Objekte in der Liste wickeln jede dieser Zeichenfolgen in der Ansicht von der mitgelieferten Ressource
bezeichnet.android.R.layout.simple_list_item_1einfachdreht sich diese Zeichenfolgen inTextviewObjekte. JeneTextviewWidgets, inwiederum wird in der Liste oder Spinner gezeigt werden, oder was auch immer Widget verwendet dieseArrayAdapter. Wenn Sie möchten, was zu sehenandroid.R.layout.simple_list_item_1wie aussieht, können Sie fi
eine Kopie davon in

Ihrer Installation SDK - suchen Sie einfach nachsimple_list_item_1.xml.

Wir werden sehen, ineinspäteren Abschnittwie Unterklasse einAdapter undÜberschreibung Reihe Schöpfung, zu geben Ihnen mehr Kontrolle darüber, wie Zeilen und Zellen erscheinen.

Listen von Frech und Nizza

Das klassische Listbox-Widget in Android ist bekannt alsListenansicht. Fügen Sie eine dieser in Ihrem Layout, rufen setAdapter (), um Ihre Daten und Kind Ansichten zu liefern, und fügen Sie einen Listenerüber setOnItemSelectedListener () zu fi
aus wann Die Auswahl hat sich
geändert. Damit haben Sie eine voll funktionsfähige listbox.

Wenn jedoch Ihre Aktivität dominierteine einzige Liste, könnten Sie auch Ihre Tätigkeit als Unterklasse von ListActivity zu schaffen, anstatt der regulären Aktivität Basisklasse. Wenn Ihre Hauptansicht nur die Liste ist, brauchen Sie nicht einmal ein Layout zu liefern - ListActivity wird eine Vollbild-Liste für Sie konstruieren. Wenn Sie das Layout anpassen möchten, können Sie, so lange, wie Sie Ihre Listview identifizieren

@android: id / list, damitListActivityweiß, welches Widgetdie Hauptliste für die Aktivität.

Zum Beispiel, hier istein Layout gezogen ausdas Auswahl / ListeBeispielprojekt:

(von

Auswahl / Liste / app / src / main /
res / Layout / main.xml)

Es ist nureine Liste mit einem Etikett auf die aktuelle Auswahl zu zeigen.

Der Java-Code zu konfigurieren,die Liste und schließen Sie die Liste mit der Beschriftung ist:

(von

Auswahl / Liste / app / src / main / java / com / commonsware /
android / Liste / ListViewDemo.java)

MitListActivity, können Sie die Liste Adapter über setListAdapter set () - in diesem Fall ein ArrayAdapter bietet eine Reihe von lateinischen Saiten gewickelt wird. Um fi
aus wanndie

Listenauswahl ändert, außer Kraft setzen onListItemClick () und geeignete Schritte auf der Grundlage der gelieferten geordneten Ansicht und Position (für diese Position in diesem Fall die Aktualisierung das Etikett mit dem Text) nehmen.

Die Ergebnisse?

Der zweite Parameter in unserenArrayAdapter - android.R.layout.simple_list_item_1 - kontrolliert, was die Zeilen aussehen. Der verwendete Wert im vorherigen Beispiel liefert die Standard-Android-Listenzeile: eine große Schrift mit viel Polsterung ein großes Touch-Ziel für den Benutzer zu bieten.

Klicks im Vergleich zu Auswahl

Einswas einige Android-Entwickler ist der Unterschied zwischen Klicks und Auswahlen verwirren können. Man könnte denken, dass sie die gleiche Sache sind - schließlich, ein Klick auf etwas wählt es, nicht wahr?

Nun, nein. Mindestens,nicht in Android. Zumindest nicht die ganze Zeit.

Android ist so konzipiert, mit Touchscreen-Geräte und Nicht-Touchscreen-Geräte verwendet werden. Historisch hat Android durch Geräte dominiertdass nur Touchscreens angeboten.

Allerdings gibt es verschiedene Geräte von Android angetrieben und mit TVs. Die meisten Fernseher sind nicht Touchscreens, und so Nutzer dieser TV-Geräte mit Android wird eine Art Fernbedienung verwenden Android zu fahren. Und einige

Android-Geräte bieten sowohl Touchscreens und eine andere Art von Zeigegerät- D-Pad, einen Trackball, Pfeiltasten usw.

Um beide Arten von Gerät aufnehmen, manchmal Android machteine Unterscheidung zwischen Auswahl Veranstaltungen und Click-Ereignisse. Widgets auf der Grundlage der "Spinner" Paradigma

— einschließlichSpinner - alles als Auswahl Ereignisse behandeln. Andere Widgets - wie Listview und Gridview - Auswahl Ereignisse behandeln, und Ereignisse anders klicken. Für diese Widgets, Auswahl Ereignisse werden durch das Zeigegerät, wie zum Beispiel mit den Pfeiltasten

angetrieben, um einen Markierungsbalken oben und unten eine Liste zu verschieben. Klicken Sie auf Ereignisse, wenn der Benutzer entweder "Klicks" das Zeigegerät (zB drückt das Zentrum D-Pad-Taste) oder tippt etwas in das Widget über den Touchscreen.

WahlModi

In der StandardeinstellungListview ist einfach einzurichten Klicks auf Listeneinträge zu sammeln. Manchmal aber wollen Sie eine Liste, die eine Wahl des Benutzers verfolgt oder möglicherweise mehrere Möglichkeiten. Listview kann damit umgehen als gut, aber es erfordert einige Änderungen.

Als erstes müssen Sieanrufen müssensetChoiceMode ()aufdasListenansichtin Java-Code zu setzendie Wahl-Modus, klassisch entweder

VersorgungCHOICE_MODE_SINGLEoderCHOICE_MODE_MULTIPLEwieder Wert. Sie können
erhalten Sie IhreListenansichtvon einListActivityübergetListView (). Sie können dies auchüber die erklärenandroid: choiceModeAttribut in Ihrem Layout XML.

Dann eherals Einsatzandroid.R.layout.simple_list_item_1wiedas Layout für die Liste Zeilen in IhrerArrayAdapterKonstruktor, können

Sieentwederandroid.R.layout.simple_list_item_single_choiceoderandroid.R.layout.simple_list_item_multiple_choicefür Single-Choice oder Multiple-Choice-Listen sind.

Zum Beispiel, hier ist eine Tätigkeit, Layout ausdas Auswahl / ChecklisteSample Projekt: (von

Auswahl / Checkliste / app / src / main /
res / Layout / main.xml)

Es ist ein VollbildListenansicht, mit demAndroid: choiceMode = "Multiple-Choice"

Attribut, um anzuzeigen,dass wir Multiple-Choice-Unterstützung möchten.

Unsere Tätigkeit nur verwendetein Standard-ArrayAdapter auf unserer Liste der lateinischen Wörtern, sondern nutzt
android.R.layout.simple_list_item_multiple_choicewiedie Reihe Layout:

(von

Auswahl / Checkliste / app / src / main / java / com / commonsware /
android / Checkliste / ChecklistDemo.java)

Wasder Benutzer sieht, ist die Liste der Wörter mit Kontrollkästchen auf der rechten Seite: Wenn wir wollten, könnten wir Methoden aufrufen, wiegetCheckedItemPositions ()auf unseremListenansichtzu fi
aus die Artikel der Benutzerüberprüft, odersetItemChecked

()wenn wir wollten (oder un-check) zuüberprüfenein spezifi Eintrag selbst.

Klicks im Vergleich zu Auswahl, Revisited

Obklickt der Benutzer eine Zeile in eineListenansichtWird ein Click-Ereignis registriert, die Auslösung Dinge wieonListItemClick ()in einem (nOnItemClickListener. Wenn der Benutzer das Zeigegerät verwendet eine Auswahl zuändern (zB durch Drücken nach oben und unten Pfeile, um eine Markierungsbalken zu bewegen, in derListenansicht),dass TriggeronItemSelected ()in einem (nOnItemSelectedListener.

Viele Male, insbesondere dann, wenndie Listview die gesamte UI gegenwärtig ist, Sie kümmern sich nur um Klicks. Manchmal, vor allem, wenn die Listview etwas angrenzt anderes (zB auf einem Fernseher, in dem Sie mehr Platz auf dem Bildschirm haben und nicht über einen Touchscreen), werden Sie mehr über Auswahl Veranstaltungen kümmern. So oder so, können Sie die Ereignisse, die Sie brauchen.

Spin Kontrolle

In Android,der Spinner ist das Äquivalent von der Drop-down-Menü Sie in anderen Toolkits fi könnten. Durch Klicken auf die Spinner fällt nach unten eine Liste für den Benutzer aus, ein Element zu wählen. Sie erhalten grundsätzlich die Möglichkeit, ein Element aus einer Liste zu wählen, ohne den ganzen Platz auf dem Bildschirm eines Listview-Aufnahme, auf Kosten eines zusätzlichen Klick auf eine Änderung vornehmen.

Wie beiListenansichtStellen Sie den Adapter für Daten und Kind AnsichtenübersetAdapter ()und Haken inein Listener-Objekt für AuswahlenübersetOnItemSelectedListener ().

NachSchneider der Ansicht verwendet wird, wenn das Drop-Down-Perspektive angezeigt wird, müssen Sie den Adapter zu konfigurieren, nicht die Spinner-Widget. Verwenden Sie die setDropDownViewResource () Methode, um die Ressourcen-ID der Ansicht zu liefern zu verwenden.

Beispielsweise ausgesondert ausdas Auswahl / SpinnerBeispielprojekt, Hier ist ein XML-Layout füreine einfache Ansicht mit einSpinner:

(von

Auswahl / Spinner / app / src / main /
res / Layout / main.xml)

Das istdie gleiche Ansicht wie gezeigt ineinem früheren Abschnitt, Nur mitein Spinner anstelle eines Listenansicht.

So füllen und Verwendungdie Spinner, benötigen wir einige Java-Code:

(von

Auswahl / Spinner / app / src / main / java / com / commonsware /
android / Auswahl / SpinnerDemo.java)

Hier legen wirdie Tätigkeit selbst als Selektions Zuhörers (spin.setOnItemSelectedListener (this)), wieSpinnerWidgets nur Auswahl Ereignisse unterstützen,keine Ereignisse klicken. Dies funktioniert, weil die Aktivität implementiert dieOnItemSelectedListenerSchnittstelle. Wir konfigurierender Adapter nicht nur mit der Liste der gefälschten Worten, sondern auch mit einer spezifi Ressource für die Drop-down-Ansicht zu verwenden (überaa.setDropDownViewResource ()). beachten Sie auch,die Verwendung vonandroid.R.layout.simple_spinner_itemwiedie sich im internenAussichtfür

Anzeige der Dokumente inder Spinner selbst. Schließlich setzen wir die Rückrufe erforderlich durchOnItemSelectedListeneranpassendie Auswahl-Label basierend auf Benutzereingaben.

Was wir bekommen ist:

Gitter Ihr Lions(Oder etwas ähnliches…)

Wieder Name schon sagt, Gridview Sie ein zweidimensionales Raster von Produkten zur Auswahl gibt. Sie haben moderate Kontrolle über die Anzahl und Größe der Spalten; die Anzahl der Zeilen wird dynamisch auf die Anzahl der Elemente der mitgelieferte Adapter sagt sind für die Anzeige zur Verfügung basierend bestimmt.

Es gibteinige Eigenschaften auf, die, wenn sie kombiniert werden, die Anzahl der Spalten und ihre Größen bestimmen:

1. android: numColumns buchstabiert, wie viele Spalten sind, oder, wenn Sie einen Wert von auto_fit liefern, wird Android die Anzahl der Spalten basierend auf den verfügbaren Raum berechnen und um die nachstehend aufgeführt.

2. android: verticalSpacingundandroid: horizontalSpacingzeigen an, wie viel Leer es in zwischen den einzelnen Posten sein solltedas Gitter.

3. android: columnzeigt an, wie weitJede Spalte sollte in Bezug auf einige Dimension Wert (zB sein,40dpoder@ Dimen / grid_column_width).

4. Android: Stretchzeigt an, für Gitter mitauto_fitfürandroid: numColumnsWas sollte für jeden verfügbaren Raum passieren nicht durch Spalten oder Abstand genommen - dies sollteSpaltenbreitehabendie Spalten aufnehmen verfügbaren Platz
oderspacingWidthhabendie Leerzeichen zwischen den Spalten absorbieren besonders viel Platz.

Andernfalls,dasRasteransichtfunktioniert ähnlich wie jede andere Auswahl-Widget-
benutzensetAdapter ()bereitstellendie Daten und Kind Ansichten, rufensetOnItemClickListener ()zu fi
aus wenn jemand klickt auf eine Zelle im Gitter usw.

Zum Beispiel, hier ist ein XML-Layout ausdas Auswahl / GitterBeispielprojekt, die zeigen,einRasteransichtKonfiguration:

(von

Auswahl / Grid / app / src / main /
res / Layout / main.xml)

Fürdieses Gitter, nehmen wir den gesamten Bildschirm, außer für das, was unsere Auswahl Etikett benötigt werden. Die Anzahl der Spalten wird durch Android berechnet (android: numColumns=

"Auto_fit") Auf der Grundlage unserer horizontalen Abstand (android: horizontalSpacing= "5dip") Und Spalten Breite (android: column= "100dip"), Mitdie Säulen jeder "Slop" Breite absorbieren übrig (Android: Stretch= "Column").

Der Java-Code zu konfigurieren,dasRasteransichtist:

(von

Auswahl / Grid / app / src / main / java / com /
commonsware / android / grid / GridDemo.java)

Die Gitterzellen sind definiert durchein separatesres / Layout / cell.xmlfi
verwiesen in unserem

ArrayAdapterwieR.layout.cell:

(von

Auswahl / Grid / app / src / main /
res / Layout / cell.xml)

Mitder vertikale Abstand von der XML-Layout (android: verticalSpacing= "40dip"),das Gitter überläuft die Grenzen des Bildschirms des Emulators:

Rasteransicht, mögenListenansicht, Unterstützt beide Click-Ereignisse und Auswahl Veranstaltungen. In diesem Beispiel registrieren wir eineOnItemClickListenerfür Click-Ereignisse zu hören.

Felder: Jetzt mit 35% weniger Tippen!

DasAutoCompleteTextView ist das für ein Hybrid zwischen dem EditText (fi
und der

Spinner. Mit Auto-Vervollständigung, während der Benutzer tippt, wird der Text als Präfix fi er behandelt, um den eingegebenen Text als Präfix mit einer Liste von Kandidaten zu vergleichen. Die Spiele werden in einer Auswahlliste angezeigt, die von der fi abklappbar

Das Benutzer
können geben Sie entweder einen Eintrag aus (zB etwas nicht in der Liste) oder einen Eintrag aus der Liste wählen, wird der Wert des fi sein

AutoCompleteTextViewSubklassenText bearbeiten, So können Sie alle Standard-Look-and-Feel Aspekte, wie Schriftart und Farbe zu konfigurieren.

In Ergänzung, AutoCompleteTextViewhat ein android: completionThresholdEigenschaft, um anzuzeigen,die minimale Anzahl von Zeichen muss ein Benutzer, bevor die Liste eintragen fi Ering beginnt.

Du kannst GebenAutoCompleteTextView einen Adapter, um die Liste der Kandidatenwerteüber setAdapter enthält (). Da jedoch der Benutzer etwas nicht in der Liste geben könnte, so AutoCompleteTextView nicht Auswahl Zuhörer unterstützen. Stattdessen können Sie eine TextWatcher registrieren, wie können Sie mit jedem EditText, benachrichtigt werden, wenn die Textänderungen. Diese Ereignisse auftreten, entweder weil der manuellen Eingabe oder aus einer Auswahl aus der Dropdown-Liste.

Im Folgenden habenein vertrautes aussehende XML-Layout, diesmal ein
enthält,AutoCompleteTextView(Gezogen vondas Auswahl / Auto-VervollständigenSample Anwendung):

(von

Auswahl / Auto-Vervollständigen / app / src

/ main / res / Layout / main.xml)

Der entsprechende Java-Code ist:

(von

Auswahl / Auto-Vervollständigen / app / src / main / java / com /
commonsware / android / auto / AutoCompleteDemo.java)

DiesZeit, unsere Tätigkeit GeräteTextWatcher, Was bedeutet, unsere Rückrufe sindOnTextChanged ().beforeTextChanged (), undafterTextChanged (). In diesem Fall sind wir daran interessiert sind nur in der fi
und wir aktualisieren die Auswahl Etikett passen dieAutoCompleteTextView'S
aktuellen Inhalt.

Hier haben wirdie Ergebnisse:

Hinweisdass die rote unterstrichen in dem vorhergehenden Screenshot ist zu Rechtschreibkorrektur fällig. Wie EditText unterstützt AutoCompleteTextView auf Rechtschreibfehler andeutend. Die Sprache des Emulators ist Englisch, da es keine Möglichkeit, in der es für Latein ist.

Customizingder Adapter

Der bescheideneListview ist eine der wichtigsten Widgets in allen Android, einfach weil es so häufig verwendet wird. Ob Sie einen Kontakt wählen oder eine E-Mail-Nachricht anzurufen oder ein EBook zuübermitteln zu lesen, Listview-Widgets werden in einer breiten Palette von Aktivitäten beschäftigt.

Natürlich wäre es schön, wennsie waren mehr als nur Klartext.

Das guteNachricht ist, dass sie so schick sein können, wie Sie wollen, innerhalb der Grenzen eines mobilen Gerätes Bildschirm, natürlich. einige Arbeit jedoch nimmt sie aufwendiger macht.

Hinweisdass während dieser Abschnitt verwenden
werdenListenansichtwiedasAdapterViewHalten Sie die gleichen Techniken für jedeAdapterView.

Die Einzel Layout-Muster

Der einfachste Weg, Brauch zu schaffenListview-Zeilen (oder Grid Zellen oder was auch immer) ist, wenn sie alle die gleiche Grundstruktur aufweisen und kann aus dem gleichen Layout XML

Ressource angelegt werden. Dies bedeutet nicht, dass sie absolut identisch sein müssen, sondern dass Sie alle nötigenÄnderungen vornehmen müssen nur von Konfi

Widgets (zB machen einige

Dinge sichtbar oder später).

Das istnicht besonders schwierig, obwohl es ein paar mehr Schritte als nicht nehmen, was wir bisher gesehen haben.

Schritt # 0: Get Set Up Things einfach

Erstellen Sie zunächst Ihre Aktivität (zB ListActivity), erhalten Sie Ihre Daten (zB Array von Java-Strings), und richten Sie IhreAdapterView mit einem einfachen Adapter Anschluss an die Schritte in den vorhergehenden Abschnitten beschrieben.

Hier werden wir untersuchendas Auswahl / DynamischeBeispielprojekt. Wir werden verwendenein einfaches ListActivity und verwenden die gleiche Liste von 25 lateinischen Wörtern, die in früheren Proben (das Standard-Layout eines Vollbild-Listview-Aufnahme). Doch dieses Mal wollen wir eine ausführlichere Reihe zu haben, unter Berücksichtigung der Länge des lateinischen Wortes.

Schritt # 1: Entwerfen Sie Ihre Row

Als Nächstes erstelleneine Layout-XML-Ressource, die eine Zeile in der Listview (oder Zelle in Ihrem Gridview oder was auch immer) vertreten wird.

Zum Beispiel unsereres / Layout / row.xmlRessource verwendenein Paar von verschachtelten LinearlayoutBehälter zwei zu organisierenTextviewwidgets und einImage:

(von

Auswahl / Dynamisch / app / src / main

/ res / Layout / row.xml)

DasImage wird eine von zwei drawable Ressourcen verwenden, eine für kurze Wörter, und eine andere für lange Worte.

Schritt 2: Erweitern ArrayAdapter

Wenn Sie nur verwendetR.layout.rowmitein StammkundeArrayAdapteres würde funktionieren, soweit sie nicht abstürzen würde. Aber,ArrayAdapternur weiß, wie zu aktualisierenein
einzelnerTextviewimeine Reihe, so wäre es unsere anderen ignorierenTextview, Geschweige denn dieImage.

Also haben wir,müssen unsere eigene ListAdapter zu schaffen, durch eigene Unterklasse zu schaffen von

ArrayAdapter.

da einAdapterist eng gekoppeltdasAdapterViewdass es verwendet, es wird in der Regel am einfachsten, die Gewohnheit zu machenArrayAdapterUnterklasse sein eine innere Klasse von wer verwaltetdasAdapterView. Daher wird in unserem Beispiel werden wir ein
erstellenIconicAdapterinnere Klasse unserer ListActivity.

Schritt # 3: Aufschalten die Constructor und getView ()

DasIconicAdapter Konstruktor kann Kette an dieübergeordnete Klasse und liefern die notwendigen Daten, wie zum Beispiel unsere Java-Array von lateinischen Wörtern. Der wirkliche Spaß kommt, wenn wir außer Kraft setzen getView ():

(von

Auswahl / Dynamisch / app / src / main / java / com / commonsware /
android / fancylists / drei / DynamicDemo.java)

UnsergetView ()Umsetzung hat dreiDinge:

• Es KettenDie Umsetzung "Super von getView (), die eine Instanz unserer Reihe anzeigen zu uns zurückkehrt, wie durch ArrayAdapter vorbereitet. Insbesondere hat sich unser Wort bereits in eine Textview gesetzt worden, da ArrayAdapter, dass normalerweise der Fall ist.

• Es fi
unser Imageund giltwelches Symbol zu setzen sollte verwendet werden,
verweist eine von zwei drawable Ressourcen eine Geschäftsregel

(R.drawable.okundR.drawable.delete).

• Es fi
unserandereTextview und füllt sie auch, indem sie in den Wert einer String-

Ressource ziehen und mit String.format () in unserem Wortlänge zu gießen.

Hinweisdass wir nennenfindViewById ()nicht auf die Aktivität, sondern eher auf die Reihe durch die übergeordnete Klasse 'Umsetzung der zurückgetView (). rufen Sie immerfindViewById ()auf etwas, das garantiert wird, um Ihnenein eindeutiges Ergebnis. ImDer Fall einesAdapterView, Gibt es viele Zeilen, Zellen, usw. sein - AufruffindViewById ()aufdie Aktivität könnte Widgets mit dem richtigen Namen zurück, sondern aus anderen Zeilen oder Zellen.

Dies gibt uns:

Der Ansatz des überwiegendengetView () funktioniert für ArrayAdapter, aber einige andere Arten von Adaptern würden Alternativen haben. Wir werden sehen, dass vor allem mit Cursor, profi
in den folgenden Kapiteln.

Optimierung mitdie ViewHolder Muster

Eine etwas teure Operation wir viel mit aufwendiger Liste Reihen zu tun ist findViewById () aufrufen. Dieser taucht in unserer Reihe und zieht Widgets durch die ihnen zugewiesenen Kennungen, so können wir die Widget-Inhalte (zB Ändern Sie den Text eines Textview, ändern Sie das Symbol in einem Image) anpassen. Da findViewById (können) fi

Widgets überall inder

Baum der Kinder von der Stammansicht der Reihe, könnte dies eine angemessene Anzahl von Anweisungen für die Ausführung benötigen, vor allem, wenn wir mit zu halten, wieder finden Widgets wir schon einmal gefunden hatte.

In einigen GUI-Toolkits,dieses Problem, indem die zusammengesetzte Objekte anzeigen, wie unsere Reihen vermieden wird, (in diesem Fall Java) in Programmcode erklärt total werden. Dann ist die individuelle Widgets den Zugriff lediglich die Frage der einen Getter Aufruf oder ein Zugriff auf
fi

Und Sie können sicher tundass mit Android, aber bekommt der Code ziemlich
ausführlich. Was wäre schön, ist ein Weg, wo wir noch das Layout XML verwenden können, doch unsere Reihe Schlüssel Kind-Cache-Widgets so dass wir nur zu Fi
sie einmal.

Das ist woder Halter Muster ins Spiel kommt, in einer Klasse nennen wir ViewHolder.

AlleView-Objekte haben getTag () und setTag () Methoden. Diese ermöglichen es Ihnen ein beliebiges Objekt mit dem Widget zu verknüpfen. Was die Inhaber Muster tut, ist verwenden, dass

"Tag", ein Objekt zu halten, die wiederum jede der Kind-Widgets von Interesse hält. Durch das Anbringen jedes Mal, wenn wir die Reihe zu verwenden, müssen diese Halterung an der Reihe Ansicht, wir bereits Zugriff auf die Kind-Widgets uns wichtig, ohne findViewById () erneut aufrufen.

Also, lassen Sie unsein Blick auf einen dieser Halter Klassen (ausdas Auswahl/ ViewHolder Beispielprojekt.eine überarbeitete Version desAuswahl / DynamischeProbe aus der Zeit vor): (von

Auswahl / ViewHolder / app / src / main / java / com / commonsware /
android / fancylists / fünf / ViewHolder.java)

ViewHolder hält sich an die Kind-Widgets, über findViewById initialisiert () im Konstruktor. Die Widgets sind einfach Paket-geschützte Datenelemente, auch von anderen Klassen in diesem Projekt ... wie zum Beispiel eine ViewHolderDemo Aktivität. In diesem Fall halten wir nur auf zwei Widgets - das Symbol und das zweite Etikett - da wir ArrayAdapter behandeln unsere fi lassen

Etikette für uns. In unserem Fall halten wir auf die Textview und Imageview-

Widgets, die in getView auffüllen möchten ().

MitViewHolderisteine Frage der eine Instanz zu schaffen, wenn wir eine Reihe und Anbringen der Instanz an die Reihe aufblasenAussichtübersetTag (), Wie sie in dieser Umschreiben gezeigtgetView (), gefunden inViewHolderDemo:

(von

Auswahl / ViewHolder / app / src / main / java / com / commonsware / android

/ fancylists / fünf / ViewHolderDemo.java)

Obder Aufruf von getTag () auf der Zeile gibt null zurück, wissen wir, dass wir einen neuen ViewHolder erstellen müssen, die wir dann auf die Zeile über setTag () für eine spätere Wiederverwendung befestigen. Dann wird das Kind-Widgets zugreifen nur eine Frage der auf den Inhaber der Datenelemente zugreifen.

Dies nutztdie Tatsache, dass die Zeilen in einem Listview recycelt bekommen - eine 25.000-Reihe Liste nicht 25.000 Zeilen nicht erstellen. Das Recycling selbst ist für uns von ArrayAdapter behandelt, also haben wir einfach unsere ViewHolder zu erstellen bei Bedarf und

Wiederverwendung der vorhandenen ViewHolder, wenn eine Zeile recycelt wird. Der fi Zeit
der Listview angezeigt wird, müssen alle neuen Zeilen erstellt werden, und wir landen einen ViewHolder für jeden zu schaffen. Wenn der Benutzer blättert, Reihen bekommen recycelt, und wir können ihre entsprechenden ViewHolder Widget Caches wiederverwenden. Wir behandeln dieses Recycling-Prozess im Detailimein späteren Kapitel.

Hinweisdass diegetModel ()Verfahren gezeigt hier ruft unser ModellSchnurfürein gegebenesPosition, durch die NutzunggetListAdapter ()(Zum Abrufen unsererIconicAdaptervondie Tätigkeit desListenansicht) undgetItem ()(Abrufendie Daten, die von dem Adapter gehalten wird, durch die Position dargestellt):

(von

Auswahl / ViewHolder / app / src / main / java / com / commonsware / android

/ fancylists / fünf / ViewHolderDemo.java)

Klarkommen mitMehrzeilenlayouts

Die Geschichte wird deutlich komplizierter, wenn unsere Mischung aus Reihen komplizierter.

Zum Beispiel, hier istder Sound-Bildschirm in den Programmeinstellungen:

Es kannschauen, wie es nicht, aber das ist ein Listview. Allerdings sind nicht alle Reihen gleich aussehen:

• Einige haben eine Textzeile (zB "Volumes")

• Einige haben zwei Textzeilen (zB "Silent Mode" plus "Off")

• Einige haben eine Zeile Text undein CheckBox (zB "Vibrieren und Ring")

• Einige sind Schriften mit völlig unterschiedlichen Textformatierung (zB "RINGTONE& Notifications ")

Dies wird behandelt, indem mehr miteine Reihe Layout-XML-Ressource als durch den Adapter verwendet. Die Komplexität kommt nicht nur in den verschiedenen Ressourcen verwalten und zu bestimmen, welche, wenn zu verwenden, aber in nur mehr als eine Ressource, die - nach allem, wir ArrayAdapter nur lehren, wie man zu verwenden. Wir werden untersuchen, wie dieses Szenario zu behandelnimein späteres Kapitel.

Besuchdie Spuren!

Um mehr zu erfahren überListview, können Sie wenden sich anErweiterte Listviews, Die zur Deckung andererTricks können Sie mit einem Listview tun.

RecyclerViewistein mächtiger (und komplexere) Ersatz fürListenansichtund

Rasteransicht. Sie können mehrüber lesenwas sie tut und wie können Sie verwenden es.

Die WebView Widget

HTML hat einen langen Weg von Sir Tim Berners-Lee die ursprüngliche Vision kommen, es zu benutzen Physik Papiere zu veröffentlichen.

Es überrascht nicht, die AnzeigeHTML, CSS und JavaScript in mobilen Anwendungen ist ziemlich beliebt, nicht nur für die vollwertigen Web-Browser erstellen, aber für die Darstellung von HTML-Inhalte von RSS / Atom-Feeds von HTML-formatierte E-Mail-Nachrichten, EBooks (wie die, die Sie gerade lesen) , und so weiter.

Es gibtein paar Möglichkeiten, HTML in Android, mit dem mächtigsten Wesen der WebView-Widget, der Schwerpunkt dieses Kapitels anzuzeigen.

Die Rolle von WebView

Wenn deinHTML ist ziemlich begrenzten Bericht dar, wie zum Beispiel, was Sie vielleicht fi
im der Körper eines Status-Update auf Twitter, können Sie die statische fromHtml () -

Methode auf der HTML-Utility-Klasse verwenden, um eine HTML-formatierten String in etwas zu analysieren, die Sie in eine Textview setzen können. Textview können einfache Formatierungen wie Stile (fett, kursiv, etc.) machen, Schriftseiten (serif, serifenlose, etc.), Farben, Links und so weiter.

Aber manchmal IhreAnforderungen für HTML transzendieren, was Textview umgehen kann. Sie Facebook nicht mit Textview werden Surfen, zum Beispiel.

Imdie Fälle, WebView wird die geeignetere Widget sein, da es eine viel breitere Palette von HTML-Tags handhaben kann. WebView können auch CSS und JavaScript handhaben, die Html.fromHtml () einfach ignorieren würde. WebView können Sie auch helfen, mit gemeinsamen "Durchsuchen"

Metaphern, wie Geschichte Liste der besuchten URLs rückwärts und vorwärts Navigation zu unterstützen.

Aufdie andere Seite ist WebView ein viel teurer Widget zu verwenden, im Hinblick auf den Speicherbedarf, als Textview ist.

Daddy, Where Do WebViews kommen?

Ursprünglich,Die Geschichte war einfach: WebView wurde durch eine ziemlich vollständige Kopie mit Strom versorgtWebKit.die Web-Rendering-Engine hinter Safari und ursprünglich Chrome.

In Android 4.4, Google geschaltet Motoren machen. Je nachdem, wer Sie gefragt,WebView wurde angetrieben durchChromoderBlinken. Chrom ist ein Open-Source-Browserdass bildet die Grundlage für Googles Chrome und Blink ist ein Fork von WebKit erstellt von Opera und Google, die wiederum Befugnisse Chrom.

Ab Android 5.0,die Umsetzung von WebView war nicht ein Teil von Android länger. Vielmehr wurde es ein separates "System WebView" app, durch den Play Store verteilt. Die Idee war, dass diese App unabhängig von dem Gerät fi aktualisiert werden konnte

Ware, sodass WebView Fehler
könnten zu mehr Geräte fi zierten schneller und verteilt werden. Dies bedeutet auch, dass Google (und unabhängig von Android OS-Version) verteilen können mehr neue und spannende Bugs schnell, wie es später in diesem Kapitel behandelt werden.

In Android 7.0,die Umsetzung von WebView wird von einem von zwei Orten gleichzeitig sein:

• die proprietäre Browser Chrome App oder

• das System WebView-App für Geräte, bei denen Chrome ist deaktiviert

Die dokumentierte Abhängigkeit vonWebView auf Apps im Play Store verteilt macht die Dinge sehr trübe für Nicht-Play-Ökosystem-Geräte wie die meisten Geräte in China. Höchstwahrscheinlich einzelnen Hersteller ihr eigenes Ding in Bezug auf WebView zu aktualisieren.

Wieein Ergebnis, vom Standpunkt der Sicherheit und Verträglichkeit, ist WebView ein "hot mess".

Hinzufügendas Widget

Für einfache Sachen,WebView ist nicht wesentlich anders als jedes andere Widget in Android - pop es in ein Layout, es sagen, welche URL über Java-Code zu navigieren, und Sie sind fertig.

Wie Sie sehen in kanndas WebKit / Browser1Beispielanwendung, hier istein einfaches Layout mit einWebView:

(von

WebKit / Browser1 / app / src / main /
res / Layout / main.xml)

Wie bei jedem anderen Widget, Siemuss es sagen, wie es um den Raum in der Layout-fi sollte (in diesem Fall ist es fi
alle Restraum).

Und ebenso wie bei anderen Widgets, können Sie fügen Sie Ihre IDE grafischen Layout-Editor.

Ein Android-Studio-Benutzer können per Dragein WebView aus dem "Layouts" in der Werkzeugpalette.

HinweisdassWebViewweiß, wie man die eigenen Inhalte zu blättern, so können Sie tunnicht brauchen es in ein zu setzenScrolloderHorizontalScrollView.

Loading Content Viaeine URL

Es gibteine Reihe von Möglichkeiten HTML-Inhalt in einem WebView Widget zu laden.

Die einfachste ist die Verwendungdie loadURL () Methode, die eine URL nimmt und ruft seinen Inhalt über das Internet. Zum Beispiel, hier ist die Aktivität Quellcode für die WebKit /

Browser1 Beispielanwendung:

(von

WebKit / Browser1 / app / src / main / java / com / commonsware /
android / browser1 / BrowserDemo1.java)

Allerdings müssen wir auch eine Änderung vornehmen zuAndroidManifest.xml, das Hinzufügen einer Zeile, in der wir die Erlaubnis beantragen, auf das Internet zuzugreifen:

(von

WebKit / Browser1 / app / src / main /

AndroidManifest.xml)

Wenn wir nicht hinzufügendiese Erlaubnis, wird sich weigern, die Browser-Seiten zu laden. Wir werden mehr über diese "Erlaubnis" Konzept diskutierenimein späteres Kapitel.

Die resultierende Aktivität aussiehteinen Web-Browser, nur mit versteckten Scrollbalken:

Wie beieine regelmäßige Android Web-Browser, können Sie es, indem Sie auf der Seite schwenken, während das Steuerkreuz die aktivierbaren Elemente auf der Seite alles, was Sie sich bewegt.

Was fehlt, ist allesdas zusätzliche Material, das einen Web-Browser, wie zum Beispiel eine Navigationsleiste bilden. WebView nicht irgendetwas davon liefern - wenn Sie diese Art von UI-Funktionen nutzen möchten, müssen Sie diese selbst zu implementieren (zB verwenden, um eine EditText oder AutoCompleteTextView für eine Browser-Adressleiste).

Links und Umleitungen

Die Probe über Belastungen gezeigtdie CommonsWare Homepage. Die Links in dieser Seite sind anklickbar. Genau das, was passiert, wenn Sie auf den Link klicken, obwohl, hängt von Umständen ab.

Traditionell,das Standardverhalten für, wenn der Benutzer klickt auf einen Link in einem WebView ist für die verlinkten Web-Seite in einem Web-Browser gestartet werden. die "Android-System WebView" Anfang Juni 2015 veröffentlicht änderte sich jedoch, dass das Standardverhalten, so dass nun der verlinkten Web-Seite nach oben in der WebView öffnet sich. Da Android 4.4 und ältere Geräte unterstützen nicht die "Android-System WebView" haben, bedeutet dies, dass das Standardverhalten von Klicks auf Links nach Gerät variiert, das macht keinen Spaß.

Auch, wenn Sie versuchen, Ladeneine Seite mit loadURL () und der Server eine serverseitige Umleitung (zB ,. HTTP 301 oder 304 Antwort), das Standardverhalten das gleiche wie ein einfacher Klick auf eine Link lautet:

• Bei Geräten mit "Android-System WebView" 43.0.2357.121 oder neuer,die umgeleitet zu Seite zeigt in der WebView nach oben

• Überallsonst erscheint die umgeleitet-Seite in einem eigenen Web-Browser App

Wir behandeln wie zu adressierendieses Problem später in diesem Kapitel.

Unterstützung JavaScript

Nun können Sie versucht sein, zu ersetzen,die URL in der obigen Quellcode mit etwas anderem, wie die Google-Homepage oder etwas anderes, das auf JavaScript angewiesen ist. Sie fi
dass solche

Seiten standardmäßig nicht besonders gut funktionieren. Das liegt daran, dass in der Standardeinstellung ist JavaScript in WebView Widgets ausgeschaltet.

Wenn du möchtestaktivieren Sie JavaScript, um Anruf(GetSettings) setJavaScriptEnabled (true).aufdasWebViewBeispiel. BeimDieser Punkt, alle JavaScript, indem Sie Ihre Web-Seite verwiesen sollte in der Regel arbeiten.

Dort sind einigePhantasie Tricks, die Sie mit WebView und JavaScript, wie mit JavaScript-Aufruf von Java-Code oder umgekehrt durchführen kann. Diese Techniken werden abgedecktimein späteren Kapitel.

Alternativenfür Loading Content
loadURL ()arbeitet mit:

• http: //undhttps: //URLs

• file: // URLs an den lokalen fi zeigen

Stengel

• file: /// android_asset /URLs, die auf einer Ihrer Anwendung Vermögen, wie erörtert werden wirdspäter imdieses Buch

• Inhalt: // URLs an einen Contentprovider zeigt die Inhalte für Streaming zur Verfügung zu veröffentlichen, wie diskutiertviel später indieses Buch

Anstatt vonloadURL ()verwenden, können Sie auchlade Daten(). Hier stellen Sie die HTML für dieWebViewangezeigt werden soll. Sie könnten nutzendies:

1. anzeigenein Handbuch, das als fi installiert wurde
mit Ihr Anwendungspaket

2. Anzeige SchnipselHTML Sie als Teil anderer Verarbeitung, wie die Beschreibung eines Eintrags in einem Atom-Feed abgerufen

3. generiereneine ganze Benutzeroberfläche mit Hilfe von HTML, anstatt das Android-Widget Satz mit

Es gibt zwei Arten vonlade Daten(). Je einfacher ein ermöglicht es Ihnen, den Inhalt, den MIME-Typ zur Verfügung zu stellen, und die Codierung, die alle als Strings. Typischerweise wird Ihre MIME-Typ text / html und Ihre Codierung wird UTF-8 für den normalen HTML sein.

Wenn Sie zum Beispiel, ersetzendie loadURL () Aufruf in dem vorherigen Beispiel mit dem folgenden:

Du erhältst:

Dies ist auch alseine voll bebaubare Probe, wieWebKit / Browser2.

Es gibt aucheinloadDataWithBaseURL ()Methode. Dies geschieht unter anderen Parametern,die

"Basis-URL" zu verwenden, wenn sie in der HTML relative URLs zu lösen. Jede relative URL

(zB<imgsrc = "images / foo.png">) Wird als relativ zum Basis URL geliefert werden interpretiertloadDataWithBaseURL (). Wenn Sie fi
dass Sie Inhalte, die ordnungsgemäß
geladen weigert sich, mitlade Daten(), VersuchenloadDataWithBaseURL ()miteinNullBasis-URL, wie es manchmaldas funktioniert besser, aus unbekannten Gründen.

Hörenfür Events

Vor allem, wenn Sie verwenden wollendie WebView als lokale Benutzeroberfläche (vs. Surfen im Web), möchten Sie in der Lage sein, die Kontrolle zu bestimmten Zeiten zu erhalten, vor allem, wenn Nutzer auf Links klicken. Sie werden diese Verbindungen sicherstellen möchten, richtig gehandhabt werden, entweder durch eigene Inhalte zurück in die WebView Laden durch eine Absicht zu Android Einreichen der URL in einem vollen Browser zu öffnen, oder durch andere Mittel. Wir werden diskutieren, eine Absicht mit einem Web-Browser zu startenimein späteres Kapitel.

Ein Haken indie WebView-Aktivität über setWebViewClient (), die eine Instanz einer WebViewClient Implementierung als Parameter übernimmt. Die Callback-Objekt geliefert wird von

einer breiten Palette von Veranstaltungen benachrichtigt, wenn im Bereich von Teilen einer Seite haben (onPageStarted (), etc.) abgerufen wurde, wenn Sie, wie die Host-Anwendung, müssen bestimmte benutzer- oder circumstance- zu handhaben initiierte Ereignisse, wie zum Beispiel: 1. onTooManyRedirects ()

2. onReceivedHttpAuthRequest ()

3. etc.

Ein gemeinsamer Haken wird shouldOverrideUrlLoading (), wo Ihr Rückruf eine URL übergeben wird (plus die WebView selbst), und Sie true zurück, wenn Sie die Anfrage oder falsch wird handhaben, wenn Sie standardmäßig wollen Handling (zB tatsächlich die Webseite durch die referenzierte holen URL). Im Falle einer Anwendung Feed-Reader, zum Beispiel, werden Sie wahrscheinlich nicht eine vollständige Browser mit Navigation in Ihren Reader eingebaut haben, so dass, wenn der Benutzer eine URL klickt, möchten Sie wahrscheinlich eine Absicht zu verwenden Android zu stellen, die Seite zu laden in eine vollständige Browser. Aber, wenn Sie ein "fake" URL
in den HTML eingefügt haben, die eine Verbindung zu einem gewissen Aktivität bereitgestellte Inhalte, können Sie die WebView selbst aktualisieren.

Zum Beispiel wollen wir änderndie fi

Browser Beispiel eine Anwendung zu sein, dass bei
einem Klick, zeigt die aktuelle Uhrzeit an.

VonWebKit / Browser3, Hier ist dieüberarbeitete Java:

Hier stellen wir ladeneine einfache Web-Seite in den Browser (Ladezeit()), Die von der aktuellen Zeit besteht, in einen Hyperlink auf eine gefälschte URL gemacht. Außerdem legen wir eine Instanz einesWebViewClientUnterklasse, die Bereitstellung unserer Implementierung
vonshouldOverrideUrlLoading (). In diesem Fall, egal, was die URL, wollen wir nur die neu zu ladenWebViewüberLadezeit().

Laufendiese Tätigkeit gibt uns:

Ein Klickder Link wird uns dazu bringen, die Seite mit der neuen Zeit neu zu erstellen.

Hinweisdass wir für die Formatierung von unserem Datum und die Uhrzeit ein DateUtils Utility-Klasse geliefert von Android verwenden. Der große Vorteil DateUtils zu verwenden, ist, dass diese

Klasse von den Einstellungen des Benutzers bekannt ist, wie sie es vorziehen, das Datum und die Zeit (zB um zu sehen, 12- Vergleich

24-

Stunden-Modus).

Es gibt aucheinWebChromeClientdass Sie mit einem RegisterWebViewüberein

AufrufsetWebChromeClient (). Diese Aufgabe wird aufgerufen, wenn verschiedene Dinge auftreten, in derWebViewdas könnte zu einem Browser "Chrome" betreffen (dh die Dinge außerhalb der HTML-Rendering-Bereich). Beispielsweise,onJSAlert ()wird auf dem heißenWebChromeClientwenn JavaScript-Code ruftaufmerksam().

Adressierungdie Verbindung / Redirect-Verhalten

Gegebendass Google durch "Android-System WebView" 43.0.2357.121, das Standardverhalten für, wenn Benutzer klicken Sie auf die Links oder Umleitungen geändert hat, ist es in Ihrem besten Interesse den Standard zu vermeiden, da der Standard ändert.

Um dies zu tun, können Sie WebViewClientundshouldOverrideUrlLoading (), Wie oben angegeben.

DasWebKit / Browser4istein Klon der ursprünglichen Probe aus diesem Kapitel, mit einer Änderung: in einem WebViewClient Hinzufügen alle Link zu zwingen, klickt die WebView Inhalte, unabhängig davon, welche Version von Android oder das "Android-System WebView"

wir verwenden zu ändern:

(von

WebKit / Browser4 / app / src / main / java / com / commonsware /
android / browser4 / BrowserDemo4.java)

Hier,dasWebViewClientist eine Instanz einer anonymen inneren Klasse,
undshouldOverrideUrlLoading ()geradedreht sich um und AnrufeloadURL ()aufdasWebViewzu handhabenDie neue URL.shouldOverrideUrlLoading ()kehrt zurückwahrum anzuzeigendass es das Ereignis verarbeitet.

Besuchdie Spuren!

Sie können mehr über leistungsstarke lernenTricks mit WebView, einschließlich der Java und JavaScript-Umgebungen zu integrieren, inein späteres Kapitel.

Definition und Verwendung von Stilen

Wie bereits inein früheres KapitelAndroid bietet Stile und Themen, fi
die gleiche Art von

Rolle, die CSS funktioniert in Web-Entwicklung. In diesem früheren Kapitel haben wir die grundlegenden Aufgaben der Stile und Themen sowie eingeführt, um die drei klassischen Thema Familien:

• Thema

• Theme.Holo

• Theme.Material

ImIn diesem Kapitel, werden wir einen etwas "tiefer Tauchgang" in Stile und Themen, zu erforschen, wie Sie Ihre eigenen und sie auf der App-Benutzeroberfläche erstellen können.

Styles: DIY DRY

Der Zweck der Stile ist zu kapselneine Reihe von Attributen, die Sie immer wieder verwenden wollen, bedingt oder auf andere Weise wollen von Layouts richtige getrennt zu halten. Der primäre Anwendungsfall ist "nicht selbst wiederholen" (DRY) - wenn Sie eine Reihe von Widgets, die gleich aussehen, einen Stil verwenden, um eine einheitliche Definition für "gleich aussehen" zu verwenden, anstatt zu kopieren das Aussehen von Widgets In den Widget.

Unddass Absatz wird ein bisschen mehr Sinn machen, wenn wir ein Beispiel betrachten, und zwardas Styles / NowStyledBeispielprojekt. Das istein triviales Projekt, mit einem Full-Screen-Taste, die das Datum und die Uhrzeit, wann die Aktivität zeigt, ins Leben gerufen wurde, oder wenn die Taste gedrückt wurde. Dieses Mal jedoch, wollen wir die Art und Weise erscheint der Text auf dem Gesicht der Schaltfläche zu ändern, und wir tun so einen Stil verwenden.

Dasres / Layout / main.xmlfi
im Dieses Projekt hat eineStilAttribut aufdasTaste:

(von

Styles / NowStyled / app / src / main /
res / Layout / main.xml)

HinweisTeil Lager XML, dass der Stil-Attribut ist und daher nicht in der
androideNamespace, es so tutnicht bekommen dieandroid:Präfix.

Der Wert,@ Style / bigred, verweist auf eine Art Ressource. Style-Ressourcen sind Werte, Ressourcen und kann in der res / Werte / Verzeichnis in Ihrem Projekt oder in anderen Ressourcengruppen (zB res / Werte-v11 / für Werte Ressourcen nur auf API-Ebene verwendet werden 11 oder höher) zu finden. Die Konvention ist für Stil Ressourcen in einem styles.xml fi gehalten werden
sowiedie eine aus dem NowStyled Projekt:

(von

Styles / NowStyled / app / src / main /
res / Werte / styles.xml)

Das<Style> Element liefert den Namen des Stils, das ist, was wir verwenden, wenn auf den Stil aus einem Layout beziehen. Die <item> Kinder des <style> Element repräsentieren Werte von Attributen zu, was der Stil in Richtung angelegt werden

— in unserem Beispiel unsereTasteWidget. Also, unsereTastewerde habeneine vergleichsweise große Schrift (android: textsizeeinstellen30sp) Und haben den Text in rot erscheinen (android: textcoloreinstellen# FFFF0000).

Gerade definierender Stil und es auf das Widget gibt uns die gewünschten Ergebnisse der Anwendung:

Elements of Style

Es gibt vierElemente zu berücksichtigen, wenn eine Art der Anwendung:

• Wo Sie setzendie Stilattribute zu sagen, dass Sie einen Stil anwenden möchten?

• Welche Eigenschaften können Sie festlegen, überein Stil?

• Wie erben Sie voneine zuvor definierte Stil (eine Ihrer eigenen oder einer von Android)?

• Welche Werte könnendiese Attribute haben in einer Stildefinition?

Wohereinen Stil zu bewerben

DasStil-Attribut kann auf ein Widget angewendet werden, um nur das Widget beeinflussen.

DasStil-Attribut kann auf einen Behälter aufgebracht werden, dass die Behälter zu beeinflussen.

Allerdings bedeutet dies nicht zu tun automatisch seine Kinder-Stil. Zum Beispiel sah suppose res /

Layout / main.xml statt wie folgt aus:

Die resultierende UI würdehaben die Button-Text nicht in einem großen roten Schrift, trotz der Stil Attribut. Der Stil wirkt sich nur aufder Behälter, nicht den Inhalt des Behälters.

Sie können auch anwendenein Stil zu einer Aktivität oder einer Anwendung als Ganzes, auch wenn es dann als ein "Thema" bezeichnet wird, die abgedeckt werdenein bisschen später in diesem Kapitel.

Die verfügbaren Attribute

Wenn Stylingein Widget oder Container, können Sie alle, dass Widgets oder Container Attribute im Stil selbst anwenden. Also, wenn es in den "XML-Attribute" zeigt nach oben oder "Inherited XML-Attribute" Teile des Android JavaDocs, können Sie es in einem Stil setzen.

Hinweisdass Android wird ungültig Stile ignorieren. So hatten wir die angemeldetegroß RotStildasLinearlayoutwie oben gezeigt, wäre alles fi laufen
gerade mit keine sichtbaren

Ergebnisse. Trotz der Tatsache dassLinearlayouthatNeinandroid: textsizeoderandroid: textcolorAttribut gibt eskeine Kompilierung-Ausfall, noch eine Laufzeitausnahme.

Auch das Layout-Richtlinien, wie zum Beispielandroid: layout_widthKann in einem Stil gesetzt werden.

Vererbenein Stil

Sie können auch angebendass Sie von einem anderen Stil Stil Attribute übernommen werden sollen, durch ein übergeordnetes Attribut für das <style> -Element angeben.

Nehmen wir zum Beispieleinen Blick auf diese Art Ressource:

(Anmerkung: in einigen Interpretationen vondieses Buch, können Sie das <item> Element aufgeteilt auf zwei Linien zu sehen - dies durch Zeilenumbruch verursacht wird, so sollte dieses Element in einer Zeile sein)

Hier sind wir angibtdass wir wollen die Theme.Holo Stil von innen Android zu erben. Daher zusätzlich zu allen unseren eigenen Attributdefinitionen, wir angeben, dass wir alle Attributdefinitionen aus Theme.Holo wollen auch.

ichn vielen Fällen wird dies nicht notwendig sein. Wenn Sie nicht ein Elternteil angeben, werden Ihre Attributdefinitionen gemischt in das, was Standardstil auf das Widget oder Behälter aufgebracht wird.

Dass? Android: attr ein bisschen seltsam aussieht, aber wir werden bekommen in das, was die Syntax bedeutet im nächsten Abschnitt.

Die möglichen Werte
typischerweiseder Wert, den Sie diese Attribute im Stil geben wird eine Konstante, wie 30sp oder

# FFFF0000 sein.

Manchmal aber wollen Sie ausführenein bisschen Indirektionsebene - wollen Sie ein anderes Attributwert aus dem Thema von Ihnen erben anzuwenden. In diesem Fall werden Sie den etwas kryptischen aufzuwickeln mit Android: attr / Syntax, zusammen mit ein paar verwandten Zaubersprüche.

Zum Beispiel sehen wir uns wieder aufdieser Stil Ressource:

Hier sind wir angibtdass der Wert vonandroid: Hintergrundistnicht irgendein konstanter Wert ist, oder auch ein Verweis auf eine ziehbare Ressource (zB@ Ziehbar / my_background). Stattdessen sind wir aufder Wert von einem anderen Attribut -activatedBackgroundIndicator- Von unserem ererbten Thema. Was auch immer das Thema definiert als dieactivatedBackgroundIndicatorist das, was unser Hintergrund sein sollte.

Dieser Teilbereich vondas System Android-Stil ist sehr unzureichend dokumentiert, bis zu dem Punkt, wo Google sich Ihnen bei der Suche empfiehltAndroid Quellcode-Listedas verschiedene Stileum zu sehen, was möglich ist.

Dies ist ein Ort, an dem Vererbenein Stil wichtig. In dem Beispiel in diesem Abschnitt gezeigt, wir geerbt von Theme.Holo, weil wir speziell den activatedBackgroundIndicator Wert von Theme.Holo wollte. Dieser Wert könnte nicht in anderen Arten existieren, oder es könnte den Wert wollen wir nicht haben.

Themen: Würdeein Stil durch irgendeinen anderen Namen ...

Themen sind Arten, auf eine Aktivität oder Anwendung angewendet,über ein Android: Thema Attribut für das <Aktivität> oder <application> -Element. Wenn das Thema, das Sie sich bewerben Sie Ihre eigene ist, verweisen Sie wie @style / ..., so wie man es in einem Stil-Attribut eines Widgets. Wenn das Thema, das Sie sich bewerben, kommt aber von Android, in der Regel werden Sie einen Wert mit @android verwenden: style / als Präfix, wie

@android: Stil / Theme.Holo.Dialogoder@android: Stil / Theme.Holo.Light.

Imein Thema, ist Ihren Fokus nicht so sehr Widgets auf Styling, aber das Styling der Tätigkeit selbst. Zum Beispiel ist hier die Definition von@android: Stil /

Theme.Holo.NoActionBar.Fullscreen:

Es spezifi
dass die Aktivität über den gesamten Bildschirm einnehmen sollte, die

Statusleiste auf Handys zu entfernen (android: windowFullscreen auf true gesetzt). Es ist auch spezifi
dass der "Inhalt Overlay" - ein Layout, die um Ihre Aktivität des Inhaltsansicht hüllt

- nichts eingestellt werden sollte (android: windowContentOverlay auf @null), die bewirkt, dass die Titelleiste zu entfernen.

Was passiert, wenn Sie kein Thema haben
die meistendie Beispielanwendungen, die wir bisher untersucht haben, nicht ein Thema, entweder auf der <application> Ebene oder die <Aktivität> Ebene definiert. Was hier geschieht, hängt dann von dem Gerät, das Ihre App läuft auf:

• Auf einem Android 1.x oder 2.x-Gerät, erhalten SieThemen wie Ihr Thema

• Auf einem Android 3.x oder 4.x-Gerät, wenn IhrminSdkVersionodertargetSdkVersionist 11 oder höher, erhalten SieTheme.Holowie deinThema; Andernfalls haften Sie
mitThemawie deinThema

• Auf einem Android 5.0+ Gerät, wenn IhrtargetSdkVersion ist 14 oder höher, Sie

Theme.Material wie Ihr Thema erhalten wird; ansonsten verhält sich Ihre Anwendung wie in der 3.x / 4.x Szenario oben

EINsa Ergebnis, Ihre Anwendung ist bei weitem nicht "gebrochen", trotz des Fehlens einer ausdrücklichen Thema. Es bedeutet aber, dass Ihre Anwendung einen anderen Blick auf diese verschiedenen Android OS Ebenen haben wird, mit einem Blick, mit anderen Anwendungen auf demselben Gerät in mehr App Mischung zu haben neigen.

Sobald jedoch wollen Sie mit dem Anpassen beginnen IhreThema, werden Sie jetzt auf ein Problem stoßen: verschiedene Themen für verschiedene OS-Versionen haben. Ein Android 2.x-Gerät weiß nichts über Theme.Material, zum Beispiel, so können Sie ein eigenes Design basiert auf Theme.Material nicht einfach erstellen und erwarten, dass es zu arbeiten. Wie wir sehen

werdenimein späteren Kapitel.die Lösung windet sich versioniert Ressourcen zu sein, wo man verschiedene Themendefinitionen für verschiedene API-Ebenen haben.

Natürlich, wenn Sie IhreminSdkVersionhoch genug ist, ist Ressource Versionierung ein Problem weniger. Zum Beispiel, wenn IhrminSdkVersion21 ist, werden alle Gerätedass Ihre Anwendung läuft auf sollte wissenTheme.Material, So wie, wenn IhrminSdkVersionwaren 11 oder höher, alle Geräte dass Ihre Anwendung laufen auf würde etwa würde wissen,Theme.Holo.

Android Studio Theme Editor

Auf Android-Studio 1.5 und höher, gibt esein spezielles Thema Editor, mit dem Sie (etwas) Vorschau Ihr Thema ermöglicht und (etwas) zu modifizieren visuell.

Beim Öffnenein Stil oder ein Thema Ressource, werden Sie ein Banner über der Spitze des XML-Editor zu erhalten, bietet das Thema im Design-Editor zu öffnen:

Ein Klickdie "Open-Editor" Link in dieser Banner wird das Theme Editor Tab bringen:

Obder Stil-Ressource einen Stil nicht definieren als Thema verwendet wird - wie es der Fall mit dem NowStyled Beispielanwendung ist, können Sie mit einem hübschen aufzuwickeln, wenn auch nur gelesen Art und Weise zu sehen, wie Farben und Einstellungen im Thema der Aktion beeinflussen Bar (hier als "App-Leiste" bezeichnet), Knöpfe, und so weiter.

Wenn Sie öffnendas Design-Editor auf einen Stil Ressource, die als Thema verwendet wird, können Sie eine Vorschau der benutzerdefinierten Thema erhalten:

In Orten, wo Sie bestimmte Farben außer Kraft gesetzt haben, wiedas Android: colorPrimary Attribut für ein Theme.Material-basiertes Thema, können Sie eine Farbauswahl verwenden diese Farbe mit einem anderen Wert zu ersetzen:

Wieder Dialog Notizen, wenn Sie die Farbe im Dialog ändern, aktualisiert der Editor die damit verbundenen Ressourcen entsprechen, und zeigen Sie den geänderten Wert in der Vorschau: Es ist möglichdass dieses Tool einen größeren Nutzen in den nächsten Jahren gewinnen zu kommen.

JAR-Dateien und Bibliotheksprojekte

Java hat so viele, wennnicht mehr, Sprache Bibliotheken von Drittanbietern als jede andere moderne Programmierung. Hier "Bibliotheken von Drittanbietern" beziehen sich auf die unzähligen JAR-Dateien, die Sie in einem Server oder Desktop-Java-Anwendung enthalten kann - die Dinge, die die Java-SDKs selbst nicht bieten.

Imder Fall von Android, die virtuelle Maschine (VM) an seinem Herzen ist nicht genau Java, und dem, was sie in ihrem SDK bietet, ist nicht genau das gleiche wie jedes herkömmliche Java-SDK.

Davon abgesehen, bieten viele Java Bibliotheken von Drittanbietern noch Funktionen, die Android nativ und daher fehlt es für die, die in Ihrem Projekt für Sie von Nutzen sein können Sie mit Android arbeiten Geschmack von Java zu bekommen. In diesem Kapitel wird erklärt, was es dauern wird, bis Sie solche Bibliotheken und die Beschränkungen auf Android Unterstützung für beliebige Code von Drittanbietern zu nutzen.

Das könnte dirdenken, dass JARs das Urmodell der Wiederverwendung von Code innerhalb Android sind. Das ist nicht wirklich der Fall. Das primäre Modell der Wiederverwendung von Code in Android ist die Android-Bibliothek-Projekt. Viele wiederverwendbare Komponenten und Frameworks werden als Bibliotheksprojekte verteilt, und wir werden im Laufe dieses Buches einige zu sehen.

Das beschriebene Beispiel inDieses Kapitel ist das Android-Support-Paket, ein Kernstück von wieder verwendbaren Code von Google selbst, verteilt teils als JAR-Dateien und zum Teil als Android-Bibliothek-Projekt.

Aber fi

Lasst uns ein bisschen mehr über Android und VMs sprechen.

Die Dalvik VM, undein bisschen ART

Wenn Sie Android Anwendungen schreiben, schreiben Sie den Quellcode von Java. Du könntest seinzu denken, dass Ihr Android-Gerät ist Java-Bytecode ausgeführt wird, wie Sie Ihren Web-Browser könnte, wenn es ein Java-Applet ausgeführt wird.

Ach, würden Sie irren.

Android tuthaben eine Java VM nicht. Android hat die Dalvik VM oder ART.

Die Dalvik VM isteine virtuelle Maschine, entlang der Linien der Java-VM, die Parrot VM (Perl), Microsofts CLR, und so weiter. Da jede VM seine eigene Bytecode aufweist, ist die Dalvik VM

Bytecode nicht die gleiche wie die Java VM-Bytecode (oder der Parrot VM-Bytecode, etc.).

Wenn Sie Ihr Projekt erstellen, wird Ihr Java-Quellcode zunächst kompiliert wurdedie Standard-javac-Compiler. Dann aber sind die Java-VM-Bytecode von javac erstellt Quer kompiliert in

Dalvik VM-Bytecode, und es ist diese Bytecodes, die in Ihre APK fi verpackt
und von

Android ausgeführt.

die meistendie Zeit, Sie werden den Unterschied nicht bemerken. Hin und wieder, obwohl, werden Sie einige Fragen im Zusammenhang mit Android die Nutzung von Dalvik, und der prominenteste von ihnen kommt im Zusammenhang auftreten, wenn Sie bereits vorhandenen Java-Code versuchen Repurposing.

ARTeine neue Laufzeit für Entwicklertests in Android 4.4. ART verwendet immer noch Dalvik Bytecodes, sondern verwendet sie als Eingang für einen Voraus-Zeit (AOT) Compilers.

Lieberauf einer Just-in-Time-Compiler (JIT) als Berufung, da die Dalvik VM tut, Dalvik-Bytecode in CPU-spezifi Anweisungen, ART AOT-Compiler wandelt alle Bytecode auf

Anweisungen bei der Installation zu übersetzen.

Bekommendie Bibliothek

Sie haben zweieinfache Möglichkeiten für Drittanbieter-Java-Code in Ihr Projekt integrieren: JAR-Dateien verwenden oder ein Artefakt in einem Repository verwenden. Der zweite Ansatz ist für Android Studio-Nutzer; jede IDE können JAR-Dateien verwenden.

Ideal,die Dokumentation der Drittanbieter-Bibliothek wird Ihnen sagen, wie es als ein Artefakt zu bekommen und es zu Ihrem Android-Studio-Projekt hinzuzufügen. Genauer gesagt, sollte es Ihnen eine Zeile, die Sie auf Ihre Abhängigkeiten Schließung der App build.gradle sollte hinzufügen fi
sowie kompilieren'Com.squareup.retrofit: Nachrüstung: 1.6.1'. Wir werden uns in die Details von dem, was diese Linie bedeutetviel später indas Buch.

Die Dokumentation sollte auch angeben, welche Artefakt-RepositoryDieses Artefakt stammt aus. Es kann Ihnen sagen, dass das Artefakt aus "Maven" oder "Maven Central" kommt, in dem Fall, dass Sie eine mavenCentral () Linie in Ihren Repositorys Schließung benötigen:

Oder es kann Ihnen etwas sagenwenn das Artefakt aus einer anderen Verwahrungsstelle zu verwenden andere, ist, wie zum Beispiel:

So zum Beispiel könnten Sie wind up mitdie folgenden in Ihrer App build.gradle
fi

Wenn Sie ein ArtefaktName (zBcom.squareup.retrofit: Nachrüstung: 1.6.1), und du hastkein Hinweis darauf, wo das Artefakt kommt, versuchen diemavenCentral ()Option.

Wenn alles, was Sie haben, isteine JAR-fi

Leg es im einlibs /Verzeichnis in Ihrem

Projektapp /Ordner unddann stellen Sie sicher, dass

IhreAbhängigkeitenVerschlußdaskompilierenfiletree ...Linie darin JAR-Dateien zu ziehen auslibs /: Viel mehr über Android Studio, Gradle und Abhängigkeiten gefunden werden kann später im das Buch, aberdies sollte Ihnen den Einstieg helfen.

Die äußeren Grenzen

Nicht alle verfügbaren Java-Code funktioniert gut mit Android. Es gibteine Reihe von Faktoren zu berücksichtigen, einschließlich:

• Erwartete Plattform-APIs: Hatder Code übernehmen eine neuere JVM als die Android basiert auf? Oder übernimmt der Code die Existenz von Java-APIs, die mit J2SE
versenden, aber nicht mit Android, wie Swing?

• Größe: Bestehende Java-Code auf Desktops oder Server für den Einsatzbrauchen nicht zu viele Sorgen über On-Disk-Größe oder bis zu einem gewissen Grad, auch in-RAM-Größe.

Android, ist natürlich kurz auf beiden. Drittanbieter-Java-Code verwenden, insbesondere wenn sie als JARs abgepackte, kann die Größe Ihrer Anwendung Ballon.

• Performance: Hatder Java-Code effektiv einen viel leistungsfähigeren CPU als übernehmen, was Sie fi nden kann
aufviele Android-Geräte? Nur weilein Desktop
kann es ohne Probleme laufen, bedeutet nicht Ihr durchschnittlicher Handy es gut behandelt.

• Schnittstelle: Hatder Java-Code eine Konsole übernehmen? Oder ist es eine reine API, die Sie Ihre eigene Schnittstelle um wickeln kann?

• Betriebssystem: Hatder Java-Code übernehmen die Existenz bestimmter

Konsolenprogramme? Übernimmt der Java-Code es eine Windows-DLL verwenden
kann?

• Sprachversion: Wardie JAR mit einer älteren Version von Java kompiliert (1.4.2 oder älter)? Wurde die JAR mit einem anderen Compiler als die offizielle von Sun (zB GCJ) zusammengestellt? War die JAR mit Java kompiliert 8, so hat es Java 8 Bytecode eher als kompatibel mit Java 6?

• Abhängigkeiten: Hatder Java-Code sind abhängig von anderen Drittanbietern JAR-Dateien, die auch einige dieser Probleme haben könnten? Ist der Java-Code hängt von

Bibliotheken von Drittanbietern (zB die org.json JSON-Bibliothek), die in Android integriert sind, aber der Dritte erwartet eine andere Version dieser Bibliothek?

EinsTrick für einige dieser Bedenken Adressierung ist Open-Source-Java-Code zu verwenden, und tatsächlich mit dem Code arbeiten, um es mehr Android freundlicher zu machen. wenn Sie werden zum Beispiel 10% der Drittanbieter-Bibliothek, vielleicht ist es lohnt sich die Teilmenge des Projekts neu zu kompilieren nur zu sein, was Sie benötigen, oder zumindest die nicht benötigten Klassen aus der JAR entfernen. Der erste Ansatz ist sicherer, dass Sie Compiler Hilfe bekommen, um sicherzustellen, dass Sie nicht einige wesentliche Teil des Codes zu verwerfen, obwohl es sehr mühsam sein kann zu tun.

JAR Dependency Management

Eine Herausforderung bei der Wiederverwendung JAR-Dateien istdass JARs manchmal auf andere JAR-Dateien ab.

Wenn Sie jedoch Android Studio verwenden,Dies ist für Sie automatisch behandelt, wenn Sie Artefakte aus einem Repository als Quelle der JAR-Dateien verwenden (zB von Maven Central oder JCenter ziehen).

OK, so was istein Bibliotheksprojekt?

Ein Android-Bibliothek-Projekt isteine spezielle Art von Android-Projekt entwickelt, Code und Ressourcen zwischen Android-Anwendung Projekte zu teilen. Es richtet sich speziell an Entwickler oder Teams zu schaffen mehrere Anwendungen von der gleichen Code-Basis ausgerichtet.

Bibliotheksprojekte können auch für wiederverwendbare Komponenten verwendet werden, wie zum Beispiel der Verteilung von benutzerdefinierten Widgets, Aktivitäten oder Frameworks an Dritte weitergegeben.

Der größte Unterschied zwischen einem Android-Bibliothek-Projekt undein JAR ist, dass ein Android-Bibliothek-Projekt entwickelt wird Ressourcen und offensichtliche Einträge sowie Java-Code zu verteilen. Wenn alles, was Sie verteilen suchen, um Java-Code ist, arbeitet ein JAR genauso gut wie ein Android-Bibliothek-Projekt. Aber wenn Sie Layouts, Themen, Aktivitäten zu verteilen und dergleichen, ein Android-Bibliothek-Projekt ist die bessere Lösung.

EINspäteren Kapitelwird beschrieben, wie ein Android-Bibliothek-Projekt zu erstellen.

Mita Library Project

Gegebendass Sie ein Bibliotheksprojekt haben - oder haben Sie verwenden möchten identifiziert

- Sie können es auf einem normalen Android-Projekt anschließen, damit der reguläre Android-Projekt Zugriff auf alles, was in der Bibliothek.

Hoffentlich,die Bibliothek-Projekt, das Sie verwenden möchten, wird als AAR verteilt - ein Android-Archiv fi
dass enthält eine kompilierte Version des Quellcodes der Bibliothek,
zusammen mit den Ressourcen und, falls vorhanden, manifestieren.

Genauer gesagt, hoffentlichdie Bibliothek-Projekt, das Sie verwenden möchten, wird als AAR als Artefakt in einem Repository verteilt. Wenn ja, können Sie es mit dem gleichen Ansatz zu integrieren, wie beschriebenfrüherdieses Kapitelfür JAR-Dateien- Fügen Sie einfach die notwendige Kompilierung Anweisung zur Schließung Abhängigkeiten.

Beispielsweise hinzufügendie CWAC-Colormixer BibliotheksprojektIhrer App Android Studio, benutzen Sie:

Obdas Android-Bibliothek-Projekt wird auf andere Weise verteilt werden, um es zu Android Studio Zugabe wesentlich komplizierter wird. Diese Szenarien werden im Einzelnen in den folgenden Kapiteln untersucht werden aufBibliotheksprojekteundGradle Abhängigkeiten. Imdieses Kapitel, werden wir auch in mehr Details über die Struktur dieser Kompilierung Anweisung gehen und die Versionierung Regeln (zB 0,5. +).

Bibliotheksprojekte: Was Sie bekommen

Nun, wenn Sie bauendas Hauptprojekt, das Android-Build-Tools werden:

• Einschließensrc / Verzeichnisse des Hauptprojekt und alle Bibliotheken (libs /) in der Quelle zusammengestellt werden.

• Fügen Sie alledie Ressourcen der Projekte mit dem Vorbehalt, dass, wenn mehr als ein Projekt die gleiche Ressource (zB res / Layout / main.xml) definiert, ist die höchste Priorität Projekt der Ressource enthalten. Das Hauptprojekt ist oberste Priorität, und die Priorität der Rest sind durch ihre Reihenfolge in den Build-Regeln (zB um in

Abhängigkeiten in Android Studio) definiert bestimmt.

Dies bedeutet, dass Sie sicher verweisen könnenR. Konstanten (zB R.layout.main) in Ihrer Bibliothek Quellcode, als zum Zeitpunkt der Kompilierung wird der Wert aus dem Hauptprojekt des erzeugten R Klasse (n) verwenden.

Sie können auch etwas manifestierenEinträge automatisch in Ihrem Manifest injiziert, Elemente aus einem Manifest von der Bibliothek geliefert hinzuzufügen.

Das Android-Support Package

Das Paket Android-Support wird von Google verteilt, enthält Klassen (in JAR-Dateien und Android-Bibliotheksprojekte), die nicht Teil des Android SDK, sind aber auf Android-Entwickler zur Verfügung.

Was ist da drin?

Sie lassen sich grob teilender Inhalt des Android-Support-Paket in zwei große Bereiche: 1. "Backports" von Fähigkeiten hinzugefügtIn den neueren Versionen von Android und Android SDK, so können sie auch auf älteren Geräten verwendet werden. Durch die
zurückportiert Klassen verwenden, können Sie die gleichen Fähigkeiten auf einer breiteren Palette von Geräten, als Sie könnten, wenn Sie nur die Klassen im Android SDK
verwendet.

2. Neue Widgets, Behälter oder anderen KlassenDas sind doch nicht im Android

SDK zu sein (für schlecht definierte Gründe), aber das Google wünscht für Android-Entwickler zur Verfügung zu stellen.

Genauer,die am häufigsten verwendeten Teile des Android-Support-Paket enthalten:

• Unterstützung-v4, die updates und verschiedene UI-Klassen enthält, auf API-

Ebene arbeitet zurück 4

• support-v13, Die identisch ist mitsupport-v4sondern auch enthältein paar Klassen, die auf API-Ebene 13 und höher arbeiten

• appcompat-v7, die eine Rückportierung der Aktionsleiste ist, ein Konzept, das wir diskutierenin einem der nächsten Kapitel

• recyclerview-v7, Das ist die Heimatdas RecyclerViewWidgetdass dient als Alternative zuListenansichtundRasteransicht

• Mediarouter-v7, In dem es eine NeuimplementierungMediarouterund verwandte

Klassen
überdie Namen

WasDieses Buch bezieht sich auf als "Android-Support-Paket" hat viele Namen.

Es wurde ursprünglich bezeichnet alsder Android Compatibility Library, zu einer Zeit, als es nur updates enthalten. Nachdem Google das Hinzufügen in die Dinge begonnen, die nicht unbedingt auf "Kompatibilität" verwandt waren, begannen sie, den Namen zu ändern, um zu versuchen mehr generisch sein. Gerade jetzt, "Android Support" scheint ziemlich konsequent zu sein, entweder gebrauchte Standalone oder in Form von "Android-Support-Paket" oder "Android Support Library".

Fürder Zweck dieses Buches, "Android-Support-Paket" bezieht sich auf die ganze Familie dieser Bibliotheken.

-v4 Versus -v13

Jedes Projektmuss entwedersupport-v4 oder support-v13(Oder manchmalweder), nicht beide. Wenn deinminSdkVersion13 oder höher, wählendassupport-v13Bibliotheküberdassupport-v4Bibliothek, alssupport-v13isteine klare Obermenge von dem, was insupport-v4.

Es bekommen

Sie fi
die "Android-Support Repository" in Ihrem SDK-Manager. Das wird ein Extras / in das Verzeichnis, wo Ihre SDK-Installation befindet, und das Android-Support-Paket innerhalb von Extras in Unterverzeichnisse gehen hinzuzufügen /.

Anbringen es zu einem Projekt

Sie können Referenzen hinzufügendie Android-Support-Paket Bibliotheken - ob diese Bibliotheken sind einfach JAR-Dateien oder Android-Bibliotheksprojekte - über ein paar Zeilen in Ihrer Abhängigkeiten Schließung, die Artefakte aus dem Android-Support Repository verweist.

Hier sinddie Kompilierung-Anweisungen für viele Artefakte in der jetzt aktuellen Version des Pakets Android Support:

Ebenfalls, Während Sie alle diese zu Ihrem Projekt hinzufügen könnten, das ist nicht notwendig. Nur anhängen Abhängigkeiten für Bibliotheken, die Sie tatsächlich verwenden. nur erhöht Ihre APK

Größe ohne guten Grund nicht genutzten Bibliotheken in Ihrem Projekt zu haben. Daher haben die meisten Projekte nur eine Teilmenge der genannten Leitungen.

Hinweisdass im Allgemeinen, wenn die Android-Support-Bibliotheken verwenden, sollten Sie setzen Ihre
compileSdkVersionseindie gleiche wie die Hauptversion der Bibliothek. Also, für eine 23.1.0Version vondie Bibliothek, IhrecompileSdkVersionsollte sein23.

Tutorial # 6Hinzufügen einer Bibliothek -

Wir wollen einige Bibliotheken von Drittanbietern in unserem Projekt zu verwenden, umerleichtern Entwicklung der App:

• dasAndroid Support-BibliothekSpeziell ihrenandroid-support-v13GLAS

• greenrobot desEventBus, Für die Kommunikation zwischen verschiedenen Stücken
von unserer App

• GooglesGsonParser von JSON-Daten

• squareRetrofitEinschließlich seiner Gson-basierten Konverter-Code, für JSON-

Daten von Web-Services abrufen,

• squareOkHttpFür allgemeineHTTP-Anfragen, wie ein ZIP-Archiv herunterzuladen

• dasCWAC-Sicherheits Bibliothek, durchDer Autor dieses Buches, das für einen

Code enthält sicher ein ZIP-Archiv entpacken

• einImplementierung vonTabs

Gerade jetzt, wir werden nur konzentrieren sich auf die Anordnung für unser Projekt in der Lage zu sein, zu verwendendie Bibliotheken. Später im Buch werden wir die Bibliotheken setzen tatsächlich zu verwenden.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt # 1: bestehender Cruft Loswerden

Wenn man sichdie app / build.gradle fi
du wirst sehendass wir einige Abhängigkeiten
automatisch gegeben wurden, wenn das Projekt erstellt wurde:

(von

EmPubLite-Android Studio / T5-Layout /

EmPubLite / app / build.gradle)

Wir sindnicht benutzen wollen irgendwelche von denen nicht:

• Daskompilierenfiletree ()Linie zieht in nackten JAR fi
von daslibs /

Verzeichnis, und wir werden werden nicht mit bloßen JAR fi

• Die anderen Aussagen ziehen in Abhängigkeiten für die Prüfung, und während des Tests isteine fi
was zu tun ist, diese Tutorials haben Sie Testfälle nicht schreiben

Aber,nicht nur das neue Projekt-Assistent diese Abhängigkeiten für uns erzeugen, sondern es auch Code-generierte einige do-nothing-Test-Code, der auf diese Abhängigkeiten abhängt. Also, werden wir diese zwei Test Abhängigkeiten allein verlassen, da es einfacher ist, sie zu ignorieren, als es, dass ein Teil von bis zu reinigen ist.

Aber gehen Sie vor und löschendaskompilierenfiletreeAussage, so dass Sie mit

Sie können erhaltenein gelbes Banner am oberen Rand des Editors, was darauf hinweist, dass ein

"Projekt-Sync" angefordert wird. Ignorieren, dass für den Moment, da wir mehr Änderungen an dieser fi machen werden

Schritt # 2: Anfordern von New Abhängigkeiten
vieleAbhängigkeiten werden wir jetzt einzurichten alle von JCenter zur Verfügung stehen, und unser Projekt bereits eingerichtet ist von dort aus zu ziehen. Allerdings ist die CWAC-Sicherheits Bibliothek nicht, und so müssen wir Gradle zu lehren, wie man fi
dass Bibliothek.

Tundass, fügen Sie den folgenden Code in Ihreapp / build.gradlefi
überdas

AbhängigkeitenSchließung:

(von

EmPubLite-Android Studio / T6-Library /

EmPubLite / app / build.gradle)

Dann fügen Sie sieben weitere Zeilendie Abhängigkeiten Schließung, die Bibliotheken zu identifizieren, die wir brauchen:

(von

EmPubLite-Android Studio / T6-Library /

EmPubLite / app / build.gradle)

Beimdieser Punkt, Ihreapp / build.gradlefi
sollte in etwa so aussehen:

(von

EmPubLite-Android Studio / T6-Library /

EmPubLite / app / build.gradle)

Obdass "Projekt sync" gelbe Fahne an der Spitze des Editors ist, klicken Sie auf "Jetzt synchronisieren" Link in der Fahne, die den * .iml fi zu synchronisieren
mit die
vorgenommenen Änderungen zu diesem build.gradle fi

Ob Sie machen nicht, wählen Sie

Tools> Android> Sync-Projekt mit Gradle Dateien, die Resynchronisation zu erzwingen.

In unserer nächsten Folge ...

… wir werdenkonfigurierenIn der Aktionsleisteauf unserem Tutorial-Projekt

Einführung in ConstraintLayout

Im Jahr 2016 veröffentlichte Googleein neuer Container-Klasse, ConstraintLayout, dass es unter den Android-Entwickler als Alternative zum Linearlayout und RelativeLayout populär geworden hofft

wird. Sicherlich, Google wird zu "ziehen alle Register" Entwickler davon zu überzeugen, ConstraintLayout zu verwenden, wie zum Beispiel mit durch Android Studio neue-Aktivität Assistenten beschäftigt in vielen der Aktivitätsvorlagen verwendet werden.

ConstraintLayout ist nützlich, aber es ist nicht für die Android-App-Entwicklung erforderlich, mehr als Linearlayout und RelativeLayout sind. Und da ConstraintLayout eine Bibliothek ist, müssen Sie einige zusätzliche Schritte zu ergreifen, um es zu einem Projekt hinzuzufügen, und es fügt ~ 100 KB auf die Größe Ihres Android-App. Ob es sich lohnt, dass besonders viel Platz und Zeit für Sie zu entscheiden.

HINWEIS: BeimZur Zeit ist ConstraintLayout noch in einem Alpha-Zustand. Es kann ein gutes Stück ändern, bevor es in fi veröffentlicht wird
bilden. Während die grafischen Layout-

Editor im Android Studio 2.2 sein soll Releasequalität, verhält sie sich, als ob es alpha-Qualität.

Künftige Ausgaben dieses Buches wird dieses Kapitel zu aktualisieren, um neuere Versionen von ConstraintLayout und erhoffte für die Stabilität in der grafischen Layout-Editor zu reflektieren.

Warum Ein weiterer Container?

Linearlayout.RelativeLayoutUnd (in geringerem Ausmaß)Tablelayoutdienten alsdas Rückgrat der meisten Android-Apps. Bisherige Versuche, eine neue Grundlage Container-Klasse zur Verfügung zu stellen -sowieGitterstruktur- Haben sich nicht als erfolgreich erwiesen.

Also, warum die Mühe, Google zu schaffenConstraintLayout?

Drag-and-Drop GUI Builders

Google möchte allen Android Studio zu verwenden, insbesondere für alle Android Studio Drag-and-Drop GUI-Builder zu verwenden.

Wie guteine Drag-and-Drop GUI-Builder arbeitet hängt viel ab, wie die Regeln für ein UI-Auslegen erhalten definiert. Mit Hilfe von Drag-and-Drop-Gesten wird der Entwickler bietet man nur mit X / Y-Koordinaten eines Widgets, basierend auf dem der Entwickler die Maustaste los und schließt den Tropfen. Es liegt an der GUI-Builder, um zu bestimmen, was das wirklich in Bezug auf Layout-Regeln bedeutet.

MitLinearlayout, Ein Widget hinzuzufügen, ist ziemlich einfach:

• Obder Entwickler fällt das Widget zwischen zwei vorhandenen Kinder ein

Linearlayout, setzen Sie das neue Widget in zwischen den vorhandenen

• Andernfalls fügendas Widget zum Ende des Linearlayout, wo der Entwickler sie
fallen gelassen

Tablelayout ist ein bisschen komplizierter, aber immer noch nicht so schlimm, wie wir Jahrzehnte Erfahrung haben mit Tabellen arbeiten zum Einfügen von Zeilen und Spalten in einer gitterartigen Struktur zu kennen.

RelativeLayout aber war schwierig für einen GUI-Builder zu behandeln. Oft wäre falsch interpretieren die Android-Studio GUI-Builder (und seine Vorgänger in Eclipse), die Entwickler Wünsche. Manchmal waren die Regeln der Entwickler ausgedrückt wollte einfach nicht verfügbar durch reine Drag-and-Drop-Operationen. Als Folge mussten die Entwickler in das XML zu tauchen etwas zu erledigen. Die Möglichkeit, das Layout XML zu lesen ist wichtig - sonst, wie diese Bücher unbrauchbar wäre. Allerdings Entwickler zwingt die XML zu schreiben besiegte den Zweck der GUI-Builder.

ConstraintLayout wurde mit GUI-Gebäude im Verstand, ist es ein bisschen leichter zu machen, die richtigen Regeln zu schließen, basierend auf dem der Entwickler geschieht ein Widget zu fallen.

Performance

RelativeLayout.Linearlayoutmitandroid: layout_weight, undTablelayoutmitandroid:

stretchColumns/android: shrinkColumns, Alle erfordern zwei Durchgängeüber ihre Kinder fi zu bestimmen

Größenund Positionen. Beispielsweise mitein gewichtetesLinearlayoutSie
benötigen einen Pass zu machen, die direkt exprimierte Größen zu berechnen (zBandroid: layout_height), gefolgt vonein zweiter Durchgang um den verbleibenden Platz nach dem Gewicht zu verteilen.

Dies wird verstärkt durchdie Tatsache, dass die Details eines Widgets oft die Größen verändernden verursachen neu berechnet werden müssen. Nehmen wir an, dass Sie den Text in einem Textview mit Android ändern: layout_width = "wrap_content". den Text ändern ändert sich die horizontalen Raum durch diesen Text aufzunehmen. So windet sich die Textview zu sagen up sein Behälter

"Hey, bitte die Größen und Positionen neu berechnen", wie der größere Textview jetzt Verschiebungen bei anderen Kindern des Behälters verursachen könnten. Je nachdem, wie der Behälter selbst ist groß, es brauchen könnte sein Behälter zu sagen, dass die Größen und Positionen neu zu berechnen.

Cascading nach oben Eltern zu haben, die Größe neu / re-Positionihre Kinder bekommt für tiefe Hierarchien sehr teuer sind, wo wir Behältnissen mit Behältnissen mit Behältnissen mit einem Behälter haben und so weiter. Eine Änderung im Text eines Textview könnte, dass ganze Hierarchie verursachen, um durch die Größe neu / re-Position zu arbeiten.

AlleSein sonst gleich:

• Tiefer Blick Hierarchien sind langsamer zu machenals sind flachere

• Ansicht Hierarchien, wo die Elternmüssen zwei Durchgänge zu Größe und Position, ihre Kinder sind langsamer zu machen als Hierarchien sind, wo nur ein Durchlauf
benötigt wird

ConstraintLayout wird mit Leistung im Auge, versuchen, so viele zwei Pass Szenarien wie möglich zu beseitigen, und indem man versucht, die Notwendigkeit für tief verschachtelte Ansicht Hierarchien zu beseitigen. Gerade jetzt, in den Alpha-Releases, ist ConstraintLayout Leistung nicht so groß. Allerdings ist es ein Schwerpunkt und sollte im Laufe der Zeit verbessern.

Vergleichen mitdie Classics

StilistischConstraintLayoutamähnlichstenRelativeLayout. Wie beiRelativeLayoutSie können Widgets auf andere Widgets innerhalb der AnkerConstraintLayoutoder zuDie Grenzen derConstraintLayoutselbst.

viele Strukturendas kann aber nicht RelativeLayout mit Linearlayout umgesetzt werden - wie zum Beispiel die Zuweisung Widget Größen auf Basis Gewichte - kann durch ConstraintLayout behandelt werden. ConstraintLayout ist so konzipiert, ohne dass zwei Durchgänge durch ihre Kinder die solche Dimensionierung zu handhaben, um diese Größen bestimmen.

Aber,Tablelayout bleibt deutlich. ConstraintLayout hat nicht den Begriff der Spalten, geschweige denn diese Spalten basierend auf ihren Inhalt und Layout-Regeln Dimensionierung.

Erste ConstraintLayout

BenutzenConstraintLayout, Müssen Sie das mit Ihrem SDK-Manager nichts tun. Alles, was Sie tun müssen, ist eine Version des zu beantragencom.android.support.constraint: Constraint-LayoutArtefakt in IhremAbhängigkeitenSchließung Ihres Modulsbuild.gradlefi

(von Container / Sampler / app / build.gradle)

Für Android 2.2+ Studio Nutzer bekommenDiese Abhängigkeit ist mit dem Rest der Stütz Bibliotheken ähnlich. Sie laden die richtigen Bits auf Ihrer Entwicklungsmaschine mit dem Android SDK Studio-Manager, und das Android-Plugin für Gradle dann weiß, wo es zu suchen. Doch aus unerklärlichen Gründen erfordert ConstraintLayout zwei zusätzliche SDK Manager-Objekte Download bereit:

BekommenConstraintLayout außerhalb von Android Studioist nicht dokumentiert und
kompliziert beimdie aktuelle Zeit.

Mit Widgets und Containervon Bibliotheken

Wenn Sie das Layout Ressourcen Widgets und Container erstellen mitdass ein Teil des Haupt Android SDK sind, können Sie:

• BenutzenAndroid: Präfixe für fast jedes Attribut, und

• Benutzeneine nackte Klassennamen (zB Taste), anstelle eines voll qualifizierten Klassennamen (zB android.widget.Button), für fast jedes Element Name

Wenn Sie Widgets und Behälter aus Bibliotheken- Auch aus dem Android-Support-Bibliotheken

- Sie:

• Benutzeneine Mischung aus einandroid:undApp:Präfixe für Attribute, wodasApp:

diejenigen sind für Attribute, die nicht Teil des Haupt Android SDK

• Benutzeneine voll qualifizierten Klassennamen für die Elementnamen (zB
android.support.constraint.ConstraintLayout)

DassApp:Präfix erfordert eine andere XML-Namespace-Deklaration:xmlns: app =

"http://schemas.android.com/apk/res-auto". Normalerweise wird dieses zum Layout-Ressource automatisch hinzugefügt werden oderüber eine Quick-Fix.

Wenn wir beginnen die Überprüfungdie XML für ConstraintLayout, werden Sie diese beiden Änderungen in Kraft treten zu sehen.

Mitein ConstraintLayout

Zurück indas Kapitel über den klassischen ContainerklassenPrüften wir verschiedene Layouts ausdasContainer / SamplerBeispielprojekt. Das Projekt kommt auch zu
verwenden,ConstraintLayout, und es hat mehrere Layouts, die zeigen, wie ConstraintLayout kann anstelle der klassischen Behälter verwendet werden. Sie dienen dazu, auch zeigen, wie ConstraintLayout im Allgemeinen zu verwenden.

Basisverankerung, Single Axis

Imdas Kapitel über die klassischen Container, hatten wir die "bottom-dann-top" Szenario mit einem kleinen Knopf auf der Unterseite unter eine andere Taste, die alle um den verbleibenden Platz nahm: Zusätzlich zu der Möglichkeit, zu implementieren,Dies Verwendung Linearlayoutund Verwendung RelativeLayout, Können Sie diese mit ConstraintLayout implementieren. Hier setzen wir die Größen und Positionen von zwei Widgets, aber nur auf einer einzigen Achse im Moment konzentriert: die vertikale Achse.

Die XML

DasConstraintLayoutAnsatzähneltdass derRelativeLayoutImplementierung. Wir verwenden LayoutRegeln zubinden den BodenTastenachder Boden derConstraintLayoutundbinden die

SpitzeTastezwischenDie Oberseite derConstraintLayoutunddie Oberseite des unterenTaste:

(von

Container / Sampler / app / src / main / res / Layout /
bottom_then_top_cl.xml)

Der BodenTastehat dreiConstraintLayoutRegeln, wie beispielsweiseApp:

layout_constraintBottom_toBottomOf = "Eltern".ConstraintLayoutRegeln sind ausführlich und ein bisschen seltsam aussehende. Es kann helfen, diese in Stücke zu entpacken:

• App:DennConstraintLayoutkommt voneine Bibliothek, nicht der Android Framework
selbst

• layout_ ist das Standard-Präfix für Regeln auf der Basis eines Containers Widget, nicht anders als das, was wir mit den klassischen Behälter sah

• Zwangwird in allen verwendetendasConstraintLayout-spezifische Regel

AttributNamen

• Unten gibt an, welche Seite des Widgets suchen wir (in diesem Fall der Boden des Widgets) zu verankern

• toBottomOfgibt an, welche Seitedas Ziel (Elternteil) Wollen wir (in diesem Fall zu verankern, den Boden desConstraintLayout)

Der Wert im Zusammenhang mitdie Regel Attribut ist entweder ein Widget-ID eines anderen Kindes aus dem gleichenConstraintLayout, oderElternteilum anzuzeigendasConstraintLayoutselbst. Also, unsereTastewird zu verankerndender Boden derConstraintLayoutMit seiner
natürlichenwrap_contentHöhe.

Die drei Regeln aufdie untere Schaltfläche sind:

• App: layout_constraintBottom_toBottomOf = "Eltern", Der Unterseite des zu bindenTastenachder Boden derConstraintLayout

• App: layout_constraintEnd_toEndOf = "Eltern", Das Ende des zu bindenTaste nachDas Ende desConstraintLayout

• App: layout_constraintStart_toStartOf = "Eltern", Den Beginn des zu binden TastenachDer Beginn derConstraintLayout

Unsere TopTastehat vierConstraintLayoutRegel-Attribute:

• App: layout_constraintBottom_toTopOf = "@ + id / another_button"AnkerDer Boden diesesTastenachdie Oberseite des unterenTaste, Auf die ID des Bodens basierendTaste

• App: layout_constraintTop_toTopOf = "Eltern"Ankerdie Oberseite des oberen TastenachDie Oberseite derConstraintLayout

• App: layout_constraintEnd_toEndOf = "Eltern"Ankerdas Ende der oberen TastenachDas Ende desConstraintLayout

• App: layout_constraintStart_toStartOf = "Eltern"Ankerder Anfang der
oberenTastenachDer Beginn derConstraintLayout

Größen von Widgets auch spieleneine Rolle. Die Höhe des unteren Knopf ist wrap_content, so dass es seine natürliche Höhe sein wird. Die Höhe des oberen Knopf ist 0DP, was darauf hinweist, dass wir es zwischen Ankerpunkten, der durch Regeln zu strecken möchten. Die Breite der beiden Tasten auch 0DP, was darauf hinweist, dass wir diese Tasten zu streck zwischen Ankerpunkten entlang der horizontalen Achse werden soll.

Jetzt könnten Sie fragen wir uns, was wir tunnicht nur die Breite der Tasten eingestellt match_parent und überspringen Sie die "Start" und "Ende" Regeln. In einer idealen Welt, ist das, was wir
würdest du. Die Entwickler vonConstraintLayout haben andere Ideen, und diese Ideen sind machen match_parent nutzlos. Wenn Sie versuchen, match_parent zu verwenden, die Sie die tatsächliche Breite erhalten wird durch die Umstände variieren und nur selten tatsächlich um den verfügbaren Platz fi nden. So sind wir mit dem 0DP-Anker-Regeln Ansatz stecken.

Das Android-Studio grafische Layout Editor

Wie bei anderen Behälter können, erstellen Sieein neues Layout-Ressource mit
einemConstraintLayoutwiedie Wurzel, mit der rechten Maustaste auf
einLayoutRessourcenverzeichnis, wählen Neu> "Layout Ressource fi" aus dem Kontextmenü und tippen inandroid.support.constraint.ConstraintLayoutfürdas Wurzelelement. Beachten Sie, dass Sie das haben, müssen hinzugefügtcom.android.support.constraint: Constraint-LayoutAbhängigkeit zu Ihrem Projekt fi

Andernfalls Sie werden Fehler erhalten, wenn Sie verwenden versuchen
dasConstraintLayoutKlasse.

Wenn Sie ziehenein Widget in die ConstraintLayout und es in einer beliebigen Stelle fallen lassen, was Sie zur Entwurfszeit als anders sein wird, was Sie bekommen, wenn Sie die Anwendung ausführen. Im grafischen Layout-Editor zeigt die Taste, wo Sie es fallen lassen:

Allerdings, wenn Sie schauendie XML, die erzeugt wurde, sehen Sie, dass dieTastehatkeine Einschränkungen. Es hat ein paar Attribute mit derWerkzeuge:Präfix:Werkzeuge:

layout_editor_absoluteXund Werkzeuge: layout_editor_absoluteY:

Attribute inWerkzeuge: Namensraum sind Vorschläge an die Entwicklungstools und haben keinen Einfluss auf das Verhalten Ihrer Anwendung, wenn es läuft. In diesem Fall erinnert Android Studio auf die linke obere Ecke, wo Sie die Taste fallen gelassen. Aber, wie eine Warnung auf den Button im Layout-Editor wird Ihnen sagen, ein Knopf ohne Einschränkungen wird eingereicht bei der Koordinate (0,0) zur Laufzeit (im Grunde, oben links für LTR Sprachen und oben rechts für RTL-Sprachen).

Das Ziehen inein Widget ist unzureichend. Sie müssen auch die grafischen Layout-Editor zu verwenden, um die Bedingungen definieren.

Wenn Sie aufein Widget, das Sie in die ConstraintLayout gezogen, wird der Entwurf Ansicht zeigen Quadrate an den Ecken und an den Rändern zentriert Kreise, zusammen mit einem länglichen Kreis in der Mitte:

Die Quadrate sind Ziehpunkte. Wahrscheinlich haben Sie gesehen,dieses Muster vor, ob in IDEs, Zeichenwerkzeuge oder andere Programme. Während Sie in der Mitte Ziehen einer Ecke sind, einige temporäre Pfeile erscheinen zeigen Sie die Breite und Höhe Sie das Widget Größe verändert haben:

Sie würden verwendendieser Ansatz, wenn Sie eine fi zierte Größe für das Widget wollte, obwohl Dimension Ressourcen, anstatt hart codierte Werte, für die Größenwerte eine gute Idee wäre. Sie können auch die Breite und Höhe durch den Bereich Eigenschaften ändern, wie mit Widgets innerhalb von anderen Arten von Containern.

Die Kreise sind wichtiger, alssie ermöglicht es Ihnen, die Einschränkungen zu definieren, durch einen Kreis zu einem gewissen Ankerpunkt ziehen:

Erschaffendie untere Schaltfläche aus dem Layout im vorherigen Abschnitt gezeigt, würden Sie seine Breite gesetzt 0DP, dann verwenden Sie die Kreise sein, die drei Bedingungen zu schaffen, auf dem Boden, beginnen, und Ende:

Erschaffendie obere Taste, finden Sie eine Schaltfläche in die ConstraintLayout ziehen würde, legen Sie seine Breite und Höhe auf 0DP, dann die vier Bedingungen einrichten, eine auf jeder Seite. Im Falle der Einschränkung aus dem Kreis der unteren Kante des oberen Knopf starten, würden Sie es an die obere Kante des unteren Knopf ziehen diese Widgets zu binden zusammen:

Basisverankerung, Dual Axis

Na sicher,ConstraintLayout kann vertikal horizontal als auch Größe und Position zu steuern. Die

"URL-Dialog" Szenario aus dem Kapitel über die klassischen Behälter können leicht genug umgesetzt werden, um eine ConstraintLayout mit:

Noch einmal,dasConstraintLayoutVersionähnelteine mehr komplexe Darstellung
vonRelativeLayoutVersion:

(from

Container / Sampler / app / src / main / res /

Layout / url_dialog_cl.xml)

DasTextviewAnwendungenApp: layout_constraintStart_toStartOf = "Eltern"sagendass seine Anfangskante ausgerichtet ist mit der Anfangskante desConstraintLayout. Es verwendet auchApp: layout_constraintBaseline_toBaselineOf = "@ + id / Eintrag"haben mit ihren Ausgangs ausrichtendie Grundlinie desText bearbeiten.

DasText bearbeitenverwendet:

• App: layout_constraintStart_toEndOf = "@ id / label"seine Ausgangskante zu haben auszurichtendie Abschlusskante desTextview

• App: layout_constraintEnd_toEndOf = "Eltern"undAndroid: layout_width = "0DP"haben ihreKante ausrichten mit der Abschlusskante der EndungConstraintLayout(Und daher Spanne zu fi nden der verbleibende Platz in der Reihe)

• App: layout_constraintTop_toTopOf = "Eltern"seiner Oberkante haben
auszurichtendie Oberkante derConstraintLayout

Die "OK"Tastehat seineKante ausrichten endet mit der desText bearbeiten(App: layout_constraintEnd_toEndOf = "@ id / entry") Und hat seine Oberkante align mit der Unterkante desText bearbeiten(App: layout_constraintTop_toBottomOf = "@ id / entry") Die "Abbrechen"Tastehat seineAbschlusskante mit der Anfangskante des "OK" alignTaste(App: layout_constraintEnd_toStartOf = "@ id / ok") Und hat seine Oberkante Angleichung an den oberen Rand des "OK"Taste(App: layout_constraintTop_toTopOf = "@ id / ok") Leitlinien

WoherConstraintLayoutbeginnt zu fahren vondie klassischen Behälter ist mit dem Einsatz vonRichtlinieWidgets.

Richtlinien in Grafikeditoren Hilfe bei der Zeichenoperationen. Zum Beispiel in einem SVG-Editor wieInkscapeSie können "Snap" Formen entlang ausrichteneine Richtlinie. Die Richtlinie selbst nicht erscheint in der Ausgabe; es ist nur etwas zu zeichnen Zeit in der Zeichnung zu helfen verwendet.

EINRichtliniedienteineähnliche Rolle mitConstraintLayout. EINRichtlinieistnicht als Teil unserer UI gemacht. Sie räumt jedoch ein, es uns ermöglichen, Widgets innerhalb der

VerankerungConstraintLayoutnachdasRichtlinie, So wie wir diese Widgets zu anderen Widgets oder der Anker kannConstraintLayoutselbst. Und wieder Name schon sagt, einRichtlinieTeil unserer GUI-Builder ist als auch, um Ihnen zu erlauben Ort visuelldasRichtlinieund schließen WidgetsdassRichtlinie.

Beispielsweise indas Kapitel über den klassischen Container, sahen wir uns an, wie konnte manVerwendung Gewichte mitein Linearlayoutzuzuteilen Größe aufProzentual. Aber, Wir machtendiese Struktur mit RelativeLayout nicht replizieren, als RelativeLayout auf eigene keine Möglichkeit, die Arbeit mit Prozentsätzen hat. ConstraintLayout auf eigene wäre auch unfähig, dieses Szenario der Handhabung ..., aber mit der Verwendung eines Paares von Leitlinie widgets, kann sie:

Und, wie esstellt sich heraus, nicht zwei Durchgänge durch seine Kinder benötigen diese Struktur zu erreichen, ConstraintLayout die Art und Weise, die Linearlayout tut, wenn Gewichtungen angewendet werden.

Es kostetdass dieses Layout wesentlich komplexer ist, als es seine Linearlayout

Gegenstück:

(von

Container / Sampler / app / src / main / res /

Layout / stacked_percent_cl.xml)

EINRichtlinieeine Orientierung hat, eingestelltüber android: Orientierung. Beide derRichtlinieWidgets verwendet hier sindhorizontal. Dies bedeutet, dass sie die Breite der SpanneConstraintLayoutUnd etwas anderes hat, um anzuzeigen, wo sie sich aufhalten vertikal innerhalb derConstraintLayout.

Imdieser Fall, dass "etwas anderes" ist dasApp: layout_constraintGuide_percentAttribut. Dies zeigt an, wie weit vonDer Beginn derConstraintLayoutdiesehorizontale LeitlinieWidgets gehören, in Bezug auf dieein Bruchteil der Gesamthöhe desConstraintLayout. In diesem Fall erscheinen sie 50% (.50) Und 80% (.80) von Anfang an.

Unsere dreiButton-Widgets ihre eigenen Höhen nicht angeben - sie 0DP für Android verwenden: layout_height. Und auch nicht ihre Höhen in Bezug auf Gewichte auszudrücken, die Art und Weise der Linearlayout Äquivalent tut. Stattdessen sie die gleichen Verankerungs Regeln verwenden, die die ganze Zeit ... bis jetzt verwendet werden, können sie auf diese beiden Leitlinie widgets neben einander und die ConstraintLayout verankern.

Also, unsere TopTasteseiner Oberkante hat ausgerichtetdie Oberkante derConstraintLayout(App: layout_constraintTop_toTopOf = "Eltern"). Aber es hat auch seine Boden verankertDie Oberseite der.50 Leitlinie(App: layout_constraintBottom_toTopOf = "@ id / guideline_50"). mit der kombinierten0DPHöhe,diese erstreckt sich dieTastezwischendie obere und die Mitte desConstraintLayout.

Die MitteTasteverankert sich zwischendie ZweiRichtlinieWidgets, mitApp:

layout_constraintBottom_toTopOf = "@ id / guideline_80"undApp:

layout_constraintTop_toTopOf = "@ id / guideline_50". Es erstreckt sich auch diese Lücke zu fi nden, und so wird es 30% der Platz in Anspruch nehmen (zwischen den.50unddas.80

LeitlinieWidgets).

Ähnlich,der BodenTastebindet sich von der an der UnterseiteConstraintLayout(App: layout_constraintBottom_toBottomOf = "Eltern") Sowie die.80 Leitlinie(App: layout_constraintTop_toTopOf = "@ id / guideline_80").

Besuchdie Spuren!

Da sind mehrDinge, die Sie mit einem ConstraintLayout darüber hinaus erreichen können, was hier präsentiert wird. Es gibt ein Kapitel auffortgeschritten ConstraintLayout Techniken dass in komplexeren Szenarien erhalten.

Wenn Sie in andere Behälter aus Bibliotheken interessiert sind,Das Buch enthält Kapitel überGitterstrukturunddie Behälter ausdie prozentuale Support-Bibliothek(Beispielsweise PercentRelativeLayout).

Die Aktionsleiste

In der Aktionsleiste- Dass Bar, die über den oberen Teil Ihrer Tätigkeit läuft - ist das Rückgrat Ihrer UI. Hier können Sie bieten Aktionen für den Benutzer auf die aktuelle Tätigkeit auszuüben (zB

"bearbeiten Sie den Kontakt, den Sie sehen") oder auf die Anwendung als Ganzes bezogen (zB:

"Hier ist die Dokumentation"). Manchmal erscheint diese Aktionen als Schaltflächen oder andere Widgets in der Aktionsleiste. Manchmal erscheinen diese Aktionen in der "Überlauf", die zu einem Menü beträgt.

In diesem Kapitel werdendas Konzept der Aktionsleiste und wie Aktionen, um es hinzuzufügen.

Bar Hopping

Android hat viele Muster für verschiedene "Balken" im Rahmen seiner UI hatte. Also, um zu helfen, zu erklären, was eine Aktionsleiste ist, hilft es, wenn wir überprüfendie Geschichte und die Rolle der verschiedenen Bars Android.

Android 1.x / 2.x

ImAm Anfang war es in der Statusleiste und in der Titelleiste.

Die Statusleiste warein dünner Streifen über den oberen Rand des Bildschirms, für Dinge wie die Uhr im Einsatz, Signalstärke, Batterieladung und Benachrichtigungssymbole (für Veranstaltungen wie neue ungelesene E-Mails). Diese Bar ist technisch Teil des OS, nicht der App UI.

DasTitelleiste war eine dünne graue Streifen unterhalb der Statusleiste, die standardmäßig, würde den Namen der Anwendung halten, ähnlich wie in der Titelleiste eines Browsers den Namen einer Website zeigen könnten.

Android 3,0-4,1, Tablets

Wenn offi

Unterstützung fürTabletten mit Android 3.0 im Februar 2011 kam, änderte sich die Geschichte.

Die Statusleiste wurde ersetzt durchdas System Leiste am unteren Rand des Bildschirms erscheint.

Dies hatte den gesamten Inhalt des alten Statusleiste, sondern hatte auch die Softkeys für BACK, HOME, usw. Android 1.x und 2.x erforderlich, dass Geräte Off-Screen-affordances für diese Vorgänge; jetzt, Gerätehersteller könnten diejenigen überspringen und die Systemleiste haben sie bieten.

In der Aktionsleiste, die standardmäßig erscheintIm oberen Teil der Aktivität, die alte Titelleiste ersetzt. Sie können festlegen, was in der Aktionsleiste geht (Symbol, Titel, Schaltflächen, etc.).

Das Symbol aufGanz links von der Aktionsleiste dient auch als Schaltfläche in der Symbolleiste, wenn Sie möchten. zurück in die "main" oder "Heimat" Aktivität Ihrer Anwendung ein gemeinsames Muster dies für die Verwendung ist, den Benutzer nehmen.

Manchmal,die ganz rechts in der Aktionsleiste wird ein "..." affordance enthalten. Dies wird als die

"Aktion Überlauf" oder "Überlaufmenü" bekannt:

Durch Antippen wird die gebender Benutzer Zugriff auf Aktionen, die Schaltflächen der Symbolleiste auf einem größeren Bildschirm gewesen sein könnte, aber es gab nicht genügend Platz. Auch kann mit niedriger Priorität Aktionen in den Überlauf gesteckt werden, anstatt den Bildschirm mit zu vielen Schaltflächen verunstalteten.

Android 4,0-4,4, Handys

Telefon große Geräte warennicht von Android 3.x nicht unterstützt Sie sprangen von Android 2.3
bis 4,0 und entlangdie Art und Weise angenommen einige der Android UI Features 3.x:

• Telefon-Anwendungen könnte eine Aktionsleiste haben, wieihre Tablet-Pendants

• Die Gerätehersteller könnte überspringendie Rückseite, Haus usw. Tasten und lassen Sie eine Teilsystemleiste diejenigen Griff

• Die Statusleiste blieb intakt ausdie Android 2.x Ansatz

Android 4,2-4,4, Tablets

Das Nexus 7, eingeführt inIm Sommer 2012 war ein 7 "Tablette, die die Tablette UI-Struktur, die alle anderen Standard-Android-Tabletten nicht folgte. Stattdessen sah es ein bisschen wie ein wirklich großes Telefon, einen oberen Statusleiste mit zusammen mit einer Bodensystemleiste nur für die Navigationstasten (BACK, HOME, etc.). Apps, wie zuvor, könnte eine Aktionsleiste haben auch.

Anfangs dachte man,dass das Nexus 7 würde in dieser Hinsicht unverwechselbar zu sein.

Stattdessen mit Android 4.2, schaltete Google alle Tabletten zu diesem Modell, die Statusleiste wieder herstellt und verbannen die Systemleiste rein für Navigationstasten.

Android 5.0+
funktionellIn der Aktionsleiste ist viel das gleiche in Android 5.0, wie es in früheren Versionen war. Allerdings ästhetisch, hat es das Symbol und machte andere kleinere stilistische Anpassungen fallen gelassen.

Und noch eine Geschichtsstunde

Back in der Dämmerung der Android Zeit, genannt von einigen als "das Jahr 2007", hatten wir Optionen-Menüs. Diese würden steigen aus dem unteren Rand des Bildschirms auf der Grundlage der Benutzer eine MENU-Taste drücken:

Dies ist, warum Sie Verweise auf "Optionen-Menü" wird verstreutdas Android SDK.

In der Aktionsleiste Muster war fi

O-Konferenz | auf der 2010 Google I von Google eintrat.

Doch zu der Zeit gab es keine tatsächliche Umsetzung dieser, außer in verstreuten Anwendungen, und auf jeden Fall nicht in der Android SDK.

Android 3.0- Aka, API Stufe 11 - hat der Aktionsleiste auf das SDK und Anwendungen, die API-Ebene Targeting wird eine Aktionsleiste erhalten, wenn auf solchen Geräten läuft.

Ihre Aktionsleiste Optionen

Es gibt verschiedene Implementierungen vonIn der Aktionsleiste fl
etwa. Sie werden
wahrscheinlich mit derjenige, der dort 11 sind ein paar updates von der Aktionsleiste jedoch Teil von Android selbst, beginnend mit API-Ebene ist, wenn Sie sie benötigen.

Rein Einheimische

Wie oben erwähnt, läuft Geräte mit Android 3.0 und haben eine höhere Unterstützung fürIn der Aktionsleiste als Teil ihrer fi

Ware unddass die Unterstützung durch das Android SDK
ausgesetzt. Zum Beispiel gibt es eine ActionBar Klasse, und Sie können eine Instanz davon für Ihre Aktivität der Aktionsleiste über getActionBar () erhalten.

Aber,Dies funktioniert nur auf Geräten mit Android 3.0 und höher. Wenn Sie versuchen, getActionBar () auf einem älteren Gerät aufrufen, werden Sie mit einem VerifyError Runtime-Ausnahme abstürzen. VerifyError ist Android Weg, Ihnen zu sagen ", während Sie fi zusammengestellt
etwasg Ihr bezieht sich der kompilierte Code "existiert nicht.

Wenn deinminSdkVersion ist 11 oder höher, Sie in der Lage sein wird, die native Aktionsleiste zu verwenden, und dieser Ansatz wird in den meisten dieses Buches verwendet werden.

updates

Wenn deinminSdkVersionist tieferals 11, haben Sie zwei wichtige Entscheidungen:

1. Benutzendie "Menü" APIs in Android, die Sachen in der Aktionsleiste auf neueren Geräten hinzufügen, sondern wird in der klassischen "Optionen-Menü" auf älteren Geräten führen.

2. Benutzendie appcompat-v7 Rückportierung der Aktionsleiste, veröffentlicht von Google im Android Support-Paket im August 2013.

In diesem Kapitel wird davon ausgegangen,dass Ihr minSdkVersion auf 11 oder höher eingestellt ist, und Sie werden die native Aktionsleiste verwenden. Ein eigenes Kapitel in den Spuren decken die Verwendung vonappcompat-v7.

Hinweisdass ab Oktober 2014 die appcompat-v7-Bibliothek nicht portiert nur die Aktionsleiste, sondern auch versucht, einen Teil der Google-Material Design Styling zurückzuportieren.

Normalerweise werden nur Material Design stammt von Android 5.0 und der Verwendung von Theme.Material. Dasappcompat-v7Kapiteldeckt abdie Bibliothek Auswirkungen sowohl auf die Aktionsleiste und auf andere Aspekte der App-UI.

Ein kurzer Hinweis Über Toasts

Imdie Beispielanwendung, die folgt, verwenden wir einen Toast der Benutzer weiß, einige Arbeiten abgeschlossen sind.

Ein Toast ist eine vorübergehende Nachricht, was bedeutet, dass es anzeigt, und verschwindet auf eigene ohne Benutzereingriff. Außerdem dauert es nicht von der currently- Fokus weg aktivAktivität, so dass, wenn der Benutzer damit beschäftigt ist, die nächste Groß Programming Guide zu schreiben, müssen sie nicht Tastatureingaben durch die Meldung "gefressen" werden.

Schon seitein Toast vergänglich ist, haben Sie keine Möglichkeit, wenn der Anwender selbst merkt es zu wissen. Sie erhalten keine Bestätigung von ihnen, noch die Nachricht für eine lange Zeit bleiben, um den Benutzer zu belästigen. Daher ist der Toast vor allem für Beratungs Nachrichten, wie was auf eine lang andauernde Hintergrund Aufgabe abgeschlossen ist, hat die Batterie fiel auf einen niedrigen-but-not-too-Low-Pegel, usw.

Herstellungein Toast ist ziemlich einfach. Der Toast-Klasse bietet eine statische Maketext () -

Methode, die einen String (oder String-Ressourcen-ID) akzeptiert und gibt einen Toast-Instanz. Die Maketext () -Methode muss auch die Aktivität (oder einem anderen Kontext) sowie eine Dauer. Die Dauer ist in der Form der LENGTH_SHORT oder LENGTH_LONG Konstanten ausgedrückt, um anzuzeigen, auf relativer Basis, wie lange die Meldung sichtbar bleiben. Sobald Ihr Toast konfiguriert ist, rufen seine Show () -Methode, und die Meldung angezeigt wird.

Rahmendas Ziel

Wenn Sie die richtige Aktionsleiste unterstützen wollen, möchten Sie API-Level 14 oder höher zur Laufzeit zum Ziel. Dazu gehört EinstellungdastargetSdkVersionImmobilien in

Ihrembuild.gradlefi

(für Android Studio-Benutzer) oder Einstellung dasandroid:

targetSdkVersionAttributdas<Verwendet-sdk>Element Ihrer Manifest (für Legacy-Pre-Gradle Projekte).

Wir sehendies im Manifest derActionBar / ActionBarDemoNativeBeispielprojekt:

(von

ActionBar / ActionBarDemoNative / app / src /
main / AndroidManifest.xml)

Genauer gesagt, haben wirAndroid: targetSdkVersion auf 19. Während 11 oder höher wird Ihnen eine Aktionsleiste, 14 oder höher wird eine bestimmte UI Marotte zu Menüoptionen im Zusammenhang

lösen. Einige Android-Geräte ab Version 4.0, aber nicht alle zeigen zwei Sichtweisen auf Überlauf Menüpunkte bekommen, wenn Sie IhreAndroid: targetSdkVersion Satz auf einen Wert zwischen 11
und 13 werden Sie haben die "..." in der Aktionsleiste selbst und eine zweite in der Systemleiste, auf Geräten, die eine haben. Einstellen android: targetSdkVersion bis 14 oder höher löst dieses Problem.

Tunnichts anderes, als die vorhergehenden Schritte uns eine Aktionsleiste geben würde, aber man ohne Toolbar-Icons oder Aktion Laufmenü. vielleicht optisch ansprechend Während, dann ist dies nicht besonders nützlich für den Benutzer, also müssen wir etwas mehr Arbeit zu tun, um die Benutzeraktionen zu geben, in der Aktionsleiste auszuführen.

HinweisDies bedeutet, dass das Manifest eine minSdkVersion von 10. hat, dass die App auf Android 2.3.3 Geräten ausgeführt werden können. Auf diesen Geräten, obwohl, wird die App nicht eine Aktionsleiste haben, da die Aktionsleiste nicht, dann gab es, und diese App wird eine Rückeinbindung wie appcompat-v7 nicht verwenden. Stattdessen wird die App einen alten Stil-Optionen-Menü auf API-Ebene 10 Geräte. Es gibt nichts wirklich falsch mit diesem, auch wenn es bedeutet, dass Ihre Anwendung auf API-Ebene 10 Geräte anders aussehen.

definierendie Ressourcen

Daseinfachste Weg, Toolbar-Icons und Aktion Überlauf Gegenstände in der Aktionsleiste zu bekommen, ist über ein Menü XML-Ressource. Dies wird als "Menü" Ressource aus historischen Gründen genannt, da diese Mittel ursprünglich für Dinge wie das Optionsmenü verwendet wurden.

Du kannst hinzufügeneinres / Menü /Verzeichnis zu Ihrem Projekt und in dort Menü XML-Ressourcen, wie zum Beispielres / menu / actions.xmlvonActionBar / ActionBarDemoNative: (von

ActionBar / ActionBarDemoNative / app / src /
main / res / menu / actions.xml)

Es gibt vierDinge, die Sie möchten auf jedem Menüpunkt (<item> Element in der XML) zu konfigurieren:

1. Die IDDer Artikel (über die Android-Version: id-Attribut in XML). Dies wird einen weiteren R.id Wert, im Zusammenhang mit diesem Menüpunkt, ähnlich wie die R.id Werte für unsere Widgets in unseren Layouts erstellen. Wir werden diese ID verwenden, um zu bestimmen, wenn der Benutzer auf einem unserer Symbolleiste Schaltflächen klickt oder die Aktion Überlauf Artikel.

2. DasTitel des Artikels (über den Android: title-Attribut in XML). Ist dieser Punkt im Aktionslaufmenü windet, oder optional im Rahmen der Symbolleiste auf die

Schaltfläche, wird dieser Text angezeigt. Außerdem wird dieser Titel als "Tooltip"

erscheinen auf dem Aktionselement in der Aktionsleiste selbst, wenn der Benutzer lange drückt auf das Icon (etwas wenige Anwender wissen zu tun). Typischerweise werden Sie einen String Ressource-Referenz verwenden (zB @ String / add), um eine bessere

Unterstützung der Internationalisierung.

3. Das Symbol fürDer Artikel (über das Android: Symbol Attribut in XML). Wenn Ihr Artikel als Schaltfläche in der Symbolleiste angezeigt wird, wird dieses Symbol mit dieser Taste verwendet.

4. Flags, die angeben, wieDieser Artikel soll (: showAsAction Attribut in XML über den Android) in der Aktionsleiste dargestellt werden. Sie wählen, um es immer eine

Symbolleiste auf die Schaltfläche sein, nur eine Schaltfläche in der Symbolleiste ifRoom sein, oder haben es nie eine Symbolleiste auf die Schaltfläche sein. Sie können auch anhängen wählen, um | withText entweder immer oder ifRoom, um anzuzeigen, dass Sie die Symbolleiste auf die Schaltfläche wollen beide das Symbol zu sein, und der Titel, nicht nur das Symbol. Beachten Sie, dass immer ist kein Symbolleiste auf die Schaltfläche garantiert sein - wenn Sie für 100 immer Einzelteile fragen, werden Sie nicht haben Platz für alle. Allerdings immer Einzelteile erhalten Priorität für Raum in der Aktionsleiste über ifRoom Gegenstände.

Ein kurzer Hinweis über Android Studio

Android Studio 2.2 eingeführt ein neues Menü-Editor, nach dem grafischen Layout-Editor modelliert. Wenn Sie ein Menü-Ressource öffnen, erhalten Sie zwei Unterregister: ein Text eine mit dem XML, und ein Design man das Menü, um eine Vorschau und in der Theorie, bearbeiten es:

Unglücklicherweise,das Designunterregister leidet andieser Fehlerunddieser Fehler, Ist es schwierig zu bedienen. FürVorerst sind Sie besser dran, direkt mit dem XML arbeiten.

Bewirbt sichdie Ressourcen

Von Ihrer Aktivität, lehren Sie AndroidüberDiese

Aktionsleiste

Elemente
durch
ein
zwingendesonCreateOptionsMenu

()Verfahren,
wiedies
ein
von
derActionBarDemoActivityvondasActionBar / ActionBarDemoNativeBeispielprojekt:

(von

ActionBar / ActionBarDemoNative / app / src / main / java / com / commonsware /
android / Inflation / ActionBarDemoActivity.java)

Hier schaffen wirein MenuInflater und ihm sagen, unser Menü XML-Ressource (R.menu.actions) und gießen Sie sie in das bereitgestellte Menü Objekt aufzublasen. Wir Kette dann zu der übergeordneten Klasse, das Ergebnis zurück.

Reagierenzu Veranstaltungen

Um fi
aus wann der Benutzer tippt auf eines dieser Dinge, müssen Sie außer Kraft
setzenonOptionsItemSelected (), so wie dieActionBarDemoActivityUmsetzung wie folgt dar: (von

ActionBar / ActionBarDemoNative / app / src / main / java / com / commonsware /
android / Inflation / ActionBarDemoActivity.java)

Sie werden übergebenein MenuItem. Sie können GetItemID () auf sie rufen und diesen Wert auf die, die aus dem Menü XML-Ressource (R.id.add und R.id.reset) vergleichen. Wenn Sie das Ereignis zu behandeln, return true; andernfalls geben den Wert auf die Durchführung des Verfahrens

"übergeordnete Klasse von verketten.

Wenn Sie möchten, zu reagierentippt auf Ihrem Anwendungssymbol auf der linken Seite der Aktionsleiste vergleichenGetItemID ()nachandroid.R.id.home, Wie wird dieMenuItembenutzt fürdass bestimmte Schaltfläche in der Symbolleiste. Beachten Sie, dass, wenn Sie Ihreandroid: targetSdkVersioneinstellen14oder höher, werden Sie auchanrufen müssen
setHomeButtonEnabled (true)aufdasAktionsleiste(Erhaltenüberein AufrufgetActionBar ()), Dieses Verhalten zu ermöglichen. Beachten Sie, dass dieses Symbol nicht vorhanden sein können, vor allem, wenn Sie mitTheme.Materialauf Android 5.0 und höher.

Der Rest vondie Probenaktivität

Also, was ist esdass wir wirklich tun, hier inActionBarDemoActivity?

In vieler Hinsicht,Dies erinnert an die ListActivity Demoseine frühere Kapitel. Wir haben eine Reihe von 25Lateinischen Worte, und wir wollen in einer Liste diese anzuzeigen.

Jedoch inIm vorliegenden Fall zeigen wir nur fünf Worte am Anfang. Ein "add" Aktionsleiste Element wird aus dem Haupt Liste von 25 Wörtern zusätzliche Wörter hinzufügen, bis die Listview alle 25 hält einen "Reset" Aktionsleiste Artikel uns auf die ursprünglichen 5 Wörter zurück.

ActionBarDemoActivityisteinListActivity. Anstatt jedoch einrichten unsereArrayAdapterdirekt indasonCreate ()Verfahren wie einigedie anderen Proben getan haben, wir, dass die Arbeit an eine delegiereninitAdapter ()Methode. Außerdem,dassinitAdapter ()Verfahren macht seine Arbeitein bisschen anders als das, was die anderen Proben haben:

(von

ActionBar / ActionBarDemoNative / app / src / main / java / com / commonsware /
android / Inflation / ActionBarDemoActivity.java)

Lieberdie ArrayAdapter gerade aus dem statischen Elemente Array erstellen wir eine frische Arraylist und gießen Sie die 5 Elemente aus Positionen hinein, dann erstellen Sie die ArrayAdapter auf dem Arraylist als erstellen. Dies mag überflüssig, aber wir werden mit unseren Aktionsleiste Artikel Vorteil dieses Ansatzes nehmen.

Wannder Benutzer klickt auf den "Reset" Artikel in der Aktionsleiste, nennen wir initAdapter () wieder, die unsere ListActivity einen frischen Satz von 5 lateinischen Wörtern zu Display gibt: (von

ActionBar / ActionBarDemoNative / app / src / main / java / com / commonsware /
android / Inflation / ActionBarDemoActivity.java)

Wannklickt der Benutzer das Element in der Aktionsleiste "add", wir ein addWord () private Methode aufrufen, die aus dem Element-Array, das nächste Wort fügt hinzu und fügt es in die Listview:

(von

ActionBar / ActionBarDemoNative / app / src / main / java / com / commonsware /
android / Inflation / ActionBarDemoActivity.java)

DasNettoergebnis von all dem ist, dass wir eine Aktivität mit unseren maßgeschneiderten Aktionsleiste haben:

Zu unseren Aktionsleiste Artikel ist ein "über" eindas wird immer im Überlaufmenü sein. Dies wird drei mögliche visuelle Ergebnisse haben.

Zuerst auf Geräten ohne Off-Screen-Taste MENU,der Überlauf-Menü wird durch eine Schaltfläche

"..." dargestellt, die das Überlaufmenü angezeigt wird, wenn geklickt haben:

Auf Android 4.x Geräten mit einem Off-Screen-Menü-Taste drückendie MENU-Taste wird das Überlaufmenü führen vom unteren Rand des Bildschirms zu erheben:

Ab Android 4.4 Geräte immer haben solltedie Schaltfläche "...", wie in dem nächsten Abschnitt beschrieben.

Android 2.3 Gerätedieser Lauf wird diese App keine Aktionsleiste haben:

Allerdings drückendie MENU-Taste wird die im alten Stil Optionen-Menü aufzurufen, in dem unsere Aktionselemente erscheinen:

Taste MENU, wussten wir kaum Ye

Zur Erweiterung aufdie Geschichte Lehren aus früher in diesem Kapitel, die alle Android 1.x und 2.x

Geräte hattenein MENU-Taste verwendet, um das Optionsmenü aufzurufen. Mit Android 3.0
und dem Aufkommen des Systems / Navigationsleiste, Gerätehersteller nicht mehr Tasten für zu Hause, zurück, und MENU benötigt. Und integriert die Aktionsleiste ein "..." affordance für den Überlauf Zugriff für Elemente, die im Optionsmenü gewesen wäre, und waren nicht Symbolleisten-Schaltflächen in der Aktionsleiste selbst gefördert werden.

Verwirrung begann, als wir Geräte begonnen habendas hatte eine Menütaste und Android 3.0+.

Einige Android 2.x-Geräte wurden auf Android 4.0 aktualisiert, und Hunderte von Millionen von Android-Geräten, von Herstellern wie Samsung und HTC, ausgeliefert mit Android 4.x und einer Taste MENU.

Um dies zu ermöglichen,das Gerät würde berichten, ob es eine "ständige Menütaste" hatte, und die Aktionsleiste wählen würde, ob die "..." affordance auf die Existenz dieser Schlüssel basiert zu zeigen. Geräte mit einem MENU-Taste, würde sich nicht die "...", sondern würde die MENU-Taste verwenden, um die Überlauf anzuzeigen.

Das irritiert viele Entwickler, für vielaus dem gleichen Grund wie, warum die MENU-Taste, die Entwickler zurück in Android 1.x / 2.x irritiert: die Existenz eines Menüs war nicht sehr auffindbar.

Viele Anwender würden schließlich erkennen, dass die MENU-Taste tippen könnte nützliche Dinge aufzudecken, aber nicht alle Benutzer würde diese Verbindung herzustellen. Doch jetzt Entwickler
könnte eine offensichtliche Alternative in Form des "..." affordance zu sehen, und so suchten sie Wege, um die Aktionsleiste in zeigt die "..." auch auf Geräten zu betrügen, die eine Taste MENU
hatte.

Unddas war, wie die Welt funktioniert ... bis Android 4.4.

Einunangekündigte Änderung in Android 4.4istdass die Schaltfläche "..." sollte nun immer in der Aktionsleiste angezeigt. Die MENU-Taste, wenn es vorhanden ist, wird immer noch funktionieren, den Überlauf zeigt. Idealerweise zeigt es den Überlauf als ein Herunterfallen von der "...", obwohl das nicht erforderlich ist. Unddie Kompatibilität Defi

Dokument für Android 4.4 mehr

Nachdruck legt nahe,dass die MENU-Taste ist veraltet.

Keiner vonsollte dies direkt Code beeinflussen. Aber:

• Wanndie Aufnahme von Schnappschüssen, denken Sie daran, dass sie zwischen den

Geräten, die die Schaltfläche "..." und diejenigen, die dies nicht tun variieren

• Wenn das Schreiben von Dokumentation oder Blog-Beiträge oder andere Lehrmaterial, versuchen Begriff Verweise aufder Überlauf, der sowohl für Arbeit jene Benutzer mit einer Schaltfläche "..." und diejenigen, die dies nicht tun

Action-Bars, Live in Living Color!

Auf Android 4.0 und höher, wenn Sie mitein Holo Thema als Basis, können Sie möchten die Farben durch die Aktionsleiste verwendet einzustellen.

Auf Android 5.0 und höher, wenn Sie mita Material Thema als Basis, werden Sie die Farben durch die Aktionsleiste verwendet einzustellen. Dies ist die Vision von Google, wie Branding funktionieren sollte, anstelle Ihres Symbol in der Aktionsleiste sein müssen.

In den folgenden Abschnitten einige Möglichkeiten skizzieren zu beeinflussendie Farben der Aktionsleiste.

Material Tint Effekte

Android 5.0 undTheme.Material Aktionsleiste Farben leicht machen einzurichten, als Teil eines Gesamt "Tönung" -Ansatz.

DasActionBar / MaterialColorBeispielprojektein Klon des

ActionBarDemoNativeProbe gezeigt früher inIn diesem Kapitel, aber eine, wo:

• UnserminSdkVersion wird auf 21, so dass die App nur auf Android laufen 5.0+

• Wir richtenein eigenes Thema, mit spezifi Tönungs Regeln, dass unser Aktionsleiste Farben beeinflussen

Farbressourcen

DasThema müssen Farben zu beziehen, und die sauberste Weg, dies zu tun ist, Farbressourcen einzurichten. Wie alle unsere anderen Ressourcen, geben wir Farbressourcen einen Namen und einen Farbwert, in der Regel in #RRGGBB oder #AARRGGBB Format. Farb Ressourcen sind "Wert"

Ressourcen, statt standardmäßig in res / Werte /, mit der Konvention der Verwendung eines Colors.xml fi
für die tatsächlichen Farben.

Zum Beispiel, hier istdasres / Werte / Colors.xmlfi
vondasMaterialColor

Beispielanwendung:

(von

ActionBar / MaterialColor / app / src / main /
res / Werte / Colors.xml)

Es definiert drei Farben,primäre, primary_dark und Akzent, mit verschiedenen Farben für jeden. In Android Studio, die Bearbeitung dieser fi

Shows ein winziger Farbfeld Sie visualisieren die

Farben zu helfen:

Tönungein Thema

Dann gegebendass wir Definitionen unserer Farben haben, können wir diese Farben auf ein eigenes Thema, gefunden in res / Werte / styles.xml gelten:

(von

ActionBar / MaterialColor / app / src / main /
res / Werte / styles.xml)

Hier unsereAppThemeist abgeleitet vonTheme.Materialundüberschreibt
dreiFarbtöne:colorPrimary.colorPrimaryDark, undcolorAccent, Die sich auf unsere drei Farbressourcen in der Reihe.

Hinweisdass wir von haben könnte geerbtTheme.Material.Lighthatten wir wolltenein Licht

"Inhaltsbereich" (wo unsere Widgets gehen) oder sogarTheme.Material.Light.DarkActionBarfürein Licht Inhalt und eine dunkle Aktionsleiste (vor dem Start wir die Aktionsleiste Farben Schneiderei).

Bewirbt sichdas Thema

Die Manifest der Anwendung erklärtdass wir AppTheme als Standarddesign für unsere

<application>, so werden alle Aktivitäten dieses Thema verwenden, es sei denn außer Kraft gesetzt auf das Aktivitätsniveau nutzen:

(von

ActionBar / MaterialColor / app / src / main /

AndroidManifest.xml)

beachten Sie auch,dass hier, wo wir angeben, dassminSdkVersion21 ist.Ein neues Android Studio-Projekt würde das tun inbuild.gradle.

Die Ergebnisse

Allessonstüber die App ist die gleiche wie dieActionBarDemoNativeProbe, einschließlich unserer Tätigkeit unddasListenansichtdass wir bevölkern.

Wenn wir jedoch laufendiese Ausgabe auf einem Android 5.0+ Gerät oder Emulator, unsere Aktionsleiste übernimmt die gewünschten Farben, speziell der colorPrimary Wert für die Hintergrundfarbe der Aktionsleiste:

Der BrauchThema wirkt sich auch auf die Farben bestimmter Widgets, wie gedeckt werdenspäter im Buch.

Wiederherstellendas Icon (Art)

Währenddas Material Design-Philosophie überspringt das Anwendungssymbol, das wir in der Aktionsleiste verwendet haben, gibt es eine Möglichkeit, es für eine Theme.Material Anwendung hinzufügen zurück, obwohl es ein wenig Arbeit erfordert, wie in der
gesehenAktionsleiste/ MaterialLogoBeispielprojekt.

Der Schlüsselwas Sie tun müssen, ist anrufensetDisplayShowHomeEnabled (true)auf

IhremAktionsleisteObjekt, das Sie durch den Aufruf erhaltengetActionBar ()in deinemAktivität:

(von

ActionBar / MaterialLogo / app / src / main / java / com / commonsware / android /
abmatlogo / ActionBarDemoActivity.java)

Dies wird verwenden, was Symbol wird fürdas Android: Symbol Attribut in Ihrem Manifest als

"Home" -Symbol in der Aktionsleiste:

Wenn Sie lieber verwendenein anderes Symbol, wie einer, der die Aktionsleiste ein bisschen besser zu fi skaliert wird, können Sie anrufenSetIcon ()auf IhremAktionsleiste, Die ID einer ziehbaren Ressource liefert (zBR.drawable.action_bar_icon), Der anstelle des drawable spezifi verwendet werden sollte,
im dasandroid: SymbolAttribut Ihrer<Aktivität>oder

<Application>imdas Manifest.

Aktionsleiste Style-Generator

FürTheme.Holo und Verwandten werden die Tönungs Regeln von Theme.Material keine

Anwendung. Stattdessen müssen Sie basteln ein gutes Stück zu tun, um das Farbschema, wie Sie wollen eingerichtet bekommen.

Oder Sie verwendenJeff Gilfelt der Aktionsleiste Style-Generator.

Das isteine Website, die Sie eine Aktionsleiste Farbschema, wo die Website für Sie alles, was wird dann, dass Sie das Farbschema zu implementieren müssen generieren entwerfen können.

Hinweisdass Herr Gilfelt hat diese Seite markiert als veraltet, mit einem Auge in Richtung Menschen Theme.Material oder die appcompat-v7-Ausgabe der Aktionsleiste. Die Seite funktioniert, aber aller Wahrscheinlichkeit nach wird es zu einem späteren Zeitpunkt eingestellt werden.

beachten Sie auch,dass die Website am besten mit Google Chrome oder Chromium-Browser funktioniert, wenn auch in der Prüfung, eine aktuelle Ausgabe von Firefox als gut funktioniert.

Wie die Website zeigt an, "Ihre Laufleistung mit anderen Browsern kann variieren".

Entwerfendas Schema

Die Website wird dominiert vonein Formular für das Farbschema der Gestaltung und einen Vorschaubereich zu zeigen, was das Design aussehen wird:

Imdie "Style Name" fi

Sie können fi im Namen möchten Sie Ihr eigenes Thema zu geben.

Was auch immer Sie in fi nden in Kleinbuchstaben mit einem führenden Großbuchstaben umgewandelt werden, die alle folgenden Themen .. So zum Beispiel fi
im AppTheme wird in
einem Stil Ressource führen namens Theme.Apptheme.

for "Style-Kompatibilität", wählen Sie "Holo". Für "Basis Thema", wählen Sie die Basis-Stil Sie wollen:

• Licht

• Dunkel

• Licht mit dunklen Aktionsleiste

the nächsten vier Optionen ( "Action-Bar-Stil", "Aktionsleiste Textur", "Tab Haarstil", "Neutral gepresstem states") sind für erweiterte Funktionen und die Standardwerte belassen werden können.

Scrollen weiter nach untendie Seite, werden Sie zu sieben Farbauswahl kommen, so dass Sie die Farben anpassen in der Aktionsleiste Implementierung verwendet werden. Jeder Pflücker, wenn es geöffnet ist, können Sie eine Farbe zu wählen, auf einer fi zierten Palette basiert, dann verfeinert einen Gradienten Selektor. Oder, wenn Sie spezifi Farben weiß (zB ein Grafikdesigner gab sie zu Ihnen), können Sie die Farbe in die mitgelieferte fi fi

Wie Sie änderndie Farben, werden Sie sehen, was sie auf den Vorschau auswirken. Am unteren Rand der Seite ist die "Output-Ressourcen" Rahmen:

Hier können Sie durch Klicken aufdie "DOWNLOAD .ZIP", um ein ZIP-Archiv mit Ihrem eigenes Thema und alle damit verbundenen Ressourcen zum Download erforderlich, um es zu implementieren.

Die Umsetzungdas Schema

UnZIPder Inhalt des ZIP-Archiv in Ihr Projekt res / Verzeichnis (zB in einem traditionellen Android Studio-Projekt, UNZIP in src / main / res / in der App-Modul). Es wird eine Reihe von fi

hinzufügen
insbesondere auch, eine fi
imres / Werte / deren Namen auf den Namen,
den Sie fi basiert
indas Web-Formular für den Themennamen (zB styles_apptheme.xml).

Wenn man sichdass fi
du wirst sehendass es definiert ein eigenes Thema für Sie, mit dem

Namen Thema. und was auch immer vorausgesetzt, Sie zu dieser Form (umgerechnet in einer der führenden Großbuchstaben und den Rest in Kleinbuchstaben). Das fi
werden eher langwierig,
da es bestimmte Stile bezeichnet für verschiedene Facetten auf die Verwendung von In der Aktionsleiste (zB Android: actionBarStyle).

Hier istdie primäre ist das Thema <style> Ressourcenelement, definieren das Thema selbst: (from

ActionBar / HoloColor / app / src / main / res /

Werte / styles_apptheme.xml)

BenutzenDieses Thema, fügen Sie einfach eineandroid: ThemaAttribut zu Ihrem<Application>(Oder vielleicht einzelne<Aktivität>Elemente) in Ihrem Manifest:

(von

ActionBar / HoloColor / app / src / main /

AndroidManifest.xml)

Die resultierende App wirdein Farbschema Spiegelung, was Sie auf dem Formular definiert:

Dieser

Screenshot,
unddie

Code-Schnipsel,
von
der
kommtActionBar

/

HoloColorBeispielprojekt, das ist die gleiche wie die Basisaktionsleiste Beispielanwendung aus diesem Kapitel mit dem benutzerdefinierten Design angewendet.

Besuchdie Spuren!

Zusätzlich zuIn diesem Kapitel können Sieerfahren Sie mehr über erweiterte Aktionsleiste Techniken undlernen über Handlungsweisen, Die vorübergehend ersetzenIn der Aktionsleiste mit neuen Produkten für die Verwendung mit kontextuellen Operationen.

Vector Drawables

Android 5.0 hinzugefügt native Unterstützung fürein VectorDrawable, die die SVG-Pfad spezifi verwendet

Vektor-Kunst darzustellen. Allerdings, wenn IhrminSdkVersion war 21 oder
höher, Vektor drawable Ressourcen nicht so nützlich waren, da es keine gute Möglichkeit war, die gleiche Grafik aufälteren Geräten zu unterstützen. Sie könnten irgendwie arrangieren PNGs für das gleiche Kunstwerk zu haben, aber dann, warum mit dem Vektorgrafiken in der fi Ort die Mühe machen?

Heutzutage Vektor drawable Ressourcen sind praktischer. Nicht nur, dass mehr Geräte laufen Android 5.0 und höher, aber wir haben eine bessere Werkzeugunterstützung. Android Studio Angeboteein Vektor-Asset-Assistenten, der Sie Vektor hinzufügen drawable Ressourcen zu Ihrem Projekt, und das Build-System automatisch generieren PNG fi hilft können
bei verschiedenen Dichten
auf älteren Geräten verwendet werden.

Wieein Ergebnis, Vektor Drawables in der Popularität wurden gewinnen, vor allem für die Aktionsleiste Symbole.

Bekommendas Kunstwerk

Sie haben zwei Hauptquellen der Vektor drawable Kunstwerk: XML-fi
bereits im der Vektor
drawable XML-Format, oder SVG fi
dass Sie wünschen drawable XML-Format zu Vektor
konvertieren. Da das Schreiben wird der Vektor drawable XML von Hand schwierig sein, am besten, Vektor drawable XML wird von SVG-fi starten

Ob Sie machen die Umwandlung,
oder ob jemand anderes die Konvertierung für Sie getan haben, ist der große Unterschied.

Für SVGdass Sie drawable XML Vektor, desto einfacher ist die SVG ist, desto wahrscheinlicher ist es, zu konvertieren, zu versuchen wollen, dass Sie Erfolg haben wird. Insbesondere SVG-Features wie Verläufe und Muster werden nicht unterstützt. Die scheinbare Vision ist für Vektor ziehbar Kunstwerke verwendet werden, vor allem fürDinge wie Aktionsleiste Icons, wo Dinge wie Verläufe und Muster nicht notwendig sind.

Android Studio Vector Asset-Assistent

Der primäre Weg, die meisten Entwickler werden Vektor drawable XML erhalten inihre Projekte ist über den Android Studio Vector Asset-Assistenten. Sie können dies mit einem Rechtsklick auf das res / Verzeichnis Ihrer gewünschten sourceSet, und wählen Sie Neu> Vector Inventar aus dem Kontextmenü aufzurufen:

Die "Nutzungsart" Radiogruppe gibt Ihnen zwei Quellen der Bilder:eine Teilmenge der offi

Material Design Symbole oder eigene SVG oder PSD fi

In der Standardeinstellungdas Material-Icon Optionsfeld ausgewählt ist. Sie können das Symbol anzeigen, indem Sie den "Icon" Taste tippen, die standardmäßig eine Interpretation des Android-Maskottchen zeigt. diese Taste tippen, bringt eine schlecht organisierte Raster von Icons für Sie bis zur Auswahl:

Wenn Sie wechselndie "Local fi" Radio-Button, wird die "Icon" Taste durch einen "Pfad" fi ersetzt
wo können Sie wählendie fi
dass Sie verwenden möchten.

In der Standardeinstellungder Vektor-Asset-Assistent versucht, Aktionsleiste Symbol große Bilder, 24dp Platz zu machen. Sie können dies umgehen, indem Sie die "Override" Checkbox und Ihre eigene Größe angeben. Die Undurchsichtigkeitsregler können Sie angeben, ob nicht-transparente Pixel soll (Wert von 0-99) oder fest (100) durchscheinend sein. Wenn das Bild Text enthält oder auf andere Weise muss für RTL Sprachen invertiert werden, gibt es eine Checkbox Auto-Mirroring-Unterstützung für das zu ermöglichen.

beachten Sie auch,dass Sie den Namen der Ressource zu definieren, unter dem Sie auf das Symbol oder SVG / PSD fi gewählt

Wann Importieren einer fi
standardmäßigder

Ressourcenname wird der gleiche wie der Basisname der fi sein

Ein Klickdie Schaltfläche "Weiter" bringt eine Konfi up

Bildschirm, wo Sie auch ändern
könnendas Modul und sourceSet wenn Sie vielleicht den Assistenten an der falschen Stelle gebracht:

Ein Klick auf Fertig stellen wird importierendie Ressource, und fügen Sie res / ziehbar / in Ihrem Projekt. Wenn Sie Ihr Projekt erstellen, wenn Ihr minSdkVersion unter 21 ist, wird das Android-Plugin für Gradle erzeugen PNG fi
nach wird benutzt für diese älteren Geräte. Beachten Sie,
dass diese erzeugte PNG-fi
zeigen sich in IhremBau / Baum, nicht als Teil des Codes

Projektquelle.

Die Vorschau gezeigt inder Assistent sollten Sie einen Hinweis geben, wenn Ihr SVG korrekt importiert werden:

Selbst wenn jedochdie Vorschau stellte sich heraus, OK, sollten Sie Ihre App zu testen, sowohl auf Android 5.0+ und (falls relevant) Android 4.4-and-ältere Geräte, um sicherzustellen, dass Ihr Kunstwerk so aussieht Sie es wollen.

Weitere Werkzeuge

Juraj Novák hälteine separate Android SVG drawable XML-Konverter Vektor alseine Webseite.

Wenn Sie mit Probleme mitDie Vector-Import Unterstützung des Asset-Assistenten, können Sie versuchen, diese Website betrachten. Es kann Ihnen besser Vektor Drawables direkt, und es gibt auf jeden Fall Sie mehr Hinweise darüber, warum Ihr SVG kann nicht richtig konvertieren.

Mitdas Kunstwerk

Sie verwenden Vektor drawable Ressourcendie gleiche Art und Weise, dass Sie jede andere drawable Ressource verwenden. Unter den Abdeckungen, die die Java-Klasse die Grafik Griffe Rendering ist VectorDrawable ... auf Android 5.0 und höher.

Wenn deinminSdkVersionist unter 21, und Sie möchten für generierte PNG fi verwendendie älteren Geräte, müssen Sie eine Linie zum hinzufügendefaultConfigSchließung in IhremandroideSchließung in Ihrem Modulbuild.gradlefi

Genauer gesagt, Siemüssen die generatedDensities Eigenschaft auf dem vectorDrawables Objekt in ein Array von Strings zu setzen, die Identifizierung der Dichten, für die Sie PNGs erzeugt. Wie bei anderen drawable Ressourcen, Betriebsgeräte auf anderen Dichten als diejenigen in der gewählten Liste wird neu Probe Symbole von einem Ihrer bereitgestellt Dichten. Wenn Sie einige Vektor Drawables haben, könnten Sie mehr Dichten auflisten und nicht viel APK Platz verbrauchen. Die Probe oben gezeigt setzt sich für zwei: HDPI für Mid-Range-Geräte und xxhdpi für High-EndGeräte.

Wenn deinminSdkVersion ist 21 oder höher, aber Sie brauchen nicht auf die erzeugte PNG
fi
wie alle Geräte, die Ihre App läuft wird der Verwendung der Vektor Drawables nativ fähig sein.

VectorDrawableCompat

Im Februar 2016 veröffentlichte Googlesupport-Vektor-ziehbar. Diese enthält ein

VectorDrawableCompatKlassedass unterstützt Vektor Drawables geht zurück auf API-Ebene 7. Google auch veröffentlichtanimiert-Vektor-ziehbar, Welche

AngeboteAnimatedVectorDrawableCompat, Auf API-Ebene unterstützt zurück 11. Diese gehen zu bekommen ist schwierig, weil sie weitgehend undokumentiert sind und signifi haben Einschränkungen.

DasDrawable / VectorBeispielprojekt demonstriertdie Verwendung vonVectorDrawableCompat. In seinemres / Drawables-nodpi /Verzeichnis, werden Sie fi
eine Handvoll Vektor drawable

Ressourcen, aus dem Android Open Source Project gekeult. Die Beispielanwendung zeigt die in einem PaarListenansichtWidgets inRegisterkarten:

• Man wird verwendenVectorDrawableCompatund wird für alle API-Ebenen arbeitendass die Projektträger (15 und höher, auf dem Projekt basiertminSdkVersion).

• Man wird verwenden nativen Vektor drawable Unterstützung. Wie Sie gleich sehen werden, gehen wir zu deaktivierendie normale PNG Generation aus den Vektor

Drawables, was bedeutet, dass diese Liste nur die Symbole auf Android 5.0 und höher, nicht ältere Geräte zeigen wird.

Gradle Konfiguration

Um sicherzustellen,VectorDrawableCompatarbeiten Siemüssen einigeÄnderungen an Ihrem Gradle bauen fi machen

• Siesein müssen mindestens die Version 1.5.0 des Android-Plugin für Gradle verwenden, wie in Ihrem Projekt auf oberster Ebene build.gradle fi definiert

• Siebrauchen eine Abhängigkeit zu haben, auf
com.android.support:support-vector-drawablein deinem Modul
build.gradle fi
ähnlich auf Ihre anderen Abhängigkeiten Android-Support

Wenn Sie mit eine 1.5.x-Version des Android-Plugin für Gradle:

• Siekonfigurieren müssen,generatedDensitiesin deinemdefaultConfigVerschluss, in Ihrem androideSchließung in IhremModulbuild.gradlefi

•

SiebrauchenadditionalParameters"--no-Version-Vektoren"in
einem

(naaptOptionsSchließung
in

Ihrem
androideSchließung
in

IhremModulbuild.gradlefi

Während bei Verwendung von 2.0.0 oder höherdas Android-Plugin für Gradle, die Sie benötigenvectorDrawables.useSupportLibrary

=
trueim
dasdefaultConfigSchließung

IhresandroideSchließung in Ihrem Modulbuild.gradlefi

Diese letzteren Schritte deaktivierendie automatische Generierung von PNG-fi
von der

Vektor drawable Ressourcen, die normalerweise standardmäßig geschehen würde.

Das Beispielprojekt verwendet Version 1.5.0 vondas Android-Plugin für Gradle, und deshalb hat es diegeneratedDensitiesunddasadditionalParameters

"--no-Version-Vektoren"Aussagen:

(von Drawable / Vector / app / build.gradle)

Miteine neuere Android Plugin für Gradle - 2.0.0 oder höher - Ihr Android Schließung würde:

Nicht zu erzeugen PNG fi
spart uns einen Speicherplatz. Aufdie andere Hand, jetzt sind wir in
mit dem Vektor drawable Backport für diese Symbole auf älteren Geräten nutzbar sein gesperrt.

Verwenden Sie in Java

Die Beispielanwendung ist aus einem anderen Buch Probe, geklont eindas hatein ViewPagermit Tabs. Die Tätigkeit setzt einfach auf dieViewPagerund Tabs,
miteinSampleAdapterfürdasViewPagerInhalt.SampleAdapter, Die wiederum lädt
einVectorFragmentoderVectorCompatFragmentindiese Registerkarten.

VectorFragmentShowsjedes der Symbole in einer Zeile einerListenansichtZusammen mit dem Ressourcenname:

(von

Drawable / Vector / app / src / main / java / com / commonsware /
android / Vektor / VectorFragment.java)

Speziell:

• Unser Array isteine Liste von den drawable Ressourcen-IDs, mit dem Namen VEKTOREN

• VectorFragmentAnwendungeneinVectorAdapterbevölkerndasListenansicht

• VectorAdapter, imgetView (), VerwendungengetResourceName

()aufeinRessourcenObjekt zu erhaltender Ressourcenname mit einer Ressource-ID
zugeordnet ist, in einem zu zeigen,Textviewimdie Reihe

• VectorAdapterDelegiertenVectorFragmentund seinapplyIcon ()Verfahren zum

AuffüllendasImagegegebeneine drawable Ressource-ID

DasVectorFragment Implementierung von applyIcon () ruft einfach setImageResource () auf dem Imageview, die ziehbar Ressourcen-ID zu liefern. Dies funktioniert fi
auf Android 5.0 und
höher, aber es wird auf älteren Geräten scheitern, weil ältere Android-Geräte tun nicht nativ über Vektor drawable Ressourcen kennen. Daher aktualisieren wir nur das Symbol, wenn wir auf API-Ebene 21 oder höher sind.

Also, auf einem Android6.0 Gerät, erhalten wir:

... Während auf einem Android-4.4-Gerät, erhalten wir:

VectorCompatFragmenterweitertVectorFragmentund einfach außer Kraft gesetztapplyIcon (): (von

Drawable / Vector / app / src / main / java / com / commonsware / android

/ Vektor / VectorCompatFragment.java)

Hier verwenden wirVectorDrawableCompat, und seinstatische create ()Verfahren zum Erstelleneindrawableanzuwenden, umdasImageübersetImageDrawable ().erstellen()nimmt drei Parameter:

• einRessourcenObjekt

• eine Ressourcen-ID eines Vektors ziehbar

• eine optionaleThema, oder null, der App-Standard-Theme zu verwenden

Dieser Ansatz funktioniert auf allen Versionen von Android unterstützt vonVectorDrawableCompat, die API-Ebene 7 und höher ist. Doch auf Android 5.0 und höher Geräte, erstellen () wird

tatsächlich eine native Vektor drawable verwenden; die Rückportierung wird nur aufälteren Geräten verwendet.

Die "Compat"Reiter des Android 6.0-Gerät und Android 4.4 Gerät zeigen sowohl die Symbole: Andere VectorDrawable Backports

Es gibt mindestens drei unabhängigen updates, obwohl,dass Sie versuchen können, wenn Sie die Vektorgrafiken direkt auf den älteren Geräten verwenden möchten, anstatt PNGs von diesem Vektorgrafiken erzeugt verwenden:

• https://github.com/wnafee/vector-compat

• https://github.com/a-student/BetterVectorDrawable

• https://github.com/telly/MrVector

Hinweisdass der letzte wurde als veraltet markiert, und die anderen an einem gewissen Punkt folgen kann, da Google jetzt eine offi hat

Rückportierung.

Tutorial # 7- Einstellung der Aktionsleiste oben

Als nächstes ist zu konfigurierenIn der Aktionsleiste auf unsere EmPubLite

Anwendung. Dies ist eine Fortsetzung der Arbeit, die wir haben indie vorherigen

Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

AbIn diesem Tutorial werden wir beginnen nun Java Quelle fi Bearbeitung

. Einige
nützliche Android Studio Tastenkombinationen sind (Windows / Linux-Syntax dargestellt):

• <Alt> - <Enter> für Schnellkorrekturen für das Problem auf den Code zu bringen, wo der Cursor befindet.

• <Strg> - <Alt> - <O>organisieren Ihre JavaeinführenAussagen, einschließlich nicht verwendeten Importe zu entfernen.

• <Strg> - <Alt> - <L> wird die Java oder XML in der aktuellen Bearbeitungsfenster umformatieren, inÜbereinstimmung steht mit den Standard-Stile in Android Studio
oder was auch immer Sie sie in den Einstellungen geändert haben.

Schritt # 1: Einige Symbole hinzufügen

Wir werdenbrauchen ein paar Icons für unsere Aktionsleiste Elemente. Heutzutage ist dies die bevorzugte Ansatz dafür ist mit Vektor Drawables zu starten.

Rechtsklicken Sie aufdie res / Verzeichnis und Neu> "Vector-Anlagen" aus dem Kontextmenü wählen. Dies bringt die fi

Seite von der Vektor Asset-Assistent:

Click auf die Symbolschaltfläche und sichten durch das Gitter der verfügbaren "Material Icons", sucht das Symbol, das ein "i" in einem Kreis ist:

Click "OK". Dadurch wird der Name des Vermögenswertes zu aktualisieren, umic_info_outline_black_24dp. Klicken Sie auf Weiter, dann auf Fertig stellen, dieses Symbol als XML-fi hinzufügen
im res / ziehbar /.

Leider fehlt Android Studio Vektor-Asset-Assistentein Standard-Hilfe-Symbol. Wir können das richtige Symbol herunterladen, indem Sie einen Besuchdas Material Design Icons Seite, die Wahldie

"Hilfe outline" Symbol und die "SVG" Download-Button klicken, dass fi irgendwo auf Ihrer Entwicklungsmaschine zu speichern.

Dann gehen Sie zurück inder Vektor-Asset-Assistenten. Dieses Mal klicken Sie auf den "Local fi"

Radio-Button und wählen Sie die heruntergeladene SVG fi
durch klicken auf die

Schaltfläche "..." auf der rechten Seite des Weges fi

Klicken Sie auf Weiter,Finish, und dann dieses neue Vektor speichern drawable res / drawable /.

Schritt # 2: Einige Optionen definieren

Als nächstes werden wir hinzufügenein paar mit niedriger Priorität Aktionselemente, für eine Hilfe-Bildschirm und einem "über" Bildschirm.

Rechtsklick aufdie res / Verzeichnis in Ihrem Projekt, und wählen Sie Neu> "Android Ressourcenverzeichnis" aus dem Kontextmenü. Dies wird einen Dialog bringen Sie einen neuen Ressourcenverzeichnis lassen zu erstellen:

Change die "Ressourcentyp" drop-down "Menü" zu sein, dann klicken Sie auf OK um das Verzeichnis zu erstellen.

Dann mit der rechten Maustaste auf Ihreneue res / Menü / Verzeichnis und wählen Sie aus dem Kontextmenü Neu> "Menü Ressource fi". Füllen Sie options.xml im "New Menu Resource File"

Dialog:

Dann klicken Sie auf OK zu erstellendie fi

Es öffnet sich inein Menü-Editor:

Unglücklicherweise,die Drag-and-Drop-Funktionen dieses Editors haben viele Fehler. Es wird einfacher für Sie, an die Text-Unterreiter des Editors zu wechseln, in dem Sie den folgenden Inhalt einfügen können:

(von

EmPubLite-Android Studio / T7-ActionBar / EmPubLite / app /
src / main / res / menu / options.xml)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Außerdem werden Siemüssen String-Ressourcen hinzufügen, fürHilfeundetwa, Durch Zugabe geeigneter<String>Elemente, um Ihre bestehendenres / Werte / strings.xmlfi

(von

EmPubLite-Android Studio / T7-ActionBar / EmPubLite / app /
src / main / res / Werte / strings.xml)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt 3: Laden und ReaktionUnserer Optionen
einfach zu definierenres / menu / options.xml ist unzureichend. Wir müssen eigentlich Android sagen zu verwenden, was wir in dieser fi definiert
und wir müssen Code hinzufügen, wenn
der Benutzer tippt auf unseren Artikeln zu reagieren.

Tundass, müssen Sie eine hinzufügenonCreateOptionsMenu ()Verfahren und eine
onOptionsItemSelected ()MethodeEmPubLiteActivity, wie folgt:

(von

EmPubLite-Android Studio / T7-ActionBar / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

HINWEIS: Kopieren und Einfügen von Java-Code kann odernicht funktionieren, je nachdem, was Sie das Buch zu lesen verwenden. Für die PDF, einige PDF-Viewer (zB Adobe Reader) sollten Sie den Code recht gut kopieren; andere eine viel schlechter Job. Neuformatierung der Code mit <Strg> -

<Alt> - <L>, nachdem es in manchmal hilft einfügen.

ImonCreateOptionsMenu ()Wir Aufblasenres / menu / options.xmlund Gießen seinen Inhalt indie mitgelieferteMenüGegenstand, der verwendet wird,von Android auf unsere Aktionsleiste aufzufüllen.

ImonOptionsItemSelected ()Untersuchen wir die mitgelieferteMenuItemund Route zu
verschiedenen Zweigen dereinSchalterAussage basiert aufdie Artikel-ID.

Bekommendies zu kompilieren, müssen Sie einige Importe als auch hinzufügen:

(von

EmPubLite-Android Studio / T7-ActionBar / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Android Studio User drücken<Alt> - <Enter> mit dem Cursor in einer Klasse Referenz, die ihre Einfuhr fehlt, dass die Einfuhr hinzuzufügen.

Schritt # 4: Unterstützung älterer Geräte

Wie wurde festgestellt, indie vorherigen Kapitel, Für unsere Vektor Drawables richtig auf älteren Geräten zu arbeiten, wirmüssen eine Linie unsere app / build.gradle fi hinzufügen Identifizierung der bestimmten Rasterdichten, für die wir PNG Ausgaben unseres Vektor Drawables wollen.

So fügendasvectorDrawables.generatedDensities= [ 'Hdpi', 'xxhdpi>Linie
dasdefaultConfigVerschluss, was zu einerapp / build.gradlefi
das sieht so etwas wie:

(von

EmPubLite-Android Studio / T7-ActionBar /

EmPubLite / app / build.gradle)

Dieser Willehaben keine unmittelbaren Auswirkungen, wie für Hilfe und über sind wir nicht wirklich die Icons. Diese Elemente werden auf immer in den Überlauf sein. Doch in späteren Tutorials werden wir mehr Action Bar Elemente hinzufügen, und einige von denen werden in der Aktionsleiste richtige und Vektor sein drawable Symbole. Darüber hinaus, wenn Sie mit Vektor Drawables beginnen, ist es am besten, die generatedDensities zu Ihrem build.gradle fi hinzufügen
damit Sie eingestellt sind, wenn Sie wirklich mit starten diese Vektor Drawables.

Schritt # 5: Der Versuch, It Out

Wenn Sie laufendies in einem Android 4.x Gerät oder Emulator, können Sie keinen Anfangs Unterschied sehen. Das wäre für Geräte oder Emulatoren, die eine Taste MENU und sind mit Android 4.3 oder darunter. Um unsere Optionen anzuzeigen, müssten Sie MENU drücken:

Hinweisdass auf einem Emulator wird die MENU-Taste, um die PgUp Taste auf der Tastatur abgebildet.

In anderen Fällen,In der Aktionsleiste wird eine "..." -Symbol in der Aktionsleiste: Durch Drückendas bringt ein Menü unsere Produkte zeigt:

In unserer nächsten Folge ...

… wir werdendefinieren unsere fi
neue Aktivitätaufdas Tutorial-Projekt.

Android-ProzessModell

Bisher haben wir unsere Tätigkeit wurde die Behandlung wie es unsere gesamte Anwendung ist.

Bald werden wir in komplexeren Szenarien zu erhalten beginnen, mehrere Aktivitäten und andere BeteiligungArten von Komponenten, wie Dienste und Content-Provider.

Aber bevor wir ineine Menge, die, ist es hilfreich zu verstehen, wie all dies in den eigentlichen OS
bindet selbst. Android basiert auf Linux und Linux-Anwendungen in OS-Prozesse laufen. ein wenig darüber, wie Android und Linux-Prozesse inter betreffen Das Verständnis zu verstehen, wie unsere Mischbeutel der Komponenten innerhalb dieser Prozesse sinnvoll sein, zu arbeiten.

Wenn Prozesse sind geschaffenes

Ein Benutzer installiert die App, geht auf ihre Home-Bildschirm Launcher, und tippt auf ein Symbol für Ihre Tätigkeit. Ihre Aktivität erscheint pflichtschuldigst auf dem Bildschirm.

Hinterdie Szenen, was passiert ist, dass Android eine Kopie eines Prozesses bekannt als die Zygote gegabelt. Als Ergebnis der Art und Weise Ihr Prozess von der Zygote gegabelt ist, Ihr Prozess enthält:

• Eine Kopie der VM (Dalvik oder ART), über Linux Copy-on-Write-Speicher-Sharing unter allen derartigen Prozessen geteilt

• Eine Kopie der Android Framework-Klassen, wie Aktivität und Button, auch per

Copy-on-Write-Speicher geteilt

• Eine Kopie Ihrer eigenen Klassen, geladen aus Ihrer APK

• Alle Objekte, erstellt von Ihnen oderdie Framework-Klassen, wie die Instanz Ihrer Aktivität Unterklasse

BACK, zu Hause und Ihren Prozess

Annehmendass Sie eine App mit nur einer Aktivität. Von der Trägerrakete Startbildschirm, tippt der Benutzer auf das Symbol mit der App Aktivität. Dann, mit Ihrer Tätigkeit im Vordergrund, drückt der Benutzer BACK.

BeimDieser Punkt, sagt der Benutzer das Betriebssystem, das sie mit Ihrer Tätigkeit durchgeführt wird. Wieder die Steuerung, was auch immer diese Tätigkeit voraus - in diesem Fall die Abschußvorrichtung auf dem Startbildschirm.

Das könnte dirdenken, dass dies Ihr Prozess beendet werden verursachen würde. Schließlich ist das, wie die meisten Desktop-Betriebssystemen arbeiten. Sobald der Benutzer das letzte Fenster der Anwendung geschlossen wird, ist der Prozess, Application Hosting beendet.

Aber,das ist nicht, wie Android funktioniert. Android wird Ihr Prozess um, für eine Weile zumindest halten. Dies ist für die Geschwindigkeit und Leistung gemacht: Wenn der Benutzer Ihre App zurückkehren zu wollen, geschieht eher früher als später, es effizienter ist, eine weitere Kopie Ihrer Tätigkeit wieder in den bestehenden Prozess einfach bringen, als es bis zu gehen setzen ein völlig neue Kopie des Prozesses. Dies bedeutet nicht, dass Ihr Prozess wird ewig leben; Wir werden diskutieren, wenn Ihr Prozess später in diesem Kapitel weggehen wird.

Statt nunder Benutzer BACK drücken, lassen Sie uns sagen, dass der Benutzer stattdessen HOME
gedrückt. Optisch gibt es kaum einen Unterschied: Der Startbildschirm erscheint wieder. Je nach Implementierung Home-Bildschirm kann es einen sichtbaren Unterschied sein, als wieder zu einem Launcher zurückkehren könnte, während HOME, um etwas anderes auf dem Home-Bildschirm zurückkehren könnten. Aber im Allgemeinen, sie fühlen sich wie sehr ähnliche Operationen.

Der Unterschied ist, was zu Ihrer Tätigkeit geschieht.

Wanndrückt der Benutzer BACK, Vordergrundaktivität zerstört wird. Wir werden in mehr von dem, was das bedeutet,imdas nächste Kapitel. Aber,Entscheidend ist dabei, dass die Aktivität selbst - die Instanz der Unterklasse der Aktivität - wird nie wieder verwendet werden, und hoffentlich ist Müll gesammelt.

Wanndrückt der Benutzer HOME, Vordergrundaktivität nicht zerstört wird ... zumindest nicht sofort.

Es bleibt in Erinnerung. Wenn der Benutzer die App startet wieder von der Trägerrakete Startbildschirm, und wenn Ihr Prozess ist immer noch rund, Android wird einfach Ihre bestehende

Aktivitätsinstanz in den Vordergrund bringen, anstatt mit einem brandneuen zu erstellen (wie es der Fall ist, wenn der Benutzer gedrückt BACK und zerstört Ihre Aktivität).

WasHOME wahrsten Sinne des Wortes macht, ist die Home-Bildschirm Aktivität wieder in den Vordergrund bringen, sonst nicht direkt Ihren Prozess zu beeinflussen viel.

Beendigung

Prozesse können nicht ewig leben. Sie nehmenein Stück RAM, für die Klassen und Objekte, und diese mobilen Geräte nur so viel RAM, mit zu arbeiten. Schließlich hat daher Android Ihres Prozesses, um loszuwerden, den Speicher für andere Anwendungen frei.

Wie lange der Prozess wird bleiben, um abhängig voneine Vielzahl von Faktoren, einschließlich:

• Wassonst das Gerät tut, entweder in den Vordergrund (Benutzer-Anwendungen
verwendet wird) oder im Hintergrund (zB automatisierte Kontrollen für neue E-Mail)

• Wie vielder Gerätespeicher hat

• Was läuft noch in Ihrem Prozess

Zurück gehen zudas Szenario von oben, haben wir eine Anwendung mit einer einzigen Aktivität aus dem Home-Bildschirm gestartet, in dem der Benutzer auf dem Home-Bildschirm entweder durch BACK drücken oder durch Drücken HOME zurückkehren können. Man könnte denken, dass dies überhaupt keinen Unterschied macht, wenn der Prozess beendet werden würde, aber das wäre falsch. HOME Drücken würde den Prozess halten um vielleicht ein bisschen länger als würde BACK drücken.

Warum?

Wanndrückt der Benutzer BACK, Ihre erste und einzige Aktivität zerstört wird. Wenn der Benutzer drückt HOME, wird Ihre Aktivität nicht zerstört. Android wird dazu neigen, Prozesse zu halten um länger, wenn sie aktiv haben (dh nicht zerstört) Komponenten in ihnen.

the Schlüsselwort "neigen dazu," da ist. Android-Algorithmen zu bestimmen, wann, um loszuwerden, welche Prozesse gebacken werden in das Betriebssystem und sind allenfalls leicht dokumentiert. Es gibt Hinweise, dass auch andere Kriterien, wie Prozess Alter vorschlagen, werden ebenfalls berücksichtigt, und so kann es vorkommen, dass ein Prozess, der eine Aktivität aufweist, läuft (aber nicht im Vordergrund) beendet sein, wenn ein Prozess ohne Lauf Aktivität möglicherweise nicht.

Aber im Allgemeinen, Prozesse mit aktiven (nicht zerstört) Komponenten wird ein bisschen länger als Prozesse bleiben, um ohne eine solche Komponenten.

VordergrundBedeutet, ich liebe dich"

Nur weil Android Prozesse beendet oben freizugebenSpeicher bedeutet nicht, dass es nur jeder Prozess beenden wird um Speicherplatz freizugeben. Vordergrundprozess - die häufigste davon ist ein Verfahren, das eine Aktivität im Vordergrund hat - ist der am wenigsten wahrscheinlich alle beendet werden. In der Tat kann man so ziemlich davon ausgehen, dass, wenn Android hat den

Vordergrundprozess zu töten, dass das Telefon ist sehr krank und wird in wenigen Augenblicken zum Absturz bringen.

(Und, zum Glück,das nicht sehr oft vorkommen)

Also, wenn Sie sind inim Vordergrund, sind Sie sicher. Es ist nur, wenn Sie nicht im Vordergrund stehen, dass Sie gefährdet sind, der Prozess beendet werden, zu haben.

Sie und Ihre Heap

Prozesse nehmen RAM.Eine signifi

Brocken von dass RAM steht für die Objekte, die Sie

(auch bekannt als "der Halde") erstellen.

Diejenigen von euch, mit signifi

Java Hintergründe kennendass die Java-VM liebt RAM (

"kann nicht genug davon bekommen!"). Java VMs routinemäßig 64 MB oder 128 MB Heap-Speicher greifen den Prozess bei der Erstellung und wachsen so groß, wie Sie sie lassen wollen (zB -Xmx Schalter zum Befehl java).

Android Speichergrößen sindnicht so groß, weil Android entwickelt, um mit beschränkten Mengen an RAM auf mobilen Geräten laufen.

Ihr Haufen Grenze als 16MB so niedrig kann, wenn Werte indie 32-48MB Bereich typischer sind mit aktuellen Generation-Geräten. Wie viel der Heap-Grenze wird, hängt ein wenig ab, welche Version von Android ist auf dem Gerät. Es hängt ziemlich viel, aber auf der Bildschirmgröße, wie größere Bildschirme größer Bitmap-Bilder zu wollen, neigen dazu, anzuzeigen, und Bitmap-Bilder können ziemlich viel RAM verbrauchen.

Der Schlüssel ist,dass der Haufen klein ist, und (im Allgemeinen) Sie es sich nicht einstellen. Es ist was es ist. Kleine Anwendungen werden selten in ein Problem mit Heap-Speicher laufen, aber größere Anwendungen könnte. Wir werden diskutieren, Werkzeuge und Techniken zur Messung und der Umgang mit Gedächtnisproblemen später in diesem Buch.

-Aktivitäten und deren Lifecycles

Eine Android-Anwendung wird mehrere diskrete UI Facetten haben. Beispielsweise,eine Kalenderanwendung muss der Benutzer zu erlauben, den Kalender zu sehen, Details eines einzelnen Ereignisses, ein Ereignis zu bearbeiten (einschließlich einer neuen hinzufügen), und so weiter. Und auf kleineren Bildschirmgeräten, wie die meisten Handys, können Sie nicht Zimmer haben all dies auf dem Bildschirm auf einmal zu drücken.

Um damit umzugehen, können Sie mehrere Aktivitäten haben. Ihre Kalenderanwendung kann eine Aktivität haben, um den Kalender anzuzeigen, ein weiteres hinzuzufügen oder ein Ereignis zu bearbeiten, eine für Einstellungen zur Verfügung zu stellen, wie der Kalender funktionieren sollte, eine andere für Ihre Online-Hilfe, usw. Einige dieser Aktivitäten könnten zu Ihrer App privat sein, während andere der Lage sein, die von dritten ins Leben gerufen werden, wie Ihre "launcher" Aktivität zu Home-Bildschirme zur Verfügung stehen.

Alledies bedeutet, dass eine Ihrer Aktivitäten, um die Mittel eine andere Tätigkeit zu starten hat.

Zum Beispiel, wenn jemand auf ein Ereignis aus dem Aktivitätssicht-Kalender klickt, möchten Sie vielleicht die View-Ereignis Aktivität für dieses Ereignis zu zeigen. Dies bedeutet, dass irgendwie, benötigen Sie den View-Ereignis Aktivität zu verursachen zu können, starten und zeigen eine spezifi Ereignis (die eine der Benutzer geklickt hat auf).

Dies kann weiter in zwei Szenarien unterteilt werden:

• Sie wissen, welche Aktivität Sie starten möchten, wahrscheinlich, weil es eine andere Tätigkeit in Ihrer eigenen Anwendung ist

• Du hastein Verweis auf ... etwas (zB eine Webseite), und Sie möchten, dass Ihre Benutzer mit ihm ... etwas zu tun zu können (zB es sehen können), aber Sie wissen nicht vorne, was die Optionen sind

In diesem Kapitel wird sowohl vondiese Szenarien.

In Ergänzung, häufig wird es wichtig sein, für Sie zu verstehen, wenn die Tätigkeiten kommen und von den Vordergrund gehen, so können Sie automatisch Daten speichern oder zu aktualisieren, etc.

Dies ist der so genannte "Aktivität Lebenszyklus", und wir werden sie im Detail zu untersuchen und in diesem Kapitel.

Erstellen Sie Ihre Second(Und Dritte und ...) Tätigkeit

Leider Aktivitäten tunschaffen sich nicht. Auf der positiven Seite, das Android-Entwickler beschäftigt gewinnbringend halten hilft.

Daher gegebenenein Projekt mit einer Aktivität, wenn Sie eine zweite Aktivität wollen, müssen Sie es selbst hinzufügen. Das gleiche gilt für die dritte Aktivität, die vierte Aktivität, und so weiter.

Die Probe, die wir untersuchen, in wirdDieser Abschnitt istAktivitäten / Explicit. Unsere fi Aktivität,ExplicitIntentsDemoActivityBegann durch die Build-Tools wie nur die Standard-Aktivitätscode erzeugt wird. Nun aber das Layout enthält einTaste:

(von

Aktivitäten / Explicit / app / src / main /
res / Layout / main.xml)

DassTaste wird ein showOther () -Methode in unserer Tätigkeit Umsetzung gebunden, die wir in Kürze untersuchen wird.

definierendie Klasse und Ressourcen

So erstellen Sie Ihre zweite (oder dritte oder was auch immer) Aktivität, Sie fi müssen die Java-Klasse
zu erstellen. Sie benötigen eine neue Java-Quellcode fi erstellen
enthaltendöffentliche Java-

Klasse, die mit Aktivität direkt oder indirekt erstreckt. Sie haben zwei grundlegende Möglichkeiten, dies zu tun:

• erstellen Sie einfachdie Klasse und Ressourcen selbst

• Benutzendas Android-Studio neu-Aktivität Assistent

Benutzendas Android-Studio neu-Aktivität Assistent der rechten Maustaste auf Ihre app / src / main /
sourceSet Verzeichnis im Projekt-Explorer, und gehen Sie in die Neu> Aktivität Teil des Kontextmenüs. Dies wird Ihnen ein Untermenü der verfügbaren Aktivitätsvorlagen - meist die gleiche Liste von Vorlagen, die wir wieder gesehen, als wir das Projekt in der fi erstellt Ort.

Wenn Sie eine derdiese Vorlagen, werden Sie mit einem Ein-Seiten-Assistent angezeigt werden, in dem die Details für diese Tätigkeit zur Verfügung zu stellen:

Was Sie hier sehen, wird auf der Grundlagedie Vorlage, die Sie gewählt haben (zB Aktivitätsnamen, Layout XML-Ressourcenname) und diejenigen ähneln sahen wir in der neuen Projekt-Assistenten zurück.

Durch Klicken auf "Fertig stellen" wird(Falls vorhanden), und manifestieren Eintrag dann die Java-Klasse, im Zusammenhang mit Ressourcen der Aktivität erstellen.

Bestückendie Klasse und Ressourcen

Sobald Sie Ihre Stub Tätigkeit eingestellt haben, können Siefügen Sie dann, fi eine onCreate () -

Methode, um es (ein vorhandenes vom Assistenten erstellt oder bearbeitet werden) im alle die Details (zB setContentView ()), genau wie Sie mit Ihrem fi tat

Aktivität. Ihreneue

Aktivität können eine neue Layout-XML-Ressource oder andere Ressourcen benötigen, die Sie auch zu schaffen würden (oder die für Sie vom Assistenten erstellt bearbeiten).

ImAktivitäten / ExplicitUnsere zweite Aktivität istOTHERACTIVITY, Mit so ziemlich der Standard-Barebone-Umsetzung:

(von

Aktivitäten / Explicit / app / src / main / java / com /
commonsware / android / exint / OtherActivity.java)

undeinähnlich einfaches Layout,res / Layout / other.xml:

(von

Aktivitäten / Explicit / app / src / main /
res / Layout / other.xml)

Als Erweiterungdas Manifest

Einfach mit einer Aktivität Implementierungnicht genug. Wir müssen auch an unsere AndroidManifest.xml fi hinzufügen

Dies wird automatisch für Sie behandelt durch Die Iden

'jeweils neuen Aktivitäts Assistenten. Wenn Sie jedoch die Aktivität "von Hand" erstellt hat, werdenmüssen seine manifeste Element hinzuzufügen, und im Laufe der Zeit müssen Sie dieses Element in vielen Fällen zu bearbeiten.

Hinzufügen einer Aktivität zuDas Manifest ist eine Sache eine andere der Zugabe<Aktivität>Element der<Application>Element:

(von

Aktivitäten / Explicit / app / src / main /

AndroidManifest.xml)

Siemüssen die android: name-Attribut auf Minimum. Beachten Sie, dass wir eine nicht enthalten

<Intent-Filter> Kind-Element, wie wir mit der ursprünglichen Aktivität tat hat. Denn jetzt, nehmen Sie es auf den Glauben, dass die ursprüngliche Aktivität des <Intent-Filter> ist, was es als startbar Aktivität in dem Startbildschirm des Launcher erscheinen lässt. Wir werden in mehr Einzelheiten zu erhalten, wie das <Intent-Filter> funktioniert und wann Sie Ihre eigenen möchtenimein späteren Kapitel.

Warnung! Enthält Explicit Intents!

EinIntent kapselt eine Anfrage gemacht, um Android, für einige Aktivitäten oder andere Empfänger etwas zu tun.

Obdie Aktivität, die Sie starten wollen ist eines Ihrer eigenen, können Sie fi
es am
einfachsten eine explizite erstellenAbsicht, die Benennung der Komponente, die Sie starten möchten.

Zum Beispiel aus Ihrer Tätigkeit, könnten Sie eine Absicht wie folgt zu erstellen: Dies würde vor,dass Sie wollten die startenHelpActivity.HelpActivitywürde haben müssen, eine entsprechende<Aktivität>Element in IhremAndroidManifest.xmlfi

ImAktivitäten / Explicit.ExplicitIntentsDemoActivityhateinshowOther ()Methodegebunden an seinenTastewidgetonClickAttribut.

Diese

Methode
verwendenstartActivity

()mit
einer
explizitenAbsicht, IdentifizierungOTHERACTIVITY:

(von

Aktivitäten / Explicit / app / src / main / java / com / commonsware / android

/ exint / ExplicitIntentsDemoActivity.java)

Unsere gestartet Aktivität zeigtdie Taste:

Ein Klickdie Taste bringt die andere Aktivität auf:

Durch Klicken auf BACK würde uns zurück zudie fi

Aktivität. ImInsofern arbeitet die

BACK-Taste in Android ähnlich wie die BACK-Taste in Ihrem Web-Browser.

Mit Implizite Intents

Die expliziteIntent Ansatz funktioniert fi
wann die Aktivität gestartet werden soll, eine
von Ihnen.

Sie können aber auch Aktivitäten starten ausdas Betriebssystem oder Anwendungen von Drittanbietern.

In diesen Fällen allerdings werden Sie nicht ein Java-Class-Objekt haben die anderen Aktivitäten in Ihrem Projekt darstellt, so dass Sie nicht die Absicht Konstruktor verwenden, die eine Klasse nimmt.

Stattdessen werden Sie verwenden, was als Bezug genommen werdendie "implizite" Intent-Struktur, die sehr viel aussieht, wie das Web funktioniert.

Wenn Sie Arbeiten an Web-Anwendungen getan haben, sind Sie sich bewusstdass HTTP basiert auf Verben auf URIs angewendet:

• Wir wollenHolen Sie sich dieses Bild

• Wir wollenPOST zu diesem Skript oder Controller

• Wir wollenPUT dieser REST-Ressource

• Etc.

Android impliziteIntent Modell funktioniert auf die gleiche Art und Weise, nur mit einem Los mehr Verben.

Zum Beispiel: Angenommen, Sie bekommeneine geografische Breite und Länge von irgendwo (zB

Körper eines tweet, Körper einer Textnachricht). Sie entscheiden, dass Sie eine Karte auf diesen Koordinaten angezeigt werden sollen. Es gibt Möglichkeiten, wie Sie eine Google Map direkt in Ihre Anwendung einbetten können - und wir werden sehen, wieimein späteres Kapitel- Aber das ist kompliziert und nimmt der Nutzer will Google Maps. Es wäre besser, wenn wir irgendeine Art von Generika schaffen könnte: "Hey, Android, eine Aktivität zeigen, die eine Karte für diesen Ort zeigt"

Anfrage.

Oder,eine einfachere Szenario: wir bekommen eine URL auf eine Webseite von einer Quelle (zB

Web-Service-Aufruf), und wir wollen auf dieser Seite einen Web-Browser zu öffnen. Dies ist in der veranschaulichtAktivitäten / LaunchWebBeispielprojekt.

Wir habeneinLaunchDemoAktivitätdass verwendet ein Layout ein, enthaltendText bearbeitenWidget undein

Taste, unter anderem:

(from

Aktivitäten / LaunchWeb / app / src /
main / res / Layout / main.xml)

DasTaste wird auf die Aktivität zu einem showme () -Methode gebunden selbst, wo wir einen Web-Browser auf die URL zu bringen möchten in das Widget EditText eingegeben:

(von

Aktivitäten / LaunchWeb / app / src / main / java / com / commonsware /
android / activities / LaunchDemo.java)

Hier nehmen wirdie URL und wandelt es in ein Uri Uri.parse über () aufrufen. Dann können wir eine Aktion namens ACTION_VIEW zu versuchen, verwenden Sie die gewünschte Web-Seite
anzuzeigen.

Beim Startder Benutzer mit unserer Dateneingabeformular vorgelegt:

Wir können fi in einer URL:

Obdas Gerät verfügt über eine Anwendung, die auf einem HTTPS zu einem ACTION_VIEW

Intent antwortet: Schema, das "Show Me!" Button wird diese App bringen, wahrscheinlich einen Web-Browser:

Wir werden diskutieren, was passiert, wenn eskeine Anwendungen einrichten, dies zu umgehen Vorsatzes, oder, wenn es mehr als eins ist,imein späteres Kapitel.

Extra! Extra!

Manchmal wünschen wir einige Daten von einer Aktivität zu übergebender nächste. Zum Beispiel könnten wir haben eine ListActivity eine Sammlung unserer Modellobjekten zeigt (zB Bücher), und wir haben einen separaten DetailActivity Informationen über ein spezifi Modellobjekt zu zeigen.

Irgendwie muss DetailActivity zu wissen, welches Modell Objekt zu zeigen.

Ein Weg, um zu erreichenDies geschieht über Intent Extras.

Es gibteine Reihe von putExtra () Methoden auf Intent, damit Sie Schlüssel / Wert-Paare von Daten zu liefern, in der Absicht gebündelt werden. Während Sie nicht beliebige Objekte, die meisten primitiven Datentypen werden unterstützt passieren können, als Strings und einige Arten von Listen.

Dasnächsten Abschnittwerde erklärenein bisschen mehr über das, was in einem Intent Extra gehen kann.

Jede Tätigkeit kann anrufen getIntent (), um die Absicht zum Abrufen verwendet, es zu starten, und dann verschiedene Formen erhalten nennen kann ... Extra () (mit der ... anzeigt, einen Datentyp), um alle gebündelt Extras abgerufen werden.

Zum Beispiel, nehmen wirein Blick auf dieAktivitäten / ExtrasBeispielprojekt.

Dies ist vor allemein Klon der Aktivitäten / Explicit Probe von oben in diesem Kapitel.

Jedoch diesmal unsere fi

Aktivität wird eine zusätzliche passieren zu der Zweite:

(von

Aktivitäten / Extras / app / src / main / java / com / commonsware /
android / extra / ExtrasDemoActivity.java)

Wir kreierendasAbsichtwie zuvor, aberdann rufenputExtra (), Einen Schlüssel (eine statische Zeichenfolge mit dem Namen VersorgungOtherActivity.EXTRA_MESSAGE) Und einem Wert (derR.string.otherString-Ressource). Dann, und nurdann tun wir nennenstartActivity ().

Unsere überarbeitetOTHERACTIVITY ruft dann, dass zusätzliche, zusammen mit dem aufgeblasenen Textview(überfindViewById ()) Und gießt diesen Text in:

(von

Aktivitäten / Extras / app / src / main / java / com / commonsware

/ android / extra / OtherActivity.java)

Visuell,das Ergebnis ist das gleiche. Funktionell ist der Text angezeigt wird von einer Aktivität zur nächsten weitergegeben.

Erwägen Parcel

Wie oben beschrieben,Intent Extras können nicht beliebige Objekte behandeln. Das liegt daran, dass die meisten der Zeit, Intent Extrasüber Prozessgrenzen hinwegübergeben bekommen. Auch wenn Sie startActivity anrufen () eine Ihrer eigenen Aktivitäten zu starten, geht die Anforderung von Ihrem Prozess zu einem Kern OS Prozess und zurück zu Ihrem Prozess. Die Absicht Extras kommen für die Fahrt entlang.

Daher,Intent Extras müssen etwas sein, das in ein Byte-Array umgewandelt werden können, als Teil der Interprozesskommunikation (IPC), die die Weitergabe um Absichtsobjekte verarbeitet. Sie werden sehen, diese auch in anderen Varianten von Android IPC kommen, wie zum BeispielRemote Services.

Allerdings gibt es zwei Möglichkeiten, in denen Sie versuchen können, Ihre eigenen Objekte zu machen arbeiten als

AbsichtExtras.

Ein Ansatz ist die UmsetzungSerializable auf Ihrer Klasse. Dies ist ein klassisches Java Konstrukt entworfen Instanzen Ihrer Klasse zu ermöglichen, und andere serialisierbare Objekte Instanzen festhalten, in fi serialisiert werden
und später Lesen Sie zurück in.

Ein weiterer Ansatz ist die UmsetzungParcel auf Ihrer Klasse. Dies ist ein Android-Konstrukt, eine, die sehr ähnlich wie Serializable ist. Allerdings ist Serializable ausgelegt für dauerhaft Speicherung von Objekten, wobeidie fi

Machtgelesen werden später in Monaten oder Jahren. So
wie,Serializable hat mit möglichen Änderungen an der Java-Code zu tun, diese Klassen die Implementierung und als solche Bedürfnisse Haken zu haben, mit der Umwandlung von alten, gespeicherten Objekte in neue Objekte zu helfen. Dies fügt Overhead. Parcel beschäftigt sich nur mit Objekten in Byte-Arrays Umwandlung über Prozessgrenzen passieren. Es kann die vereinfachenden Annahme, dass die Klassendefinition nicht verändert, wenn das Objekt in Bytes gedreht wird und wenn die Bytes wieder in ein Objekt verwandelt. Als Ergebnis ist Parcel schneller als Serializable für IPC Nutzung des Android.

Sie sind herzlich eingeladen zu implementierenParcel auf Ihre eigenen Klassen, wenn Sie möchten, an welcher Stelle sie umüber Intent Extras weitergegeben werden können. Darüber hinaus, obwohl Sie alle Java-Klassen in den Android JavaDocs sehen, die Parcel umsetzen können in Intent Extras gestellt werden. So zum Beispiel implementiert Uri Parcel, und so können Sie einen Uri in eine Intent Extra setzen. Nicht alles, was im Android SDK ist Parcel, aber einige der wichtigsten Klassen wie Uri sind Parcel.

Viel mehr Detail auf Parcel, einschließlich, wie Sie es auf Ihrem eigenen Klassen implementieren können, erscheintspäter imdieses Buch.

Asynchronität und Ergebnisse

Hinweisdass startActivity () ist asynchron. Die andere Aktivität wird nicht angezeigt, bis irgendwann nach der Steuerung des Hauptanwendungsthread auf Android zurück.

Normalerweise,dies ist nicht wirklich ein Problem. Aber manchmal eine Aktivität könnte eine andere beginnen, wo die fi

Aktivität möchte einige "Ergebnisse" zu wissen, von der Zweite. Zum

Beispiel könnte die zweite Aktivität eine Art von "Chooser", kann der Benutzer zu ermöglichen, einen fi zu holen
oder Kontakt oder ein Lied oder so etwas, und die fi

Aktivität muss
wissen, was der Benutzer wählen. Mit startActivity () asynchron, ist es klar, dass wir () selbst werden nicht diese Art von Ergebnis als Rückgabewert von startActivity bekommen.

So behandelnDieses Szenario gibt es eine separatestartActivityForResult ()Methode. Während es auch asynchron ist, ermöglicht esdie neu gestartete Aktivität ein Ergebnis (über eine zu liefernsetResult ()Methode)dassüber eine zu der ursprünglichen Aktivität zugeonActivityResult ()Methode. Wir werden prüfen,startActivityForResult ()näherimein späteres Kapitel.

Schroedingers Aktivität

Eine Aktivität, allgemein gesprochen, ist in einem von vier Zuständen an einem beliebigen Punkt inZeit: 1. Aktiv:vom Benutzer wurde die Aktivität gestartet wird, ausgeführt wird, und ist in den Vordergrund. Dies ist, was Sie denken in Bezug auf Ihre Tätigkeit des

Betriebs verwendet werden.

2. Pausiert:durch den Anwender wurde die Aktivität gestartet wird, ausgeführt wird, und ist sichtbar, aber eine andere Aktivität ist Teil des Bildschirms überlagert. Während dieser Zeit kann der Benutzer Ihre Aktivität sehen, aber nicht in der Lage sein, mit ihr zu interagieren. Das ist ein
relativ selten Zustand, da die meisten Aktivitäten zu fi eingestellt der Bildschirm, haben nicht ein Thema, das sie aussehen wie eine Art Dialogfeld macht.

3. Gestoppt:die Aktivität wurde von dem Benutzer ausgeführt wird, aber es wird von anderen Aktivitäten, die versteckt gestartet bzw. eingeschaltet worden sind.

4. Tot:wurde die Aktivität, vielleicht aufgrund der Benutzer drücken Sie die Taste BACK
zerstört.

Leben, Tod und Ihre Aktivität

Android wird in Ihre Aktivität nennen alsdie Aktivitätsübergänge zwischen den vier Staaten oben aufgeführt sind.

Hinweisdass für diese alle, sollten Sie Kette nach oben und die übergeordnete Klasse 'Ausgabe der Methode aufrufen oder Android kann eine Ausnahme ausgelöst.

onCreate ()undonDestroy ()

Wir haben die UmsetzungonCreate () in allen unseren Aktivitäts Subklassen in allen Beispielen. Diese erhalten in zwei primären Situationen genannt:

• Wanndie Aktivität fi
gestartet (Beispielsweise seit ein Neustart des Systems),
onCreate ()

wird aufgerufen mitein Null-Parameter.

• Obdie Aktivität hatte laufen und Sie haben Ihre Aktivität einrichten verschiedene Ressourcen genannt basierend auf unterschiedlichen Gerätezustände (zB Landschaft im Vergleich zu Hochformat), wird Ihre Aktivität neu erstellt und onCreate () werden zu lassen. Wir werden dieses Szenario näher besprechenspäter imdieses Buch.

Hier ist, wo Sie Ihre Benutzeroberfläche zu initialisieren und einrichten alles dass muss einmal durchgeführt werden, unabhängig davon, wie die Aktivität verwendet wird.

Aufdas andere Ende des Lebenszyklus, onDestroy () aufgerufen werden kann, wenn die Aktivität heruntergefahren wird, wie zum Beispiel, weil die Aktivität genannt finish () (die "fi die

Aktivität) oder der Benutzer drückt die Taste BACK. Daher onDestroy () ist vor allem für sauber Ressourcen freigegeben werden Sie in onCreate erhalten () (falls vorhanden), und darauf achten, dass alles, was Sie außerhalb der Lifecycle-Methoden in Betrieb genommen wird gestoppt, wie Hintergrund-Threads.

Denken Sie aber daran,dass onDestroy () nicht aufgerufen werden. Dies würde in einigen Umständen auftreten:

• Sie stürzt mit einer nicht behandelten Ausnahme

• Der Benutzer Kraft hält Ihre Anwendung, wie zum Beispiel durchdie App Einstellungen

• Android hat eine dringendemüssen frei RAM (zB Handhabung eines eingehenden

Telefonanruf), will Ihr Prozess zu beenden, und nicht die Zeit nehmen können, um rufen alle Lifecycle-Methoden

Daher,onDestroy () ist sehr wahrscheinlich, genannt werden, aber es ist nicht garantiert.

Auch beachtendass es eine lange Zeit für onDestroy () dauern kann aufgerufen werden. Es heißt schnell, wenn der Benutzer BACK drückt zu fi
die Vordergrundaktivität. Wenn jedoch

HOME drückt der Benutzer den Startbildschirm zu bringen, wird Ihre Tätigkeit nicht sofort zerstört.

onDestroy () wird erst Android aufgerufen werden entscheidet Ihren Prozess ordnungsgemäß zu beenden, und das könnte später Sekunden, Minuten oder Stunden.

onStart (). onRestart (), undOnStop ()

Eine Aktivität kann kommender Vordergrund entweder weil es fi

Sein ins Leben gerufen,
oder weil sie wieder in den Vordergrund gebracht wird nach (zB durch eine andere Tätigkeit, durch einen eingehenden Anruf) versteckt wurde.

DasonStart () Methode wird in jedem dieser Fälle genannt. Die onRestart () -Methode wird in dem Fall genannt, wo die Aktivität abgebrochen wurde und neu gestartet wird jetzt.

Umgekehrt,OnStop () wird aufgerufen, wenn die Aktivität um gestoppt zu werden. Es kann auch nicht genannt werden, aus den gleichen Gründen, dass onDestroy () nicht aufgerufen werden.

Allerdings ist OnStop () in der Regel ziemlich schnell, nachdem die Aktivität nicht mehr sichtbar ist, so genannt, die Chancen, dass OnStop () aufgerufen werden, sind sogar noch höher als die von onDestroy ().

onPause ()undauf Wiederaufnahme()

DasonResume () -Methode aufgerufen wird kurz vor Ihrer Tätigkeit kommt in den Vordergrund, entweder nachdem sie ursprünglich ins Leben gerufen, aus einem gestoppten Zustand neu gestartet wird, oder nach einem Pop-up-Dialog (zB eingehender Anruf) gelöscht wird. Dies ist ein großartiger Ort, die Benutzeroberfläche zu aktualisieren, basierend auf Dinge, die seit dem Benutzer aufgetreten sein können, zuletzt bei Ihrer Tätigkeit war auf der Suche. Zum Beispiel, wenn Sie Abfrage ein Service fürÄnderungen an einigen Informationen (zB neue Einträge für einen Feed) sind, onResume () ist eine fi

Zeit sowohl aktualisieren Sie die aktuelle Ansicht und ggf.

einen Hintergrund-Thread kick off die Ansicht zu aktualisieren (zB über einen Handler).

Im Gegensatz dazu etwasdass übernimmt Benutzereingabe - meist, die Aktivierung einer anderen Aktivität - wird in Ihrem onPause führen () aufgerufen wird. Hier sollten Sie etwas rückgängig machen Sie in onResume tat (), wie Hintergrund-Threads zu stoppen, die Freigabe keine exklusiven Zugriff auf Ressourcen Sie erworben haben (zB Kamera), und dergleichen.

EinmalonPause () aufgerufen wird, Android behält sich das Recht vor, Ihre Aktivität des Prozesses an jedem beliebigen Punkt zu töten. Daher sollten Sie nicht auf den Empfang keine weiteren Ereignisse angewiesen sein.

Also was ist die Differenz zwischen onPause () und OnStop ()? Wenn eine Aktivität kommt in den Vordergrund, die fi
der Bildschirm, wird Ihre aktuellen Vordergrundaktivität mit onPause ()

und OnStop () aufgerufen werden. Wenn jedoch in den Vordergrund eine Tätigkeit kommt, die nicht auf den Bildschirm nicht fi nden, Ihre aktuellen Vordergrund Aktivität nur mit onPause () aufgerufen werden, da es noch sichtbar ist.

Stock an die Paare

Wenn Sie etwas zu initialisierenimonCreate ()Reinigen Sie es inonDestroy (). Wenn Sie initialisieren etwas inonStart ()Reinigen Sie es inOnStop ().

Wenn Sie etwas zu initialisierenimauf Wiederaufnahme()Reinigen Sie es inonPause ().

Mit anderen Worten, halten Sie sich andie Paare. Zum Beispiel, nicht initialisieren etwas in onStart () und versuchen Sie es in onPause () zu reinigen, da es Szenarien, wo onPause () kann mehrfach hintereinander aufgerufen werden (dh bringt Nutzer ein nicht Vollbild-Aktivität nach oben , welche auslöst onPause (), aber nicht OnStop () und daher nicht onStart ()).

Welche Paare von Lifecycle-Methoden, die Sie wählen, ist bis zu Ihnen, je nach Ihren Bedürfnissen.

Sie können entscheiden,dass Sie benötigen zwei Paare (zB onCreate () / onDestroy () und onResume () / onPause ()). Nur nicht zwischen ihnen mischen.

Wenn Aktivitäten Die

Also, was wird von einer Aktivität zu befreien? Was kann auslösendie Kette von Ereignissen, die Ergebnisse in
onDestroy ()gerufen werden?

In erster Linie, wenndrückt der Benutzer die BACK-Taste, wird die Vordergrundaktivität zerstört werden, und die Steuerung wird in der Benutzer zum vorherigen Tätigkeit zurückzukehren Navigationsfluss (dh unabhängig von Aktivitätsie waren, bevor die nun zerstört Aktivität in den Vordergrund trat) wider.

Sie können erreichendie gleiche Sache durch finish () von Ihrer Aktivität aufruft. Dies ist vor allem für Fälle, in denen eine andere UI-Aktion hinweisen würde, dass der Benutzer mit der Aktivität durchgeführt wird (zum Beispiel stellt die Aktivität eine Liste für den Benutzer zur Auswahl -

Klick auf einen Listeneintrag könnte die Aktivität schließen). Aber bitte nicht künst und

Ihre eigene "exit" hinzufügen, "quit" oder andere Menüpunkte oder Schaltflächen auf Ihre Aktivität

- nur ermöglichen es dem Benutzer normale Android Navigationsoptionen zu verwenden, wie zum Beispiel die BACK-Taste.

Obkeine Ihrer Aktivitäten stehen im Vordergrund mehr, Prozess Ihrer Anwendung ein Kandidat beendet werden soll RAM freizugeben. Wie bereits erwähnt, je nach Umständen kann Android oder rufen Sie möglicherweise nicht onDestroy () in diesen Fällen (onPause () und OnStop () aufgerufen worden wäre, wenn Sie Ihre Aktivitäten im Vordergrund links).

ichf der Benutzer das Gerät verursacht durch eine "Konfigurationsänderung", wie das Umschalten zwischen Hoch- und Querformat, Androids Standardverhalten zu gehen, ist Ihre aktuelle Vordergrund Aktivität zu zerstören und eine völlig neue an seiner Stelle erstellen. Wir decken diese mehr inein späteres Kapitel.

Und wenn Sie Ihre Aktivität eine nicht behandelte Ausnahme hat, wird Ihre Aktivität zerstört werden, obwohl Android wirdnicht fordern sie auf, keine weiteren Lebenszyklus Methoden, wie es Ihre Tätigkeit annimmt in einem instabilen Zustand befindet.

Durch Laufendas Lifecycle

Um zu sehen, wenndiese verschiedenen Lebenszyklus Methoden erhalten genannt, lassen Sie uns die untersuchen

Aktivitäten / LifecycleBeispielprojekt.

Dieses Projekt istdie gleiche wie dieAktivitäten / ExtrasProjekt, mit Ausnahmedass unsere beiden Aktivitäten erben nicht mehr ausAktivitätdirekt. Stattdessen stellen
wireinLifecycleLoggingActivitywieeine Basisklasse und haben unsere Aktivitäten von ihm erben:

(von

Aktivitäten / Lifecycle / app / src / main / java / com / commonsware /
android / Lebenszyklus / LifecycleLoggingActivity.java)

AlleLifecycleLoggingActivity tut, ist jeder der Lifecycle oben genannten Methoden außer Kraft setzen und eine Debug-Zeile zu LogCat emittieren anzeigt, wer was genannt.

Wenn wir fi nden
starten die Anwendung, unsere fi

Stapel Lifecycle-Methoden
aufgerufen wird, in die erwartete Reihenfolge:

04-01 11: 47: 21,437: D / ExplicitIntentsDemoActivity (1473): onCreate ()

04-01 11: 47: 21,827: D / ExplicitIntentsDemoActivity (1473): onStart ()

04-01 11: 47: 21,827: D / ExplicitIntentsDemoActivity (1473): onResume ()

Wenn wir klickendie Taste auf der fi

Aktivität zu starten die zweite, erhalten wir:

04-01 11: 47: 54,776: D / ExplicitIntentsDemoActivity (1473): onPause ()

04-01 11: 47: 54,877: D / OTHERACTIVITY (1473): onCreate ()

04-01 11: 47: 54,947: D / OTHERACTIVITY (1473): onStart ()

04-01 11: 47: 54,974: D / OTHERACTIVITY (1473): onResume ()

04-01 11: 47: 55,347: D / ExplicitIntentsDemoActivity (1473): OnStop ()

Beachtendass unsere fi

Aktivität wird angehalten, bevor die zweite Aktivität startet, und dass

OnStop () auf dem fi verzögert

Aktivität bis nach die zweite Aktivität ist erschienen.

Wenn wir drückendie BACK-Taste auf der zweiten Aktivität, auf die fi Rückkehr

Aktivität,
sehen wir:

04-01 11: 48: 54,807: D / OTHERACTIVITY (1473): onPause ()

04-01 11: 48: 54,857: D / ExplicitIntentsDemoActivity (1473): onRestart ()

04-01 11: 48: 54,857: D / ExplicitIntentsDemoActivity (1473): onStart ()

04-01 11: 48: 54,857: D / ExplicitIntentsDemoActivity (1473): onResume ()

04-01 11: 48: 55,257: D / OTHERACTIVITY (1473): OnStop ()

04-01 11: 48: 55,257: D / OTHERACTIVITY (1473): onDestroy ()

Beachten Sie, wie wieder einmal geht aufder Bildschirm geschieht zwischen onPause () und OnStop () der Aktivität Verlassen des Bildschirms in. Beachten Sie auch, dass onDestroy () unmittelbar nach OnStop () aufgerufen wird, weil die Aktivität war fi
über die BACK-Taste.

Wenn wir jetzt drückendie HOME-Taste, die Home-Bildschirm-Aktivität in den Vordergrund zu bringen, sehen wir:

04-01 11: 50: 30,347: D / ExplicitIntentsDemoActivity (1473): onPause ()

4-1

11: 50: 32,227: D / ExplicitIntentsDemoActivity (1473): OnStop ()

Es gibteine Verzögerung zwischen onPause () und OnStop () als Home-Bildschirm hat seine Anzeige Arbeit, und es gibt keine onDestroy (), weil die Anwendung noch läuft und nichts

fi
die Aktivität. Schließlich wird das Gerät unser Prozess zu beenden, und wenn das normalerweise der Fall ist, würden wir die onDestroy () LogCat Meldung.

Recycling-Aktivitäten

Nehmen wir an, dass wir drei Aktivitäten haben, mit dem Namen A, B und C. A startet eine Instanz von B bis basierend auf einigen Benutzereingaben und B später beginnt eine Instanz von C durch einige weitere Benutzereingaben auf.

Unser "Aktivität Stack" ist jetzt ABC, was bedeutet,dass, wenn wir von C drücken BACK kehren wir nach B, und wenn wir von B drücken, kehren wir zurück nach A.

Nun nehmen wir an,dass aus C, wir wollen zum Beispiel A. zurück zu navigieren, vielleicht drückte der Benutzer auf das Symbol auf der linken Seite unseres Aktionsleiste, und wir wollen die "Heimat Aktivität" als Ergebnis zurück, und in unserem Fall das passiert A. Wenn C-Aufrufe startActivity () unter Angabe A zu sein, wickeln wir mit einer Aktivität Stack, die ABCA ist.

Das ist, weil die Aktion gestartet, die standardmäßig erstellteine neue Instanz dieser Aktivität. So, jetzt haben wir zwei unabhängige Kopien von A.

Manchmal,Dies ist das gewünschte Verhalten. Zum Beispiel könnten wir eine einzige ListActivity haben, die verwendet wird, um "Drill-Down" über eine hierarchische Datensatz, wie ein Verzeichnisbaum. Wir könnten zu halten wählen Instanzen des gleichen ListActivity starten, aber mit verschiedenen Extras, auf jeder Ebene dieser Hierarchie zu zeigen. In diesem Fall würden wir unabhängige Instanzen der Aktivität wollen, so die BACK-Taste verhält sich wie der Benutzer erwarten könnte.

Wieimmer, wenn wir in die "Heimat-Aktivität" navigieren, können wir nicht eine separate Instanz von A. wollen

Wie Adressierendies hängt ein wenig auf, was Sie die Aktivität Stapel aussehen soll nach A.

Navigation

Wenn Sie eine Aktivität Stapel wollendas ist BCA - so die vorhandene Kopie von A wird in den Vordergrund gebracht, aber die Fälle von B und C sind allein gelassen - dann können Sie hinzufügenFLAG_ACTIVITY_REORDER_TO_FRONTauf IhreAbsichtbenutzt mit startActivity (): Wenn stattdessen wollen Sie eine Aktivität Stapeldas ist nur ein - so, wenn der Benutzer wieder drückt sie Ihre Anwendung zu beenden - dann würden Sie zwei Flaggen
hinzu:FLAG_ACTIVITY_CLEAR_TOPund FLAG_ACTIVITY_SINGLE_TOP:

Dies fi
alle Aktivitäten in der Stapel zwischen der aktuellen Aktivität und die, die Sie beginnen - in unserem Fall fi

C und B.

Anwendung: Transcendingdie Aktivität

AktivitätAbgeleitet voneine Klasse mit dem NamenKontext. Viele der Methoden, die wirüber unsere Aktivitäten fordern, wiestartActivity ()Werden geerbt vonKontext.

Aber,Aktivitätistnicht der einzige relevante UnterklasseKontext. Wir werden sehenBedienung später imdas Buch, beispielsweise. Und manchmal werden wir schlicht zu sehenKontextObjekte, wie zum Beispiel, wenn wir abzudeckenRundfunkempfängerspäter imdas Buch.

eine andereKontextBemerkenswert istAnwendung. Eine InstanzAnwendungerstellt wird, wenn unsere App startet. DasAnwendungInstanzeine natürliche Singletons; es sollte genau eine Instanz seinAnwendungin unserem Prozess.

Normalerweise,diese Singleton ist eine InstanzAnwendungselbst. Wir können jedoch SubklasseAnwendungwenn wir wollen,dann einen Verweis auf unsere eigene Anwendungsklasse in eineandroid: nameAttribut aufdas<Application>Element im Manifest.

Dann, wenn Android unsere App startet, wird es eine Instanz unserer benannten
erstellenAnwendungsunterklasse, sondern als eine Instanz der gewöhnlichen Anwendungsklasse zu schaffen.

Wir können abrufendasAnwendungan jedem Punkt Objekt durch den AufrufgetApplicationContext ()auf jedemKontextObjekt.getApplicationContext ()wird zurückkehreneinKontext; wenn wir brauchen, um das BezugsAnwendungoder unsere spezifischen AnwendungUnterklasse, wirmüssen nach unten Guss der zurückKontextnachdie entsprechenden Typs.

Wir können benutzenAnwendungimein paar Möglichkeiten, in Android-Apps.

In erster Linie, wenn wirmüssen auf ein anderes Objekt in einem statischen Datenelement zu halten, und das andere Objekt braucht einen Kontext, wir wollen, dass es zu sein, die Anwendung verwenden, nicht wirklich eine Aktivität, Dienstleistung, usw. Da Anwendung ein Singleton ist, es ist effektiv "pre -leaked ". Wir können es nicht irgendwie Leck weiter, um es eine andere indirekte statische Referenz haben. Im Gegensatz dazu nehmen wir ein statisches Datenelement auf eine Aktivität halten haben. Nun, wenn die Aktivität zerstört wird, es (und alle gilt, wie Widgets und Hörer) nicht Garbage Collection sein. Dies entsprichtein Speicherleck.

Sie konnte es noch einen Schritt weiter und habendie Anwendung verwalten diese statische Daten, sondern als getrennte Singletons verwenden. Es gibt Vor- und Nachteile dieses Ansatzes, aber im Großen und Ganzen Google ist kein großer Fan davon. Davon abgesehen, Anwendung eine

onCreate hat (), die aufgerufen wird, kurz nachdem es instanziiert wird, und die Unterklasse der Anwendung könnte das außer Kraft setzen und es verwenden, einige "global" Daten zu initialisieren.

Während jedochdie JavaDocs zeigen, dass es ein OnTerminate () -Methode auf Anwendung ist -
was darauf hindeutet, dass wir fi nden, wenn die Anwendung geht weg und unser Prozess beendet wird - das Verfahren in der Praxis nie aufgerufen wird.

Der Fall vondas Unsichtbare Aktivität

Manchmal wollen Sie eine Aktivitätdas hat keine Benutzeroberfläche.

Das ist eher ungewöhnlich. Meistens wird es Fälle geben, wo etwasim System sonst sagt, dass es Ihnen eine Aktivität haben muss, aber wo haben Sie nicht wirklich alles, was Sie wollen in einem traditionellen Aktivität Stil UI für den Benutzer angezeigt werden soll.

Zum Beispiel Launcher Icons Home-Bildschirm nur Aktivitäten starten. Sie können jedoch habenein Bedarf für eine Trägerrakete Startbildschirm, die einfach etwas Arbeit löst im Hintergrund durchgeführt werden, vielleicht einen Dienst mit (wie diskutiert wirdspäter imdas Buch).

Sie haben zwei Möglichkeiten, eine unsichtbare Tätigkeit der Einrichtung, die beide Beteiligung miteine bestimmte android: Thema Wert auf <Aktivität> Element.

Am meisteneffiziente Option ist Theme.NoDisplay zu verwenden. Mit diesem Wert tut Android nichts in Bezug auf die Einstellung für Sie eine Benutzeroberfläche auf. Allerdings ist die wesentliche Einschränkung, dass alle Arbeiten die Aktivität tun wird muss in onCreate abgeschlossen werden (), und dort müssen Sie Finish () aufrufen, um die Aktivität auszulösen zerstört werden. Die meiste Zeit wird, diese Arbeit nur fi

Gelegentlich Sieeine unsichtbare Tätigkeit benötigen, die für ein paar Sekunden zu hängen, um hat, vielleicht auf einige Rückruf Ergebnisse zu warten, bevor sie zerstört werden kann. Mit Theme.NoDisplay wird immer noch funktionieren ... aber nur auf älteren Android-Geräte. Auf Android 6.0 und höher, mit Theme.NoDisplay ohne Finish () aufrufen, in onCreate () (oder, technisch gesehen, vor onResume ())stürzt die App.

Die Abhilfe ist zu verwenden,Theme.Translucent.NoTitleBar. Dies macht eigentlich eine Benutzeroberfläche für Sie zuweisen, sondern setzt es einen transparenten Hintergrund und keine Aktionsleiste zu haben auf. Der Benutzer kann noch wahrnehmen, dass die Aktivität ist um - zum Beispiel, wird es im Übersichtsbild angezeigt (aka, neu-Aufgaben-Liste). Auch, weil die Aktivität

"wirklich da" ist, kann der Benutzer nicht in der Lage sein, zu interagieren mit dem, was der Benutzer kann, wie die zugrunde liegenden Home-Bildschirm zu sehen. Aber, wenn die Aktivität beenden kann () sich schnell und wird in der Zwischenzeit mit dem Benutzer interagieren (zB
einige System-Dialog angezeigt wird), können Sie in der Lage sein, mit diesem Ansatz wegzukommen.

Tutorial # 8- Einstellung eine Tätigkeit Up

Natürlich wäre es schön, wenndiese "Hilfe" und "Über" Menüoptionen, die wir hinzugefügtimdie vorherigen Tutorialtatsächlich tat etwas.

ImIn diesem Tutorial werden wir ein anderes Aktivitätsklasse, ein definieren, die für die Anzeige einfach Inhalte wie unsere Hilfetext und "über" Details zuständig sein wird. Und, ordnen wir, dass die Aktivität zu starten, wenn diese Aktionsleiste Elemente ausgewählt sind. Die Tätigkeit wird eigentlich nichts sinnvoll noch angezeigt werden, wie das wird das Thema der nächsten Tutorials.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository des Buches.

Schritt 1: Erstellendie Stub Aktivitätsklasse und Manifest Eintrag

Als erstes werden wirmüssen, um die Java-Klasse für unsere neue Tätigkeit zu
definieren,SimpleContentActivity.

Rechtsklicken Sie auf Ihremmain / sourceSet Verzeichnis im Projekt-Explorer, und wählen Sie Neu> Aktivität> Leere Aktivität aus dem Kontextmenü. Dies wird eine neuen- Aktivität Assistenten bringen:

ErgänzeSimpleContentActivity in der "Aktivitätsname" fi
und entfernen Sie die

Markierung das "Layout-Datei generieren" aktivieren. Lassen Sie "Launcher Activity"

deaktiviert ist, und deaktivieren Sie die "Rückwärtskompatibilität (AppCompat)" aktivieren.

Wenn der Paketname Dropdown-der Paketname der App zeigt, lassen sie allein. Auf der anderen

Seite, wenn der Paketname Dropdown-leer ist, klicken Sie darauf und der App-Paketnamen wählen. Klicken Sie anschließend auf Fertig stellen.

Beimdieser Punkt, IhreSimpleContentActivityKlasse sollte folgendermaßen aussehen: (von

EmPubLite-Android Studio / T8-Aktivitäten / EmPubLite / app / src / main / java / com /
commonsware / empublite /

SimpleContentActivity.java)

Schritt 2: Starten Unsere Aktivität

Jetzt dass wir, dass die Aktivität erklärt haben, vorhanden ist und verwendet werden können, können wir es benutzen.

Gehen inEmPubLiteActivityundändernonOptionsItemSelected ()in einem gewissen Logik hinzuzufügen indasR.id.aboutundR.id.helpZweige, wie unten dargestellt:

(von

EmPubLite-Android Studio / T8-Aktivitäten / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Imdiese beiden Zweige, schaffen wir eineAbsichtUnd zeigte auf unserer
neuenSimpleContentActivity. Dann nennen wirstartActivity ()aufdassAbsicht. Gerade jetzt, beideHilfeundetwamachendie gleiche Sache - wir einige Smarts hinzufügen, werden haben sie in diesem Buch später unterschiedliche Inhalte laden.

Du wirstmüssen eine Import hinzufügen fürandroid.content.Intentbekommendies zu kompilieren.

Wenn Sie laufenDiese App in einem Gerät oder Emulator, und Sie entweder die Hilfe oder über Menüoptionen wählen, was ist geschehen scheint, dass die ProgressBar verschwindet. In Wirklichkeit ist was passiert, dass unsere SimpleContentActivity erschienen, aber leer ist, wie wir es eine vollständige UI noch nicht gegeben haben.

In unserer nächsten Folge ...

… wir werdenbeginnen Fragmente unter Verwendung vonin unserem Tutorial-Projekt.

Die Taktik des Fragments

Die Fragmente sind eine optionale Ebene, die Sie zwischen Ihren Aktivitäten und Ihre Widgets setzen können, die Ihnen neu konfigurieren, um Ihre Aktivitäten zu helfen, Bildschirme zu unterstützen, sowohl große (zBTabletten) und kleine (zB Handys).

Dieses Kapitel deckt grundlegenden Verwendungen von Fragmenten.

Die Sechs Fragen

Imdie Welt des Journalismus, bestehen die Grundlagen jeglicher Nachrichten Geschichte von sechs Fragen,das Fünf Ws und One H. Hier werden wir diese sechs Fragen anwenden, um Rahmen, was wir reden in Bezug auf Fragmente.

Was?

Die Fragmente sindnicht Aktivitäten, obwohl sie von Aktivitäten verwendet werden.

Die Fragmente sindkeine Behälter (dh Subklassen von Viewgroup), obwohl sie in der Regel eine Viewgroup erstellen.

Vielmehr sollten Siedenken Sie an Fragmente als Einheiten der UI Wiederverwendung zu sein. Sie definieren ein Fragment, ähnlich wie Sie eine Aktivität definieren könnte, mit Layouts und Lifecycle-Methoden und so weiter. Allerdings können Sie dann das Fragment in einer oder mehreren Aktivitäten an, je nach Bedarf.

Android tutnicht genau UI Architekturen wie Model-View-Controller (MVC), Model-View-Presenter (MVP), Model-View-Viewmodel (MVVM) usw. In dem Maße umzusetzen, die Sie wünschen Android in die MVC-Architektur zu schieben, Fragmente und Aktivitäten kombinieren, um die Controller-Schicht. Fragmente dienen als lokale Steuerung,
konzentrierte sich aufihre Satz von Widgets, so dass sie von Modelldaten bevölkern, und ihre Behandlung von Ereignissen. Die Aktivitäten werden als mehr von einer Orchestrierung Schicht
dienen, grenzüber Fragment gesamte Kommunikation (zB ein Klick in Fragment A muss eine Änderung zu bewirken, was in Fragment B angezeigt wird).

Funktionell Fragmente sind Java-Klassen, die sich voneine Basis Fragment Klasse. Wie wir sehen werden, gibt es zwei Versionen der Fragment-Klasse, eine native API Stufe 11 und einer von der Android-Support-Paket geliefert.

Woher??

Da Fragmente Java-Klassen sind, befinden sich Ihre Fragmente in einem Ihrer Anwendung Java-Pakete. Der einfachste Ansatz ist zu setzensie in der gleichen Java-Paket, das Sie für Ihr Projekt verwendet insgesamt und wo Sie Ihre Aktivitäten liegen, obwohl Sie Ihre UI-Logik in andere Pakete bei Bedarf umgestalten können.

Wer?!?

Normalerweise erstellen Sie Fragment Implementierungen selbst,dann Android sagen, wenn sie zu benutzen. Einige Drittanbieter-Android-Bibliotheksprojekte können Fragment-Implementierungen, die Sie wiederverwenden können, wenn Sie dies wünschen.

Wann?!!?

Einige Entwickler beginnen Hinzufügen von Fragmenten aus der NäheBeginn der

Anwendungsentwicklung - das ist der Ansatz ist, dass wir in den Übungen stattfinden wird. Und wenn Sie eine neue Anwendung von Grund auf neu beginnen, Fragmente frühzeitig zu definieren, ist wahrscheinlich eine gute Idee. Davon abgesehen, ist es durchaus möglich,

"retrofi
einAndroid-Anwendung vorhandenen Fragmente zu verwenden, obwohl dies
eine Menge Arbeit sein kann. Und es ist durchaus möglich, Android Anwendungen überhaupt ohne Splitter zu erzeugen.

Die Fragmente wurden mit Android 3.0 eingeführt (API Stufe 11, auch bekannt als Honeycomb).

WARUM?!?!?

Ah,das ist die große Frage. Wenn wir es geschafft haben, es bis hierher durch das Buch ohne Fragmente zu machen, und wir müssen nicht Fragmente müssen Android-Anwendungen zu erstellen, was ist der Sinn? Warum sollten wir die Mühe machen?

Der primäre Grund für Fragmente war es zu macheneinfacher, mehrere Bildschirmgrößen zu unterstützen.

Android gestartet Telefone unterstützen werden. Telefone könnenvariieren in der Größe, von winzigen diejenigen mit weniger als 3 "Größe Bildschirmdiagonale (zB Sony Ericsson X10 mini), um Monster, die mehr als 5 sind" (zB Samsung Galaxy Note). diese Variationen in Bildschirmgröße verblassen im Vergleich zu den Unterschieden zwischen den Telefonen und Tablets oder Handys und Fernsehern jedoch.

Einige Anwendungen werden einfach erweitern, um fi größere Bildschirmgrößen. Viele Spiele werden diesen Ansatz, einfach den Benutzer mit größeren interaktive Elemente bieten, größere Spielbretter, usw. Jeder der allseits beliebten Angry Birds Spiele-Serie, wenn sie auf einem Tablet gespielt, gibt Ihnen größere Vögel und größere Schweine, kein Telefon großen Spielfläche von Werbebannern umgeben.

Allerdings ist ein weiteres Design-Ansatz zu berücksichtigenein Tablet-Bildschirm eine Sammlung von Handy-Bildschirme, die Seite an Seite wirklich zu sein.

Der Benutzer kann alle zugreifendass die Funktionalität auf einmal auf einem Tablett, während müssten sie fl

Zurück und her zwischen separaten Bildschirmen auf ein Telefon.

Für Anwendungen,das kann dieses Entwurfsmuster fi, Fragmente ermöglicht es Ihnen, Handys und Tabletten von einer Code-Basis zu unterstützen. Die Fragmente können durch einzelne Aktivitäten auf einem Telefon verwendet werden, oder sie können für eine Tablette durch eine einzige Tätigkeit zusammengenäht werden.

Details zu Fragmenten mit großen Bildschirmgrößen zu unterstützenein Thema fürein späteres Kapitel in diesem Buch. Dieses Kapitel konzentriert sich aufdie grundlegenden Mechanismen der Einrichtung und Nutzung von Fragmenten.

OMGOMGOMG, WIE?!?! ??

Nun, die Beantwortungdiese Frage ist, was der Rest dieses Kapitels ist für, zusätzlich Erfassung erweiterte Verwendung von Fragmenten an anderer Stelle in diesem Buch.

Wo erhalten Sie Ihre Fragmente aus

Die meisten Entwickler verwendendie Umsetzung von Fragmenten, die 11. Teil von Android seit API-Ebene wurde Sie android.app.Fragment verwenden und sie durch Ihre regelmäßigen Aktivitäten gehostet werden.

Jedoch gibt esein Backport des Fragments System im Android-Support-Paket zur Verfügung. Dies funktioniert wieder auf API-Ebene 4, so dass, wenn IhrminSdkVersionist tieferals 11, und Sie wollen

Fragmente zu verwenden, ist die Rückportierung etwas, das Sie in Betracht ziehen werden wollen. Sie müssen das hinzufügensupport-v4JAR zu Ihrem Projekt

(zBüberkompilieren'Com.android.support:support-v4: ...'in deinem Abhängigkeitenimbuild.gradle, Für einen Wert von...). Du wirst auchverwenden müssen,android.support.v4.app.FragmentAnstatt vonandroid.app.Fragment. Außerdem müssen Sie die Fragmente in einer Aktivität zu hosten Vererben vonandroid.support.v4.app.FragmentActivity(wiedie regelmäßigeandroid.app.ActivityBasisklasse tutwissenüber Fragmente nicht vor der API-Ebene 11).

Dieses Buch konzentriert sich vor allem auf mitdie native API Stufe 11 Implementierung von Fragmenten, mit dem gelegentlichen Beispiel die Rückportierung der Verwendung, wo die Backport für einen oder anderen Grund notwendig ist.

Ihr erstes Fragment

In vielerlei Hinsicht ist esleichter Fragmente zu erklären, bei einer Implementierung durch suchen, um so mehr, als zu versuchen, sie als abstrakte Konzepte zu diskutieren. Also, in diesem Abschnitt werden wir einen Blick auf dieFragmente / StaticBeispielprojekt. Das istein nahezu Klon desAktivitäten / LifecycleBeispielprojekt ausdie vorherigen Kapitel. Wir haben jedoch umgewandeltder Launcher Aktivität von einer, die Widgets direkt selbst zu einem Host wird, die ein Fragment beherbergen wird, die wiederum schafft Widgets.

Das Fragment-Layout

Unser Fragment wird unsere UI zu verwalten, so haben wireinres / Layout / mainfrag.xml Layout fi
enthält unsereTaste:

(von

Fragmente / Static / app / src / main / res /

Layout / mainfrag.xml)

Beachten Sie jedoch,dass wir verwenden, um die Android nicht: onClick-Attribut. Wir werden erklären, warum wir in Kürze das Attribut aus den früheren Ausgaben dieser Probe fallen gelassen.

Das Fragment Klasse

Das Projekt hateine ContentFragment Klasse, die dieses Layout verwenden und handhaben die Taste.

Wie bei den Aktivitäten gibt eskein Konstruktor auf einer typischen Fragment Unterklasse. Die primäre Methode, die Sie, wenn auch außer Kraft setzen, ist nicht onCreate () (obwohl, wie wir später in diesem Kapitel sehen werden, das ist möglich). Stattdessen ist die primäre Methode

überschrieben onCreateView (), die zur Rückführung des UI verantwortlich ist für dieses Fragment angezeigt werden:

(von

Fragmente / Static / app / src / main / java / com / commonsware /
android / sfrag / ContentFragment.java)

Wir übergebenein LayoutInflater, die wir zum Aufblasen eines Layouts fi verwenden können die Viewgroup, die schließlich alles halten wir, und das Bündel aufblasen, die die Aktivität des onCreate () -Methode übergeben wurde. Während wir auf Framework-Klassen verwendet werden, unser Layout Ressourcen für uns geladen haben, können wir "aufblasen" ein Layout Ressource jederzeit eine LayoutInflater verwenden. Dieser Prozess liest im XML, analysiert er, geht das Element Baum, schafft Java für jedes der Elemente Objekte und Stiche, die Ergebnisse zusammen in einer Eltern-Kind-Beziehung.

Hier aufblasen wirres / Layout / mainfrag.xml, Android zu sagen, dass ihr Inhalt wird schließlich in die gehenViewgroupabernicht sofort hinzuzufügen. Während es einfacher Aromen
deraufblasen()Verfahren aufLayoutInflaterIst auch dieses erforderlich

Falldie Viewgroup geschieht ein RelativeLayout zu sein, so können wir in geeigneter Weise alle der Positionierung und Dimensionierungsregeln verarbeiten.

Wir verwenden auchfindViewById ()zu fi
unserTasteWidget und ihm sagen, dass wir, das

Fragment, sind seineOnClickListener.ContentFragmentsollendann implementieren
dieView.OnClickListenerSchnittstelle zu machendiese Arbeit. Wir tun dies, stattandroid: onClickroutendasTasteklicken Sie auf Veranstaltungendas Fragment, nicht die Aktivität.

Da wir implementierendasView.OnClickListenerSchnittstelle wirmüssen die
entsprechendenonClick ()Verfahren Umsetzung:

(von

Fragmente / Static / app / src / main / java / com / commonsware /
android / sfrag / ContentFragment.java)

Jedes Fragment kann anrufengetActivity ()zu fi
die Aktivität, die es beherbergt. In unserem

Fall ist die einzige Aktivität wird möglicherweise dieses Fragment Gastgeber

istStaticFragmentsDemoActivity, So können wir das Ergebnis werfengetActivity

()nachStaticFragmentsDemoActivity, So dass wir Methoden, die auf unserer Tätigkeit nennen.

Insbesondere erzählen wir die Aktivität der anderen Aktivität zu zeigen, durch Aufruf dershowOther ()Methodedass wir in der Original gesehenAktivitäten / LifecycleProbe (und werden sehen, in Kürze wieder).

Das ist wirklich alles,daß für dieses Fragments benötigt. Allerdings überschreibt ContentFragment auch viele andere Fragment Lifecycle-Methoden, und wir werden diese prüfenspäter im dieses Kapitel.

Der Vorgang Layout

Ursprünglich, die res / Layout / main.xml durch die Aktivität verwendet wurde, wo wir unser Knopf-Widget hatte. Nun wird die Taste durch das Fragment behandelt. Stattdessen muss unsere Aktivität Layout für das Fragment zu erklären selbst.

Imdiese Probe werden wir ein statisches Fragment zu verwenden. Statische Fragmente sind einfach zu Ihrer Anwendung hinzuzufügen: nur verwenden Sie das <Fragment> Element in einem Layoutfi
sowieunsere überarbeitetres / Layout / main.xml:

(von

Fragmente / Static / app / src / main /
res / Layout / main.xml)

Hier haben wir unsere UI deklarieren vollständig von einem Fragment umfasst sein, deren Umsetzung(com.commonsware.android.sfrag.ContentFragment) Wird durch die identifiziertandroid: nameAttribut aufdas<Fragment>Element. Anstatt vonandroid: name, Können SieKlasse, Obwohl die meisten der Android-Dokumentation wurde nun umgeschaltet zuandroid: name.

Android Studio Benutzer können per Drag ein Fragment aus dem "Custom" des grafischen Layout-Editor-Tool-Palette, falls gewünscht, anstatt das <Fragment> Element direkt in der XML-Einrichtung.

Die Aktivität der Klasse

StaticFragmentsDemoActivity- Unsere neuen Starter-Aktivität - sieht identisch mit der vorherigen Version, mit Ausnahme der Klassenname:

(von

Fragmente / Static / app / src / main / java / com / commonsware / android /
sfrag / StaticFragmentsDemoActivity.java)

Schon seitdasres / Layout / main.xmlfi
hat das<Fragment>Element wird das Fragment
einfach in die richtige Position in dem Aufruf geladensetContentView ().

Das Fragment LifecycleMethoden

Die Fragmente haben Lifecycle-Methoden, wie Aktivitäten. Eigentlich,sie unterstützen die meisten die gleichen Lebenszyklus Methoden wie Aktivitäten:

• onCreate ()

• onStart ()(aber nichtonRestart ())

• auf Wiederaufnahme()

• onPause ()

• OnStop ()

• onDestroy ()

Im Großen und Ganzen,die gleichen Regeln für Fragmente gelten wie für Aktivitäten in Bezug auf diese Lebenszyklus Methoden tun (zB onDestroy () nicht aufgerufen werden).

In Ergänzung auf diese und die Methode onCreateView () wir weiter oben in diesem Kapitel untersucht, gibt es vier weitere Lifecycle-Methoden, die Sie wählen können außer Kraft zu setzen, wenn Sie dies wünschen.

onAttach () wird aufgerufen, fi
sogarVoronCreate (), so dass Sie wissen, dass Ihr Fragment
einer Aktivität angehängt wurde. Sie haben die Aktivitätübergeben, die Ihr Fragment beherbergen wird.

onViewCreated ()wird aufgerufen, nachdemonCreateView (). Dies ist besonders nützlich, wenn Sie die ererbenonCreateView ()Umsetzung abermüssen die daraus resultierenden Ansichten, wie mit einem zu konfigurierenListFragmentundbenötigen einen Adapter einzurichten.

onActivityCreated ()wird aufgerufen, nachdemonCreate ()undonCreateView ()um anzuzeigen, dass die die AktivitätonCreate ()hat vervollständigt. Wenn es etwas gibt,dass Sie benötigen in Ihrem Fragment zu initialisieren, die von der Aktivität des abhängtonCreate ()ihre Arbeit abgeschlossen haben, können Sie verwendenonActivityCreated ()fürdass die Initialisierung der Arbeit.

onDestroyView ()wird aufgerufen, bevoronDestroy (). Dies ist das Gegenstück zuonCreateView ()wo setzen Sie Ihre Benutzeroberfläche auf. Wenn es gibtDinge, die Sie benötigen spezifi zu Ihrer Benutzeroberfläche zu bereinigen, können Sie diese Logik setzen inonDestroyView ().

onDetach () wird nach onDestroy () aufgerufen, damit Sie wissen, dass Ihr Fragment von seiner Hosting-Aktivität distanzierte wurde.

onAttach () Versus onAttach ()

Wenn Sie Ihr Projekt festgelegt habenein compileSdkVersion von 23 oder höher, und Sie versuchen, onAttach () außer Kraft zu setzen, können Sie eine deprecation Warnung erhalten: Das ist, weil es zwei Versionen vononAttach ()(undonDetach ()) Mit API-Ebene Start 23. Man nimmt einAktivitätwieein Parameter, der andere nimmt einKontextwieein Parameter.

Die Rollen vononAttach () und onDetach () gleich sind entweder mit Parameter: Sie wissen lassen, wenn das Fragment zu oder von seinem Wirt angebracht und davon gelöst wurde. Doch jetzt könnte der Wirt alles sein, was Kontext erstreckt, nicht nur eine Aktivität.

Auf API-Ebene 22 und unten, aber nurdie Aktivität Geschmack von onAttach () und onDetach () vorhanden ist. Dies führt zu einem Rätsel, wie Sie versuchen, genau zu bestimmen, wie dies für Ihre Anwendung zu handhaben.

Aufdas Ganze, wenn Ihr minSdkVersion unter 23 ist, zwingende onAttach (Aktivität) gerade ist die beste Route. Es funktioniert auf allen Android-Geräten, die Fragmente unterstützen. nur onAttach (Context) Aufschalten wird nicht funktionieren, da ältere Geräte ignorieren wird (trotz Aktivität eine Unterklasse von Context ist). Sie könnten beide Methoden außer Kraft setzen, sondern auf API-Ebene 23+ Geräte, werden beide Varianten genannt werden, was keine gute Idee für Ihre Fragment Unterklasse sein kann oder nicht.

Ihre erste dynamische Fragment

Statische Fragmente sind ziemlich einfach, sobald Siedas Fragment Umsetzung: fügen Sie einfach die

<Fragment> -Element, wo Sie Ihre Aktivität des in das Layout haben wollen, erscheint das Fragment.

Diese Einfachheit, nicht aber mit einigen Kosten kommen. Wir werden einige überprüfendiese Beschränkungenimdas nächste Kapitel.

Diese Beschränkungen können durch überwunden werdendie Verwendung von dynamischen Fragmente. Anstatt Angabe zu Android, dass Sie ein Fragment mit Hilfe eines <Fragment> Element in einem Layout verwenden möchten, werden Sie ein FragmentTransaction verwenden, um ein Fragment zur Laufzeit von Java-Code hinzuzufügen.

Mitin diesem Sinne, einen Blick auf dieFragmente / DynamischBeispielprojekt.

Das istdas gleiche Projekt wie die für statische Fragmente, außer dieser Zeit werden wir OTHERACTIVITY einstellen ein dynamisches Fragment zu verwenden, nämlich eine

ListFragment.

Die ListFragment Klasse

ListFragmentdientdie gleiche Rolle für Fragmente alsListActivitytut für Aktivitäten. Es hüllteinListenansichtfür die bequeme Nutzung. So habeneine
interessantereOTHERACTIVITYBeginnen wir mit einOtherFragmentdas ist einListFragment, Entworfen unser Favorit 25 lateinische Wörter zu zeigen, wie in den vorherigen Beispielen gesehen.

Genauso wieeinListActivitytutmüssen nicht anrufensetContentView (), einListFragmenttutmüssen nicht außer Kraft setzenonCreateView (). Standardmäßig wird das gesamte Fragment eines einzelnen bestehenListenansicht. Und ebenso wieListActivityhateinsetListAdapter ()Verfahren zu assoziieren einAdaptermitdasListenansicht, Tut dies auchListFragment:

(von

Fragmente / Dynamisch / app / src / main / java / com / commonsware

/ android / dfrag / OtherFragment.java)

Wir nennensetListAdapter ()imonViewCreated ()Wie wir wissen, dass dieListenansichtist jetzt einsatzbereit.

Diese Klasse wird auch viele Fragment Lifecycle-Methoden, Protokollierungihre Ergebnisse,ähnlich wie unsere anderenFragmentundLifecycleLoggingActivity.

Die Aktivität der Klasse

Jetzt,OTHERACTIVITYmuss nicht mehr ein Layout zu laden - wir entfernt habenres / Layout /
other.xmlvondas Projekt vollständig. Stattdessen werden wir eine
verwendenFragmentTransactionhinzuzufügen unser Fragment auf der Benutzeroberfläche: (von

Fragmente / Dynamisch / app / src / main / java / com /
commonsware / android / dfrag / OtherActivity.java)

Arbeiten miteinFragmentTransaction, Müssen Sie dieFragmentManager. Diese Aufgabe kennt alle Fragmenteüber die in Ihrer Aktivität vorhanden sind. Wenn Sie die native API Stufe 11 Ausgabe von Fragmenten verwenden, können Sie sich IhreFragmentManagerdurch den

AufrufgetFragmentManager (). Wenn Sie das Android-Support-Paket verwenden, müssen Sie anrufengetSupportFragmentManager ()stattdessen.

GegebeneinFragmentManagerKönnen Sie beginnen, einFragmentTransactiondurch den Aufruf begintransaction ()Werden, welches dieFragmentTransactionObjekt.FragmentTransactionarbeitet aufdie Erbauer, so dass die meisten Methoden
aufFragmentTransactionRückkehrdasFragmentTransactionselbst, so können Sie Ketteeine Reihe von Verfahren nennt man nach dem nächsten.

Wir nennen zwei Methoden auf unsererFragmentTransaction: add () und commit (). Die Methode add (), wie Sie sich vorstellen können, gibt an, dass wir ein Fragment, das dem UI hinzufügen möchten. Wir liefern das eigentliche Fragment-Objekt, in diesem Fall durch eine neue OtherFragment zu schaffen.

Wir müssen auch angeben, wo in unserem Layout wir das Fragment befinden soll. Hätten wir beladenein Layout, könnten wir dieses Fragment in jedem gewünschten Behälter fallen. In unserem Fall, da wir kein Layout laden, liefern wir android.R.id.content als ID des Behälters unser Fragment-Ansicht zu halten. Hier identifiziert android.R.id.content den Behälter, in dem die Ergebnisse der setContentView () gehen würde - es ist ein Behälter, der durch Aktivität geliefert selbst und dient als obersten Container für unsere Inhalte.

einfach anrufenadd () ist unzureichend. Wir müssen dann commit () passieren die Transaktion tatsächlich zu machen.

Sie fragen sich vielleicht, warum wir sindversuchen zu fi
ein Fragment in unserem

FragmentManager bevor das Fragment tatsächlich zu schaffen. Wir tun das, um mit

Konfigurationsänderungen befassen, und wir werden das weiter erforschenimdas nächste Kapitel.

Fragmente undIn der Aktionsleiste

Die Fragmente können Elemente hinzufügen In der Aktionsleiste durch den

AufrufsetHasOptionsMenu (true)vononCreate ()(Oder einer anderen frühen Lebenszyklus-Methode).

Dies zeigtdie Aktivität, die es braucht, um nennenonCreateOptionsMenu

()undonOptionsItemSelected ()aufdas Fragment.

DasFragmente / ActionBarNativeBeispielanwendung demonstriert dies. Das hatdie gleiche Funktionalität wie auch dieActionBar / ActionBarDemoNativeProbe ausdas KapitelIn der Aktionsleiste, Nur mitdie Aktivität umgewandelt in ein dynamisches Fragment.

ImonCreate (), wir nennensetHasOptionsMenu (true), Um anzuzeigen, dass wir an der Teilnahme an der Aktionsleiste interessiert sind:

(von

Fragmente / ActionBarNative / app / src / main / java / com / commonsware /
android / abf / ActionBarFragment.java)

(wir werden diskutierendasssetRetainInstance (true)Anrufimein späteres Kapitel) Das wird unser Fragments auslösenonCreateOptionsMenu ()und
onOptionsItemSelected ()Methoden bei aufgerufen werdendie entsprechende Zeit:

(von

Fragmente / ActionBarNative / app / src / main / java / com / commonsware /
android / abf / ActionBarFragment.java)

Hier initialisieren wir unsere Aktion Bar aus dem R.menu.actions Menü XML Ressource, zusammen mit der Logik auf das Add reagieren und Aktionsleiste Punkte zurückzusetzen.

Unsere Tätigkeit hatnichts Besonderes tun müssen, um das Fragment zu ermöglichen, in der Aktionsleiste zu tragen - es wird nur das dynamische Fragment nach oben:

(von

Fragmente / ActionBarNative / app / src / main / java / com / commonsware /
android / abf / ActionBarFragmentActivity.java)

Fragmente Innerhalb Fragmente: Sagen Sie einfach "Vielleicht"

Historisch gesehen, ist eine Hauptbeschränkung mit Fragmentendass sie nicht andere Fragmente enthalten könnten. In den meisten Fällen ist dies nicht stellen ein großes Problem. Allerdings gibt wird seinZeiten, wenn man über diese Einschränkung auslösen könnten, wie beispielsweise bei der Verwendung von a

ViewPager wird, wie beschrieben werdenein späteres Kapitel.

Android 4.2- Und das Android-Support-Paket - Unterstützung für verschachtelte Fragmente.

Während eine Tätigkeit arbeitet über eine mit FragmentenFragmentManagererhalten
übergetFragmentManager ()odergetSupportFragmentManager ()Fragmente können über einen Aufruf mit verschachtelten Fragmenten arbeitengetChildFragmentManager ().

Allerdings Android 3.0 bis 4.1 habeneine Version von Fragmenten, die nicht über
getChildFragmentManager (). Daher haben Sie zwei Möglichkeiten:

1. BenutzenDie Android-Rückportierung von Fragmenten des Unterstützungspakets, so lange, bis Sie die Unterstützung für Android 4.1 und früher fallen können, oder

2. Machenkeine verschachtelten Fragmente für verwenden die Zeit.

Wir werden sehen, wiegetChildFragmentManager ()arbeitet indas Kapitelüber ViewPager.

Fragmente undMehrere Aktivitäten

Ein Fragment sollte Funktionalität rein innerhalb des Fragments selbst behandeln. Alles, was außerhalb des Fragments sollte in der Verantwortung des anrufenden Tätigkeit. Zum Beispiel, wenn der Benutzer tippt auf ein Element in einem ListFragment und die Auswirkungen dieses Ereignisses könnte über das hinausgehen, was im Inneren des ListFragment selbst ist, sollte die ListFragment das Ereignis an die Hosting-Aktivität weiterleiten, so kann es vielleicht zusätzliche Schritte

ausführen (zB eine Aktivität, zu starten, ein weiteres Fragment durch die Aktivität gehostet aktualisieren).

Wie wir sehen werdenimein späteres KapitelEs ist durchaus möglich,- Vielleicht sogar wahrscheinlich -, dass einige unserer Fragmente werden durch mehrere verschiedene Aktivitäten stattfinden. Zum Beispiel könnten wir ein Fragment haben, die in einem Fall durch eine Aktivität für größere Bildschirme (zB Tabletten) und in einem anderen Fall durch eine Aktivität für kleinere Bildschirme (zB Handys) konzipiert entworfen gehostet wird.

Imdiese Fälle, weiß, dass das Fragment bei der Kompilierung nicht die Aktivitätsklasse wird es zur Laufzeit bewirten. Für diese Fälle gibt es drei wesentliche Optionen:

1. Habendie Aktivitäten eine gemeinsame Schnittstelle implementieren, und haben das Fragment, das das Ergebnis des Aufrufs getActivity werfen () auf diese Schnittstelle, so kann es ohne zu wissen, seine genaue Umsetzungsmethoden auf der Hosting-Aktivität aufrufen.

2. Habendie Aktivitäten liefern ein Listener-Objekt, mit einer gemeinsamen Schnittstelle, an das Fragment über einen Setter, und haben das Fragment, das Hörer verwenden, um Ereignisse für das Anheben und so weiter.

3. Verwenden Sie ein Event-Bus, wie wir erforschenspäter imdieses Buch.

Wir werden sehen, viel mehr aufdieses Thema, wenn wir bekommen in Großbild-Strategienimein späteren Kapitel.

Tutorial # 9- Start Unsere Fragmente

Viel vonder Inhalt eines digitalen Buches in EmPubLite gesehen zu werden in Form von HTML und zugehörige Vermögenswerte (CSS, Bilder, etc.) sein. Daher werden wir schließlich unsere Inhalte in einem WebView-Widget zu machen brauchen, für die besten Ergebnisse mit halb beliebigen HTML-Inhalte.

Um dies zu tun, werden wir auf Fragmente für Setdie Bits des Inhalts:

• jedes Kapitel (oder in unserem Fall, HTML fi
enthaltend Kapitel)

• andere Materialien, wie unsere "Hilfe" und "über" Seiten

Im Moment konzentrieren wir uns auf nur einige der Einrichtungdie Basisklassen für diese Fragmente - wir werden sie mit Inhalt und zeigt sie in den nächsten paar Tutorials laden.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Erstellenein SimpleContentFragment

Android hatein WebViewFragment für die native API-Level 11+ Implementierung von

Fragmenten, entworfen, einige Web-Inhalte in einem WebView zu zeigen. In diesem Schritt werden wir eine Unterklasse von WebViewFragment erstellen, die in ein wenig EmPubLite spezifische Geschäftslogik hinzu.

Rechtsklicken Sie aufdie com.commonsware.empublite Paket in Ihrem java / und Neu> "Java Class" aus dem Kontextmenü wählen. Das wird ein neuen- Klasse Dialog aufzurufen: ErgänzeSimpleContentFragmentfürden Namen und dieandroid.app.Fragmentfürdieübergeordnete Klasse. Klicken Sie dann auf OK, um diese Klasse zu erstellen.

Dann ersetzender Inhalt des Fragments Klasse mit dem folgenden Code:

(von

EmPubLite-Android Studio / T9-Fragmente / EmPubLite / app / src / main / java / com /
commonsware / empublite /

SimpleContentFragment.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt 2: Untersuchen SimpleContentFragment

SimpleContentFragmenteinfach ist, mitinsgesamt vier Methoden:

• onCreate (), Wo wir nennensetRetainInstance (true)- Die Nützlichkeit dieser wird detaillierter untersucht werdenin einem der nächsten Kapitel.

• onCreateView (), wo wir auf die übergeordnete Kette (haben sie die WebView
erstellen), dann so konfigurieren, dass JavaScript zu akzeptieren und Zoomvorgänge unterstützen. Wir haben es dann einige Inhalte zu laden, in Form einer URL von einem privaten getPage () -Methode abgerufen. Schließlich kehren wir, was die
übergeordnete Klasse von onCreateView () zurückgegeben wird - wirksam sind wir
einfach in unserer eigenen Konfigurationslogik Spleißen.

• einnewInstance ()statische Factory-Methode. Diese Methode erstellt eine

InstanzSimpleContentFragment, Nimmt einübergebenes inSchnur(zeigt aufdie fi
laden) auf, bringt es ineinBündelnerkannt alsKEY_FILE, Hände, welche
dieBündelnnachdas

Fragment als Argumente und kehrtDie neu erstellte

SimpleContentFragment.

• getPage (), wo sie einen Wert aus dem "Argumente" Bundle kehrt zum Fragment geliefert - speziell die Zeichenfolge als KEY_FILE identifiziert.

Das heisstdass alle, die verwendenSimpleContentFragmentsollte nutzendie Factory-Methode, den Pfad zu dem Inhalt zu liefern zu laden. Wir werden sehen, warum wir
umgesetztSimpleContentFragmentauf diese Weise indas nächste Kapitel.

In unserer nächsten Folge ...

… wir werdenset up horizontale swipingvon Buchkapiteln in unserem Tutorial-Projekt.

Swiping mit ViewPager

Android, überdie Jahre hat sich immer mehr Wert auf UI-Design setzen und eine Flüssigkeit und konsistente Benutzererfahrung (UX) mit. Während einige mobile Betriebssysteme "der Stick"

Konzept für die UX nehmen (zwingen Sie durch bestimmte Muster zu halten oder Ihre Anwendung verboten werden, um zu verteilen), nimmt Android "die Karotte" Ansatz, Widgets und Behälter anbieten, die bestimmte Muster verkörpern, die sie einstehen. In der Aktionsleiste, zum Beispiel entstand aus dieser und ist heute das Rückgrat vieler Android-Aktivitäten.

Ein weiteres Beispiel istdie ViewPager, die es dem Benutzer ermöglicht, horizontal Swipe zwischen verschiedenen Abschnitten Ihrer Inhalte zu bewegen. Jedoch ist ViewPager nicht als Teil des fi verteilten
ware, sondern überdas Android-Support-Paket. Daher, obwohl ViewPager
ein relativ neues Widget, können Sie es auf Android verwenden

1.6 und höher.

Dieses Kapitel konzentriert sich auf, wo Sie sich bewerben solltenein ViewPager und wie man bis zu setzen.

Stücke eines Pagers

AdapterViewKlassen, wieListenansicht, arbeiten mitAdapterObjekte,
wieArrayAdapter.ViewPagerjedoch ist keinAdapterViewTrotz vieler der Muster Annahme vonAdapterView.ViewPagerDaher funktioniert nicht mit einAdapter, Aber stattdessen mit einerPagerAdapter, Das eine etwas andere API.

Android Schiffe zweiPagerAdapterImplementierungen indas Android-Support-

Paket:FragmentPagerAdapterundFragmentStatePagerAdapter. Ersteres ist gut für eine kleine Anzahl von Fragmenten, wo sie sofort alle im Speicher halten
arbeiten.FragmentStatePagerAdapterfür Fälle, in denen alle möglichen Fragmente halten sein gesehen indie ViewPager wäre zu viel, wo Android Fragmente verwerfen nach Bedarf und halten Sie auf die (vermutlich kleiner) Zustände dieser Fragmente statt.

Paging-Fragmente

Die einfachste Art und Weise zu verwenden,ein ViewPager ist es Seitenfragmente in zu haben und aus dem Bildschirm basierend auf Benutzer klaut.

Sehendies in Aktion, wird untersucht, dieser Abschnitt derViewPager / FragmenteBeispielprojekt.

Das Projekt hateine Abhängigkeit von der Paket Android Unterstützung, zu verwenden, um zu könnenViewPager. In Android Studio, ist dies einkompilierenAussage
indasAbhängigkeitenSchließungbuild.gradle:

(von ViewPager / Fragmente / app

/ build.gradle)

Der Vorgang Layout

Das Layout, die vondie Aktivität enthält nur die ViewPager. Beachten Sie, dass seit ViewPager nicht im android.widget Paket ist, müssen wir den Klassennamen in das Element vollständig qualifizieren: (von

ViewPager / Fragmente / app / src / main /
res / Layout / main.xml)

Hinweisdass ViewPager für Drag-and-Drop in den IDE grafischen Designer nicht verfügbar ist, wahrscheinlich, weil es aus dem Android-Support-Paket und übernimmt somit für alle Projekte nicht zur Verfügung.

Die Aktivität

Wie du siehst,dasViewPagerFragmentDemoActivityselbst ist herrlich klein:

(von

ViewPager / Fragmente / app / src / main / java / com / commonsware / android /

Pager / ViewPagerFragmentDemoActivity.java)

Alles, was wir tun, ist Lastdas Layout, die abgerufen werdenViewPagerüberfindViewById ()Und bieten einSampleAdapternach dasViewPagerübersetAdapter ().

Die PagerAdapter

UnserSampleAdapterAbgeleitet vonFragmentPagerAdapterund implementiert zwei
erforderlichen Rückrufmethoden:

• getCount ()um anzuzeigen, wie viele Seiten in der seinViewPager, und

• getItem ()Werden, welches einFragmentfüreine bestimmte Position innerhalb der

ViewPager(verwandt mitgetView ()imein KlassikerAdapter)

(von

ViewPager / Fragmente / app / src / main / java / com / commonsware /
android / Pager / SampleAdapter.java)

Hier stellen wir sagendass es 10 Seiten total sein, wird eine Instanz eines EditorFragment sein, von denen jeder. In diesem Fall, anstatt den Konstruktor für EditorFragment verwenden, verwenden wir eine newInstance () Factory-Methode. Die Begründung dafür wird im nächsten Abschnitt erläutert.

Das Fragment

EditorFragmentwird Gastgeber seinein VollbildText bearbeitenWidget fürder Benutzer in einem Stück Prosa zu geben, wie es in der definiert ist,res / Layout / editor.xmlRessource: (von

ViewPager / Fragmente / app / src / main /
res / Layout / editor.xml)

Wir wollen passierendie Positionsnummer des Fragments innerhalb des ViewPager, einfach den Hinweis in der EditText bevor der Benutzer tippt in etwas angezeigt anpassen. Bei normalen Java-Objekte, können Sie diese in über den Konstruktor übergeben, aber es ist keine gute Idee, einen Konstruktor auf einem Fragment zu implementieren. Stattdessen ist das Rezept eine statische Factory-Methode (in der Regel genannt newInstance ()) zu erstellen, die das Fragment und geben Sie die Parameter, um es schaffen wird durch das Fragment des "Argumente" Aktualisierung (a Bundle):

(von

ViewPager / Fragmente / app / src / main / java / com / commonsware /
android / Pager / EditorFragment.java)

Sie fragen sich vielleicht, warum wir mit Mühe werdenDieses Bundle, anstatt nur eine regelmäßige Datenelement verwendet. Die Argumente Bundle ist ein Teil unserer "gespeichert Instanz Zustand", für mit Dingen wie Bildschirm Drehungen zu tun - ein Konzept, das wir in bekommenlater imdas Buch. Fürder Moment, nehmen Sie es auf den Glauben, dass dies eine gute Idee ist.

ImonCreateView ()wir aufblasen unsereR.layout.editorRessource, erhaltendasText bearbeitenvon ihm, unsere Position aus unseren Argumenten, Format erhaltenein Hinweis, die Position, die (eine String-Ressource verwendet wird), und den Hinweis auf die EinstellungText bearbeiten:

(von

ViewPager / Fragmente / app / src / main / java / com / commonsware /
android / Pager / EditorFragment.java)

Das Ergebnis

Wenn zunächst ins Leben gerufen,Die Anwendung zeigt die fi

Fragment:

Sie können jedoch horizontal Swipe zu bekommendas nächste Fragment:

Swiping funktioniert in beide Richtungen, so lange, wie es eine andere Seite in die gewünschte Richtung.

Paging Other Stuff

Sie machenmüssen nicht Fragmente innerhalb eines verwendenViewPager. Ein

StammkundePagerAdaptertatsächlich HändeAussichtObjektedasViewPager. Das mitgelieferte fragmentbasiertePagerAdapterImplementierungen erhaltendasAussichtvonein Fragment und verwenden Sie das, aber Sie sind herzlich eingeladen, Ihre eigenen erstellenPagerAdapterdass meidet Fragmente.

Wenn Sie also wollenViewPagerzu Seiteandere Dinge als Fragmente, ist die Lösung nicht zu verwendenFragmentPagerAdapteroderFragmentStatePagerAdapter, Sondern eine eigene

Implementierung des erstellenPagerAdapterSchnittstelle, eindaß vermeidet die Verwendung von Fragmenten.

Wir werden sehen, ein BeispielDiesimein späteres KapitelAuch wenn wir untersuchen,wie haben mehr als eine Seite der ViewPagersichtbar aneine Zeit.

Indikatoren

An sich gibt eskeine visuellen Indikator, wo der Benutzer innerhalb des Satzes von Seiten in der ViewPager enthalten. In vielen Fällen wird dies perfekt sein fi
wie die Seiten werden sich

Hinweise wie auf Position enthalten. Aber auch in diesen Fällen kann es nicht völlig klar sein, an den Benutzer, wie viele Seiten sind, welche Richtungen für swiping aktiv sind, usw.

Daher möchten Sie vielleicht einige andere Widget zu befestigendie ViewPager, die Ahnung, den Benutzer in, wo sie sind in "Seitenraum" helfen kann.

PagerTitleStrip und PagerTabStrip

Die primären integrierte Anzeige-Optionen zur Verfügung stehen zu
nutzenPagerTitleStripundPagerTabStrip. Wie der Name schon sagt,PagerTitleStripistein Streifen, der Titel Ihrer Seiten zeigt.PagerTabStripist vieldie gleichen, aber die Titel etwas wie Tabs formatiert, und sie sind anklickbar (Sie auf den geklickten auf Seite umschalten), währendPagerTitleStripist nicht interaktiv.

Benutzenentweder von diesen, Sie fi
sollenfügen Sie es zu Ihrem Layout, in IhremViewPager,

Wie in der gezeigtenres / Layout / main.xmlRessource vondasViewPager /

AnzeigeBeispielprojekt,ein Klon desViewPager / FragmenteProjektfügt hinzu, dass
einePagerTabStripauf unsere UI:

(von

ViewPager / Anzeige / app / src / main /
res / Layout / main.xml)

Hier setzen wirdasandroid: layout_gravityvondasPagerTabStripnachoben, So scheint es,über die Seiten. Sie könnten setzen esähnlichBodenhaben es unten angezeigtdie Seiten.

UnserSampleAdaptermuss eine andere Methode:getPageTitle (), Die den Titel in der wird wieder angezeigtPagerTabStripfüreine bestimmte Position:

(von

ViewPager / Anzeige / app / src / main / java / com / commonsware /
android / pager2 / SampleAdapter.java)

Hier nennen wireine statische getTitle () -Methode auf EditorFragment. Das ist ein Überarbeitete Stück Code aus unserer früheren onCreateView () -Methode, wo wir die Zeichenfolge für den Hinweis erstellen - wir den Hinweistext als unsere Seitentitel verwenden:

(von

ViewPager / Anzeige / app / src / main / java / com / commonsware /
android / pager2 / EditorFragment.java)

Andere Indicator Optionen

Es gibt viele andere Optionen für die Registerkarte Stil Indikatoren mitein ViewPager.

TabLayout ist die einzige andere offiziell von Google unterstützt. Es kommt vondas Design Support-Bibliothek, welches inwiederum erfordert appcompat-v7.

die meistendie Optionen sind Open-Source-Bibliotheken. Das Kapitel über die Design Support Bibliothek demonstrierteine solche Drittanbieter-Bibliothek, Die Android-ArsenalsListe von ViewPagerAdd-onsmeist von Indikatoren besteht, sowohldiejenigen, formatiert wie Tabs und diejenigen, die andere Ansätze verwenden.

NeubetrachtungDie Behälter Sampler

Zuvordas Buch, sahen wir viele verschiedene Layout-Ressourcen aus der beiContainer /

SamplerBeispielprojekt. Diese waren zu veranschaulichen, wie verschiedene Layout-Strukturen arbeiten. Die gesamte Benutzeroberfläche ist verpackt inein ViewPager mit einem PagerTabStrip.

Allerdings setzen wir die FragmentPagerAdapter und die Fragmente nach oben auf der Grundlage einer Liste von verfügbaren Musterlayouts, getrieben von Ressourcen.

Das Layout

Das Layoutdas ist für die verwendeteViewPagerundPagerTabStripist weitgehenddas gleiche wie das, was wir früher in diesem Kapitel gesehen haben:

(from

Container / Sampler / app / src / main /
res / Layout / main.xml)

Also haben wireinViewPagergenanntFunkrufempfänger, mit einemPagerTabStripverankert andie obenüberAndroid: layout_gravity = "top".

Die Daten

Die Daten über das, was Layouts zu zeigen,Registerkarten in einem Paar von Array-Ressourcen enthalten sind. Array-Ressourcen, wie der Name schon sagt, sind Ressourcen, die auf eine halten Sammlung von Gegenständen. Die Konvention ist,dass sie gehen inres / Werte / arrays.xml, Obwohl die tatsächliche fi
ist nicht erforderlich sein,arrays.xml.

Die Beispielanwendung hateinres / Werte / arrays.xmlfi
mit zwei Array-

Ressourcen:ein<String-array>genanntTitelund ein generisches<Array>genanntLayouts:

(von

Container / Sampler / app / src / main / res

/ Werte / arrays.xml)

Wieder Name schon sagt, ein <string-array> hält Strings. Hier hält es Literalzeichenfolgen.

Alternativ mit denen könnte Verweise auf String-Ressourcen sein, die gleiche

@string / ... Namenskonvention, die wir an anderer Stelle im Buch gesehen.

DasLayouts Array enthält Verweise auf die entsprechenden Layout-Ressourcen, mit

@Layout/...Syntaxidentifizieren, diese Ressourcen.

Diese beiden Arrays eingerichtet sind indie gleiche Reihenfolge, so dass die fi

Titel
für den fi-Layout verwendet wird, wird der zweite Titel für das zweite Layout verwendet wird, und so weiter.

Das Fragment

Das Fragment fürdie Seiten in der ViewPager ist eine statische verschachtelte Klasse innerhalb der MainActivity, genannt LayoutFragment. Dies ist untypisch; in der Regel ein Fragment in einem eigenen Java-Klasse sein. Das ist, weil in der Regel ein Fragment viel Code zugeordnet hat. In diesem Fall ist LayoutFragment eher kurz:

(von

Container / Sampler / app / src / main / java / com / commonsware / android /

Container / Sampler / MainActivity.java)

Wenn wir eine Instanz vonLayoutFragment durch die newInstance () Factory-Methode,übergeben wir in einem Layout-Ressourcen-ID. Durch die Argumente Bundle, das wird zu unserem onCreateView () -Methode zur Verfügung, die einfach, dass das Layout aufbläst und gibt es zurück.

Das Fragment ist so kurz, weil wiretwas zu tun, nicht mit den Widgets innerhalb des aufgeblasenen Layout, wie fi
sie mit Daten oder Ereignis-Listener einrichten.

Die Aktivität

DasHauptaktivitätdas beinhaltetLayoutFragmenthat nur eine eigene Methode:onCreate (), Die bläht sich derres / Layout / main.xmlRessource oben gezeigt, fidasViewPagerUnd setzt seinen Adapter eine seinSampleAdapter:

(von

Container / Sampler / app / src / main / java / com / commonsware / android /

Container / Sampler / MainActivity.java)

Mit anderen Worten,diese onCreate () ist so ziemlich das gleiche wie die anderen in diesem Kapitel gesehen. Wo der Spaß liegt in dieser Beispielanwendung Ausgabe von SampleAdapter.

Die PagerAdapter

SampleAdapter verwendet den Inhalt dieser beiden Array-Ressourcen, um zu bestimmen, wie viele Seiten es gibt, was in den Registerkarten zu zeigen, und welche ID-Layout-Ressource auf dem LayoutFragment weitergeben müssen:

(von

Container / Sampler / app / src / main / java / com / commonsware / android /

Container / Sampler / MainActivity.java)

SampleAdapterhält sich aneinSchnurAnordnung vondie Titel. Dies wird bevölkert
von(GetResources). GetStringArray ()imdasSampleAdapterKonstruktor, der in liest dasTitel <string-array>Ressource. Diese Saiten sinddann verwendet, für diegetPageTitle ()Verfahren, unddie Länge derStreicherArray wird verwendet fürgetCount ().

Bekommendieäquivalente Array derintWerte fürdie Layout-Ressourcen-IDs ist umständlicher. Wir könnten versuchen, rufengetIntArray ()aufdasRessourcenObjekt zurückgegeben durchGetResources (). Aber das funktioniert nur für<Int-Array>Ressourcen. Wir können nicht zu verwendenjene inres /

Werte / arrays.xmlweil Android hält

@Layout/...seineine Ressourcen-ID, nicht nur eine einfache ganze Zahl ist.

Arbeiten mitein generisches<Array>Ressource, wiranrufen müssenobtainTypedArray ()aufdasRessourcenObjekt, das wir tun, indasgetLayoutsArray ()Helfer-Methode. Diese ErträgeeinTypedArray, Die effektiv ist ein Array von beliebigen Ressourcentypen. Wir wissen, dass unser Angebot alle Layout Ressourcen-IDs sein sollte, so ordnen wir einintArray unser Ergebnis zu sein (basierend aufdasLänge()vondasTypedArray),dann durchlaufen alle Einträge über und die Ressourcen-ID für diese Position im Array abgerufen werden (unter Verwendung vongetResourceId ()). Imdas Ende,Ergebnishat eine Reihe von Ressourcen-IDs, unddiejenigen erhalten, die vongetItem ()versorgenLayoutFragmentmitdas entsprechende Layout Ressourcen-ID
für diese Position der Seite.

Besuchdie Spuren!

Es gibtein Kapitel über die erweiterte ViewPagerTechnikendass Sie interessieren könnten!

Tutorial # 10- Aufriggen ein ViewPager

Ein ViewPager ist eine ziemlich glatte Art und Weise ein digitales Buch zu präsentieren. Sie können einzelne haben Teile des Buches durch horizontale swiping zugegriffen werden kann, mit dem Prosa innerhalb eines Abschnitts durch Scrollen vertikal abgerufen. Während nicht von einem Book-Reader-Software "Seite-at-a-time" Modelle anbieten, ist es viel einfacher einzurichten.

So das istder Ansatz, den wir mit EmPubLite verwenden. Das bedeutet unter anderem, dass wir eine ViewPager zur App hinzufügen müssen.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository des Buches.

Schritt 1: Fügenein ViewPager in den Layout

Jetzt sofort,dasMainLayout verwendet vonEmPubLiteActivitynur hateinTextview. Wir müssen dasändern müssen unsereViewPager.

Schon seitViewPager ist nicht verfügbar für Drag-and-Dropüber die IDE-grafischen Layout-Editoren, auch IDE-Benutzer werden dieses Mal in das Layout XML zu haben, zu tauchen.

erschließenres / Layout / main.xml und wechseln Sie in das Textunterregister der XML-Rohdaten zu sehen. Ersetzen Sie den Inhalt mit:

(von

EmPubLite-Android Studio / T10-ViewPager / EmPubLite / app

/ src / main / res / Layout / main.xml)

Dies ergänzt unsere ViewPager, Darunter einMaterialTabsIm Inneren einesvertikale Linearlayout.MaterialTabsist eine ImplementierungRegisterkarten für eineViewPager, Eine, die wir näher erkundenspäter imdas Buch.

Schritt 2: Erstellenein ContentsAdapter

EINViewPagerbraucht einPagerAdapteraufzufüllen seinen Inhalt,ähnlicheinListenansichtbraucht einListAdapter. Wir können nicht vollständig konstruieren einPagerAdapterdoch, wie wir nochmüssen lernen, wie unser Buch Inhalte von fi zu laden

. Aber wir können Part- Weg
hin zu einer nützlichen, diePagerAdapterjetzt.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeContentsAdapterwieden Namen und klicken Sie auf OK die leere Klasse zu erstellen.

Dann ersetzendie erzeugteContentsAdapter.javafi
mit die folgenden Inhalt:

(von

EmPubLite-Android Studio / T10-ViewPager / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt 3: Einrichtendie ViewPager

Jetzt wirbenötigen einen Code hinzufügen, um die ViewPager abzurufen, füllen Sie es mit der ContentsAdapterUnd mit diesen Registerkarten etwas Nützliches tun.

Fügen Sie zunächst zwei fi
nachEmPubLiteActivity:

(von

EmPubLite-Android Studio / T10-ViewPager / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Dies erfordert das Hinzufügeneineinführenfürandroid.support.v4.view.ViewPager. Dann fügen Sie ein paar Zeilen auf den GrundonCreate ()vonEmPubLiteActivity:

(von

EmPubLite-Android Studio / T10-ViewPager / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Dies erfordert eineinführenErklärung fürio.karim.MaterialTabs. Was wir tun, ist:

• Abrufen unsererViewPager, hielt sich an sie in ihrer fi

• Erstellen Sie eine Instanzdie do-nothingContentsAdapter.

• assoziierendasContentsAdaptermitdasViewPager.

• AbrufendasMaterialTabs, und

• Anbringendie Laschen an dieViewPager

Beimdieser Punkt, IhreEmPubLiteActivityaussehen sollte etwas wie:

(von

EmPubLite-Android Studio / T10-ViewPager / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

DasNetto-Effekt, wenn Sie diese modifizierte Version der Anwendung ausführen, ist, dass wir eine große leere Fläche haben, durch unsere leeren ViewPager aufgenommen:

DasViewPageristleer, nur weil unsereContentsAdapterist zurückgekommen0von
getCount (), was darauf hinweist, dass keine Seiten angezeigt werden.

In unserer nächsten Folge ...

… wir werdenfi
unser "Hilfe" und "über" Bildschirme in unserem Tutorial-Projekt.

Ressourcen Sets und Konfigurationen

Geräte manchmal ändern, während die Benutzer verwendensie, in einer Weise, die unsere Anwendung kümmern uns um:

• Der Benutzer kann sich drehender Bildschirm von Hoch- auf Querformat oder umgekehrt

• Der Benutzer könnte setzendas Gerät in einem Auto oder Schreibtisch-Dock, oder es aus einem solchen Dock entfernen

• Der Benutzer könnte setzendie Vorrichtung in einem "Netbook-Dock", die eine vollständige QWERTY-Tastatur fügt hinzu, oder es aus einem solchen Dock entfernen

• Der Benutzer kann wechselneine andere Sprache über die Anwendungseinstellungen, Rückkehr danach zu unserer laufenden Anwendung

• Und so weiter

In allendiesen Fällen ist es wahrscheinlich, dass wir, welche Ressourcen, die wir nutzen wollen zu ändern. Zum Beispiel unser Layout für ein Porträt Bildschirm kann zu hoch sein, im Querformat zu verwenden, so würden wir in einem anderen Layout ersetzen wollen.

In diesem Kapitel wird untersucht, wie alternative Mittel zu erhalten,diese verschiedenen Szenarien -

"Konfigurationsänderungen" genannt - und erklärt, was unsere Aktivitäten geschieht, wenn der Benutzer die Konfiguration ändert, während wir im Vordergrund stehen.

Was isteine Konfiguration? Und wie sie sich ändern?

Verschiedene Stücke von Android Hardware kann verschiedene Funktionen haben, wie zum Beispiel:

• Verschiedene Bildschirmgrößen

• Verschiedene Rasterdichten (dots per inch)

• AndersAnzahl und Fähigkeiten der Kameras

• Verschiedene Mischung aus Radios (GSM? CDMA? GPS? Bluetooth? WiFi?

NFC? Etwassonst?)

• Und so weiter

Einigediese, in den Augen des Core-Android-Team, könnte die Auswahl von Ressourcen, wie Layouts oder Drawables fahren. Verschiedene Bildschirmgrößen könnten die Wahl des Layouts fahren. Verschiedene Rasterdichten könnte die Wahl der ziehbar (unter Verwendung eines höher-auflösendes Bild auf einer höheren Dichte Gerät) fahren. Diese werden als Teil des Geräts

"Konfiguration".

Weitere Unterschiede- Diejenigen, die die Auswahl von Ressourcen nicht fahren - sind nicht Teil der Konfiguration des Gerätes, sondern nur sind "Features", die einige Geräte und andere Geräte nicht.

Zum Beispiel, Kameras und Bluetooth und WiFi sind Funktionen.

Einige Teileeine Konfiguration nur auf unterschiedlichen Geräten variieren. Ein Bildschirm wird nicht Dichte im laufenden Betrieb ändern, zum Beispiel. Aber einige Teile einer Konfiguration kann während des Betriebs der Vorrichtung, beispielsweise Ausrichtung (Hochformat oder Querformat) oder Sprache geändert werden. Wenn eine Konfiguration auf etwas anderes wechselt, das ist ein

"Konfigurationsänderung" und Android bietet spezielle Unterstützung für solche Ereignisse Entwicklern zu helfen, stellen ihre Anwendungen die neue Konfiguration anzupassen.

Konfigurationen und Ressourcen Sets

Ein Satz von Ressourcen kannnicht in allen Situationen fi wo Ihre Anwendung verwendet werden können. Eine nahe liegende Bereich kommt mit String-Ressourcen und den Umgang mit der Internationalisierung (I18N) und Lokalisierung (L10N). alle Fäden in einer Sprache Putting arbeitet fi

- Wahrscheinlich zumindest für den Entwickler - aber deckt nur eine Sprache.

Das istnicht das einzige Szenario, in dem Ressourcen, obwohl zu unterscheiden brauchen könnte.

Hier sind andere:

1. Bildschirmausrichtung: istder Bildschirm in einem Hochformat? Landschaft?

2. Bildschirmgröße: istdies etwas bemessen wie ein Handy? Ein Tablett? Ein Fernseher?

3. Bildschirm Dichte: Wie viele Punkte pro Zoll tutder Bildschirm haben? Werden wir brauchen eine höher auflösende Ausgabe unseres Symbol, damit es nicht zu klein erscheint?

4. Tastatur: Welche Tastatur tuthat der Benutzer (QWERTY, numerisch, weder), entweder jetzt oder als Option?

5. Andere Eingabe: tutLassen Sie das Gerät eine andere Form der Eingabe, wie ein Steuerkreuz oder Click-Rad?

Die Art und Weise Android verarbeitet derzeitdies ist durch mehrere Ressourcen-Verzeichnisse, die mit den Kriterien für die jeweils in ihren Namen eingebettet.

Nehmen wir zum Beispiel, wollen Sie Zeichenfolgen in Englisch und Spanisch unterstützen.

Normalerweise fürein Single-Sprache-Setup, würden Sie Ihre Strings in einem fi setzen genannt res / Werte / strings.xml. Um sowohl Englisch als auch Spanisch unterstützen könnten Sie zwei Ordner, res / Werte-en / und res / Werte-es /, wobei der Wert nach dem Bindestrich ist dieISO

639-1Zwei-Buchstaben-Code fürdie gewünschte Sprache. Ihre englischsprachigen Strings in res /

Werte-en / strings.xml und die spanischen diejenigen in res / Werte-es / strings.xml gehen würde.

Android wird die richtige fi wählen
basierend auf Die Geräteeinstellungen des Benutzers.

Beachten Sie, dass Android 5.0 Unterstützung fürBCP 47 Drei-Buchstaben Sprache und locale Werte, obwohldiese erfordern auch Gradle für Android 1.1.0 (oder höher) und Android Studio 1.1.0 (oder höher).

Aber,der bessere Ansatz ist für Sie einige Sprache, um Ihre standardmäßig zu betrachten und diese Zeichenfolgen in res / Werte / strings.xml setzen. Erstellen Sie dann andere Ressourcen-Verzeichnisse für Ihre Übersetzungen (zB res / Werte-es / strings.xml für Spanisch). Android wird versuchen, eine spezifi Sprache Satz von Ressourcen zu entsprechen; falls dies nicht möglich, wird es wieder auf die Standardeinstellung von res / Werte / strings.xml fallen. Auf diese Weise, wenn Ihre Anwendung auf einem Gerät mit einer Sprache, windet sich, dass Sie nicht erwarten, Sie zumindest servieren Strings in der gewählten Standardsprache. Andernfalls, wenn es keine solche Verzug ist, wickeln Sie mit einem ResourceNotFoundException auf, und Ihre Anwendung zum Absturz bringen.

Dies ist deshalbdas Fundament Ressourcenset Strategie: einen vollständigen Satz von Ressourcen im Standardverzeichnis haben (zB res / Layout /), und diese Ressourcen in anderen Ressourcengruppen gebunden außer Kraft setzen Konfigurationen nach Bedarf (zB res / Layout-Land /) zu spezifi.

Hinweisdass Android Studio hat einÜbersetzungen Editorum Ihren String-Ressourcen für Ihre Standardsprache zu verwalten und zu was auch immer Übersetzungen, die Sie in Ihrer Anwendung gehen aufzunehmen.

Bildschirmgröße und Ausrichtung

VielleichtDie wichtigste Ressource Set-Qualifikation, die wir sind die, die auf Bildschirmgröße und Orientierung im Zusammenhang mit noch nicht gesehen haben. Hier "Orientierung" bezieht sich auf, wie das Gerät gehalten wird: Hoch- oder Querformat.

Die Orientierung ist ziemlich einfach, da kann man einfach nutzen-Port oder -land als Ressource-Qualifikation gesetzt Ressourcen in einem Verzeichnis zu einer spezifi Orientierung zu beschränken.

Die Konvention ist Landschaft Ressourcen in einem -land Verzeichnis (zB res / Layout-Land /) zu setzen und zu setzen

Portrait Ressource indas Standardverzeichnis (zB res / Layout /). Dies ist jedoch nur eine Konvention, und Sie sind willkommen zu verwenden -Port, wenn Sie es vorziehen.

Die Bildschirmgröße istein bisschen komplizierter, weil die zur Verfügung stehenden Ansätze im Laufe der Jahre verändert haben.

Die Original: Android-Defined Schaufeln

Weg zurück inder Anfang, mit Android 1.0 wurden alle Bildschirmgrößen gleich ... vor allem, weil es nur eine Bildschirmgröße, und dass vor allem war da nur ein Gerät war.

aber Android 1.5 eingeführt, drei Bildschirmgrößen und zugehörige Ressource gesetzt Qualifikation mitein viertes (-xlarge) später hinzugefügt:

• -klein für Bildschirme an oder unter 3 "in Diagonale

• -Normal für Bildschirme zwischen 3 "und 5" in Diagonale

• -Große für Bildschirme zwischen 5 "und 10" Bilddiagonale

• -xlarge für Bildschirme oder über 10 "Bilddiagonale

Wie wir sehen werden,diese Ressource gesetzt Qualifikations untere Schranken für etablieren, wenn der Wert eines Verzeichnisses von Ressourcen verwendet werden. So ein res / Layout-normal /

Verzeichnis wird nicht für -small Bildschirme verwendet werden, sondern würde für -normale verwendet werden, -große und -xlarge Bildschirme.

DasModern: Entwickler-Defined Schaufeln

Das Problem mitdie klassische Größe Eimer ist, dass sie ziemlich unflexibel waren. Was ist, wenn Sie denken, dass so genannte "phablets", wie das Samsung Galaxy Note-Serie, sollte mehr haben Layouts wie Telefone, während größere Tabletten, wie die 8,9 "Kindle Fire HD sollte Layouts haben mehr wie 10" Tabletten? Das war nicht möglich, die fi zierten Eimer gegeben.

Android 3.2 hat uns mehr Kontrolle. Wir können unsere eigenen Eimer für Bildschirmgröße haben, unter Verwendung vondie etwas verwirrende -swNNNdp Ressourcenset Qualifier. Hier wird die NNN, indem Sie mit einem Wert ersetzt, in dp gemessen, für die kleinste Breite des Bildschirms.

"Kleinste Breite" bedeutet im Wesentlichen die Breite des Bildschirms, wenn das Gerät im Hochformat gehalten wird. Daher, anstatt basierend auf Bildschirmdiagonale Messung, wie mit den klassischen Eimer, werden Ihre benutzerdefinierten Eimer auf der Basis der linearen Bildschirmgröße des kürzesten Bildschirmseite.

Beispiel: Angenommen,dass Sie wünschen eine Trennlinie zwischen den Ressourcen zu prüfen, an der 7 zu sein "Punkt - 7" und kleinere Geräte würde eine Reihe von Layouts erhalten, während größere Geräte einen anderen Satz von Layouts erhalten würde. 7 "Tabletten haben in der Regel eine kleinste Breite von etwa 3,5" bis 3,75 ", gegeben gemeinsamen Seitenverhältnisse. Seit dem 1. dp 1

/ 160th von einem Zoll ist, gleichzusetzen jene kleinsten Breiten 560-600 dp. Daher könnten Sie eine -sw600dp Ressource-Set für Ihre größeren Layouts und stellen die kleineren Layouts in einem Standard-Ressource-Set einzurichten.

Mashups: Breite und Höhe Schaufeln

Mit-swNNNdp nicht Ausrichtung ansprechen, als die kleinste Breite gleich ist, unabhängig davon, ob das Gerät im Hoch- oder Querformat gehalten wird. Daher müssten Sie -swNNNdp-Ressource Boden gesetzt für die Landschafts Ressourcen für den gewünschten Trennlinie hinzuzufügen.

Eine Alternative ist die Verwendung-wNNNdpoder-hNNNdp. Diese Ressource gesetzt Qualifikations funktionierenähnlich wie-swNNNdp, Vor allem in Hinblick darauf, wasNNNMittel. Während jedoch-swNNNdpbezieht sich aufdie kleinste Breite,-wNNNdpbezieht sichdie aktuelle Breite und-hNNNdpbezieht sich aufdie aktuelle Höhe. Daherändern sich diese mit Orientierungsänderungen.

Über diese API-Ebene

-swNNNdp, -wNNNdp und -hNNNdp wurden in API-Ebene hinzugefügt 13. Daherältere Geräte werden alle Ressourcengruppen mit diesen Qualifier ignorieren.

Allgemein gesagt,dies könnte wie ein großes Problem scheinen, für die Entwickler noch ältere Geräte unterstützen.

In der Praxis ist es weniger ein Problemals Sie die überwiegende Mehrheit der älteren Geräten erwarten könnte, einfach weil waren Telefone, keine Tabletten. Die einzigen Android 2.x Tabletten, die in jeder signifi Menge verkauft wurden drei 7 "Modelle:

• die ursprüngliche Kindle Fire

• das Original Barnes & Noble NOOK-Serie

• die ursprüngliche Samsung Galaxy Tab

Vondiejenigen, nur das Galaxy Tab hatte die damals Android Market (jetzt Play Store). wenn Sie also über den Play Store zu verteilen, können Sie in der Lage sein, einfach Pre-API Stufe 13

Tabletten ignorieren. Verwenden Sie -swNNNdp auf Ihre Trennlinie für größere Geräte zu erstellen, und das Galaxy Tab wird einfach die Layouts für Ihre kleineren Geräte verwenden.

Obdies betrifft Sie, oder Sie sind auch das Feuer anzündet und frühen Nooks unterstützen, können Sie das Layout-Aliase verwenden können Code-Duplizierung zu minimieren. Angenommen, dass Sie eine res / Layout / main.xml haben Sie verschiedene Versionen für Smartphones und Tablets, und die Sie verwenden möchten -swNNNdp für Ihre Trennlinie, wo die Tablette Layouts gewöhnen, aber Sie auch haben wollte wollen die älteren Tabletten zu haben, wie das Galaxy Tab, verwenden Sie das folgende Rezept:

• Setzen Sie Ihren Tablet-Größe Layoutsres / Layout /, Jedoch mit
unterschiedlichen fi (zBres / Layout / main_to_be_used_for_tablets.xml)

• Imres / Werte-swNNNdp / layouts.xml, Für den gewünschten WertNNNsetzen, Aliase (via<Item>Elemente) für die ursprünglichen Namen (über dieNameAttribut), der aufdie Ressourcen wollen Sie verwenden-swNNNdpGeräte:

• Imres / Werte-large / layouts.xmlsetzen, die gleichen Aliase

Nun, beide ältere und neuere Geräte, wenn Referenzierungdie gleiche Ressourcenname wird gerouteten an die richtigen Layouts für ihre Bildschirmgröße erhalten.

Der Umgang mit Komplexität

WoherDinge beginnen, ist wenig komplizierter, wenn Sie mehrere unterschiedliche Kriterien für Ihre Ressourcen verwenden müssen.

Beispiel: Angenommen,dass Sie drawable Ressourcen, die locale-abhängig, wie ein Stoppschild sind. Vielleicht möchten Sie die Ressourcengruppen von Drawables an Sprache gebunden zu haben, so können Sie für verschiedene Schauplätze in verschiedenen Bildern ersetzen. wollen jedoch könnten Sie auch diese Bilder ändern sich je nach Dichte, auf höherer Dichte Geräte mit höherer Auflösung Bilder verwenden, so dass alle die Bilder um die gleiche physikalische Größe kommen.

Tundass, würden Sie Verzeichnisse mit mehreren Ressourcenset Qualifier aufzuwickeln, wie zum Beispiel:

• res / ziehbar-LDPI /

• res / ziehbar-MDPI /

• res / ziehbar-hdpi /

• res / ziehbar-xhdpi /

• res / ziehbar-en-RUK-LDPI /

• res / ziehbar-en-RUK-MDPI /

• res / ziehbar-en-RUK-hdpi /

• res / ziehbar-en-RUK-xhdpi /

• Und so weiter

(mitdie Standardsprache Wesen, sagen, US-Englisch, ein US-Stoppschild mit)

Sobald Sie inobwohl diese Art von Situationen, ein paar Regeln ins Spiel kommen, wie zum Beispiel:

1. Die Konfigurationsoptionen (zB-en) haben eine besondere Rangordnung, und sie müssen in dieser Reihenfolge im Verzeichnisnamen erscheinen. Dasandroide Dokumentation

Umrissedie spezifi Reihenfolge, in der diese Optionen angezeigt werden können. Für die Zwecke dieses Beispiels ist Bildschirmgröße wichtiger als Bildschirmausrichtung, die als Rasterdichte wichtiger ist, die als wichtiger ist, ob das Gerät eine Tastatur enthält.

2. Es kann nur einen Wert vonjede Konfigurationsoption Kategorie pro Verzeichnis.

3. Die Optionen sind Groß- und Kleinschreibung

Zum Beispiel könnten Sie verschiedene Layouts auf Bildschirmgröße und Ausrichtung zu haben. Da Bildschirmgröße ist wichtigerals Orientierung in der Ressource-System würde die Bildschirmgröße der Orientierung, im Verzeichnisnamen erscheinen vor wie zum Beispiel:

• res / Layout-sw600dp-Land /

• res / Layout-sw600dp /

• res / Layout-Land /

• res / Layout /

Die Wahl der richtigen Ressourcen

Gegebendass Sie N verschiedene Definitionen einer Ressource haben kann, wie funktioniert Android wählen die man zu verwenden?

Zuerst wirft Android aus Einsen, die speziell für ungültig. So zum Beispiel, wenn die Sprache des Gerätes -ru ist, wird Android Ressourcengruppen ignorieren, die anderen Sprachen angeben (zB

-ZH). Die Ausnahmen sind Dichte-Qualifikation und Bildschirmgröße Qualifier - wir später auf diese Ausnahmen erhalten.

Dann Android wähltdie Ressourcengruppe, die die gewünschte Ressource und hat die wichtigsten deutliche Qualifier. Hier von "wichtigsten", dann meinen wir das, das im Verzeichnisnamen am weitesten links angezeigt wird, basierend auf den Verzeichnisnamensregelndiskutiert above. Und von

"distinct" meinen wir, wenn keine andere Ressource Satz, dass die Qualifier hat.

Wenn da istkeine spezifi Ressource-Set, das passt, wählt Android den Standardsatz - die man ohne Suffixe auf den Verzeichnisnamen (zB res / Layout /).

Mitdiese Regeln beachten, lassen Sie uns in einigen Szenarien aussehen, die Basisfall und die oben genannten Ausnahmen zu decken.

Szenario # 1: Etwas Einfaches

Nehmen wir an,dass wir einmain.xmlfi
im:

• res / Layout-Land /

• res / Layout /

Wenn wir rufensetContentView (R.layout.main)Android, wählt diemain.xmlimres / Layout-Land

/obdas Gerät im Querformat. Das Set bestimmte Ressource ist in diesem Fall gültig, und es hat die wichtigsten deutliche Qualifier (-Land). Wenn das Gerät im Hochformat ist, obwohl dieres / Layout-Land /Ressourcengruppe tutnicht qualifizieren, und so ist es heraus geworfen. Das lässt uns mitres /

Layout /, So Android verwendet, dassmain.xmlVersion.

Szenario 2: Ungleiche Ressourcen Set Kategorien

Es ist möglich, wenn auch bizarr, für Sie habenein Projekt mit main.xml in:

• res / Layout-en /

• res / Layout-Land /

• res / Layout /

Imdiesem Fall, wenn das Gebietsschema des Geräts eingestellt ist Englisch zu sein, Android wird res

/ Layout-en /, unabhängig von der Ausrichtung des Geräts wählen. Das liegt daran, -en eine wichtige Ressource ist gesetzt, Qualifier - "Sprache und Region" erscheint höher in der "Tabelle 2.

Konfiguration Qualifier Namen" aus dem Android-Dokumentation, als dies "Bildschirmausrichtung"

(für -land). Wenn das Gerät für Englisch nicht gesetzt, obwohl, Android, dass die Ressourcengruppe heraus werfen, an welcher Stelle der Entscheidungsprozess der gleiche wie in Szenario 1 oben ist.

Szenario 3:Multiple-Qualifikation

Lassen Sie uns jetzt vorstellenein Projekt mit main.xml in:

• res / Layout-en /

• res / Layout-land-v11 /

• res / Layout /

Das könnte dirdenken, dass res / Layout-land-v11 / würde die Wahl, wie es ist mehr spezifi

Matching auf zwei Ressourcensatz-Qualifikation gegendie eine oder keine von den
anderen Ressourcengruppen.

(eigentlich,Der Autor dieses Buches gedacht war dies die erste Wahl für viele Jahre) ImIm vorliegenden Fall ist jedoch die Sprache wichtiger als jeder Bildschirmausrichtung oder Android API-Ebene, so dass der Entscheidungsprozess ist ähnlich dem Szenario # 2 oben: Android wähltres / Layout-en /für englischsprachige Geräte,res / Layout-land-v11 /für Landschaft API-Level 11+ Geräte oderres / Layout /für allessonst.

Szenario 4:Multiple-Qualifikation, Revisited

Lassen Sie uns änderndie Ressource-Mix, so jetzt haben wir ein Projekt mit main.xml in:

• res / Layout-land-Nacht /

• res / Layout-land-v11 /

• res / Layout /

Hier, während-Land ist die wichtigste Ressource Set-Qualifikationsspiel ist es nicht unterscheidbar -

Wir haben mehr als eine Ressource mit -land gesetzt. Daher müssen wir prüfen, welche ist die nächste wichtigste Ressource Set-Qualifikationsspiel. In diesem Fall, das heißt -night, als Nachtmodus eine wichtige Kategorie ist als ist Android API-Ebene, und so wird Android res / Layout-land-Nacht wählen /, wenn das Gerät im Nachtbetrieb ist. Ansonsten wird es res / Layout-land-v11 wählen / wenn das Gerät 11 API-Ebene oder höher ausgeführt. Wenn das Gerät nicht in den Nachtmodus ist und nicht API Stufe 11 oder höher ausgeführt wird Android mit res / Layout / go.

Szenario # 5: Rasterdichte

Nun, schauen wir uns andie fi

Ausnahme nach die Regeln: Rasterdichte.

Android wird immer akzeptiereneine Ressourcengruppe, die eine Rasterdichte enthält, auch wenn es nicht um die Dichte des Geräts übereinstimmt. Wenn es eine genaue Übereinstimmung Dichte ist natürlich verwendet Android es. Ansonsten wird es, was es fühlt sich an die nächstbeste Spiel, basierend auf verwenden, wie weit es tatsächliche Dichte des von der Vorrichtung ist und ob die andere Dichte höher oder niedriger als die tatsächliche Dichte des Geräts.

Der Grund fürhierfür ist, dass für drawable Ressourcen, Android wird das Bild automatisch neu berechnen oder Upsampling, so dass die ziehbar erscheint die richtige Größe zu sein, auch wenn Sie ein Bild in dieser spezifi Dichte nicht vorsah.

Der Haken ist zweifach:

1. Android giltdiese Logik auf alle Ressourcen, nicht nur Drawables, also auch wenn es keine Übereinstimmung genaue Dichte auf, sagen wir, ein Layout, Android wird immer noch eine Ressource von einer anderen Dichte Eimer für das Layout wählen

2. Wieein Nebeneffekt der vorherigen Punkt, wenn Sie mit einer Dichte Ressource gesetzt Qualifier enthalten, werden Android ignorieren jede mit niedrigerer Priorität Ressource-Qualifikation gesetzt (es sei denn, es mehrere Verzeichnisse mit der gleichen Dichte Ressource festgelegt, Qualifier sind, wobei in diesem Fall die mit niedrigerer Priorität Qualifikations dienen als "Tie-Break")

So, jetzt lassen Sie uns so tun,dass unser Projekt hat main.xml in:

• res / Layout-MDPI /

• res / Layout-nonav /

• res / Layout /

Android wird wählenres / Layout-MDPI /, auch für -hdpi Geräte, die nicht über eine "non-Touch-Navigation-Methode" haben. Während -mdpi -hdpi nicht übereinstimmt, wählen Android wird noch -mdpi. Wenn wir mit Drawables Ressourcen zu tun hatten, würde Android das -mdpi Bild Upsampling.

Szenario # 6: Bildschirmgrößen

Wenn Sie die Ressourcengruppengebunden an Bildschirmgröße, wird Android das wählen, das am nächsten an der tatsächlichen Bildschirmgröße noch kleiner als die tatsächliche Bildschirmgröße ist.

Ressourcensätze für Bildschirmgrößen größer als die tatsächliche Bildschirmgröße werden ignoriert.

Dies funktioniert für-swNNNdp.-wNNNdp, und-hNNNdpfür alle Geräte. Auf-großeoder-xlarge Geräte, Android giltdie gleiche Logik für die klassischen Bildschirmgröße Qualifier (-small,

-normal.-große.-xlarge). Allerdings ist Android nicht anwendbarDiese Logik für-kleinoder

-normalGeräte- ein-normalGerät wirdkeine Last,-kleinRessource.

Lassen Sie uns jetzt so tun,dass unser Projekt hat main.xml in:

• res / Layout-normal /

• res / Layout-Land /

• res / Layout /

Android wird wählenres / Layout-normal /obdas Gerät ist nicht-klein. Andernfalls wird Android wählenres / Layout-Land /obdas Gerät ist die Landschaft. Wenn alles andere fehlschlägt, wird Android wählenres / Layout /.

Und falls wir haben:

• res / Layout-w320dp /

• res / Layout-Land /

• res / Layout /

Android wird wählenres / Layout-w320dp /für Geräte, deren Bildschirmbreite ist 320dp oder höher.

Andernfalls wird Android wählenres / Layout-Land /obdas Gerät ist die Landschaft. Wenn alles andere fehlschlägt, wird Android wählenres / Layout /.

API-Versionierte Ressourcen

Wie zuvor erwähnt inIn diesem Kapitel zeigen die -vNNN Satz von Suffixen, dass die Ressourcen in diesem Verzeichnis für den genannten API-Ebene oder höher. So zum Beispiel res / Werte-v21 / zeigt an, dass die Ressourcen in diesem Verzeichnis nur auf API-Ebene 21 (Android 5.0) und höher verwendet werden. Geräte ältere Versionen von Android laufen wird, diese Ressourcen zu ignorieren.

Das istEine besonders wichtige Gruppe von Suffixen für mit großen Android-Version Änderungen zu tun haben. Das Look and Feel einer Aktie Android App deutlich verändert auf API-Ebene 11

(Android 3.0) und API Stufe 21 (Android 5.0). Sie können fi
möchten, dass Sie beginnen
verschiedene Ressourcen auf diesen API-Ebene Splitpunkte zu haben, so dass die

Benutzeroberfläche, die Sie unterstützen in geeigneter Weise auf allen Versionen von Android aussieht.

Use Case: Themen von API-Ebene

Ein großer Anwendungsfall fürDiese Funktion wird mit verschiedenen Themen, die von API-Ebene.

Selbst wenn IhrminSdkVersion ist 11 oder höher, können Sie zwei unterschiedliche Themen für Ihre Anwendung haben wollen:

• Eine, von API-Ebene verwendet 11-20, basierend aufTheme.Holo

• Eine andere, verwendet von API Stufe 21 ab, basierend aufTheme.Material

Ihre grobe Alternative zu bedienendas appcompat-v7BackportvonIn der Aktionsleiste und Bits des Material Design Ästhetik. Für stark stilisierte Apps oder in Fällen, in denen Sie sicher sind, dass Sie
sich auf Pre-Android 5.0-Geräte Material Design wollen, appcompat-v7 ist eine Überlegung wert.

Aber wenn Sie in besser auf jeder Haupt nativen UI-Variante zu mischen wollen, möchten Sie Theme.Holo auf Android 3.x und 4.x und Theme.Material danach zu unterstützen.

Die harte Arbeit hier ist die Einrichtung IhresThemen sich, wie dargelegt, was wieder indas Kapitel über die Aktionsleiste. Nachdemsie werden beide zur Verfügung, je nach Gerätevariante ist nur eine Frage der Ressourcen in die richtigen Verzeichnisse setzen.

Nehmen wir zum Beispielein Blick auf dieActionBar / VersionedColorBeispielprojekt. Das istein

"Mashup" von derHoloColorundMaterialColorBeispielprojekte, bei denendie Bestimmung, welches Thema zu verwenden, ist auf API-Ebene.

Imdasres / Werte /Verzeichnis, haben wir einstyles.xmlfi
das ist die gleiche wie die, in
derHoloColorBeispiel nur mitdie fi
standardisiertnachstyles.xml. Es verwendet ein eigenes

Thema (Theme.Apptheme) Von der Aktionsleiste Style-Generator erzeugt.

Es gibt aucheinres / Werte-v21 /Verzeichnis, Werte Ressourcen anzeigt, auf API-Ebene 21 und höher verwendet werden. Es hatdas Thema ursprünglich in der gesehenMaterialColorWenn
beispielsweiseder Stil Ressource wird umbenanntTheme.Apptheme, Die man passend definiert inres

/ Werte /.

Dann, mit<Application>ReferenzierungTheme.Apptheme, Erhalten wir die richtige Aktionsleiste auf der rechten Seite Gerät.

Hier, mitdie Stil Ressourcen Namen die gleiche Bedeutung, wie wir den Namen in das <application>

-Element im Manifest verweisen. Um in die richtige zu ziehen, müssen wir sie beide den gleichen Namen haben. Allerdings Ressourcen, die nur von einem dieser Themen bezeichnet werden, wie Farbe und ziehbar Ressourcen, könnte in einem versionierten Verzeichnis gehen oder nicht, wie Sie fi sehen

Sie haben in versioniert Verzeichnisse zu gehen und haben müssendie gleichen Namen, wenn Sie mehrere Ausgaben wünschen, wo die API-Ebene wählt, welche Edition zu verwenden.

Beispielsweise,dasTheme.Material-basierendThema definiert inres / Werte-v21 / styles.xmlverweist auf drei Farbressourcen. Der fi
für diese Ressourcen geschieht
sein auch inres / Werte-v21 /(Colors.xml). Da wir jedoch sindnicht auf der Suche die Farben basierend auf API-Ebene zu ersetzen, dieColors.xmlfi
könnte platziert inres / Werte /und
arbeiten genauso gut. Und wenn wir wollten verschiedene Farben von API-Ebene zu haben, würden wirmüssen die Farben in allen relevanten Ressourcengruppen definiert, wie beideres / Werte / und res

/ Werte-v21 /.

Standard Wechselverhalten

Wenn Sie anrufen Methoden indas Android SDK, das eine Ressource geladen werden (zB die oben genannten setContentView (R.layout.main)), Android wird diese Ressource-Sets zu Fuß durch, fi
die richtige Ressource für die jeweilige Anforderung, und es verwenden.

Aber was passiert, wenndie Konfiguration ändert, nachdem wir für die Ressource gefragt? Zum Beispiel, was passiert, wenn der Benutzer sein Gerät im Portrait-Modus hielt, dreht sich dann um den Bildschirm Landschaft? Wir würden eine -land Version unserer Layouts wollen, wenn eine solche Versionen existieren. Und da wir bereits die angeforderten Ressourcen, hat Android keine Möglichkeit, uns überarbeitet Ressourcen verteilen on the fly ... außer uns zwingen, diese Ressourcen neu Anfrage.

Damit,das ist, was Android tut, die standardmäßig in unseren Vordergrund Aktivität, wenn die Konfiguration im laufenden Betrieb verändert.

Zerstören und neu erstellendie Aktivität

Der GrößteSache, die Android tut, ist zu zerstören und unsere Aktivitäten neu zu erstellen. Mit anderen Worten:

• Android AnrufeonPause ().OnStop (), undonDestroy ()auf unserer
ursprünglichen Instanzdie Aktivität

• Android schaffteine brandneue Instanz der gleichen Aktivitätsklasse, die gleiche Absicht verwenden, die verwendet wurde, die ursprüngliche Instanz zu erstellen

• Android AnrufeonCreate ().onStart (), undauf Wiederaufnahme()vondie neue

Aktivitätsinstanz

• Dasneue Aktivität auf dem Bildschirm erscheint

Dies mag ... invasiv. Das könnte dirnicht erwarten, dass Android eine ganz gute Aktivität auslöschen würde, nur weil der Benutzer ihr Handgelenk schnippte und den Bildschirm ihres Telefons gedreht.

Dies ist jedoch die einzige Möglichkeit, Android hat die garantiert, dass wir erneut Wunsch alle unsere Ressourcen.

wieder aufbauendie Fragmente

Wenn Ihre Aktivität wird unter Verwendung von Fragmenten,die neue Instanz der Aktivität die gleichen Fragmente, die die alte Instanz der Aktivität enthält. Dies schließt sowohl statische als auch dynamische Fragmente.

Standardmäßig zerstört Android und wieder aufs Neue schafftdie Fragmente, so wie es zerstört und stellt die Aktivitäten. wie wir jedoch sehen, wir haben eine Option, Android zu sagen, bestimmte dynamische Fragment Instanzen zu behalten - für diejenigen, wird es die neue Instanz die gleichen Fragment-Instanzen verwenden, wie durch die alte Tätigkeit verwendet wurden, statt neue Instanzen der Schaffung von kratzen.

Recreatedie Ansichten

Unabhängig davon, obnicht Android alle Fragmente neu erstellt, wird es onCreateView () aller der Fragmente (plus nennen onDestroyView () auf den ursprünglichen Satz von Fragmenten) nennen.

Mit anderen Worten, nachbildet Android alle der Widgets und Container, in die neue Aktivitätsinstanz zu gießen.

Behalten einige Widget Staat

Android hält andie "Instanz-Zustand" von einigen der Widgets wir in unserer Tätigkeit und Fragmente. Meist hält sie auf offensichtlich Benutzer veränderbare Zustand, wie zum Beispiel:

• Was warin eine typisierteText bearbeiten

• ObeinCompoundButton, wie einCheckBoxoderRadio knopfWird oder nicht geprüft

• Etc.

Android sammelndiese Informationen aus den Widgets der alten Aktivitätsinstanz führen, dass die Daten auf neue Aktivitätsinstanz, und aktualisieren Sie den neuen Satz von Widgets, die denselben Zustand zu haben.

Aber:

• Widgetsmüssen eine ID haben ihren Staat gerettet zu haben. Wenn Sie die Widgets aus einem Layout Ressource aufblasen, und die Widgets android: id-Werte, erfüllen Sie diese Forderung. Wenn jedoch werden Sie die Widgets-Code direkt in Java erstellen, geben Sie diese Widgets keine ID haben. Sie müssten setId () aufrufen
gebenihnen eine ID oder verwalten den Zustand selbst (mit dem
onSaveInstanceState ()beschriebene Technik später indieses Kapitel).

• Die ID-Wertemüssen eindeutig sein. Wenn es mehrere Widgets mit der gleichen ID sind, werden Sie auf Probleme stoßen. Normalerweise sind die einzigen Fälle, wo wir mehrere Widgets mit derselben ID haben, wenn diese Widgets von einem Adapter kommen, wie zum Beispiel ein ArrayAdapter. Und, in der Regel werden diese Widgets nur gelesen werden und haben keinen Zustand zu speichern. Wenn Sie jedoch versuchen, setzen Anwender
veränderbare Widgets in den Layouts durch den Adapter aufgeblasen, oder Sie haben mehrere Benutzer veränderbare Widgets mit der gleichen ID, müssen Sie den Zustand selbst (wieder zu verwalten, die onSaveInstanceState () Technik beschrieben später in diesem Kapitel).

Szenarien Sparzustand

Wannder Benutzer den Bildschirm dreht, oder wird das Gerät in einem Auto-Dock, oder ändert sich die Sprache des Geräts, ist Ihr Prozess nicht beendet. Ihre Vordergrund Aktivität wird standardmäßig neu erstellt werden - ebenso wie Ihre Widgets und Fragmente - aber der Prozess klebt um.

Allerdings gibt es viele Fälle, in denen Ihr Prozess beendet wird, sobald Sie sich bewegen inder Hintergrund. Das könnte automatisch von Android oder manuell durch den Benutzer erfolgen.

Je nachdem, wie Ihr Prozess beendet wird, kann es sein, Wege dass der Benutzer auf Ihre App zurückkehren und erwarten, dass sie zu ihm zurückkehren wird, wie sie es verlassen. Angenommen, der Benutzer in der App ist, dann drückt HOME Ihre App im Hintergrund zu verschieben. Stunden vergehen, und Android endet Ihre Prozess-Speicher für andere Anwendungen freizugeben. Einige Zeit danach, bringt der Benutzer die letzten Aufgaben Liste nach oben und klopft auf Ihrer App in dieser Liste. Aus der Sicht des Benutzers, sollten sie, um Ihre Anwendung im gleichen Zustand zurückkehren, dass sie es verlassen, wenn sie nach Hause gedrückt. wenn Ihr Prozess standardmäßig wurde jedoch beendet, Sie das ganze Staat verloren.

Einigedie Techniken, um mit einer Konfigurationsänderung zu tun - diejenigen, die die "gespeicherten Instanz Zustand Bundle" - werden Sie auch die neu-Aufgaben-Liste Szenario behandeln helfen.

Einige der anderen Techniken - wie zum Beispiel ein Fragment Halte - nur im Umgang mit Konfigurationsänderungen helfen und wird für Sie in Bezug auf die jüngsten-Aufgaben-Liste Szenario nichts zu tun. Die allgemeine Faustregel gilt daher, das Bundle zu verwenden, wo Sie können, und verwenden andere Techniken (zB beibehalten Fragmente), wo das Bündel unpassend oder unzureichend ist. Wir werden diese Techniken in den nächsten Abschnitt.

Jedoch beachtendass alle dieser Zustand für transiente Daten, Daten konzipiert, dass der Benutzer nichts dagegen, wenn sie nie wieder sehen. Angenommen, der Benutzer in der App ist, dann drückt HOME Ihre App im Hintergrund zu verschieben. Stunden vergehen, und aufgrund der Benutzer damit beschäftigt ihr Gerät verwendet haben, können Sie "fallen" die jüngste-Aufgabenliste, da diese Liste nicht auf unbestimmte Zeit verlängern. In diesem Fall, wenn der Benutzer wieder die App startet (zB über das Launcher-Symbol Home-Bildschirm), werden Sie keine Zustandsinformationen zurück zur Verwendung kommen. Die Daten, die der Benutzer fi
in die alte App Beispiel, wo
die Daten in Erinnerung und in jeder zukünftigen Lauf Ihrer Anwendung wiederverwendet werden müssen, müssen sich beharrte werden, in einer Datenbank oder eine andere Art von fi Mit allenin diesem Sinne, lassen Sie uns mit dem Übergangszustand für den Umgang mit dem Schwerpunkt auf Konfigurationsänderungen unsere Optionen zu prüfen.

Ihre Optionenfür Konfigurationsänderungen

Wie angemerkt,eine Konfigurationsänderung ist ziemlich invasive auf Ihre Tätigkeit, es geradezu mit allen neuen Inhalt ersetzt (wenn auch vielleicht mit einigen Informationen aus der alten Tätigkeit des Widgets Vortrag in die neue Tätigkeit des Widgets).

Daher haben Sie mehrere mögliche Ansätze für Konfigurationsänderungen in einer bestimmten Aktivität Handhabung.

Nichts tun

Daseinfachste Sache, natürlich zu tun, ist überhaupt nichts zu tun. Wenn alle Ihre Zustand wird automatisch in Sachen Android Griffe gebunden, brauchen Sie nichts mehr als die Standardwerte zu tun.

Beispielsweise,die ViewPager / Fragmente Demo ausdie vorangegangenen KapitelWerke korrekt

"out of the box". Alle unsere "Staat" ist in EditText Widgets, die Android Griffe automatisch gebunden. So können wir Sachen in einem Bündel von diesen Widgets geben, drehen Sie den Bildschirm (zB über <Strg> - <F11> im Emulator auf einem Windows- oder Linux-PC), und unsere eingegebenen Text beibehalten wird.

Ach, es gibt viele Fälle, in denendie sich im internen Verhalten ist entweder unvollständig oder einfach falsch, und wir werden mehr Arbeit tun müssen, um sicherzustellen, dass unsere Konfigurationsänderungen richtig gehandhabt werden.

Bewahren Sie Ihre Fragmente

Ein Ansatz für die Handhabungdiese Art von Konfigurationsänderungen ist Android behalten ein dynamisches Fragment zu haben.

Hier "behalten" bedeutetdass Android das gleiche Fragment Instanz über die Konfigurationsänderung zu halten, ist es von der ursprünglichen Hosting-Aktivität lösen und es zu einem neuen HostingAktivität zu befestigen. Da es das gleiche Fragment Instanz ist, irgendetwas in diesem Beispiel enthalten ist, selbst zurückgehalten und wird daher nicht verloren, wenn die Aktivität zerstört und neu erstellt.

Sehendies in Aktion, werfen Sie einen Blick auf dieConfigChange / FragmenteBeispielprojekt.

Die Business-Logik fürDiese Demo (und für alle anderen Demos in diesem Kapitel) ist, dass wir dem Benutzer, wählen Sie einen Kontakt aus der Liste von Kontakten auf dem Gerät oder Emulator gefunden zulassen möchten. Wir werden das tun, indem der Benutzer Presse mit einem "Pick" Taste, zu welchem Zeitpunkt wir eine Aktivität zeigen, dass der Benutzer den Kontakt und geben das Ergebnis zu uns holen lassen. Dann werden wir eine Schaltfläche "View" aktivieren und der Benutzer die Details des ausgewählten Kontakts anzuzeigen lassen. Der Schlüssel ist, dass unsere gewählten Kontakt über Konfigurationsänderungen beibehalten werden muss - andernfalls wird der Benutzer den Bildschirm drehen, und die Aktivität wird angezeigt über den ausgewählten Kontakt zu vergessen.

Die Aktivität selbst nur lädtdas dynamische Fragment, nach dem Rezept, die zuvor in diesem Buch gesehen:

(von

ConfigChange / Fragmente / app / src / main / java / com / commonsware / android /

Rotation / frag / RotationFragmentDemo.java)

Der Grund für die Überprüfung fürdie Existenz des Fragment sollte nun klarer sein. Da Android wird neu automatisch (oder behalten) unsere Fragmente über Konfiguration

Änderungen, was wir tunnicht wollen, eine zweite Kopie des gleichen Fragments zu erstellen, wenn wir eine vorhandene Kopie bereits haben.

Das Fragment wird ein zu verwenden,R.layout.mainLayout-Ressource, mit zwei

Implementierungen. Eine, inres / Layout-Land /Wird in der Landschaft verwendet werden: (von

ConfigChange / Fragmente / app / src / main /
res / Layout-Land / main.xml)

Das PorträtAusgabe, in res / Layout / ist identisch mit Ausnahme der Ausrichtung der Linearlayout:

(von

ConfigChange / Fragmente / app / src / main /
res / Layout / main.xml)

Hier istdie vollständige Umsetzung derRotationFragment:

(von

ConfigChange / Fragmente / app / src / main / java / com / commonsware /
android / Rotation / frag / RotationFragment.java)

ImonClick (), Wir die "Pick" -Taste, um ein HakenpickContact ()Methode. Dort nennen wirstartActivityForResult ()mit einemACTION_PICK Intent, Was darauf hinweist, dass wir etwas wollen von der zu holenContactsContract.Contacts.CONTENT_URISammlung von Kontakten. Wir werden diskutierenContactsContractnäherspäter im dieses Buch. Fürder Moment, nehmen Sie es auf den Glauben, dass Android hat eine solcheACTION_PICKAktivität, eindas wird die Liste der verfügbaren Kontakte an den Benutzer angezeigt werden:

In ErgänzungzumACTION_PICK IntentLiefern wir auch eine einzigartigeintnach
startActivityForResult (). Diesintsollte seinein 16-Bit-Wert (0nach65535) das ist einzigartig fürdiese besondere startActivityForResult () Anruf von dieser Tätigkeit. Dieser Wert muss nicht im Vergleich zu solchen Anrufe von anderen Aktivitäten von Ihnen eindeutig sein, geschweige denn über das gesamte Gerät.

Obder Benutzer wählt einen Kontakt, kehrt die Steuerung zu unserer Tätigkeit, mit einem Aufruf an onActivityResult ().onActivityResult ()ist bestanden:

• die eindeutige ID wir startActivityForResult () geliefert wird, zu helfen, dieses Ergebnis von allen anderen identifizieren wir empfangen werden könnten

• RESULT_OKobder Benutzer hat wählen Sie einen Kontakt
oderRESULT_CANCELEDobder Benutzer verlassen die Pick-Aktivität

• einIntent das Ergebnis von der Pick-Aktivität enthalten, die in diesem Fall eine Uri, die die ausgewählten Kontakt enthalten, abgerufen via getData ()

Wir speicherndass Uri in einem Datenelement, und wir ermöglichen die Schaltfläche "View", die, wenn sie angeklickt wird, wird eine ACTION_VIEW Aktivität auf dem ausgewählten Kontakt über seinen Uri bringen:

Bis inonCreateView (), wir riefen ansetRetainInstance (true). Dies sagt Android dieses Fragment Instanzüber Konfigurationsänderungen zu halten. Daher haben wir ein Kontakt im Portrait-Modus auswählen können, drehen Sie dann den Bildschirm (zB<Strg> - <F11>imder Emulator unter Windows oder Linux) und Aussichtder Kontakt im Landscape-Modus. Obwohl die Aktivität und die Tasten als Ergebnis der Drehung ersetzt wurden, wurde das Fragment nicht, und die auf die Uri gehalten Fragment des ausgewählten Kontakt.

Hinweisdass setRetainInstance () funktioniert nur mit dynamischen Fragmenten, nicht statisch Fragmente. Statische Fragmente werden immer neu erstellt, wenn die Aktivität selbst zerstört und neu erstellt.

Der VorteilDiese Technik, die über andere, ist, dass Sie jede Art von Daten beibehalten können Sie wollen: einen beliebigen Datentyp, jede Größe usw. Allerdings ist dieser Ansatz nicht Zustand speichern, die nach dem Prozess gegeben wird, um Sie wieder beendet worden war, wie wie wenn der Benutzer auf Ihre App über die letzten Aufgaben Liste geht zurück.

Modell Fragment

Eine Variation dieses Themas ist das "Modell Fragment". Während normalerweise Fragmente auf die Lieferung von Abschnitten der UI für einen Benutzer fokussiert sind, ist, dass nicht wirklich eine Anforderung. Ein Modell Fragment ist eines, das einfach setRetainInstance (true) verwendet, um sicherzustellen, dass es klebt um als Konfigurationen ändern. Dieses Fragment hält dann auf jedes Modelldaten, die der Host-Aktivität benötigt, um die Aktivität zerstört und neu erstellt wird, klebt die Modelldaten um im Modell Fragment.

Dies ist besonders nützlich für die Datendass sonst vielleicht nicht ein Fragment zu Hause haben.

Zum Beispiel vorstellen, eine Tätigkeit, deren UI besteht vollständig aus einem ViewPager, (wie die Tutorial-App). Auch wenn das ViewPager Fragmente halten könnte, wird es in den meisten Pagern viele Seiten sein. Es kann einfacher sein, eine separate, UI-Modell weniger Fragment hinzufügen und haben es die Aktivität des Datenmodells für die ViewPager halten. Dies ermöglicht die Aktivität noch zerstört und neu erzeugt werden, und ermöglicht sogar die ViewPager zerstört und neu erstellt werden, während immer noch die bereits geladenen Daten beibehalten werden.

Google empfiehlt die Verwendung vonein Modell-Fragment anstelle setRetainInstance (true) mit einem regelmäßigen Fragment zu verwenden. Je weniger das vorbehaltene Fragment hält, desto weniger wahrscheinlich ist es, dass Sie etwas halten, die Sie sollten nicht, wie eine Zeichenfolge abhalten, die aus einem String-Ressource aufgrund einer möglichen locale Änderung neu geladen werden muss. Davon abgesehen, wenn Sie vorsichtig sind und stellen Sie sicher, dass alle Ihre Datenelemente für richtig bilanziert werden, mit setRetainInstance (true) von jedem Fragment kann sicher gemacht werden.

Hinzufügenzum Bundle

Wenn Sie möchten Zustand gehalten werdennicht nur für Konfigurationsänderungen, sondern auch für die Prozessabbrüche, möchten Sie verwendenonSaveInstanceState ()undonRestoreInstanceState ().

Sie können außer Kraft setzenonSaveInstanceState ()in Ihrer Tätigkeit. Es wirdübergebeneinBündeln, In denen Daten gespeichert werden, dieüber die Konfigurationsänderung beibehalten werden sollte.

Der Haken ist, dass währendBündelnsieht ausein bisschen wie es istHashMapEs kann eigentlich nicht beliebige Datentypen enthalten, die die Art von Informationen begrenzt Sieüber behalten könnenonSaveInstanceState ().onSaveInstanceState ()heißt umdie Zeit deronPause ()und OnStop ().

Das Widget Zustand automatisch durch Android gehalten ist überdie integrierte Implementierung von onSaveInstanceState (). Wenn Sie es selbst außer Kraft gesetzt, in der Regel werden Sie an die Kette auf die übergeordnete wollen diese ererbte Verhalten zu erhalten, zusätzlich zu den Dingen in das Bündel setzen sich selbst.

DassBundle ist bestanden, an zwei Stellen Sie zurück:

• onCreate ()

• onRestoreInstanceState ()

Schon seitonCreate ()wird in vielen Fällen andere genanntals aufgrund einer

Konfigurationsänderung, die häufig die bestandene-inBündelnistNull.onRestoreInstanceState ()Auf der anderen Seite wird nur dann aufgerufen, wenn es ein istBündelnbenutzt werden.

Um zu sehen, wiedies funktioniert, werfen Sie einen Blick auf dieConfigChange / BundleBeispielprojekt.

Hier,RotationBundleDemo ist eine Tätigkeit, mit den gleichen Kerngeschäftslogik wie in unserem Fragment in der vorangegangenen Demo war. Da die Aktivität auf einer Konfigurationsänderung zerstört werden und neu erstellt, außer Kraft setzen wir onSaveInstanceState () und onRestoreInstanceState () unser Kontakt zu halten, wenn man vor der Konfigurationsänderung ausgewählt wurde:

(von

ConfigChange / Bundle / app / src / main / java / com / commonsware / android /

Rotation / Bündel / RotationBundleDemo.java)

Hier verwenden wirputParcelable ()stellendasUriin dasBündeln.Parcelist eine Schnittstelle,dass Sie auf einer Java-Klasse implementieren eine Instanz davon zu erlauben, in ein zu
setzenBündeln.Urigeschieht zu implementierenParcel. Die vollständigen Einzelheiten darüber, wasParcelbedeutet, und wie kann man machenDinge umsetzenParcelwerden zur Verfügung gesellt sind vorhandenspäter imdieses Buch.

Der Nachteildieser Ansatz ist, dass nicht alles in einem Bundle gehen kann. Ein Bundle kann nicht beliebige Datentypen enthalten, so dass Sie nicht einen Sockel in ein Bündel, zum Beispiel setzen.

Außerdem muss das Bundle recht gering sein, da sie über Prozessgrenzen hinweg geführt wird, so dass Sie kann große Objekte nicht setzen (zB Bitmaps) in das Bündel. Für diese Fälle werden Sie für die Rück-Fragment-Ansatz begleichen müssen.

Fragmente undein Bündel

Die Fragmente haben auch eineonSaveInstanceState ()Methodedass sie überschreiben. Es funktioniert genau wie dieAktivitätgleichwertig- Sie können die Daten in der mitgelieferten speichernBündelnDas wird später zu Ihnen geliefert zurück. Der größte Unterschied ist, dass es keineonRestoreInstanceState ()Methode- Stattdessen sind Sie übergeben dieBündelnin anderen Lebenszyklus-Methoden:

• onCreate ()

• onCreateView ()

• onViewCreated ()

• onActivityCreated ()

Wir sehenDies ist in derConfigChange / FragmentBundleBeispielprojekt. Dies ist wirkungsvollein Mashup von den vorangegangenen zwei Proben: Fragmente verwenden, sondern auch
mitonSaveInstanceState ()Anstatt vonsetRetainInstance (true).

UnserRotationFragmentJetzt hat einonSaveInstanceState ()Methodedas sieht viel wie die von derConfigChange / BundleProbe der Aktivität:

(von

ConfigChange / FragmentBundle / app / src / main / java / com / commonsware / android /

Rotation / fragbundle / RotationFragment.java)

UnseronCreateView ()Verfahren untersuchtdieübergebene inBündelnUnd wenn es nicht istNull versucht zu erhalten, unsereKontaktdavon:

(von

ConfigChange / FragmentBundle / app / src / main / java / com / commonsware / android /

Rotation / fragbundle / RotationFragment.java)

Dies giltnicht unser Fragment erlauben auf beliebige Daten zu halten, hat die Art und Weise setRetainInstance (true). Doch wie bei onSaveInstanceState () auf das Aktivitätsniveau, gibt es Szenarien, die onSaveInstanceState () Griffe, die Fragmente beibehalten wird nicht, wie Ihr Prozess aufgrund der geringen Speicher beendet, doch der Benutzer später verwendet BACK, um zurückzukehren, was hätte sein sollen, Ihre Aktivität (und seine Fragmente).

onRetainNonConfigurationInstance ()

Wenn Sie waren zu frühen Versionen zurück zu gehen vonDieses Buch, eine der Optionen, die in diesem Kapitel besprochen wurde onRetainNonConfigurationInstance (). Dieser Ansatz wurde in API-Level 11, ersetzt bei gleichbleibender Fragmente veraltet.

Doch in einem beispiellosen Schritt, Google un-veraltet
onRetainNonConfigurationInstance ()in API-Level 24, so dass es wieder sicher für den Einsatz.

Trotzdie wirklich lange Methodennamen, seine Verwendung ist einfach:

• ImplementierenonRetainNonConfigurationInstance ()auf IhremAktivität, (Fast)

jedes Objekt zurückkehren Sie wollen.

• ImonCreate ()IhrerAktivität, AnrufgetLastNonConfigurationInstance (). Wenn es das nicht istNull, Dann ist es das gleiche Objekt, das Sie zurück
ausonRetainNonConfigurationInstance ()Millisekunden vor, als Teileine

Konfigurationsänderung. Sie können die GussgetLastNonConfigurationInstance

()Rückgabewertdie entsprechende Art, speichern Sie sie in einem fi

(oder was auch
immer), und es verwenden, aber Sie wurden mit ihm in die bisherige Aktivitätsinstanz.

Wenn dumüssen mehr als ein Objekt auf diese Weise zurückgehalten werden, haben
einfachonRetainNonConfigurationInstance ()einpackendie Objekte in einem gewissen Datenstruktur von Ihrem eigenen Design.

DasConfigChange / RetainBeispielprojekt ist nahezu identisch mitdasConfigChange / BundleBeispiel früher gezeigt. Imdiesem Fall wird die gespeicherte Instanz ZustandBündelnwurde ersetzt durchein Objekt beibehalten. Schon seitonRetainNonConfigurationInstance ()kann ein Objekt von RückTyp, können wir nur die RückkehrUrivertreten unsere Verbindung:

(von

ConfigChange / Retain / app / src / main / java / com / commonsware / android /

Rotation / behalten / RotationRetainDemo.java)

ImonCreate (), legen wir festKontaktseindas Ergebnis vongetLastNonConfigurationInstance ()(Gießen, es zueinUri) Und aktualisieren Sie dieViewbuttonzu reflektieren,
obnichtKontaktistNull:

(von

ConfigChange / Retain / app / src / main / java / com / commonsware / android /

Rotation / behalten / RotationRetainDemo.java)

Wanndreht der Benutzer den Bildschirm, die Uri von der alten Aktivitätsinstanz auf die neue übergeben wird, und so erinnern wir uns zuvor ausgewählten Kontakt.

Unterdie Abdeckungen, behielt Fragmente VerwendungenonRetainNonConfigurationInstance () undgetLastNonConfigurationInstance ().

WieDadurch werden die BeschränkungenonRetainNonConfigurationInstance ()erinnern andie Beschränkungen auf einbehaltene Fragmente:

• Machennicht zurückübertragenAnsichtenvononRetainNonConfigurationInstance (),

Wie sie auf den alten Aktivitätsinstanz gebunden wird, nicht der neue

• Machenkeine Objekte zurück, die (von String-Ressourcen erzeugt zB Strings)

in die Konfigurationsänderung aufgrund ersetzt müssen möglicherweise werden

• MachenVerwenden Sie diese nicht die gespeicherte Instanz Zustand Bundle zu ersetzen -
die auch andere Szenarien, wie zum Beispiel Prozessbeendigung Griffe - aber verwenden Sie es stattdessen für Dinge, die nicht in diesem Bundle aufgrund ihrer Größe oder Datentyp gehen

HINWEIS: Wenn Sie versuchen, mitonRetainNonConfigurationInstance ()Und es zeigt, mit der Geringschätzung durchgestrichener Formatierung in Ihrer IDE, wird IhrcompileSdkVersionist irgendwo zwischen 11 und 23 Raise es bis zu 24 zu klärendie deprecation Warnung.

DIY

Imzu komplex ist oder zu langsam ein paar Fällen sogar ein Fragment erhalten ist unzureichend, weil die Übertragung und Wieder den Zustand der Anwendung. Oder in einigen Fällen wird die Hardware in die Quere kommen, wie wenn man versucht, die Kamera zum Aufnehmen von Bildern zu verwenden - ein Konzept, das wir später in diesem Buch zu decken.

Wenn Sie völlig verzweifelt sind, können Sie Android sagen, nicht zerstören und neu erstellendie Aktivität auf einer Konfigurationsänderung ... obwohl dies seine eigene Reihe von Konsequenzen hat.

Um dies zu tun:

• Setzen Sie einandroid: configChangesEintrag in IhremAndroidManifest.xmlfi

Auflistungdie Konfigurationsänderungen Sie sich im Vergleich zu ermöglichen Android behandeln möchten für Sie zu behandeln

• ImplementierenonConfigurationChanged ()in deinemAktivität, Die aufgerufen wird, wenn eine der Konfiguration, die Sie in aufgelistetÄnderungenandroid:

configChangesauftritt

Nun, für jede Konfigurationsänderung Sie möchten, können Sie umgehendie ganze Aktivitäts- Prozess Zerstörung und bekommen einfach einen Rückruf dass Sie der Änderung wissen.

Nehmen wir zum Beispielein Blick auf dieConfigChange / DIYBeispielprojekt.

ImAndroidManifest.xmlFügen wir dieandroid: configChangeszuschreibendas

<Aktivität> -Element, was darauf hinweist, dass wir mehrere Konfiguration behandeln möchtenändert uns:

(von

ConfigChange / DIY / app / src / main /

AndroidManifest.xml)

Viele Rezepte fürdies haben Sie behandelnOrientierungundkeyboardHidden. Aber heute, müssen Sie auch behandelnBildschirmgröße(Und in der Theorie,smallestScreenSize), Wenn Sie Ihreandroid: targetSdkVersionauf 13 oder höher. Hinweisdass dies Ihre Build-Ziel (zB
erfordern,compileSdkVersionin Android Studio) bis auf 13 oder höher eingestellt werden.

Daher ist fürdiese speziellen Konfigurationsänderungen, Android wird die Aktivität nicht zerstören und neu zu erstellen, sondern rufen onConfigurationChanged (). In der

RotationDIYDemo Implementierung, schaltet diese einfach die Ausrichtung der Linearlayout die Ausrichtung der Vorrichtung zu entsprechen:

(von

ConfigChange / DIY / app / src / main / java / com / commonsware /
android / Rotation / DIY / RotationDIYDemo.java)

Schon seitdie Aktivität während einer Konfigurationsänderung nicht zerstört, müssen wir überhaupt über die Uri des ausgewählten Kontakts keine Sorge - es ist nicht überall.

Das Problem mitDiese Implementierung ist zweifach:

1. Wir sindalle möglichen Konfigurationsänderungen nicht handhaben. Wenn der Benutzer, sagen wir, das Gerät in ein Auto Dock bringt, wird Android zerstören und unsere

Aktivitäten neu zu erstellen, und wir werden unsere ausgewählten Kontakt verlieren.

2. Wir könnten einige Ressource vergessendass muss aufgrund einer Konfigurationsänderung geändert werden. Zum Beispiel, wenn wir die Saiten von den Layouts verwendet

Übersetzen beginnen, und wir sind locale in Android: configChanges, wir nicht nur die Linearlayout, sondern auch die Beschriftungen der Buttons Widgets aktualisieren müssen, da Android wird nicht automatisch für uns tun.

Es istdiese beiden Probleme, die sind, warum Google, wenn es unbedingt notwendig, aber nicht die Verwendung dieser Technik empfehlen.

Auch beachtendass dieser Ansatz für Haltezustand überhaupt nicht zu helfen, wenn Ihr Prozess beendet ist und der Benutzer kehrt in die App über die letzten-Aufgaben-Liste.

Blocking Verdrehungen

Kein Zweifeldass Sie haben einige Android-Anwendungen gesehen, die einfach jeden Versuch ignorieren, um den Bildschirm drehen. Viele Spiele funktionieren auf diese Weise, rein in Landscape-Modus betrieben wird, unabhängig davon, wie das Gerät positioniert ist.

Um dies zu tun, fügenAndroid: screenOrientation = "sensorLandscape"Oder gegebenenfallsAndroid: screenOrientation = "sensorPortrait", Zu Ihrem Manifest. Die "Sensor" Teile dieser Namen zeigen, dass Ihre Anwendung in regelmäßigen oder "Reverse" Versionen der Orientierung (zB "normale"

Landschaft arbeiten können, wird das Gerät um 90 Grad gegen den Uhrzeigersinn von Porträt, während "rückwärts" Landschaft ist die Gerät um 90 Grad gedreht vom Hochformat im Uhrzeigersinn). Auf API-Level 18+, könnten SieuserLandscapeoderuserPortraitstattdessen alsdiese werden dem System des Benutzers Ebene Wahl der Ehre, ob Bildschirm-Rotation zu sperren oder nicht, um das Verhalten von säumigensensorLandscapeodersensorPortraitobDer Benutzer hat kein Bildschirm-Rotation gesperrt.

Auch, wenn Sie verwendendies zu einer bestimmten Ausrichtung eines oder mehrere Ihrer Aktivitäten zu sperren, auch die entsprechende <Uses-Funktion> Element in Ihrem Manifest verwenden:

• <Uses-Funktion android: name = "android.hardware.screen.portrait" />wenn Sie eine Aktivität haben Porträt gesperrt

• <Uses-Funktion android: name = "android.hardware.screen.landscape" />wenn Sie eine Aktivität haben, um Landschaft gesperrt

DiesElement würde als Kind der Wurzel <manifest> -Element, aber außerhalb des

<Application>Element.

Die Rolle vonDiese <Uses-Funktion> Element ist im Play Store und ähnliche App Vertriebskanäle, die Ihre Anwendung erfordert bestimmte Hardware-Features zu werben. Solche Kanäle könnten Verteilung Ihrer App-Plattformen blockieren, wo Sie die gewünschte Ausrichtung nicht unterstützt wird (zB Portrait Aktivitäten auf einem TV-centric Gerät wie Android TV).

Und nun,ein Wort aus dem Android-Projekt-Ansicht

Zuvordas Buch, wenn Android Studio Einführung haben wir gesehen,das Android-Projekt Aussicht.

Einer vondie Gründe, warum die Android-Projekt Ansicht erstellt wurde, war es Ihnen gelingt, Ressourcen zu helfen, vor allem in verschiedenen Ressourcengruppen.

Zum Beispiel, hier istein Screenshot von der gleichen Android-Projekt, diesmal aber mit der Werte Ressourcen im Baum erweitert:

Der Baum erscheinen lässt, alsobwohl es nur einres / Werte / dimens.xmlfi
aber dass die
fi
irgendwie hat Kinder. Ein Kind hat nurdie bloßedimens.xml
fi
währendder andere hat eine "(w820dp)" angehängt.

Dies spiegeltdie Tatsache, dass es zwei Versionen vondimens.xml: Ein inres / Werte /
und eine inres / Werte-w820dp /:

Imdas Android-Projektansicht werden die Ressourcen von Ressource organisiert, nicht durch Ressourcengruppe. Dies kann nützlich sein, fi
alle fi
dass müssen angepasst
werden, wenn Sie gehen eine Version der Ressource anzupassen, zum Beispiel.

Material Design Basics

Wir haben bereits ausgesetzt warenTheme.Material als Teil dieses Buches, wie mit der Aktionsleiste.

Android 5.0+, kombiniert mitTheme.Material, gibt Ihnen eine Menge von Fähigkeiten, die Google-Material Design Ästhetik gebunden. In diesem Kapitel werden wir einige grundlegende Material Design-Funktionen abdecken, die Ihre Theme.Material App auf Android 5.0 und höher, beginnend mit Farbe beeinflussen.

Ihre App, in Technicolor!

Einige Entwickler ändern möchtendie Farben, die durch ihre App verwendet, um einige bestimmte Farbe oder eine Farbpalette anzupassen. In einigen Fällen werden die Farben in Frage zu der App-Branding gebunden. In anderen Fällen will der Entwickler einfach etwas anders als die Lager Farben, die Sie von so etwas wie Theme.Holo oder Theme.Holo.Light bekommen.

Erstellen von benutzerdefiniertenThemen Farben Theme.Holo und kin war genug von einem Schmerz zu beantragen, dass eingetrennteThema Generatorwurde für sie geschaffen, unabhängig vonder Generator für benutzerdefinierte Aktionsleiste Farben.

Affecting Farbänderungen in Ihrem Theme.Material-basierten Android-App ist in
beträchtlichem Ausmaß simplifi

- Sowohl für die Aktionsleiste und den Widgets -
mit freundlicher Genehmigung von Theme.Material der Tönungsoptionen.

Grundtönungs Optionen

Imdas Kapitel über die Aktionsleiste, sahen wir, wie oben zu setzenein eigenes Themabeyogen auf Theme.Material, die benutzerdefinierte Farbtönung Regeln hatte, die die Aktionsleiste betroffen: (von

ActionBar / MaterialColor / app / src / main /
res / Werte / styles.xml)

Beimdass die Zeit, konzentrierten wir uns auf die Auswirkungen, die diese Farbtöne auf der Aktionsleiste selbst hatte. Doch mit Theme.Material, nicht nur Auswirkungen auf die Farbtöne der Aktionsleiste, aber sie beeinflussen die Widgets selbst.

DasBasicMaterialVerzeichnis enthält Klone einigerdasGrund Widget Proben skizzierte früher inDieses Buch, in dem jeder das benutzerdefinierte Thema für die Aktionsleiste gezeigt, umfasst.

In manchen Fällen,die benutzerdefinierten Farbtöne sind normalerweise nicht sichtbar, wie mit einem Knopf:

Wenn Sie jedochTippen Sie auf die Schaltfläche, die animierte "Ripple-Effekt" auf die Schaltfläche gezeigt wird Ihre Akzentfarbe verwenden.

ichn anderen Fällen zeigt der Akzentfarbe in einem "stabilen Zustand", wie in einem überprüften CheckBox up:

In ähnlicher Weise zeigt Ihre Akzentfarbe bis inDinge wie:

• die "underbar" und Drag-Cursor in einem EditText:

• die Überprüfungsstatus (und sich allmählich ausbreitende Wirkung, wenn der Zustand Makeln) eines

Radio knopf:

• unddie "geprüft" Zustand eines Switch:

Offizielle Google-Prüfzeichen Farben

Natürlich sind Sie herzlich willkommen, was Farben Sie für Ihre gerne holenThema. Google hat seine Meinung, was es denkt, dass gute Ideen sind.

Im Rahmendas Material Design-DokumentationSie fi
eine "Farbpalette" Seite dass
skizziert mögliche Farben zu verwenden.

Ein Redditorwurde ebenfalls veröffentlichtein Android-Farbressource fi dass enthält alle Farben in dem Material Design Guide beschrieben.

Es gibt auchdasMaterialpalette Website, Die erzeugteine Farbressource fi
basierend auf

Farben dass Sie aus einem großen Raster von Farbfeldern wählen.

Der Umgang mit Themen

Benutzer wie bissig-Anwendungen. Benutzer tunwie Anwendungen, die nicht die träge fühlen.

Die Art und Weise der Anwendung zu helfenfühlen bissig ist die Standard-Threading-Fähigkeiten in Android gebaut zu verwenden. In diesem Kapitel werden die Themen durchlaufen in Android mit Thread-Management beteiligt und führt Sie durch einige der Optionen laufen für die Benutzeroberfläche knackig und reaktionsschnell zu halten.

DasHauptanwendung Thema

Wenn Sie anrufensetText () auf einem Textview, werden Sie wahrscheinlich denken, dass der Bildschirm mit dem Text aktualisiert wird Sie liefern, dann und dort.

Sie wäre falsch.

Vielmehr allesdass modifiziert das Widget-basierte UI geht durch eine Nachrichtenwarteschlange.

Anrufe auf setText () nicht den Bildschirm zu aktualisieren - sie legen einfach eine Nachricht in einer Warteschlange, das Betriebssystem zu sagen um den Bildschirm zu aktualisieren. Das Betriebssystem erscheint diese Nachrichten aus dieser Warteschlange und das tut, was die Nachrichten benötigen.

Die

Warteschlange
von
einem

Thread
verarbeitet
wird,
verschiedentlich
genanntdie

"Hauptanwendungsthread" und die "UI-Thread". Solange dieser Thread die Verarbeitung von Nachrichten zu halten, wird der Bildschirm aktualisieren, werden Benutzereingaben behandelt werden, und so weiter.

Aber,Hauptanwendungsthread ist auch für fast alle Rückrufe in Ihre Aktivität verwendet. Ihre onCreate (), onClick (), onListItemClick () und ähnliche Verfahren sind alle auf der Hauptanwendung Thread aufgerufen. Während Ihr Code in diesen Verfahren ausgeführt wird, ist Android nicht Nachrichten in der Warteschlange verarbeiten, und so wird der Bildschirm nicht aktualisieren, wird eine Benutzereingabe nicht behandelt, und so weiter.

Dies ist natürlich schlecht. So schlecht,dass, wenn Sie mehr als ein paar Sekunden dauern, die Arbeit an der Hauptanwendung Thread zu tun, die gefürchtete Android kann off "Programm reagiert nicht"

Dialog (ANR kurz), und Ihre Aktivität kann getötet werden angezeigt.

Heutzutage jedoch,die größere Sorge ist jank.

"Jank"wie in Android verwendet, bezieht sich auf träge UI-Updates, insbesondere dann, wenn etwas Animieren wird. Zum Beispiel, haben Sie möglicherweise einige Anwendungen auftreten, wenn Sie eine Listview in der App blättern, das Listview nicht reibungslos bewegen.

Vielmehr rollt sie ruckartig, mit Perioden Perioden der schnellen Bewegung die Verschachtelung, wodie Animation ist gesperrt. Die meiste Zeit wird dies durch den Autor App verursacht zu viel Arbeit auf dem Hauptanwendungsthread zu tun.

Android 4.1 eingeführt "Projekt Butter", die unter anderem eine Grundlage für etablierte "auf dem Hauptanwendungsthread zu viel Arbeit zu tun". Wir werden "drop frames", wenn wir mehr nehmen als ~ 16 ms pro Bild (60 Bilder pro Sekunde) und dropped Frames sind die Quelle von jank. Da wir viele Male während eines Rahmens bezeichnet werden kann, muss jeder unserer Rückrufe sehr billig sein, idealerweise unter 1 ms. Wir werden uns viel mehr in der Ausgabe von jankspäter imdas Buch, Aber es ist wichtig zu verstehen, jetztdass jeder signifi

Verzögerung indie

Ausführung unserer Code auf der Hauptanwendungsthread kann für den Benutzer sichtbar Auswirkungen haben.

Daher wollen Sie sicherstellendass alle Ihre Arbeit auf dem Thread Hauptanwendung geschieht schnell. Das bedeutet, dass etwas langsam in einem Hintergrund-Thread getan werden sollte, um nicht die Hauptanwendung Thread zu binden. Dazu gehören Dinge wie:

1. Internet-Zugang, wie beispielsweise das Senden von Daten zuein Web-Service oder ein Bild herunterzuladen

2. signifi
fi

Operationen, da fl

Lagerung merklich langsam
anmal

3. Jede Art von komplexen Berechnungen

Glücklicherweise unterstützt Android-Threadsdie Standard-Thread-Klasse von Java, sowie alle der Wrapper und Kontrollstrukturen Sie würden, wie die java.util.concurrent Klasse Paket erwarten.

Jedoch gibt es eine große Einschränkung:Sie können die Benutzeroberfläche von einem Hintergrund-Thread zu ändern. Sie können nur die Benutzeroberfläche aus dem Hauptanwendungsthread ändern. Wenn Sie setText () auf einem Textview von einem Hintergrund-Thread aufrufen, wird Ihre Anwendung zum Absturz bringen, mit Ausnahme an, dass Sie versuchen, die Benutzeroberfläche von einem "nicht-UI-Thread" (dh einem anderen Thread als die Hauptanwendung Thread zu ändern ).

Das istein Schmerz.

Bekommenzum Hintergrund

Daher Siebrauchen, um lang laufende Arbeit in den Hintergrund Fäden bewegt, aber diese Themen müssen etwas tun, um zu arrangieren die Benutzeroberfläche mit dem

Hauptanwendungsthread zu aktualisieren.

Es gibt verschiedene Einrichtungen in Android für mit diesem zu helfen.

Einige sind High-Level-Frameworks für die AdressierungDieses Problem für große

Funktionsbereiche. Ein Beispiel hierfür ist der Loader Rahmen für Informationen von Datenbanken abzurufen, und wir werden dies untersuchenimein späteres Kapitel.

Manchmal gibt es asynchrone Optionen in anderen Android-Operationen gebaut. Zum Beispiel, wenn wir diskutierenSharedPreferencesimein späteres Kapitel, wir werden sehendass wir auf diese Einstellungen können synchron oder asynchron Änderungen bestehen bleiben.

Und da sindeine Handvoll von Low-Level-Lösungen für dieses Problem zu lösen, diejenigen, die Sie für Ihre eigenen Geschäftslogik anwenden können.

Asyncing Gefühl

Ein beliebter Ansatz für den Umgang mitDieses Einfädeln Problem ist AsyncTask zu verwenden.

Mit AsyncTask, Android wird auf einem Hintergrund-Thread getan all die Aufgaben zu koordinieren separaten Arbeit im Vergleich zu auf dem UI-Thread behandeln. Darüber hinaus Android selbst ordnet und entfernt diesen Hintergrund-Thread. Und, es unterhält eine kleine Arbeitsschlange, weiter die "fi e und vergessen" Akzentuierung fühlen AsyncTask.

Die Theorie

Theodore Levitt wird mit den Worten, in Bezug auf Marketing zitiert: "Die Menschen wollen nicht to ein Viertel-Zoll-Bohrer kaufen, sie ein Viertel-Zoll-Loch "wollen. Baumärkte können Löcher nicht verkaufen, so verkaufen sie die nächstbeste Sache: Geräte (Bohrer und Bohrer), die Schaffung Löcher einfach zu machen.

Ebenso viele Android-Entwickler, die mit Hintergrund-Thread-Management zu kämpfen haben zu tunHintergrund-Threads nicht wollen - sie wollen Arbeit aus dem UI-Thread zu tun, jank zu vermeiden. Und während Android kann nicht auf magische Arbeit verursachen nicht
verbrauchen UI-ThreadZeit kann Android Dinge bieten, die solche Hintergrundoperationen einfacher und transparenter zu machen. AsyncTask ist ein solches Beispiel.

BenutzenAsyncTask, Müssen Sie:

1. Erstelleneine Unterklasse vonAsyncTask

2. Überschreiben Sie eine oder mehrereAsyncTask Methoden, um die Hintergrundarbeit zu erreichen, und was auch immer die Arbeit mit der Aufgabe verbunden, die auf dem UI-Thread getan werden muss (zB aktualisieren Fortschritt)

3. Wannbenötigt, um eine Instanz der AsyncTask Unterklasse und Anruf erstellen
execute () zu haben, es zu tun ihre Arbeit beginnen Was

Sie tun müssen, um nicht zu tun ist:

1. Erstellen Sie Ihre eigenen Hintergrund-Thread

2. Beendendass Hintergrund-Thread zu einem geeigneten Zeitpunkt

3. Rufen Sie alle Arten von Methodenfür Bits der Verarbeitung zu arrangieren auf dem UI-Thread zu tun

AsyncTask, Generics, und varargs

Erstelleneine Unterklasse von AsyncTask ist nicht ganz so einfach, wie, sagen wir, die Runnable-Schnittstelle implementiert. AsyncTask verwendet Generika, und so müssen Sie drei Datentypen angeben:

1. DasArt der Informationen, die die Aufgabe zu verarbeiten, benötigt wird

(beispielsweise herunterladen URLs)

2. DasArt der Information, die innerhalb der Task übergeben wird Fortschritte, um anzuzeigen,

3. DasArt der Information, die übergeben wird, wenn die Aufgabe an die Post-Task-Code abgeschlossen ist

Was machtdies umso mehr verwirrend ist, dass die fi
zwei Daten Typen werden als varargs
tatsächlich verwendet wird, was bedeutet, dass eine Anordnung dieser Art in Ihrer AsyncTask Unterklasse verwendet wird.

Dies sollte klarer werden, wenn wir uns auf den Weg zu einem Beispiel arbeiten.

Die Stufen der AsyncTask

Es gibt vier Methoden können Sie außer Kraft setzen inAsyncTask Ihre Ziele zu erreichen.

Die Sie außer Kraft setzen müssen, fürdie Taskklasse, nützlich zu sein, ist doInBackground (). Dies wird durch AsyncTask auf einem Hintergrund-Thread aufgerufen werden. Es kann so lange laufen, wie es braucht, um zu erreichen, was Arbeit für diese spezifi Aufgabe erledigt werden muss.

Beachten Sie jedoch, dass Aufgaben sein sollen fi
e - AsyncTask für eine unendliche Schleife
wird nicht empfohlen.

DasdoInBackground () -Methode erhalten als Parameter ein varargs Array der fi der Typen drei aufgeführten Daten über - die Daten benötigt, um die Aufgabe zu verarbeiten. Also, wenn Ihr Aufgabe der Mission, um eine Sammlung von URLs zum Herunterladen ist, doInBackground () wird diese URLs empfangen zu verarbeiten.

DasdoInBackground () -Methode muss einen Wert des dritten Datentyp zurückgeben oben aufgeführten - das Ergebnis der Hintergrundarbeit.

Vielleicht möchten Sie außer Kraft setzenOnPreExecute (). Diese Methode wird aus dem UI-Thread aufgerufen, bevor der Hintergrund-Thread ausgeführt doInBackground (). Hier könnten Sie eine ProgressBar initialisieren oder auf andere Weise zeigen, dass Hintergrundarbeit beginnt.

Auch können Sie möchten außer Kraft setzenOnPostExecute (). Diese Methode wird aus dem UI-Thread aufgerufen, nachdem doInBackground () abgeschlossen ist. Er empfängt, als ein Parameter, der Rückgabewert von doInBackground () (zB Erfolg oder Misserfolg Flagge). Hier können Sie die ProgressBar entlassen und die Nutzung der Arbeit im Hintergrund, wie die Aktualisierung des Inhalts einer Liste fertig zu machen.

In Ergänzung,können Sie möchten außer Kraft setzenonProgressUpdate (). ObdoInBackground ()Anrufedie AufgabenpublishProgress ()Methode,das Objekt (e) zu dieser Methode übermittelt werden bereitgestellt, umonProgressUpdate (), Aber in der UI-Thread. Dieser

Weg,onProgressUpdate ()kann alarmierender Benutzer über den Fortschritt, die auf dem Hintergrundarbeit durchgeführt wurde. DasonProgressUpdate ()Verfahren erhaltenein varargs des zweiten Datentyp aus der obigen Liste - die veröffentlichten Daten vondoInBackground ()überpublishProgress ().

Eine Beispielaufgabe

Wie bereits erwähnt, die Umsetzung einerAsyncTask ist nicht ganz so einfach wie ein Runnable implementieren. Allerdings, wenn Sie vorbei an den Generika und varargs bekommen, ist es nicht so schlimm.

Um zu sehen, ein AsyncTaskin Aktion,In diesem Abschnitt wird untersucht, dieThemen / AsyncTask Beispielprojekt.

Das Fragment und seine AsyncTask

Wir habeneinListFragment, genanntAsyncDemoFragment:

(von

Themen / AsyncTask / app / src / main / java / com / commonsware /

Android / asynchroner / AsyncDemoFragment.java)

Dies ist eine weitere Variantedie Lorem ipsum Liste von Wörtern, die häufig in diesem Buch verwendet. Dieses Mal, anstatt einfach nur die Hand der Liste von Wörtern zu einem ArrayAdapter, zu simulieren, die wir diese Worte im Hintergrund mit AddStringTask, unsere AsyncTask Umsetzung zu schaffen, zu arbeiten.

ImonCreate (), wir nennensetRetainInstance (true), So Android wird dieses Fragmentüber Konfigurationsänderungen, wie ein Bildschirm-Rotation beibehalten. Da unser Fragment wird neu initialisieren wir erstellt werden unsereModell-ein ... seinAnordnungslistevonSchnurWerte sowie Kick-off unsererAsyncTask(dasAddStringTaskInnenklasse, wie unten beschrieben),

SpeicherndasAddStringTaskimeinAufgabeDatenelement. Dann in onViewCreated ()Setzen wir den Adapter und befestigen Sie es an die obenListenansichtAuch die

VorbeugungListenansichtBildlaufleisten aus Abklingen wieihre Norm.

Imdie Erklärung von AddStringTask, verwenden wir die Generika die spezifi Arten von Daten einzurichten wir nutzen werden. Speziell:

1. Wir tunmüssen alle Konfigurationsinformationen in diesem Fall nicht, so dass unsere fi

Typ Void

2. Wir wollen passierenjede Saite "generiert" durch unsere Hintergrundaufgabe zu onProgressUpdate (), so können wir es zu unserer Liste hinzufügen, so dass unsere zweite Typ ist String

3. Wir tunkeine Ergebnisse haben, streng (über die Updates) zu sprechen, so dass unsere dritte Typ ist Void

DasdoInBackground () Methode wird in einem Hintergrund-Thread aufgerufen wird. Daher können wir so lange dauern, wie wir wollen. In einer Produktionsanwendung, würden wir vielleicht eine Liste von URLs iterieren und jeder Download bereit. Hier iterieren wirüber unsere statische Liste von Lorem Ipsum Worten rufen publishProgress () für jeden, und dann 400 Millisekunden schlafen wirkliche Arbeit zu simulieren getan. Wir rufen auch isCancelled () bei jedem Durchlauf, um zu sehen, ob unsere Aufgabe abgebrochen wurde,Überspringen der Arbeit, wenn es so können wir diesen Hintergrund-Thread aufzuräumen.

Da wir gewählt habenkeine Konfigurationsinformationen, sollten wir keine Parameter müssen doInBackground (). Allerdings, sagt der Vertrag mit AsyncTask wir brauchen eine varargs der fi zu akzeptieren

Daten geben, weshalb unsere Methodenparameter ist Void ....

Da wir gewählt habenkeine Ergebnisse, sollten wir nichts zurückbringen müssen. Auch hier, obwohl, sagt der Vertrag mit AsyncTask wir ein Objekt der dritten Datentyp zurückkommen müssen. Da dieser Datentyp Void ist, ist unsere zurückgegebene Objekt null.

DasonProgressUpdate () -Methode auf dem UI-Thread aufgerufen, und wir wollen, etwas zu tun, um den Benutzer zu informieren, wir diese Saiten auf Laden bis voran. In diesem Fall addieren wir einfach die Zeichenfolge an den ArrayAdapter, so wird es an das Ende der Liste angehängt. Aber wir tun dies nur, wenn wir nicht bereits abgesagt.

DasonProgressUpdate () Methode erhält einen String ... varargs da, dass der zweite Datentyp in unserer Klassendeklaration ist. Da wir nur vorbei eine Zeichenkette pro Anruf publishProgress () sind, brauchen wir nur die fi zu untersuchen

Eintrag indie varargs Array.

DasOnPostExecute () -Methode auf dem UI-Thread aufgerufen, und wir wollen etwas tun, um anzuzeigen, dass die Hintergrundarbeit abgeschlossen ist. In einem realen System kann es einige ProgressBar zu entlassen oder eine Animation zu stoppen. Hier heben wir einfach einen Toast und setzen Aufgabe auf null. Wir brauchen nichtüber Aufruf isCancelled () zu sorgen, denn OnPostExecute () nicht aufgerufen werden, wenn unsere Aufgabe abgebrochen wurde.

Da wir gewählt habenkeine Ergebnisse, sollten wir keine Parameter benötigen. Der Vertrag mit AsyncTask sagt, dass wir einen einzigen Wert des dritten Datentyp akzeptieren. Da dieser Datentyp Void ist, ist unsere Methode Parameter nicht verwendet Void.

BenutzenAddStringTask wir einfach eine Instanz erstellen und rufen Sie () auf ausführen. Das beginnt die Kette von Ereignissen schließlich zu dem Hintergrund-Thread führt seine Arbeit zu tun.

ObAddStringTask erforderlichen Konfigurationsparameter, würden wir nicht Void als unsere fi-Datentyp verwendet haben, und der Konstruktor würde null oder mehr Parameter des definierten Typs akzeptieren. Diese Werte würden schließlich zu doInBackground geben werden ().

Unser Fragment hat auch eineonDestroy () -Methode, die () auf dem AsyncTask ruft abbrechen, wenn sie noch aussteht (Aufgabe ist nicht null). Diese Arbeit der Task annullieren und zuüberprüfen, ob die Aufgabe abgebrochen wird aus zwei Gründen besteht:

1. Effizienz, wie sollten wir jede ernsthafte Arbeit überspringendass ist nicht erforderlich, wenn unsere Aufgabe selbst ist nicht erforderlich

2. Vermeidenein Absturz, wenn wir einen Toast auf einer zerstörten Aktivität, wie der Benutzer startet die Aktivität, dann wieder drücken, bevor wir den Hintergrund der Arbeit vervollständigen und zeigen den Toast zu erhöhen versuchen

Die Aktivität unddie Ergebnisse

AsyncDemo ist eine Tätigkeit, mit dem Standardrezept für Tritte eine Instanz eines dynamischen Fragment aus:

(von

Themen / AsyncTask / app / src / main / java / com / commonsware

/ Android / asynchroner / AsyncDemo.java)

Wenn Sie bauen, installieren und ausführenDieses Projekt, sehen Sie die Liste in "Echtzeit" über ein paar Sekunden von einem Toast die Beendigung gefolgt bevölkert wird.

Themen und Konfigurationsänderungen

Ein Problem bei derdie Standard-zerstören-und-create-Zyklus, der Aktivitäten auf einer Konfigurationsänderung durchlaufen kommt von Hintergrund-Threads. Wenn die Aktivität etwas Hintergrundarbeit begonnen hat - durch eine AsyncTask, zum Beispiel - und dann wird die Aktivität zerstört und neu erstellt, irgendwie muss die AsyncTask darüber wissen. Andernfalls könnte das AsyncTask auch Updates und fi senden

Ergebnisse nach die alte Tätigkeit, mit der neuen

Aktivität nicht klüger. In der Tat könnte die neue Tätigkeit beginnen wieder die Hintergrundarbeit, Ressourcen zu verschwenden.

Deshalb ist, indie Probe oben, wir behalten das Fragment Instanz. Das Fragment Beispiel hält sich an seine Datenmodell (in diesem Fall die Arraylist von lateinischen Wörtern) und weiß nicht, einen neuen AsyncTask nur, weil die Konfiguration geändert zu beginnen. Darüber hinaus behalten wir
das Datenmodell, so dass die neue Listview durch die Konfigurationsänderung mit einem neuen Adapter kann von alten Datenmodell gesichert erstellt arbeiten, so dass wir nicht unsere vorhandenen Satz von lateinischen Wörtern verlieren.

Wir müssen auch sehr vorsichtig sein,nicht zu versuchen, auf die Aktivität bezieht (über getActivity () auf dem Fragment) von unserem Hintergrund-Thread (doInBackground ()). Weil sei angenommen, dass in der Mitte des doInBackground () Verarbeitung, dreht der Benutzer den Bildschirm. Die Aktivität mit denen wir arbeiten im laufenden Betrieb ändern wird, an der Hauptanwendungsthread, unabhängig von der Arbeit im Hintergrund durchgeführt werden. Die Aktivität zurück von getActivity () nicht für uns in einem nützlichen Zustand sein, während diese Konfigurationsänderung vor sich geht.

Allerdings ist es sicher für uns zu nutzengetActivity () von OnPostExecute () und sogar von onProgressUpdate (). Für die Rückrufe, entweder die Konfigurationsänderung noch nicht geschehen ist, oder es abgeschlossen wurde - wir werden nicht in der Mitte des Wandels sein.

Woher Nicht zu verwenden AsyncTask

AsyncTask, insbesondere in Verbindung mit einem dynamischen Fragment, ist eine wunderbare Lösung für die meisten Bedürfnisse für einen Hintergrund-Thread.

the Schlüsselwort in diesem Satz ist "die meisten".

AsyncTask verwaltet einen Thread-Pool, aus dem er die Fäden zieht von Aufgabeninstanzen verwendet werden. Thread-Pools gehen davon aus, dass sie ihre Fäden zurück nach einer angemessenen Frist erhalten. Daher ist AsyncTask eine schlechte Wahl, wenn Sie nicht wissen, wie lange Sie den Faden benötigen (zB Gewinde an einer Steckdose für einen Chat-Client zu hören, in dem Sie den Thread, bis der Benutzer muss den Client beendet).

überdie AsyncTask Thread Pool

Außerdem,der Thread-Pool, der AsyncTask verwaltet hat in der Größe variiert. In

Android 1.5 war es ein einzelner Thread.

In Android 1.6 wurde erweitert viele parallele Threads zu unterstützen, wahrscheinlich mehrals Sie jemals brauchen werden.

In Android 3.2 hat es geschrumpft zurückzu einem einzigen Thread, wenn Ihr Android: targetSdkVersion auf 13 oder höher eingestellt. Dies war Adresse Bedenken über:

• Forking zu viele Threads undVerhungern die CPU

• Entwicklerzu denken, dass es eine Ordnung Abhängigkeit zwischen gegabelten

Aufgaben, wenn sie mit der parallelen Ausführung gibt es keine

Wenn Sie möchten, beginnend mit API Stufe 11 können Sie Ihre eigene VersorgungExecutor (aus dem java.util.concurrent-Paket), das, was Sie Thread-Pool hat wollen, so können Sie dies selbst

verwalten können. Neben dem serialisierten, one-at-a-time-Executor, gibt es einen Einbau-Executor, der den alten Thread-Pool realisiert, dass Sie Ihre eigenen verwenden können, anstatt rollen.

Wenn deinminSdkVersionist 11 oder höher, verwendenexecuteOnExecutor

(AsyncTask.THREAD_POOL_EXECUTOR)wenn Sie möchten gezielt entscheiden inein MultiThread-Thread-Pool. Wenn deinminSdkVersionunter 11 ist, werden Sie noch viel zu tundass ... aber nur auf API-Ebene 11+ Geräte, fallen zurück zuausführen()aufdie älteren Geräte. Diese statische Hilfsmethode behandelt dies für Sie:

Um dies zu nutzen, rufenexecuteAsyncTask (), Vorbei an in IhremAsyncTaskInstanz unddie Parameter, die Sie normalerweise vergangen wäreausführen().

Eine Erklärung dafür, was wir hier tun, in Bezug auf diedie @TargetApi Annotation und solche wird kommenspäter imdas Buch.

beachten Sie auch,dass die Anzahl der Threads in dem Threadpool Multithread hat sich auch im Laufe der Jahre verändert. Ursprünglich konnte das Pool, so viele wie 128 Threads klettern, die viel zu viele war. Ab Android 4.4,der Thread-Pool wird nur wachsen, "die zu Anzahl der CPU-Kerne * 2

+ 1 ", So auf einem Dual-Core-Gerät, wird der Thread-Pool bei 5 Fäden begrenzen. Weitere Aufgaben werden die Warteschlange gestellt, bis zu einem Maximum von 128 Warteschlange Aufgaben.

Alternativenzu AsyncTask

Es gibt andere Möglichkeiten der Handhabung Hintergrund-Threads ohne VerwendungAsyncTask:

• Sie können beschäftigenein Handler, die eine handle () Methode hat, die Message-Objekte verarbeiten wird, von einem Hintergrund-Thread geschickt, an der

Hauptanwendungsthread

• Sie können liefernein Runnable auf der Hauptanwendung Thread ausgeführt werden, um Post()auf jedemAussicht, oder zurunOnUiThread ()aufAktivität

• Sie können lieferneinRunnableSowie eine Verzögerungszeit in Millisekunden,
bispostDelayed ()auf jedemAussicht, Laufen dieRunnableaufHauptanwendungsthread,
nachdem zumindest die Anzahl der Millisekunde verstrichen

Vondiesen sind die Runnable Optionen sind am einfachsten zu verwenden.

Diese können auch verwendet werden, zu ermöglichen,Hauptanwendungsthread Arbeit zu verschieben, später auf der Hauptanwendungsthread zu tun. Zum Beispiel können Sie postDelayed () verwenden, um eine leichte Polling "Schleife" in einer Aktivität einzurichten, ohne den Aufwand eines zusätzlichen Thread benötigen, wie die durch Timer und Timertask erstellt. Um zu sehen, wie das funktioniert, sehen wir uns den einen Blick nehmenThemen / PostDelayedBeispielprojekt.

Dieses Projekt enthälteine einzige Tätigkeit, mit dem NamenPostDelayedDemo:

(von

Themen / PostDelayed / app / src / main / java / com / commonsware /
android / post / PostDelayedDemo.java)

Wir wollen zeigeneinToastalle fünf Sekunden. Um dies zu tun, inonCreate (), Bekommen wir unsere Hände auf den Behälter für ein UI-Aktivität, bekannt alsandroid.R.id.contentüberfindViewById ().

Dann inauf Wiederaufnahme()Wir nennenLauf()Verfahren auf unsere Tätigkeit, die
anzeigtdasToastund AnrufepostDelayed ()an sich selbst planen (Als ImplementierungRunnable) Laufen wieder werden inPERIODEMillisekunden. Während unserer Tätigkeit ist inin den Vordergrund, dieToasterscheint jedenPERIODEMillisekundenein Ergebnis. Sobald etwas kommt
sonst in den Vordergrund - wie durch den Benutzer BACK drücken - unsereonPause ()Methode aufgerufen wird, wo wir nennenremoveCallbacks ()rückgängig machen"daspostDelayed ()Anruf.

Und nun die Caveats

Hintergrund Fäden, während eminent möglich mitAsyncTask und Verwandten, sind nicht alle Glück und warme Welpen. Hintergrund-Threads nicht nur Komplexität, aber sie haben reale Kosten in Bezug auf das verfügbare Speicher, CPU, und die Lebensdauer der Batterie.

NachHierzu gibt es eine breite Palette von Szenarien, die Sie für die Zusammenarbeit mit Hintergrund-Thread-Konto müssen, einschließlich:

1. Die Möglichkeitdass die Nutzer mit Ihrer Aktivität der Benutzeroberfläche interagieren, während der Hintergrund-Thread entlang tuckern wird. Wenn die Arbeit, die der

Hintergrund-Thread von der Benutzereingabe geändert wird oder für ungültig erklärt wird tun, müssen Sie dies dem Hintergrund-Thread zu kommunizieren. Android enthält viele Klassen in der java.util.concurrent Paket, das Sie sicher mit Ihrem Hintergrund-Thread helfen kommunizieren.

2. Die Möglichkeitdass der Prozess beendet wird, während Sie Ihre Arbeit noch im Gange ist. Aus diesem Grund ist in vielen Fällen eher als eine AsyncTask verwenden oder mit einem nackten Thema erhalten Sie einen Service-Wind-up verwenden, wie zum

Beispiel ein IntentService. Dies wird in grßerem Detail untersucht werdenspäter imdieses Buch.

3. Die Möglichkeitdass Ihr Benutzer wird gereizt, wenn Sie viel CPU-Zeit und Lebensdauer der Batterie kauen, ohne Amortisation zu geben. Taktisch bedeutet dies unter Verwendung von ProgressBar oder andere Mittel zu lassen, der Benutzer wissen, dass etwas geschieht.

Strategisch dies bedeutet, dass Sie immer noch effizient sein müssen, was Sie tun -

Hintergrund-Threads kein Allheilmittel für die träge oder sinnlos Code sind.

4. Die Möglichkeitdass Sie einen Fehler bei der Hintergrundverarbeitung auftreten. Zum Beispiel, wenn Sie Informationen aus dem Internet sammeln, kann die

Gerätekonnektivität verlieren. Alarmierung der Benutzer über das Problem über eine Benachrichtigung und Schließen des Hintergrund-Thread nach unten kann die beste

Option sein.

Event-Busse
event-gesteuerte Programmierung ist seit fast einem Vierteljahrhundert um. Vieles von dem UI-Modell des Android ist ereignisgesteuert, wo wir fi nden
aus etwa diese Ereignisse über

Rückrufe (zB onCreate () für das Ereignis "eine Aktion starten") und registrierte Hörer (zB

OnClickListener für, wenn der Benutzer tippt auf ein Widget).

Aber ursprünglich, Android tatnicht eine sehr Fi

-grained Ereignis oder Message-Bus-

Implementierungdass wir als Entwickler nutzen könnten. Die Intent-System funktioniert wie ein Nachrichten-Bus, aber es ist bei Interprozesskommunikation (IPC), so viel wie prozeß Kommunikation ausgerichtet, und das kommt mit einigen Kosten.

Jedoch überZeit, vor allem ab 2012, Event-Busse in Betrieb genommen, um Pop, und diese sind sehr nützlich für die Kommunikation innerhalb Ihres Android-Anwendung organisiert und über Threads.

Richtig eingesetzt, kann ein Ereignis Bus die Notwendigkeit AsyncTask und die anderen Lösungen für die Kommunikation wieder in die Hauptanwendung beseitigen

Gewinde, während gleichzeitig helfen Sie logisch unabhängige Stücke des Codes entkoppeln.

Was ist ein Ereignis Bus?

Ob es sich um ein "Event-Bus" (oder "Message-Bus") betrachten,die "Publisher / Subscriber"

(oder "pub / sub") ein Muster oder eine Teilmenge der "Beobachter" Muster, das Programmiermodell, wo Komponenten Ereignisse erzeugen, die andere verbrauchen in der modernen Software-Entwicklung recht üblich ist.

Ein Ereignis-Bus dient zur Entkopplungdie Quellen der Ereignisse aus den Verbrauchern dieser Ereignisse. Oder,als ein Ereignis Bus Autor Putes:

Ich möchte eine einfache, zentralisierte Weise Code zu benachrichtigen, dass in
bestimmten Arten von Ereignissen interessiert ist, wenn diese Ereignisse ohne direkte Kopplung zwischen dem Code der auftreten ein Ereignis und den Code veröffentlicht, der sie empfängt.

Mitdie traditionelle Java Hörer oder Betrachter Muster Implementierung muss die Komponente ein Ereignis produziert direkten Zugang zu den Verbrauchern dieses Ereignisses. Manchmal wird die Liste der Verbraucher auf einen einzelnen Verbraucher beschränkt, wie bei vielen Event-Handler, die mit Android-Widgets (zB nur ein OnClickListener). Aber diese Quelle-hält-die-Senken Codierungsmuster Grenzen Flexibilität, da sie von den Verbrauchern mit den Produzenten von Veranstaltungen explizit eine Registrierung erforderlich ist, und es kann nicht so einfach sein, dass der Verbraucher die Produzenten zu erreichen. Weiterhin werden solche direkte Verbindungen als eine relativ starke Kopplung zwischen diesen Komponenten zu sein, und oft unser Ziel ist es lockerer Kopplung zu haben.

Ein Event-Bus bietetein Standard-Kommunikationskanal (oder "Bus"), die Event-Produzenten und Ereignisverbraucher in Haken können. Event-Produzenten müssen lediglich das Ereignis an den Bus zu übergeben; der Bus behandeln diese Ereignisse zu relevanten Verbraucher zu lenken. Dadurch verringert sich die Kopplung zwischen den Produzenten und Konsumenten, manchmal sogar die Menge an Code zu reduzieren erforderlich, um Quelle und diese Ereignisse sinken.

OK, aber warum Belästigen wir mit diesem?

Später werden wir anderen Komponenten habenals unsere Aktivitäten. Insbesondere werden wirDienstleistungen, Die so gestaltet sind kurz laufen inder Hintergrund eine Operation durchzuführen. So wie die Kommunikation zwischen Aktivitäten lose gekoppelt zu werden neigt, so sind auch die Kommunikation zwischen Aktivitäten und Dienste. Ein

Ereignis-Buseine gute Möglichkeit für den Dienst anderen Stücken der App wissen zu lassen, dass bestimmte Arbeit getan war (zB "ist der Download abgeschlossen ist, so aktualisieren Sie die UI").

ImKurzfristig werden wir ein Event-Bus zu haben, eine VerwendungModell FragmentLassendie App wissen, dass einige Daten geladen wurde. In den Tutorials, "einige Daten" werden die Buchinhalte sein; in der Beispielanwendung in diesem Kapitel dargestellt, "einige Daten" werden einige lateinische Worte.

Die Einführung des EventBus greenrobot

Die Veranstaltung Bus-Implementierungdass wir in den Tutorials verwenden werden wirdgreenrobot des EventBus, Eine Open-Source-Implementierung basiert aufdie Veranstaltung Bus des Guava Projekt. Mit greenrobot des EventBus, ist es ziemlich einfach, eine Nachricht von einem Teil Ihrer Anwendung auf einen anderen disparate Teil Ihrer App zu senden.

Um seine Verwendung zu illustrieren, nehmenein Blick auf dieEventBus / AsyncDemoBeispielprojekt.

Das isteine Bearbeitung eines vorherigen Beispiel, die eine AsyncTask verwendet, so zu tun, unsere Liste der lateinischen Worte zum Download, ein Listview mit diesen Worten bevölkern, wie sie ankommen. Diese Probe ersetzt das AsyncTask mit einem Modell-Fragment, das den Überblick über die Worte und einem Hintergrund-Thread halten wird, die die Worte "Download". Wir werden Ereignisse durch das Modell Fragment angehoben verwenden das UI-Fragment zu lassen Worte wissen, wie sie ankommen.

Anforderndas Artifact
greenrobot des EventBus wird als Artefakt verteilt dass Sie über die Abhängigkeiten in Ihrem Moduls build.gradle fi in Ihrem Projekt integrieren

(von EventBus / AsyncDemo / app

/ build.gradle)

Hier sind wir ziehen in der Version 2.2.1. Neuere Versionen, beginnend mit 3.0 habenanders ein anderes Artefakt und ein bisschen arbeiten - diese abgedeckt istspäter imdieses Kapitel.

definieren von Veranstaltungen

Mit greenrobot des EventBus,die "Ereignisse" sind Objekte beliebiger Klassen, die Sie definieren.

Jede andere Klasse stellt eine andere Art von Veranstaltung, und Sie können so viele verschiedene Ereignisklassen definieren, wie Sie möchten. Diese Klassen müssen nicht aus irgendeinem speziellen Basisklasse erben, oder eine spezielle Schnittstelle zu implementieren, oder irgendwelche magischen Anmerkungen. Sie sind nur Klassen.

Vielleicht möchten Sie Datenelemente zu setzen, Konstrukteure und Accessormethoden aufdie Ereignisklassen für alle Daten möchten Sie das Ereignis selbst um spezifi passieren. Ein SearchEvent, zum Beispiel, könnte die Suchabfrage Zeichenfolge als Teil des Ereignisobjekts gehören.

In unserem Fall haben wireinWordReadyEventdas enthält das neue Wort:

(von

EventBus / AsyncDemo / app / src / main / java / com / commonsware /
android / EventBus / WordReadyEvent.java)

Veröffentlichung Veranstaltungen

Um ein Ereignis zu veröffentlichen, alles, was Sietun müssen, ist eine Instanz eines EventBus erhalten - in der Regel über die getDefault () -Methode auf EventBus - und rufen post () auf sie, im Falle vorbei jedem Interessenten in Ihrer App geliefert werden.

Mitin diesem Sinne, lassen Sie uns die ModelFragment suchen, die in unseren Worten werden Laden wird:

(von

EventBus / AsyncDemo / app / src / main / java / com / commonsware /
android / EventBus / ModelFragment.java)

Dieses Fragment hatkeine Benutzeroberfläche - es existiert nur ein Datenmodell im Namen der Rest der Hosting-Aktivitäten zu verwalten. Daher gibt es keine onCreateView () oder jede andere UI-Logik direkt in diesem Fragment.

ImonCreate (), rufen wir setRetainInstance (true), so dass, wenn der Benutzer den Bildschirm dreht oder auf andere Weise löst eine Konfigurationsänderung, unser Modell Fragment wird die Änderung überleben und auf die neue Aktivitätsinstanz angebracht werden. Dann wird, wenn wir nicht schon die LoadWordsThread begonnen haben, tun wir dies. LoadWordsThread iteriert über unsere Liste von Wörtern, für für 400ms wirkliche Arbeit zu simulieren, zu tun, fügt jedes Wort zu einem Arraylist von Wörtern, die es schafft ... und ruft post () eine WordReadyEvent zu erhöhen, etwas anderes zu wissen, dass das Modell geändert hat.

Empfangen von Events

Um geschrieben Ereignisse empfangen zu können,müssen drei Dinge zu tun:

1. AnrufNeu registrieren()aufdasEventBuszu sagen, esdass Sie ein Objekt, das Ereignisse empfangen möchte

2. Anrufderegistrieren ()aufdasEventBuszu sagen, es liefert Ereignisse zu stoppenein zuvor registriertes Objekt

3. ImplementierenonEventMainThread () oder andere onEvent () -Methode Aromen, die Art des Ereignisses, um anzuzeigen, die Sie erhalten möchten (und zu verarbeiten, tatsächlich jene Ereignisse)

Diese Beispielanwendung hat eineAsyncDemoFragmentdass führt diese drei Schritte: (von

EventBus / AsyncDemo / app / src / main / java / com / commonsware /
android / EventBus / AsyncDemoFragment.java)

Das Fragment beginnt durch zwingendeonViewCreated (), Wo wir schaffen ein

ArrayAdapterund Verwendungdass zum Auffüllen derListenansicht.

DasonAttach ()undonDetach ()Methoden sind, wo wir zeigen aufdasEventBusdass dieses Fragment Objekt will relevant geschrieben Ereignisse zu empfangen.onAttach ()AnrufeNeu
registrieren();onDetach ()Anrufederegistrieren ().

DasonEventMainThread ()Verfahren, über dessen Parameter anzeigtdass wir daran interessiert sind,WordReadyEvents, wie sie erhoben werden. UnseronEventMainThread ()Verfahren wird für genannt werdenjederWordReadyEventweitergereicht anPost()aufdasEventBus. Da das Verfahren Name schon sagt,onEventMainThread ()wird aufgefordert,Hauptanwendungsthread, so ist es sicher, dass wir unsere UI zu aktualisieren. greenrobot des EventBus ist dafür verantwortlich, dass diese Veranstaltung zu den Hauptanwendungsthread - beachten Sie, dass wir die Veranstaltung von der EntsendungLoadWordsThread, Das ist ein Hintergrund-Thread.

ImonEventMainThread (), Erhalten wir die neu hinzugefügte Wort, das wir in unseren hinzufügenArrayAdapter.hinzufügen()aufArrayAdapteranfügt das Wort zum Ende der Liste, und informiert die beigefügteListenansichtdass die Daten geändert, so dasListenansichtkann selbst neu zu zeichnen.

Was istobwohl, aus dem Code nicht offensichtlich ist, ist in dieser Klasse, wie wir das bekommenModell-dass wir verwenden inonViewCreated ().AsyncDemoFragmenthat sein
eigenesAnordnungslistevon Worten, eingestelltüberdassetModel ()Methode.

UnserArrayAdaptergewickelt umdieses Model. Aber die Master-Kopie der Wörter wird durch die gehaltenModelFragment. wenn derModelFragmenthatdas Modell und dieAsyncDemoFragmentmuss das Modell, wie werden die beiden zusammen?

Die Aktivität

Dies wird durch unsere Hosting-Aktivität behandelt, wie es einrichtetDiese zwei Fragmente:

(von

EventBus / AsyncDemo / app / src / main / java / com / commonsware

/ android / EventBus / AsyncDemo.java)

ImonCreate ()Wir fi nden
sehen wenn wir bereits eine Instanz unseres Modells Fragment
haben, gehalten von dasFragmentManageruntereinMODEL_TAG-Tag. Obnicht schaffen wir eine Instanz derModelFragmentund fügen SiedasFragmentManagerUnter diesem Tag,über
eineFragmentTransaction.

Wirdann sehen, wenn wir bereits eine Instanz haben unsererAsyncDemoFragment. Wenn nicht, erstellen wir ein und fügen Sie ihn in dieFragmentManager, Gießen seine UI
inandroid.R.id.content,Über eine andereFragmentTransaction.

Dann verbinden wirdie beiden, ruftgetModel ()aufdasModelFragmentundÜbergabedas

ErgebnissetModel ()aufdasAsyncDemoFragment.

Bei unserer Tätigkeit ist die neu ins Leben gerufen,weder Fragment existiert. Beide Fragmente werden erzeugt, und dieAsyncDemoFragmenterhält seine Modellanordnung ausdasModelFragment.

Das Array ist zunächst leer. da dieModelFragmentfügtElemente in das Array, bucht sie dieWordReadyEvent, Die löst
dieAsyncDemoFragmenterzählendasArrayAdapterundListenansichtdass die Modelldaten geändert.

Wenn wir unterzieheneine Konfigurationsänderung, dieModelFragmentwird beibehalten, aberdasAsyncDemoFragmentistnicht. Daher wird die Aktivität immer werden die Schaffung einerAsyncDemoFragment. Aber das Modell geben wir dieAsyncDemoFragmentkann schon Worte in ihm haben, unddiese Worte wird erscheinen, wenn dieArrayAdaptergewickelt umdas Model. wenn derLoadWordsThreadläuft noch,das neueAsyncDemoFragmentabholen jedeneuWordReadyEvents, die ausgelöst werden, die Auslösung es die AktualisierungListenansichtwie vorher.

greenrobot des EventBus 3.x

Einige Beispiele indieses Buch eine neuere Version von greenrobot des EventBus verwenden.

Beginnend mit der Version 3.0, greenrobot der EventBus hat drei Änderungen zu dem, was wir in den vorangegangenen Abschnitten gesehen.

Zuerst,das Artefakt hat ein anderes Paket (org.greenrobot) zusätzlich zu der höheren Versionsnummer:

(von EventBus / AsyncDemo3 /
app / build.gradle)

Zweite,die Import-Anweisungen werden in Klassen aus dem Pull
org.greenrobot.eventbusJava-Paket stattde.greenrobot.event.

Aberdie größte Veränderung besteht darin, wie man die Methoden schreiben, die Ereignisse empfangen. Mit EventBus 2.x, musste man einen magischen Namen zu verwenden, wie
onEventMainThread (). Beginnen mit

Version 3.0, verwenden Sie jetzt Java-Annotationen zuidentifizieren und die Methode konfigurieren, die jede Methode Namen haben, die Sie wollen.

ImdasEventBus / AsyncDemo3Beispielprojekt, haben wirder gleiche Code wie bei der früheren EventBus Probe, aber aktualisiert, um die Teilnehmer Ansatz zu verwenden. Nun wird das Verfahren inAsyncDemoFragmentdass empfängt die Worte genannt wirdonWordReady ():

(von

EventBus / AsyncDemo3 / app / src / main / java / com / commonsware /
android / EventBus / AsyncDemoFragment.java)

Wir zeigen aufdas EventBus System, das diese Methode geeignet ist
erhaltenWordReadyEventVeranstaltungen überdas@AbonnierenAnmerkung. Java-Annotationen können mit Schlüssel-Wert-Paare konfiguriert werden; greenrobot des EventBus Anwendungendies für Dinge wie die Thread-Modus. So, anstatt zu habenMainthreadbeimdas Ende der Methodennamen (wie mitonEventMainThread ()), Können wir nun an,threadMode= ThreadMode.MAIN.

Andernfalls,Diese Probe wird von der 2.x Ausgabe der Probe unverändert.

Insgesamt,Dieses Buch ist die Migration langsam auf EventBus 3.x, so dass man eine Mischung aus 2.x und 3.x für eine Weile sehen.

Besuchdie Spuren!

Wir decken viel mehr über jank, und wie es zu erkennen und zu diagnostizieren, imeine spätere Kapitel.

Es gibt viele weitere Funktionen indie greenrobot EventBus Umsetzung. Wir werden einige von denen, plus andere Eventbus Implementierungen in einem späteren Kapitel sieheEvent Bus Alternativen.

Anfordern von Berechtigungen

ImEnde der 1990er Jahre, eine Welle von Viren über das Internet verbreiten, per E-Mail geliefert, Kontaktinformationen von Microsoft Outlook gekeult werden. Ein Virus würde einfach eine E-Mail Kopien von sich selbst an jeden der Outlook-Kontakte, die eine E-Mail-Adresse hatte. Dies war möglich, weil zu der Zeit, Outlook keine Schritte unternommen habe, Daten von Programmen mithilfe des Outlook-API zu schützen, da die API für gewöhnliche Entwickler konzipiert wurde, nicht Virenautoren.

Heutzutage haben viele Anwendungendass halten auf Kontaktdaten, dass die Daten sichern, indem sie verlangen, dass ein Benutzer explizit Rechte für andere Programme gewähren die Kontaktinformationen zugreifen zu können. Diese Rechte könnten auf einer Fall-zu-Fall-Basis oder alle auf einmal zum Zeitpunkt der Installation gewährt werden.

Android ist, dass es nicht anders, erfordert es Berechtigungen für Anwendungen zu Kontaktdaten lesen oder zu schreiben. Android Erlaubnis System ist nützlich, weit über die Kontaktdaten und für Anbieter von Inhalten und Diensten über die vom Android Framework geliefert.

Sie, als Android-Entwickler, wird häufigmüssen Sie Ihre Anwendungen haben die entsprechenden Berechtigungen, um sicherzustellen, zu tun, was Sie mit anderen Anwendungen "Daten machen wollen. Dieses Kapitel behandelt dieses Thema, sowohl den klassischen Ansatz für alle Berechtigungen vor Android verwendet 6.0 und der neuen Laufzeit Berechtigungssystem für bestimmte Berechtigungen in Android verwendet 6.0+.

Du könntest auchelect Berechtigungen erfordern für andere Anwendungen Ihre Daten oder Dienste zu nutzen, wenn Sie diejenigen zu anderen Android-Komponenten machen. Dies wird
diskutiertspäter imdieses Buch.

Häufig gestellte Fragen zu Berechtigungen

Berechtigungen sind gelegentlichein verwirrendes Thema in Android-App-Entwicklung, um so mehr jetzt, dass Android 6.0 ist da und hat das Berechtigungssystem ein gutes Stück verändert. Hier sind einige häufig gestellte Fragen zu Berechtigungen, die uns helfen beginnen.

Was isteine Genehmigung?

Eine Berechtigung ist eine Möglichkeit für Android (oder manchmal eine Drittanbieter-App) eine App-Entwickler, um den Benutzer über etwas zu informieren, dass die App das tun könnten Bedenken mit dem Benutzer zu erhöhen. Nur wenn eine Anwendung eine gewisse Berechtigung hält, kann die App bestimmte Dinge tun, die von dieser Erlaubnis verteidigt werden.

Mechanisch Berechtigungen nehmendie Form der Elemente in dem Manifest. Im Moment konzentrieren wir uns auf Ihr Interesse und hält Berechtigungen und so werden wir mit dem <Uses-permission> Element arbeiten.

Wann wirdIch benötige einen Permission?

Die meisten Berechtigungendass Sie von Android selbst mit kommen beschäftigen.

Üblicherweise wird die Dokumentation Ihnen mitteilen, wann Sie zu beantragen und eine dieser Berechtigungen halten.

Jedoch gelegentlichDie Dokumentation hat Lücken.

Wenn du bisteinige Code versucht, und Sie mit einem Security die Beschreibung der Ausnahme abstürzen kann Ihnen sagen, dass Sie eine gewisse Berechtigung zu halten brauchen

— das bedeutet, Sie müssen die entsprechende hinzufügen<Uses-permission>Element zu Ihrem Manifest.

Code von Drittanbietern, einschließlich Google-eigenen Play Services SDK kann definierenihre eigenen Berechtigungen. Wieder einmal, im Idealfall, Sie fi
aus dass Sie benötigen eine

Genehmigung durch Dokumente zu verlangen, und sonst Sie fi
aus durch während des Tests
abstürzt.

Was sind einige gemeinsame Berechtigungen, und was tun, sie verteidigen?

Es gibt Dutzende auf Dutzende von Berechtigungen in Android. Hier sind einige derdie Berechtigungen werden wir in diesem Buch:

• INTERNET, wenn Ihre Anwendung wünscht, auf das Internet durch irgendwelche Mittel von Ihrem eigenen Prozess zugreifen, indem etwas von rohen Java-Socketsüber die

WebView-Widget

• WRITE_EXTERNAL_STORAGE, Für Daten auf externe Speicher schreiben

• ACCESS_COARSE_LOCATIONundACCESS_FINE_LOCATIONZum

Bestimmen, wo das Gerät ist

• READ_CONTACTS, um persönlich identifizierbaren Informationen von beliebigen

Kontakten zu erhalten, die der Benutzer in ihre Kontakte-App hat

Imdieses Buch und in ungezwungenen Gespräch, verweisen wir auf die Rechte, um den einzigartigen Teil ihrer Namen (zB Internet). Wirklich, der vollständige Name der Genehmigung wird in der Regel android.permission haben. als Präfix (zB android.permission.INTERNET), für Android-defi

Berechtigungen. Individuelle Berechtigungen von Drittanbieter-

Anwendungen verwenden solltenein anderes Präfix. Sie werden die vollständige Erlaubnis Namen benötigen, einschließlich des Präfix, in Ihrem Manifest-Einträge.

Wie machtIch bitte um Erlaubnis?

Stellenein<Uses-permission>Element in Ihrem Manifest, als direktes Kind der Wurzel

<Manifest>Element (dh als Peer Element<Application>), mit einem
android: name Attribut identifiziert, die Berechtigung, die Sie interessieren.

Zum Beispiel, hier isteine Probe manifestieren, mit der Bitte, das zu halten,

WRITE_EXTERNAL_STORAGEErlaubnis:

(von

Dateien / FilesEditor / app / src / main

/ AndroidManifest.xml)

Dies ist ausrei
für die meisten Berechtigungen und die meisten Geräte. Berechtigungen
angesehen werdengefährlich benötigen besondere Aufmerksamkeit auf Android 6.0+, und wir werden, dass in großem Detail abdeckenspäter imdieses Kapitel.

Hinweisdass Sie sind willkommen, null, eins zu haben, oder mehrere solcher<Uses-permission> Elemente. beachten Sie auch,dass einige Bibliotheken, die Sie ihre eigenen wählen könnten zu verwenden hinzufügen

<Uses-permission>Elemente zu Ihrem Manifest, durch einen Prozess namens"Manifest Zusammenschluss".

Wann istder Benutzer informiert über diese Berechtigungen?

Gut,dass wird kompliziert. Es hängt von der Genehmigung, die Android-Version der Benutzer verwendet, aus dem der Benutzer die App installiert wird, und die Phase des Mondes.

(gut, ok,nicht wirklich, dass letzte)

Installation Durch SDK-Tools

Wer will eine App mit Android Studio installiertnicht für Berechtigungen aufgefordert. Das gleiche gilt für jedermann mit irgendetwas anderes auf der Basis der Android SDK-Tools -
während die App-Berechtigungen anfordern kann, wird der Benutzer nicht für sie aufgefordert werden, und die Berechtigungen erteilt werden.

(Android6.0+ und gefährliche Berechtigungen ändern, dies ein wenig auf - mehr dazuspäter in diesem Kapitel)

Installierenaus dem Play Store, Android 5.1 und älter

Obder Benutzer ein Android 5.1 oder älteres Gerät ausgeführt wird, und der Benutzer geht die App aus dem Play Store zu installieren, wird der Benutzer mit einer Liste von Erlaubnis vorgestellt Gruppendie enthalten Berechtigungen, die Sie anfordern, und die gelten als gefährlich:

Wir werden mehr über Berechtigungsgruppen zu diskutieren unddiese gefährliche Konzeptspäter im dieses Kapitel.

Installierenaus dem Play Store, Android 6.0+

Auf Android6.0 und höher, wenn der Benutzer die App aus dem Play Store installiert, was geschieht, hängt vom Wert von targetSdkVersion für Ihre Anwendung.

Wenn deintargetSdkVersion ist 22 oder niedriger, können Sie das gleiche Verhalten bekommen, wie oben beschrieben, in dem der Benutzer die Liste der Berechtigungsgruppen sieht die Berechtigungen enthalten, die Sie fordern und, die als gefährlich zu sein.

Wenn deintargetSdkVersion 23 oder höher ist, wird der Benutzer nicht bei der Installation zu Berechtigungen aufgefordert. Stattdessen tritt diese Aufforderungen, wenn der Benutzer die App läuft und wenn Sie den Benutzer für die Berechtigungen fragen, wie wir sehen werdenspäter imDies Kapitel.

Die Installation von anderenDie Mittel, Android 5.1 und älter

Wenn Sie eine App auf Android 5.1 oder älter, mit irgendwelchen Mitteln (zB installieren, das Herunterladen voneine Website), werden Sie mit einer Liste aller angeforderten Berechtigungen aufgefordert werden:

Hinweisdass diese Aufforderung wird nicht angezeigt, bis Sie die App tatsächlich heruntergeladen haben, und haben Sie den Installationsprozess begonnen. Bis dahin prüfen das Gerät nicht das Manifest in der APK fi
zu fi
die Berechtigungen.

Die Installation von anderenDie Mittel, Android 6.0+

Wenn Ihre ApptargetSdkVersion ist 23 oder höher, und Sie die App auf einem Android 6.0+ Gerät mit anderen Mitteln als der Play Store installieren, werden Sie nicht bei der Installation über alle Berechtigungen aufgefordert:

Eigenschaften von Berechtigungen

Mehrere Bits an Informationen bildeneine Erlaubnis, und einige von denen beeinflussen App-Entwickler oder Anwender.

Name

Wir haben bereits gesehen,dass die Berechtigungen Namen haben, und verwenden Sie sie im android: name-Attribut des <Uses-permission> Element eine Erlaubnis zu identifizieren, die Sie Ihre Anwendung zu halten möchten.

Android Framework definierten Berechtigungen mit beginnenandroid.permission. Berechtigungen aus Bibliotheken oder Drittanbieter-Anwendungen wird ein anderes Präfix haben. Stellen Sie sicher, dass, wenn Sie erstellen Ihre<Uses-permission>Element, das Sie den vollqualifizierten Erlaubnis Namen verwenden, einschließlichandroid.permissionoder jede andere Präfix.

beachten Sie auch,dass Android case-sensitive ist, so stellen Sie sicher, dass Sie den Fall der Genehmigung verwenden, wie dokumentiert (zB android.permission.INTERNET). Einige Versionen von Android Studio hatte einen Fehler, wenn Sie die IDE auto-complete a lassen

<Uses-permission>Element für Sie, manchmal hätte es dieandroid: name

Wert erscheinen in GROSSBUCHSTABEN. Das istein Fehler, der da gewesen fi zierte hat, so wird es hoffentlich in der Zukunft beeinflussen Sie nicht.

Schutzstufe

Die Definition voneine Erlaubnis, im Rahmen oder im Code von Drittanbietern, einen

"Schutzniveau" haben. Diese beschreibt, wie die Erlaubnis selbst validiert werden soll. Die beiden Schutzstufen, die Sie am häufigsten begegnen werden sind normal und gefährlich.

Normal

Eine normale Berechtigungs ist etwas, das der Benutzer über möglicherweise interessieren, aber wahrscheinlich nicht. Während wir also über die Genehmigung im Manifest müssen zu beantragen

<verwendet-permission>, wird der Benutzer nicht über diese Berechtigung belästigt werden Zeit zu installieren.

Das klassische Beispiel istINTERNET Erlaubnis. Die meisten Android-Apps eingereicht diese Erlaubnis gebeten, entweder für die von den Entwicklern oder Funktionalität geschrieben Funktionalität in von Bibliotheken gezogen (zB Werbebanner). INTERNET gilt als normal, also, während wir das Internet Erlaubnis im Manifest zu beantragen müssen, wird der Benutzer nicht über diese Genehmigung informiert mehr zum Zeitpunkt der Installation.

(Das "mehr" Bemerkenswert ist, weil indie frühen Tage von Android, die Nutzer über alle Berechtigungen informiert wurden, unabhängig von Schutzstufe)

Nutzer sehennormalen Berechtigungen, aber in anderen Orten:

• die Liste der Berechtigungen für den Play Store angezeigt, wenn auf einem

"Berechtigungen" Link klicken

• die Liste der Berechtigungen in den Einstellungen für eine Anwendung gezeigt

• Tools von Drittanbieterndass der Benutzer verstehen, welche Fähigkeiten für
die Anwendungen zur Verfügung stehen, die der Benutzer installiert

Gefährlich

Eine gefährliche Erlaubnis ist eine, die die definers der Erlaubnis (zB Google) sicherstellen will, dass der Benutzer ist sich dessen bewusst und hat sich bereit erklärt zu.

Klassisch,dies bedeutet, dass der Benutzer für diese Erlaubnis bei der Installation aufgefordert werden würde. Auf alten Versionen von Android und dem Play Store, würden gefährliche Berechtigungen, bevor die normale Berechtigungen aufgeführt werden.

Mit Android6.0+, während gefährliche Berechtigungen zur Zeit nicht angezeigt werden, installieren (für Anwendungen mit einem targetSdkVersion von 23 oder höher), so werden diese dem Benutzer angezeigt werden, während die App ausgeführt wird, bevor die App versucht, etwas zu tun, die eine dieser Berechtigungen erfordert. Dies ist ein signifi

Verhaltensänderung, so werden wir es in der Tiefe werden Bedeckungspäter imdieses Kapitel.

Berechtigungsgruppe

Die Berechtigungen werden in Berechtigungsgruppen gesammelt.

Imdie frühen Tage von Android, App-Entwickler waren dies nicht bewusst, als Berechtigungsgruppen keine Auswirkungen auf die App-Entwicklung, Laufzeitverhalten hatte, oder User Experience.

ImIn den letzten Jahren, die "Erlaubnis" aufgefordert, zum Zeitpunkt der Installation haben wirklich über Berechtigungsgruppen wurden aufgefordert. Der Benutzer wird gesagt, dass die App-Berechtigungen von bestimmten Gruppen anfordert. Darüber hinaus, dass der Segen der Benutzer gibt - durch die Fortsetzung der App zu installieren - ist von der Gruppe, nicht mit Genehmigung.

Wenn einige zukünftige Update für die App für eine neue Erlaubnis fragen würde, aber aus einer Gruppe, die der Benutzer vorher vereinbart, dass der Nutzer über diese neue Berechtigungsanfrage informiert.

Mit Android6.0 Berechtigungsgruppen auch auf das Runtime-Erlaubnis UX erweitern, wie während wir Entwickler noch einzelne Berechtigungen anfordern wird, wird der Benutzer aufgefordert werden, Rechte in Bezug auf Berechtigungsgruppen zu gewähren.

Maximale SDK Version

<Verwendet-permission> haben kann ein Android: maxSdkVersion Attribut. Dies zeigt die höchste API-Ebene, für die wir die Erlaubnis benötigen. Wenn die App auf neuere Versionen von Android läuft, lassen Sie die Erlaubnis.

Dies ist für Fälle, in denen Android entspannt Einschränkungen überZeit. Wir werden ein Beispiel dafür, in Form der WRITE_EXTERNAL_STORAGE Erlaubnis zu sehen, die inein kommenden Kapitel.

Mindest SDK Version

Das könnte dirdenken, dass<Uses-permission>hätte einandroid: minSdkVersion Attribut als zu dienendas Pendant zuandroid: maxSdkVersion. DasminSdkVersion
würde anzeigen,die niedrigste API-Ebene, für die eine Genehmigung zu beantragen; ältere Geräte würde die Erlaubnis überspringen.

Ach,Dies ist nicht verfügbar.

Jedoch gibt esdie ungeschickt genannte<Uses-Erlaubnis-sdk-23>Element.

DiesElement funktioniert genauso wie <verwendet-permission> auf Android 6.0+ Geräte. Bei älteren Geräten, wird er ignoriert.

DiesElement zeigt ein Problem mit dem Berechtigungssystem in Android: Sie alle Berechtigungen zu setzen, die Sie im Manifest wollen. Vor der Runtime-Berechtigungssystem in Android 6.0, würde dies bedeuten, dass Entwickler, die eine umstrittene Erlaubnis benötigen (zB READ_CONTACTS) für einige Rand Funktion müssten, die Erlaubnis von jedermann zu verlangen, nicht nur diejenigen, die die Funktion verwenden. Wie wir sehen werden, können die Laufzeitberechtigungssystem uns den Benutzer nicht die Mühe, bis sie die geschützte Funktion versuchen Sie es mit. <Verwendet-

Erlaubnis-sdk-23> würde uns mit der Erlaubnis überhaupt auf älteren Geräten zu nicht zulassen, dass die Mühe, wo seine Anwesenheit könnte potenzielle Nutzer abschrecken.

Neue Funktionen Berechtigungen in Alt-Anwendungen

Manchmal Android präsentiertneue Berechtigungen, die das Verhalten regeln, die früher keine Berechtigungen erforderlich war. WRITE_EXTERNAL_STORAGE ist ein Beispiel - ursprünglich, Anwendungen überhaupt auf externe Speicher ohne Erlaubnis schreiben konnte. androide 1.6
eingeführtWRITE_EXTERNAL_STORAGE, erforderlich, bevor Sie auf externe Speicher
schreiben kann. Jedoch können die Anträge, die vor dem Android geschrieben wurden 1,6 konnte unmöglich, dass die Erlaubnis beantragen, da es nicht zu der Zeit noch nicht gab. diese Anwendungen zu brechen scheint ein harter Preis für den Fortschritt zu sein.

Was Android tut, ist "Großvater" in bestimmten Berechtigungen für Anwendungen früheren SDK-Versionen zu unterstützen.

Zum Beispiel, wenn IhrminSdkVersion 3 oder weniger, sagen, dass Sie Android 1.5 unterstützt, wird Ihre Anwendung automatisch anfordern WRITE_EXTERNAL_STORAGE und

READ_PHONE_STATE, auch wenn Sie fordern nicht explizit diese Berechtigungen. Menschen Ihre Anwendung auf einem Android 1.5 Gerät installieren wird diese Anfragen zu sehen.

Wenn schließlich fallen Sie die Unterstützung fürdie ältere Version (zB wechseln minSdkVersion von 4 oder höher), Android wird nicht mehr verlangen, automatisch diejenigen Berechtigungen. Daher wirklich, wenn Ihr Code tut müssen diese Berechtigungen, müssen Sie sie selbst fragen.

Android 6.0+ Runtime Berechtigungssystem
in Android6.0 und höher Geräte, Berechtigungen, die über gefährlich sein, nicht nur aufgefordert werden, müssen in Betracht gezogen werden <verwendet-permission> Elemente, aber Sie müssen auch den Benutzer fragen Sie diese Berechtigungen zur Laufzeit zu gewähren. Was Sie gewinnen, ist jedoch, dass die Benutzer nicht mit diesen Berechtigungen sind gestört bei der Installation, und Sie können für bestimmte Berechtigungen zu verzögern wählen, bis zu dem Zeitpunkt, zu fragen, wie der Benutzer tatsächlich etwas tut, das sie braucht.

In diesem Abschnitt wird zeigen gelegentlich Code-Schnipsel ausdasBerechtigungen /

PermissionMongerBeispielprojekt.

Lassen Sie uns erkundendie Laufzeitberechtigungen System über eine neue Reihe von Fragen.

Berechtigungen Sind davon betroffen?

Es gibtneun Berechtigungsgruppen, die Android 6.0 verwaltet als Benutzer steuerbare Berechtigungen:

Erlaubnis

Erlaubnis

Gruppe

KALENDER

READ_CALENDAR.WRITE_CALENDAR

KAMERA

KAMERA

KONTAKT

GET_ACCOUNTS.READ_CONTACTS.WRITE_CONTACTS

LAGE

ACCESS_COARSE_LOCATION.ACCESS_FINE_LOCATION

MIKROFON

TON AUFNEHMEN

ADD_VOICEMAIL.CALL_PHONE.PROCESS_OUTGOING_CALLS.READ_CALL_LOG.

TELEFON

READ_PHONE_STATE.USE_SIP.WRITE_CALL_LOG

SENSOREN

BODY_SENSORS

READ_CELL_BROADCASTS.READ_SMS.RECEIVE_SMS.RECEIVE_MMS.

SMS

RECEIVE_WAP_PUSH.SMS SENDEN

LAGERUNG

READ_EXTERNAL_STORAGE.WRITE_EXTERNAL_STORAGE

Die Benutzer können die Berechtigungen von Gruppe zu widerrufen, durchdie Einstellungen App.

Sie können für Ihre Anwendung in die Seite zu gehen, klicken Sie auf Berechtigungen, und sehen Sie eine Liste der Berechtigungsgruppen, für die Sie Berechtigungen anfordern: Was geht indas Manifest?

Das Gleiche<Verwendet-permission> Elemente wie zuvor. Diese erklären die Ober aller möglichen Berechtigungen, die Sie haben können. Wenn Sie nichtüber eine <Uses-permission> Element für eine bestimmte Berechtigung haben, können Sie nicht für ihn zur Laufzeit fragen, und der Benutzer kann es Ihnen nicht gewähren.

Wie machtIch weiß, wenn ich die Erlaubnis habe?

Auf Android6.0+, können Sie einen AnrufcheckSelfPermission ()Verfahren, auf jederKontext(ZB

IhreAktivität). Dies wird zurückkehrenentwederERLAUBNIS ERTEILToderERLAUBNIS

VERWEIGERT, Je nachdem, ob der Benutzer Ihnen die Erlaubnis erteilt oder Sie erhielten die Erlaubnis automatisch gegeben (zB fürnormalBerechtigungen).

Füreine einfacherebooleanüberprüfen, um zu sehen, wenn Siedie Erlaubnis, könnten Sie Ihre eigene habenhasPermission ()Methode:

(von

Berechtigungen / PermissionMonger / app / src / main / java / com /
commonsware / android / permmonger / MainActivity.java)

Dann können Sie verwendendasshasPermission ()in dem Siebrauchen.

Beispielsweise,die PermissionMonger App fordert fünf Berechtigungen im Manifest: (von

Berechtigungen / PermissionMonger / app / src /
main / AndroidManifest.xml)

Die Benutzeroberfläche istdann eine Tabelle mit den aktuellen Status dieser fünf Berechtigungen zeigt: (von

Berechtigungen / PermissionMonger / app / src / main / java / com /
commonsware / android / permmonger / MainActivity.java)

Beimder Anfang, wir haben nur die eine "normale" Erlaubnis: INTERNET:

DascheckSelfPermission ()Verfahren aufKontextnur auf API-Ebene 23. Sie können, wenn Sie es wünschen, wickeln Sie Ihren AnrufcheckSelfPermission ()imeineÜberprüfung der API-Ebene des Geräts laufen Sie auf:

Ein einfacher Ansatz ist die VerwendungContextCompat, von demsupport-v4Bibliothek. Das hateinstatischImplementierung voncheckSelfPermission ()das dauert einKontextund Ihre Berechtigungszeichenfolge als Parameter. Es gibtder gleiche Wert

(zBPackageManager.PERMISSION_GRANTEDebenso wie) dascheckSelfPermission ()dass Schiffe mit Android 6.0. Aber, wenn Sie auf einemälteren Gerät ausgeführt wird,überprüft es die Version für Sie und kehrtPackageManager.PERMISSION_GRANTEDfürältere Geräte. Damit,Der obige Code-Schnipsel verwandelt sich in:

(unter der Annahme,dassDiesisteine Unterklasse vonKontext, mögenAktivität)

Wie machtIch weiß, wenn die Benutzerberechtigungen nimmt weg von mir?

Obräumt der Nutzer Sie zu einem gewissen Berechtigungsgruppe zuzugreifen, kann der Benutzer die einzige Möglichkeit, zu widerrufen kann, ist über die App Einstellungen. Wenn der Benutzer Zugriff auf eine Berechtigungsgruppe tut sperren, wird Ihr Prozess beendet.

Während also der Code ausgeführt wird, finden Sie alle Berechtigungendass Sie mit, plus alle neuen gestartet, räumt der Nutzer auf der Fliege auf der Grundlage Ihrer Anfrage. Es sollte keinen Umstand sein, wo Ihr Prozess läuft noch eine Genehmigung verlieren.

Aber sagen, dass Ihre Appnicht speziell über den Verlust der Genehmigung mitgeteilt. Sie sollten Aufruf checkSelfPermission werden (), um zu bestimmen, was Sie können und was nicht, zumindest für jeden Prozessaufruf. Und da der Anruf ziemlich billig zu sein scheint, sollten Sie es nur nennen, wenn Sie müssen wissen, ob Sie eine bestimmte Operation durchführen können.

Hinweis dass in der Regel Ihre Anwendung wird im Hintergrund sein, wenn sie überhaupt ausgeführt wird, zu dem Zeitpunkt, wenn eine Laufzeit die Erlaubnis widerrufen wird.

Insbesondere in einem Mehrfensterumgebung 7.0+ Android, ist es jedoch möglich, dass Sie immer noch sichtbar sein wird, wenn der Benutzer eine Erlaubnis Laufzeit widerruft. Ihr Prozess wird in jedem Fall beendet, und wenn Sie zu sehen waren, die Benutzeroberfläche wird vom Bildschirm entfernt.

Wie machtIch frage den Benutzer um Erlaubnis?

Fragender Benutzer für eine der Laufzeit-Berechtigungen, rufen requestPermissions () auf Ihre Aktivität. Das dauert ein String Array der Berechtigungen, die Sie fordern und eine lokal eindeutige ganze Zahl Anfrage von allen anderen ähnlichen Anforderungen zu identifizieren, die Sie werden machen können. Dieser int dient in der gleichen Rolle wie die int tut in startActivityForResult () übergeben, wenn Sie den Wert auf 8 Bit (0 bis 255) für maximale Kompatibilität halten sollte.

Zum Beispiel wird PermissionMonger Check-inonCreate (), um zu sehen, ob wir Standorte oder Zugang Kontakte zugreifen können, und wenn nicht, wird es den Zugang zu diesen beiden Berechtigungen anfordern:

(von

Berechtigungen / PermissionMonger / app / src / main / java / com /
commonsware / android / permmonger / MainActivity.java)

INITIAL_PERMSund INITIAL_REQUESTsind nur statischFinaleDatenelemente:

(von

Berechtigungen / PermissionMonger / app / src / main / java / com /
commonsware / android / permmonger / MainActivity.java)

(von

Berechtigungen / PermissionMonger / app / src / main / java / com /
commonsware / android / permmonger / MainActivity.java)

WannDie App ist fi
ins Leben gerufen, Dialoge werden angezeigt, eine pro Erlaubnis den

Benutzer auffordert, dass Sie aufgefordert, wenn sie wäre so gut wie Ihre Anwendung zu erlauben, die Dinge zu tun, die Sie angefordert:

Wannder Benutzer durch die Dialoge fort, werden Sie mit aufgerufen werden
onRequestPermissionsResult (). Sie sind drei Parameterübergeben:

• die lokal eindeutige ganze Zahl von IhremrequestPermissions ()Aufrufidentifizieren denenrequestPermissions ()Anrufdies ist das Ergebnis für

• ein String Array der angeforderten Berechtigungen

• einintAnordnung vondie entsprechenden Ergebnisse (ERLAUBNIS ERTEILToder

ERLAUBNIS VERWEIGERT)

Egal, ob Siediese beiden letztgenannten Parameter oder rufen Sie einfach an checkSelfPermission () wieder bis zu Ihnen ist. Unabhängig davon, an diesem Punkt sollten Sie bestimmen, was Sie haben, so dass Sie wissen, wie sie reagieren, wie die Dinge zu deaktivieren, die der Benutzer kann nicht das Fehlen von Erlaubnis verwenden.

Genauso wieContextCompatbietet aneine rückwärtskompatible UmsetzungcheckSelfPermission ().ActivityCompatbietet aneine rückwärtskompatible UmsetzungrequestPermissions ()dass Sie verwenden können. Andernfalls werden Sie andere Maßnahmen zu ergreifen, um sicherzustellen, dass Sie nur anrufenrequestPermissions ()auf API-Ebene 23+ Geräte.

Wenn DoIch frage den Benutzer um Erlaubnis?

Das hängt davon abein wenig von der Art der Genehmigung.

In einer idealen Welt, können Sie Ihre App funktioniert ohne vondie widerrufliche Berechtigungen, wenn auch vielleicht in einer begrenzten Art und Weise zu Ihnen, gewährt. In diesem Fall könnten Sie um Erlaubnis bitten, nur, wenn der Benutzer etwas zu tun versucht (zB tippt auf einer Aktionsleiste Artikel), für die Sie auf jeden Fall die Erlaubnis benötigen.

Aber manchmal werden Siebenötigen eine Berechtigung überhaupt nützlich für den Benutzer zu sein.

In diesem Fall müssen Sie um Erlaubnis fragen, wenn die App öffnet.

Imentweder Fall tragen Sie jedoch, dass im Auge, während der Benutzer den Dialog um Erlaubnis zu fragen sehen werden, kann der Benutzer nicht verstehen, warum Sie sich für diese Erlaubnis fragen.

Siemüssen sicherstellen, dass der Benutzer die Kosten / benefi trade-off bei der Erteilung der Erlaubnis versteht - mit anderen Worten, was der Benutzer aus dem Geschäft nicht bekommen?

Für Berechtigungendass Sie basierend auf Benutzereingaben anfordern möchten, können Sie einen eigenen Dialog oder andere UI-Pop zu erklären, was Sie wollen und warum Sie es wollen, bevor requestPermissions () aufrufen. Für Berechtigungen, die Sie wollen, wäre zu fragen, wenn die Anwendung startet, stellen Sie sicher, dass Sie deutlich die Notwendigkeit für die Berechtigungen erklären und was der Benutzer erhält im Austausch als Teileine einmalige Einführungstutorial, einsdas könnte auch über einen Überlauf Artikel oder nav Schublade Eintrag als Teil Ihrer App Hilfeeinrichtung zugegriffen werden.

Wenn DoIch Fragen Sie nicht den Benutzer um Erlaubnis?

Eine Einschränkung mitdie requestPermissions () Implementierung ist, dass es nicht bewusst ist auf Konfigurationsänderungen.

Beispiel: Angenommen,dass in onCreate () Ihrer Tätigkeit, Sie überprüfen, um zu sehen, ob Sie eine Runtime-Erlaubnis (via checkSelfPermission ()) gewährt wurden, und wenn Sie nicht haben, rufen Sie requestPermissions () es vom Benutzer anzufordern. Dadurch wird das Dialogfeld. Nun dreht der Benutzer den Bildschirm. Wenn der Benutzer die Erlaubnis verweigert, standardmäßig wird sofort der Benutzer sehen die Erlaubnis Dialog wieder ... weil Ihre Aktivität zerstört wurden, werden und neu erstellt, und Ihre onCreate () werden sehen, dass Sie nicht über die Berechtigung haben, und so fragen Sie wieder.

In Fällen wie diesem, werden Siemüssen zu verfolgen, ob Sie in der permission-Anforderungsablauf sind (zB über eine boolean im Instanz Zustand gespeichert Bundle) und überspringen die ersuchende Erlaubnis, wenn Sie neu erstellt worden sind indie Mitte dieser Strömung. Wir werden sehen, diese in Aktion indie kommende Laufzeitberechtigungen Tutorial.

Was tunIch tun, wenn der Benutzer sagt "Nein"?

Wenn Sie wurden beantragt die Berechtigung alseine direkte Antwort auf einige wenig Benutzereingaben (zB Benutzer auf einer Aktionsleiste Element abgegriffen) und der Benutzer lehnt die Erlaubnis Sie die Arbeit tun müssen, natürlich können Sie die Arbeit nicht machen. Je nach Gesamtablauf, einen Dialog oder zeigt etwas zu erklären, warum Sie nicht tun können, was der Benutzer gefragt, für erforderlich sein. In einigen Fällen kann halten Sie es aufgrund der Tatsache, offensichtlich zu sein, dass der Benutzer die Erlaubnis-Anfrage Dialog sah und sagte: "Verweigern".

Wenn Sie die Berechtigung wurden anfordernden präventiv, wie wenndie Aktivität beginnt, müssen Sie entscheiden, ob diese Entscheidung in der aktuellen UI reflektiert werden muss (zB "keine Daten verfügbar" Meldungen, deaktiviert Aktionsleiste Artikel).

Einswas Sie tun können, hier zu helfen, ist zu erkennen, wenn diese, bevor Sie Berechtigungen erneut anfordern aufgetreten ist. Bevor Sie requestPermissions () aufrufen, können Sie shouldShowRequestPermissionRationale () aufrufen, den Namen einer Erlaubnis zu liefern. Dies wird return true, wenn der Benutzer zuvor abgelehnt hatte Ihnen die Erlaubnis zu erteilen, in Fällen, in denen Android denkt, dass der Benutzer von Lernen ein wenig mehr über profitieren könnten, warum Sie die Erlaubnis benötigen. Sie können diese verwenden, um festzustellen, ob Sie einige erklärende Benutzeroberfläche der eigenen fi zeigen sollte
bevor Sie mit derdie

Berechtigungsanfrage, oder wenn Sie einfach weitermachen sollte und rufen requestPermissions ().

HinweisdassActivityCompathat aucheine rückwärtskompatible

UmsetzungshouldShowRequestPermissionRationale (), So können Sie Ihre eigenen API-Ebene Kontrollen zu vermeiden.

Was tunIch tun, wenn der Benutzer sagt: "Nein, und Bitte hör auf zu fragen"?

Der ZweiteMal ein Benutzer für eine bestimmte Laufzeit um Erlaubnis bitten, hat der Benutzer eine "Nie wieder fragen" aktivieren:

Obder Benutzer überprüft, ob und klickt auf die Schaltfläche Ablehnen, nicht nur erhalten Sie die Runtime-Erlaubnis nicht jetzt, sondern alle zukünftigen Anfragen werden sofort anrufen onRequestPermissionsResult (), das anzeigt, dass Ihr Antrag auf die Erlaubnis verweigert wurde. Der einzige Weg, kann der Benutzer jetzt Sie diese Berechtigung erteilen ist über die App Einstellungen.

Siemüssen diese Situation mit Anmut und Gelassenheit zu behandeln. Zur Auswahl stehen:

• Deaktivieren der UI-Eingang (zB Aktionsleiste Artikel)das kann nicht ausgeführt werden, da Sie die Berechtigung fehlt

• Anzeigenein Dialog, um die Situation zu erklären, mit einer Taste, die den Benutzer über Ihre App-Bildschirm in den Einstellungen verbindet, so kann der Benutzer Sie diese Berechtigung erteilen

• Es werden Inline-Nachrichten darüber, warum Sie können keine Daten zeigen (zBeine Liste der Kontakte, die Sie nicht zeigen kann, weil der Benutzer nicht Sie Zugriff) gewähren, vielleicht mit einem Hyperlink, der einen Bildschirm mit zusätzlichen

Informationen über die Situation zeigt

Für Berechtigungendass, wenn verweigert, Ihre Anwendung in einem völlig nutzlosen Zustand verlassen, können Sie sich einfach wickeln einen Bildschirm, auf App-Start anzeigt, die sagt "sorry, aber diese App ist nutzlos für Sie" mit Optionen für den Benutzer, die App oder Zuschuss zu deinstallieren Sie können die gewünschten Berechtigungen.

Hinweis dassshouldShowRequestPermissionRationale ()kehrt zurückfalschobder Benutzer lehnte die Genehmigung undüberprüft das Kontrollkästchen Sie bitten, den Benutzer zu stoppen belästigen.

Was passiert, wennIch liefere diesen zu einem älteren Gerät?

Ältere Geräte verhalten sich wiesie haben immer. Da Sie noch die Berechtigungen in der Manifest-Liste, werden diese Berechtigungen Sie werden gewährt, wenn der Benutzer die App installiert, und der Benutzer wird über diese Berechtigungen als Teil des Installationsprozesses benachrichtigt.

Wenn Sie die API Überprüfung Ebene selbst, oder Sie verwenden ContextCompat und

ActivityCompat wie oben beschrieben, sollten Sie Ihren Code einfach funktionieren.

Was passiert, wennMeine App hat eine niedrigere Ziel SDK Version?

Apps mitein targetSdkVersion unter 23, die auf der Oberfläche, auf Android 6.0+ verhalten, wie sie es auf einem älteren Gerät: der Benutzer für alle Berechtigungen aufgefordert wird, und die App diese Berechtigungen erteilt, wenn die App installiert ist.

Aber,der Benutzer noch in der Lage sein, in Einstellungen zu gehen und den Widerruf von Berechtigungen von diesen Anwendungen, für alle Berechtigungen der App-Anforderungen, die in einer der Laufzeit Berechtigungsgruppen sind.

Im Allgemeinen werden Sie wind up ignorierenDas Thema. Alle Anrufe werden auf Methoden durch Berechtigungen geschützt, dass der Benutzer revoke noch "arbeiten", soweit sie nicht eine Security werfen. Allerdings werden Sie nur keine Ergebnisse zurückbekommen oder die beabsichtigten Wirkungen haben. So zum Beispiel, wenn Sie versuchen, die Abfrage (), um die ContactsContract Contentprovider, und der Benutzer widerrufen Ihr Zugang zu kontaktieren bezogenen Berechtigungen, die Abfrage () einen leeren Cursor zurück. Dies ist eine völlig gültige Antwort, auch die Erlaubnis Problem zu ignorieren, da es durchaus möglich ist, dass der Benutzer keine Kontakte hat. Ihre Anwendung sollte diese Fälle werden Umgang mit anmutig sowieso. Daher, auch
in der Theorie, wenn Sie nichts weiter tun, die verlorenen Rechte in Bezug auf, sollten Sie Ihre App überleben, wenn auch mit reduzierter Funktionalität für den Anwender. Dave SmithUmrissedas erwartete Ergebnisse für Legacy-Anwendungen Methoden sans Erlaubnis aufrufen.

Jedoch alleUnter sonst gleichen Bedingungen, sollten Sie Ihre targetSdkVersion zu mindestens 23
und entscheiden sich in der Runtime-Berechtigungssystem eingestellt.

Was passiert, wennder Nutzer Löscht My App Data?

Obder Benutzer löscht die Daten Ihrer App durch die App Einstellungen werden die Runtime-Berechtigungen ebenfalls gelöscht. Verhalten an diesem Punkt wird sein, als wenn die App gerade installiert worden war - checkSelfPermission () wird PERMISSION_DENIED zurückkehren, und Sie müssen die Berechtigungen zu beantragen.

Wie kannIch Automatisieren Permission Grants?

Währenddie Laufzeit Berechtigungssystem bietet eine vernünftige Benutzer gerichtete UI, mit diesem UI ständig als ein Entwickler ein signifi zu beschäftigen

Schmerz. Zum Testen und

Debuggen Zwecke gibt es einige Befehlszeilenoptionen für die Gewährung und Entziehen von Berechtigungen dass Sie verwenden können.

SollteIch verwenden PermissionChecker?

checkSelfPermission ()aufContextCompatimmer wiederERLAUBNIS ERTEILTobentweder:

• Ihre Anwendung hateintargetSdkVersionunter 23, oder

• Ihre Anwendung läuft aufein Gerät älter als Android 6.0

ERLAUBNIS VERWEIGERTwenn Sie entschieden sich nur haben zurück indie neue Runtime-Berechtigungssystem (targetSdkVersionvon 23 oder höher), laufen Sie auf Android

6.1
oder höher undder Benutzer entweder gewährt nie die Erlaubnis oder es durch die App Einstellungen widerrufen.

Der Schlüssel ist,dass selbst wenn Sie auf Android 6.0, mit einemälteren
laufentargetSdkVersion(Sowerden alle Berechtigungen angefordert zu installierenZeit und werden Sie automatisch gewährt),checkSelfPermission ()noch gibtERLAUBNIS ERTEILTselbst wennder Benutzer keine Genehmigung des in den Einstellungen.

Die Android-Support-Bibliotheken- speziellsupport-v4- Hat einPermissionCheckerKlasse miteincheckpermission ()statische Methode. Wenn Sie laufen auf Android6.0+ mit einer älterentargetSdkVersion.checkpermission ()wird
zurückkehrenPERMISSION_DENIED_APP_OPobder Benutzer keine Genehmigung des in den

Einstellungen.

Daher,PermissionChecker ist nützlich in Fällen, in denen Sie einen wirklich großen Code-Basis haben, und Sie wollen eine bessere Behandlung von Fällen, um zu versuchen, wo Benutzer-

Berechtigungen widerrufen, aber Sie sind in der Lage nicht eine vollständige Implementierung der Laufzeitberechtigungen zu tun

System. Es ist jedoch lediglicheine Notlösung - sollte Ihr langfristigen Plan, um Ihre targetSdkVersion bis 23 oder höher und implementieren, um die Laufzeit-Berechtigungen ordnungsgemäß zu erhöhen.

Wo kannIch sehe dies in Aktion?

Das Buch hatein eigenständiges Tutorialdemonstriert, wie man hinzufügendie Laufzeit Erlaubnis überprüft, eine bestehende App.

Tutorial: Runtime Permission Unterstützung

Android 6.0 die Laufzeit-Berechtigungen einfach klingen aufdie Oberfläche: einfach anrufencheckSelfPermission ()um zu sehen, wenn Siedie Erlaubnis, dann
rufenrequestPermissions ()wenn Sie tunnicht.

In der Praxis sogareine ziemlich einfache Anwendung, die diese Berechtigungen verwendet, hat eine bemerkenswerte Menge an Code hinzuzufügen, alle Kombinationen von Staaten zu handhaben, sowie mit einigen Besonderheiten in der API beschäftigen. Und natürlich, da nicht jeder wird ein neues Gerät ausgeführt werden, haben wir auch die Abwärtskompatibilität zu prüfen.

Dieses Standalone-Tutorial- Nicht Teil der EmPubLite Reihe von Tutorials für den Rest der Kernkapitel - konzentriert sich auf die Laufzeit Erlaubnis Unterstützung einer bestehenden Android-Anwendung hinzuzufügen.

Wie beidie anderen Code-Schnipsel in diesem Buch, wenn Sie sich von der PDF zu kopieren und versuchen, werden Sie neigen dazu, die besten Glück haben, wenn Sie die offi verwenden Adobe Acrobat Reader-App.

Wenn Sie möchten, können Sie arbeiten mitdas Tutorial-Code von GitHub, einschließlich:

• das fertige Projekt

• das Hauptaktivitätfürdas fertige Projekt

Bestimmtes,letztere Verbindung, wobei einfachen Text, kann einfacher sein, von zu kopieren und einzufügen, für Situationen, in denen wir den Code modifizieren direkt zu entsprechen, was im fertigen Projekt sein wird.

Auch als Teil der Arbeit anIn diesem Tutorial werden Sie viele Schnipsel von Java-Code hinzufügen. Sie müssen Import-Anweisungen für die neuen Klassen von diesen Code-Schnipsel

eingeführt hinzuzufügen. Klicken Sie einfach auf den Namen der Klasse, rot markiert, in Android

Studio und Presse<Alt> - <Enter>aufrufen Der Quick-Fix die erforderliche hinzufügeneinführen Erklärung.

Schritt # 0: Installierendas Android 6.0 SDK

Sie werden zumüssen die Android 6.0 (API 23) SDK-Plattform (oder höher), um der Lage sein, Runtime-Erlaubnis Unterstützung zu implementieren. Sie können es schon haben, oder Sie können es installieren.

Wenn Sie eröffnen-Manager Android Studio SDK, über Extras> Android> "SDK-Manager", dann sollten Sie Android 6.0 als Option angezeigt wird:

Wenn Sie habenein Gerät mit Android 6.0+ auf sie, sind Sie herzlich eingeladen, die Beispielanwendung zu laufen, und es sollten Sie Bilder und Videos aufnehmen können. Wenn Sie die Beispielanwendung auf einem Android 6.0+ Emulator laufen zu lassen, dass die Berechtigungen Logik werden wir zum Tutorial App das Hinzufügen funktionieren wird, aber es wird nicht wirklich Bilder oder Videos aufnehmen nehmen. Wenn Ihr Emulator Bild 1+ Kameras konfiguriert ist (siehe

"Erweiterte Einstellungen", um bei der Definition oder Bearbeiten Ihrer AVD), nehmen die Aktivitäten ein Bild und Aufzeichnung wird ein Video kommen aber nur eine unbestimmte Fortschrittsanzeige zeigen. Ob

Ihr Emulator Bild hatkeine Kameras konfiguriert, werden diese Aktivitäten nur
unmittelbar fi
und Rückkehr Kontrolle zu unserem Beispielhaupttätigkeit der

App.

Schritt 1: Import und Bewertungdas Starter-Projekt

Herunterladendas Starterprojekt ZIP-Archivund entpacken Sie es irgendwo auf Ihrer Entwicklungsmaschine.

Dann verwenden Sie Datei> Neu> Projekt importieren, dieses Projekt in Android Studio zu importieren. Android Studio können Sie für weitere Updates aus dem SDK-Manager veranlassen (zB

Build-Tools), je nachdem, was Sie auf Ihrer Entwicklungsmaschine eingerichtet haben.

Wenn Sie laufendas Projekt auf einem Android 4.0+ Gerät oder Emulator, werden Sie unsere hochentwickelte Benutzeroberfläche, bestehend aus zwei großen Tasten sehen:

Tappingdie "Bild aufnehmen", um eine Kameravorschau, mit einem schwimmenden Aktionstaste (FAB) ein Bild aufzunehmen bringen:

Tappingder FAB (und der Aufnahme eines Bildes) oder BACK drücken werden Sie auf die ursprüngliche Zwei-Tasten-Aktivität zurück. Dort wird die "Video aufnehmen" Taste tippen eine ähnliche Tätigkeit zu bringen, in dem Sie die grüne Aufzeichnung FAB drücken können, um den Anfang eines Videoaufzeichnung:

Wenn Sie die Aufnahme starten,die FAB wird auf einem roten Stopp-Taste ändern. Tippen Sie das, oder BACK aus jedem Zustand drücken, kehren Sie in die Ausgangs Zwei-Tasten-Aktivität.

Die Anwendung nutzt zwei Dritt Abhängigkeiten aller ziehendies aus:

• Philip CalvinsIconButton

• die AutorenCWAC-Cam2, Die Arbeitsgeräte die Foto- und Video-Aktivitäten

Unsere zwei Layouts,res / Layout / main.xmlundres / Layout-Land / main.xml, Nimm zweiIconButtonWidgets ineinLinearlayoutMit gleichen Gewichten, so dass die Tasten Hälfte des Bildschirms jeweils aufzunehmen:

(von

Berechtigungen / tutorial / Start / RuntimePermTutorial / app /
src / main / res / Layout-Land / main.xml)

MainActivity verwendet dann CWAC-Cam2 jeder der Tastenklicks zu handhaben:

(von

Berechtigungen / tutorial / Start / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Die Details, wie CWAC-Cam2 Werkenicht besonders relevant für das Tutorial, aber man kann darüber mehr erfahrenspäter imdas Buchwenn Sie interessiert sind.

Aufnehmen von Bildern und Videoaufnahmen benötigen drei Berechtigungen:

• KAMERA

• WRITE_EXTERNAL_STORAGE(woherder Ausgang wird)

• TON AUFNEHMEN(Für Videos)

Unser Manifest fordertkeine dieser Berechtigungen:

(von

Berechtigungen / tutorial / Start / RuntimePermTutorial / app /
src / main / AndroidManifest.xml)

Die Berechtigungen kommen ausdie CWAC-Cam2 Bibliothek, mit freundlicher Genehmigung von einem Prozess bekannt alsmanifestieren Fusion.

Sie fragen sich vielleicht, warum wir würden die Mühe machendies mit einer Kamera Bibliothek in unserer eigenen App. Die meisten Android-Geräte mit Kamera-Hardware haben eine Kamera-App, und die meisten Kamera-Anwendungen - insbesondere vorinstallierte Kamera-Anwendungen -
haben Aktivitäten, die wir nehmen Bilder oder Videos aufnehmen aufrufen könnte. Allerdings sind diese Aktivitäten selten getestet, und viele nicht richtig funktionieren. Da sie unzuverlässig sind, können Sie glücklicher sein, etwas verwenden, das eine Bibliothek, in der App gepackt.

Hinweisdass MainActivity hat einige scheinbar superfl

BitsCode. Insbesondere wir
delegierendie tatsächliche CWAC-Cam2 Arbeit takePictureForRealz () und recordVideoForRealz (), anstatt nur, dass die Arbeit in der Takepicture tun () und recordVideo () Methoden, die von den Tasten aufgerufen. Der Grund für diese scheinbare Ineffizienz ist die Menge der Arbeit zu reduzieren, die Sie ergreifen, um die Laufzeit Berechtigungen hinzuzufügen, durch ein winziges bisschen Buchhaltung vor der Zeit der Handhabung.

Schritt # 2: Update Gradlefür Android 6.0

In der Standardeinstellung, wenn Sie laufenDiese App von Ihrem IDE auf einem

Android-6.0-Gerät scheint nichts anderes zu sein. Die App läuft, wie es tat.

Wenn Sie es zu installieren waren überein Download, wie von einer Website, sucht der Installationsprozess, wie es bei früheren Android-Versionen der Fall ist, den Benutzer für jede der Berechtigungen aufgefordert werden:

Aber,der Benutzer kann immer noch in Einstellungen gehen und unseren Zugriff auf die Berechtigungen wählen zu deaktivieren:

In unserem Fall,nicht alle sind diese Berechtigungen immer benötigt, und es wäre nützlich zu wissen, ob wir eine Genehmigung, und so die Einführung des neuen Runtime-Berechtigungsmodell halten wäre eine gute Idee zu sein scheinen.

Der fi

Schritt auf Die Straße, die zu tun ist, um einige Werte in unserem app / Moduls einstellen build.gradlefi

• VeränderungcompileSdkVersionbis 23, wie wirmüssen Methoden aus dem aktuellen SDK
verwenden

• VeränderungbuildToolsVersionbis 23.0.0, es synchron zu halten mitdas
compileSdkVersion, und

• VeränderungtargetSdkVersion bis 23, zu sagen, Android, dass unsere App mit dem Runtime-Berechtigungsmodell in Verstand geschrieben wurde

Dies wird Ihnen einandroid Schließung wie:

(von

Berechtigungen / tutorial / Ziel /

RuntimePermTutorial / app / build.gradle)

Schritt # 3: Reviewdie geplante UX

Also, unsere App ist hier Bilder und Videos aufnehmen. Vondie drei Berechtigungen, die unsere App insgesamt anfordert, zwei sind von wesentlicher Bedeutung für die App etwas Sinnvolles zu tun: CAMERA und WRITE_EXTERNAL_STORAGE. RECORD_AUDIO, hingegen ist nicht
erforderlich, wenn der Benutzer nur wünscht Bilder aufzunehmen.

Teil vondas Ziel der Systemlaufzeit-Berechtigungen ist es, Ihnen zu ermöglichen Anfrage Berechtigungen lazy-, die viele Benutzer nicht brauchen kann. Wenn es einige Franse-Funktion in Ihrer Anwendung, die, sagen wir, READ_CONTACTS braucht, anstatt alle zwingen Sie READ_CONTACTS zu geben, können Sie es fordern nur der Benutzer, die in die

Benutzeroberfläche auf dem Weg gehen, die dem Feature führt, die benötigt READ_CONTACTS-gesichert Fähigkeiten.

Daher werden wir nur fragen nachdie RECORD_AUDIO Erlaubnis, wenn der Benutzer tippt die

"Video aufnehmen" klicken.

Fürdie beiden anderen Berechtigungen, könnten wir den Ansatz zu fragen, für sie nur, wenn der Benutzer eine der beiden Tasten tippt. Allerdings sind diese Berechtigungen wesentlich für App Betrieb, und so ein weiterer Ansatz ist für die Berechtigungen für fi fragen

Lauf von die

App, und nur über sie auf Tastenklicks Sorgen machen, wenn unsere ursprüngliche Anfrage abgelehnt wurde. Sie könnten eine Art "Onboarding" welcome Tutorial haben, die ein wenig erklärt, warum wir für die Berechtigungen zu fragen gehen. Oder könnten Sie fragen Sie einfach für die Berechtigungen, und hoffen, dass die Nutzer haben, bevor diese Art der Anfrage Dialoge gesehen, da diese App (der Einfachheit halber so viel wie irgendetwas anderes) zu tun.

Wannder Benutzer auf eine Schaltfläche klickt, müssen wir sehen, nochmals zu überprüfen, ob wir die Rechte haben, und vielleicht den Benutzer auffordern, erneut für die Berechtigungen. Auf dem Weg dorthin können wir einige "rationale" zeigen wollen - eine Erklärung, in der eigenen Benutzeroberfläche, warum wir die Berechtigungen benötigen, die wir für die zuvor gefragt, und der Benutzer "Nein" gesagt.

Wenn jedochder Benutzer lehnt nicht nur uns etwas die Erlaubnis zu erteilen, sondern überprüft auch das Kontrollkästchen anzeigt, dass wir bitten, nicht zu halten sind, werden wir die betroffenen Taste (n) zu deaktivieren und kann, da der Benutzer nicht diese Funktionalität nutzen können. Alternativ könnten wir die Tasten klickbare halten, aber anstatt die eigentliche Arbeit zu tun (was wir aus Mangel an Berechtigungen nicht kann), eine Meldung den Benutzer auf die Einstellungen App fl Regie
die Schalter und erteilen die Berechtigungen zu unserer App. Die App in diesem

Tutorial zufrieden geben nur die Tasten zu sperren.

So fürjedes unserer Berechtigungen sind wir in einem von vier Zuständen:

1. Wir haben nie gefragtdie Erlaubnis, bevor

2. Wir fragten nachdie Erlaubnis, und der Benutzer es gewährt

3. Wir fragten nachdie Erlaubnis, und der Benutzer entweder abgelehnt unser Verlangen oder vielleicht ist es gewährt aber änderte dann ihren Geist und drehte die Erlaubnis wieder aus in den Einstellungen

4. Wir fragten nachdie Erlaubnis, und tat nicht nur der Benutzer ablehnen, aber der Benutzer auch (über eine Checkbox) darauf hingewiesen, dass wir nicht wieder zu fragen,

Wir werdenmüssen zwischen diesen vier Staaten im Rahmen unserer App Logik zu
unterscheiden, um das richtige Verhalten in jedem Fall zu präsentieren.

Schritt # 4: ErkennenDer erste Lauf

Wenn wir gehen, um zu bittenDie Kamera und die WRITE_EXTERNAL_STORAGE

Berechtigungen für den fi

Lauf unserer App, wir müssen wissen, wann die fi

Laufunserer App ist passiert. Um dies zu tun, werden wirein typischer Ansatz, einen Booleschen Wert in SharedPreferences, um festzustellen, ob wir vor ausgeführt haben.

MitIn diesem Sinne, fügen Sie die folgende Konstante Erklärung MainActivity:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dies dient alsder Schlüssel zu unseremboolean SharedPreferencesWert. Dann füge
hinzufolgendeprefsDaten MitgliedHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Als nächstes initialisierenprefsimHauptaktivitätKurz nach demsetContentView ()Anruf: (von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dann füge hinzudie folgende MethodeHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dies ruftdie vorhandenen Wert auf true säumigen wenn es keinen solchen Wert. Wenn wir diesen Standard zurück, aktualisieren wir dann die SharedPreferences für die zukünftige Verwendung falsch zu speichern.

Schließlich wird beider Grund vononCreate ()vonHauptaktivitätFügen Sie die folgenden Zeilen: Wir ersetzendass Kommentar kurz.

Schritt # 5: On First Run, Fragen Sie nach Berechtigungen

Wie in bedeckt zurückSchritt 3Wir wollen zu
fragendasKAMERAundWRITE_EXTERNAL_STORAGEBerechtigungen fürdie fi

Laufunserer App. Tunzu erreichen, müssen wir nennenrequestPermissions ()von
innendassobBlock haben wir inden vorherigen Schritt.

requestPermissions ()nimmt zwei Parameter:

1. Ein String-Array der vollqualifizierten Namen der Berechtigungen, die wir wollen, 2. Einintdas wird uns in eine zurückgeschickt werdenonRequestPermissionsResult

()Callback-Methode, so können wir unterscheidenDie Ergebnisse
einesrequestPermissions ()Anruf von einem anderen

Sie fragen sich vielleicht, warum, wenn das HinzufügenDiese im Jahr 2015 nutzen die Android-Ingenieure eines Callback-Objekt eine Art nicht, sondern als Kampf mit int-Werten. Auch Manchmal fragt sich der Autor dieses Buches.

Aber, egal,das ist, was wir brauchen, und wir hatten am besten beginnen, es zu implementieren.

Erstens, um unseren Code machenein bisschen leichter zu lesen, die folgenden statischen Import-Anweisungen zu MainActivity hinzufügen:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Wenn Sie habennicht diese Java-Syntax zuvor gesehen, importiert eine statische Import grundsätzlich eine statische Methode oder fi
von eine Klasse (in diesem Fall von

Manifest.permission). Das Ergebnis des Imports ist, dass wir auf die importierten Elemente beziehen können, als ob sie auf unserer eigenen Klasse statische Elemente waren. So können, haben wir nur einen Verweis auf CAMERA, zum Beispiel, anstatt jedes Mal so etwas wie

Manifest.permission.CAMERA zu buchstabieren.

Als Nächstes fügenfolgendestatic StringArrayHauptaktivität, Eine, die einige unserer neu hinzugekommenen verwendetstatischImporte:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

fügen Sie auchfolgendeintkonstantHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Jetzt können wir unsere Rechte fordern. Allerdings, wenn wir nennenrequestPermissions () auf Aktivität, wir haben ein Problem: das Verfahren nur in API-Level 23 hinzugefügt wurde Wenn unsere minSdkVersion 23 oder höher waren, ist das kein Problem sein würde. Allerdings ist unsere minSdkVersion 15, und es wäre schön, Android 4.x und 5.x Geräten zu unterstützen.

Die empfohlene Lösung fürdies ist eine ActivityCompat Klasse zu verwenden, durch die Unterstützung-v4 Teil der Android-Support-Bibliothek geliefert. Diese Klasse enthält unter anderem eine requestPermissions () statische Methode, wird Konfi
dass wir auf einem Gerät neu
genug sind requestPermissions zu unterstützen (). Bei älteren Geräten, es degradiert anmutig (in diesem Fall nichts zu tun, wie wir bereits unsere Berechtigungen).

Also, mitin diesem Sinne, bearbeiten Sie diebuild.gradlefi
im dasapp /Modul hinzufügen im
support-v4:

(von

Berechtigungen / tutorial / Ziel /

RuntimePermTutorial / app / build.gradle)

Dann aktualisierendasobBlock inonCreate ()vonHauptaktivitätaussehen:

Der entsprechende Rückruf fürrequestPermissions ()istonRequestPermissionsResult (). So fügen Sie eine Stub-Implementierung dieser RückrufHauptaktivität:

Nach wie vor werden wir ersetzendass // TODO später im Tutorial ein wenig.

Beimdieser Punkt, die App auf Ihrem Android-6.0-Umgebung ausgeführt werden. Ab sofort, sollten Sie für die Berechtigungen aufgefordert:

Dann deinstallierendie App. Auf diese Weise, egal, ob Sie diese Berechtigungen angenommen oder abgelehnt, das nächste Mal, wenn Sie die App ausführen, werden Sie "ausgehend von einem sauberen Schiefer". Eine Alternative zur Deinstallation wäre die Daten Ihrer App aus dem Inneren der App Einstellungen zu löschen, wie das wird auch Ihre Berechtigungen zurücksetzen, um ihre just-nachinstallieren Zustand.

Schritt # 6: Überprüfenfür Berechtigungen vor der Aufnahme

Wenn wir Glück haben, unsere Nutzer uns gewährendie Berechtigungen, die wir angefordert. Wir werden nicht immer Glück haben; Einige Benutzer werden unsere Anfrage ablehnen. Darüber hinaus wurden einige Benutzer könnten diese Berechtigungen für unsere App in den Einstellungen ändern, die Erteilung oder den Widerruf sie als jene Benutzer fi sehen

Also, wennder Benutzer tippt die "Take Picture" klicken, müssen wir sehen, nochmals zu überprüfen, ob wir tatsächlich die Rechte haben, die wir brauchen. Wenn wir das nicht tun, können wir nicht weitermachen und das Bild aufzunehmen "für realz", wie wir es mit einem Security abstürzen, weil wir die Erlaubnis fehlt.

Mitin diesem Sinne, fügen Sie den folgendenhasPermission ()MethodeHauptaktivität: (von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dies ist nureine bequeme Methode Unordnung an anderer Stelle in der Klasse zu reduzieren, wenn wir, ob wir eine Erlaubnis versuchen zu bestimmen, haben. Dieses Verfahren
verwendetContextCompat, Eine andere Kompatibilitätsklasse aussupport-v4zu sehen, zu, wenn wir die mitgelieferte Berechtigung haben. Während wir nennen könntecheckSelfPermission ()direkt auf unsererHauptaktivität, Würden wir in das gleiche Problem laufen, die wir haben
mitrequestPermissions ()-checkSelfPermission ()nurgibt es auf API-Ebene 23+.

DasContextCompatAusgabe des Verfahrens verschlechtert anmutig auf älteren Geräten, RückkehrERLAUBNIS ERTEILTDa wir bereits die Erlaubnis haben.

Als Nächstes fügenfolgendecanTakePicture ()MethodeHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Hier,canTakePicture ()einfachüberprüft, um zu sehen, ob wirübernehmen könnenein Bild, indem geprüft wird, ob wir haben dieKAMERAundWRITE_EXTERNAL_STORAGEBerechtigungen.

Dann,ändern dieein Bild machen()Methode vonHauptaktivitätaussehenDies:

Hier haben wir nur versuchen,zu nehmen, wenn die Abbildung haben wir die Berechtigungen.

Natürlich, wenn wir nicht haben,die Berechtigungen, gerade jetzt ignorieren wir die Benutzer klickt auf unsere "Bild aufnehmen" klicken. Wir sollten wirklich mehr Feedback bieten hier, und wir werden das kleine Problem in späteren Schritten dieses Tutorials anpacken.

Nun laufendie App auf einem Android-6.0-Umgebung. Wenn Android Sie für die Berechtigungen fordert, akzeptieren sie. Dann tippen Sie auf die "Take Picture" klicken, und Sie sollten sich ein Bild zu machen können.

Dann deinstallierendie App und starten Sie es erneut, dieses Mal die Berechtigungen Ablehnung, wenn Sie gefragt. Dann tippen Sie auf die "Take Picture" klicken, und Sie sollten keine Antwort von der App erhalten.

Schließlich deinstallierendie App.

Schritt 7: Erkennen, wenn wir einige Rationale sollte zeigen

Nachdemkeine Antwort auf Antippen der Taste "Bild aufnehmen", wenn wir nicht über die erforderlichen Berechtigungen verfügen, ist nicht eine sehr gute User Experience. Wir sollten wieder fragen für die Berechtigungen ... wenn es eine Chance gibt, dass der Benutzer sie uns tatsächlich gewähren.

Diese Chance wird verbessert, wenn wir erklären,sie, ein bisschen mehr, warum wir für diese Berechtigungen fragen immer wieder. 6.0 Android hat eine shouldShowRequestPermissionRationale (), die wir verwenden können, um zu entscheiden, ob wir einige UI zeigen sollte (und dann fragen, später für die Berechtigungen wieder) oder ob der Benutzer überprüft hat das Kontrollkästchen "nicht noch einmal fragen", und wir sollten sie in Ruhe lassen .

MitIn diesem Sinne, fügen Sie die folgende Methode MainActivity:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

DiesshouldShowTakePictureRationale ()einfachüberprüft, ob wir zu sehenmüssen Gründe zu zeigen, für jede der Berechtigungen erforderlich, um ein Bild aufzunehmen. Es nutzt
dieshouldShowRequestPermissionRationale ()Methode, die zurückfalschob:

• Sie haben nie gefragt, fürdie Erlaubnis, oder

• Du hast bereitsdie Erlaubnis (in diesem Fall sollten Sie wahrscheinlich nicht belästigen, diese Methode zu nennen), oder

• Sie haben gefragtdie Erlaubnis, ein paar Mal, und das letzte Mal, verweigert der Benutzer nicht nur die Erlaubnis, sondern überprüft auch das Kontrollkästchen Sie um die Erlaubnis, in der Zukunft wieder zu fragen, zu verhindern,

Andernfalls,shouldShowRequestPermissionRationale ()wird zurückkehrenwahr.

Wie beidie anderen Laufzeit permission-spezifi hier verwendeten MethodenHauptaktivität, Während es gibt eine im SDK für den direkten Einsatz (shouldShowRequestPermissionRationale ()aufAktivität) Wurde hinzugefügtin API Stufe 23. Die Rückportierung

(shouldShowRequestPermissionRationale ()aufActivityCompat) Wird Fälle behandeln, in denen wir auf einerälteren Version von Android laufen.

Dann,ändern Sie die vorhandeneein Bild machen()Verfahren aussehenDies:

So, jetzt prüfen wir, ob wir zeigen sollteder Benutzer eine Erklärung für die Berechtigungen ...

obwohl wir nicht, dass nur noch zu tun. Wir werden im nächsten Schritt auf das zu bekommen.

Schritt 8: HinzufügenBerechtigungen eine Begründung UI und Re-Request

Wirmüssen etwas tun, um den Benutzer zu erklären, warum wir diese Berechtigungen benötigen.

Eine schlechte Wahl wäre ein Toast anzuzeigen. Das sind zeitlich begrenzt und so sind nicht gut für längere Nachrichten zeigt.

Wir könnten anzeigeneinDialogodereinImbissbude… aber wir habennicht darüber gesprochen, wie entweder von denen nur noch in diesem Buch zu tun.

Wir könnten etwas von unserem Hilfesystem angezeigt werden, oder gehen Sie durchDer einleitende Tutorial noch einmal oder so ähnlich ... aber diese App nicht über alle diese Dinge.

So werden wir stattdessen nehmeneine sehr grobe UI-Ansatz: eine versteckte Panel mit unserer Mitteilung addieren, die wir zeigen werden, wenn nötig. Da dies als ein Toast nicht annähernd so fein ist, werden wir dieses Panel die breadcrust nennen.

Mitdass als Hintergrund, lassen Sie uns ein hinzufügenTextviewzu unsererres / Layout /
main.xmlfi
dassistdasbreadcrustselbst:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app /
src / main / res / Layout / main.xml)

Hier sind wir es nehmen seinen Anteil ander Raum, die gleichen wie die beiden Tasten (Android: layout_weight = "1") Und einen gelben Hintergrund zu geben (Android: background = "@ color /

Akzent"). DasAndroid: textAppearance = "android: attr / textAppearanceLarge"Android ist die cumbersome Art und Weise "verwenden, um die Standard-große-Type-Font" zu sagen.

Endlich,android: Sichtbarkeit = "weg"Mitteldass dieseTextviewtatsächlich wirdnicht zu sehen, bis wir es sichtbar uns in Java-Code zu machen.

Wirmüssen eineähnliche hinzufügenTextviewnachdasres / Layout-Land / main.xmlfi
einfach Invertierung die Achsen für die Breite, Höhe und Gewicht:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src /
main / res / Layout-Land / main.xml)

Als Nächstes fügenein Datenelement für diebreadcrustnachHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dann inonCreate ()vonHauptaktivitäthinzufügen, um einen Anruf zufindViewById ()nachschlagendas breadcrust:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Als nächstes wird inres / Werte / strings.xml, für die Nachricht wollen in einem String-Ressource fügen wir in der breadcrust zu zeigen, wenn wir den Benutzer (wieder) um Erlaubnis fragen werden Bilder zu machen:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app /
src / main / res / Werte / strings.xml)

Also, was wir haben wollen passieren, wennder Benutzer tippt die "Take Picture" Taste ist:

• Wenn wir die Erlaubnis haben, zu nehmendas Bild, nehmen Sie das Bild

• Wenn wir das tunhaben keine Berechtigung, aber der Benutzer kann die breadcrust sehen (und so können unsere Gründe für den Antrag auf Genehmigung sehen), fordern Sie die Berechtigungen wieder

• Wenn wir das tunkeine Berechtigung haben, und die breadcrust nicht sichtbar ist, dann müssen wir die breadcrust mit unserer Begründung Nachricht zu zeigen,

Nachdass Ende, zu modifizierenein Bild machen()aufHauptaktivitätaussehenDies:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Obbreadcrustist
sichtbar,wir
schaffen
dasWEGwieder
und

CallrequestPermissions.

Obbreadcrustistnicht sichtbar, können wir es machenSICHTBARund legen Sie die Nachricht andie String-Ressource, die wir definiert.

Dort sind einigeDinge fehlt. Die größte ist dienetPermissions ()Methode:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Diese Methode iteriert über unseren Input String-Array von Berechtigungen und fi ers aus denen, die wir bereits zu halten. Dies ist erforderlich, da ein Aufruf an requestPermissions () fordert jede Erlaubnis, die wir bitten um ... auch Berechtigungen, die der Benutzer bereits erteilt hat.

Angenommen, dass auf der ersten Ausführung unserer App, der Benutzer die

WRITE_EXTERNAL_STORAGE die Erlaubnis erteilt, aber lehnte die CAMERA Erlaubnis zu erteilen. Wir wollen nur den Benutzer für die Kamera um Erlaubnis zu fragen. Ideal, requestPermissions ()würde einen Blick auf unsere Array und fi er heraus diese Berechtigungen, die wir bereits gewährt wurden, den Benutzer für den Rest zu fragen.

Unglücklicherweise,requestPermissions ()tuttun dies nicht, so haben wir die fi zu tun, um uns Ering, wie wir sind innetPermissions ().

netPermissions ()gerade iteriertdie Anordnung von Berechtigungsnamen und verwendet ein hasPermission ()Verfahren zu fi er heraus diejenigen, die wir schon halten.

Außerdem sollten Sie Ihre IDE klagendassRESULT_PERMS_TAKE_PICTUREistnicht definiert ist, hinzufügen, so dass als eine weitere Konstante aufHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Wenn wir nennenrequestPermissions ()undder Benutzer gewährt die Berechtigungen, sollten wir vorangehen und das Bild aufzunehmen. Wir müssen auch mit dem Fall zu behandeln, in denen der Benutzer die Erlaubnis verweigert hat und überprüft die "hör auf zu fragen" aktivieren, da unsererequestPermissions ()rufen Sie leitet direkt zuonRequestPermissionsResult ()ohne Aufforderungder Benutzer. Also müssen wir etwas mehr Logik der
hinzufügenonRequestPermissionsResult ()Callback-Methode in Hauptaktivität, So ändern Sie Ihr wie folgt aussehen:

Hier wird, wenndasAnfrage Codeistdas, was wir in unserem Call verwendetrequestPermissions ()(RESULT_PERMS_TAKE_PICTURE), Und wenn wir die Erlaubnis haben jetzt zu nehmenein Bild, nehmen wir das Bild.

Wenn aufAuf der anderen Seite, wir sind inonRequestPermissionsResult ()(Damit wir wissen, wir haben gefragt, fürdie Erlaubnis) undshouldShowTakePictureRationale ()kehrt zurückfalschWissen wir, dass wir möglicherweise nicht mehr die Erlaubnis zu bekommen, andere als durch den Benutzer in die App Einstellungen gehen und manuell es uns gewähren. So zeigen wir einToastinformierender Benutzer darüber.

Ihre IDE wird sich beschweren,dass es keinenR.string.msg_no_permWert, fügen Sie so eine andere Zeichenfolge-Ressource zu Ihremstrings.xmlfi

Nun laufendie App auf Ihrem Android-6.0-Umgebung. Wenn fragt die App für Berechtigungen für die fi

Lauf, ablehnen mindestens eine der Sie. Dann tippen Sie auf die "Take Picture" klicken, und Sie sollten die breadcrust sehen erscheinen:

Wenn duTippen Sie erneut auf die "Bild aufnehmen" klicken, werden die breadcrust gehen weg, und Sie werden für alle Berechtigungen aufgefordert, den Sie noch nicht gewähren hat. Wenn Sie alle Berechtigungen hier ablehnen, sind Sie zurück, wo Sie waren; wenn Sie alle Berechtigungen akzeptieren, wird die App ermöglicht es Ihnen, ein Bild zu machen. Wenn stattdessen Sie alle Berechtigungen verweigern und überprüfen Sie die "fragen nicht wieder", um für mindestens einen von ihnen, sollten Sie die Toast sehen angezeigt, wenn Sie versuchen, Klopfen "Bild aufnehmen".

Dann deinstallierendie App.

Schritt # 9: Überprüfenfür Berechtigungen vor der Videoaufnahme

Bisher haben wir ignoriertdie "Record Video" Taste, also lasst uns auch für sie Verdrahtung Unterstützung starten. Der große Unterschied mit dieser Taste - neben der Aufnahme eines Videos statt ein Bild zu nehmen - ist, dass wir nicht nach vorne für die RECORD_AUDIO Erlaubnis fragen.

Aber,dass nicht einige der Grundlagen ändern, wie zu sehen, wenn wir die Erlaubnis haben, um Videos aufzunehmen und nur versuchen, Videos aufnehmen, wenn wir es tun.

Zuerst fügendie folgende MethodeHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

DiescanRecordVideo ()Verfahren zurückkehrenwahr, wenn wir ein Bild machen können und dieTON

AUFNEHMENErlaubnis.canTakePicture

()bereitsüberprüftdasKAMERAundWRITE_EXTERNAL_STORAGEBerechtigungen, so sind wir nur auf Verkettungsdie zusätzliche Berechtigungsprüfung.

Dann,ändernEin Video aufnehmen()imHauptaktivitätbenutzenDies:

Wenn Sie laufendie Beispielanwendung, und Sie die "Video aufnehmen" Taste tippen, sollten Sie keine Antwort erhalten, da wir nie für die RECORD_AUDIO Erlaubnis gebeten haben, so canRecordVideo () sollte false zurück. Dann deinstallieren Sie die App.

Schritt # 10: Erkennen, wenn wir einige Rationale sollte zeigen(Aufs Neue)

Wir auchmüssen arrangieren die breadcrust zu zeigen, mit einem Video-bezogene Nachricht, wenn wir ein Video zu nehmen sind nicht berechtigt, aber könnte es zu bekommen.

So fügendie folgende MethodeHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Wieder einmal prüfen wir, ob wirbrauchen eine Begründung zu zeigen, sei es, weil der Kamera bezogenen Berechtigungen (shouldShowTakePictureRationale ()) Oder aufgrund derTON

AUFNEHMENErlaubnis.

Dann füge hinzuein paar zusätzliche Zweige zum recordVideo () Methode:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Ihre IDE wird sich beschweren,dass Sie zwei Konstanten fehlen. Man ist PERMS_ALL, die Liste der Berechtigungen erforderlich, um ein Video aufzunehmen, so hinzufügen, dass MainActivity: (von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Wir auchmüssen hinzufügenRESULT_PERMS_RECORD_VIDEOnachHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Sie werden auch nicht fehlendasmsg_record_videoString-Ressource, so hinzufügendass: Das istdie gleiche Strömung wie wir mit der hatteein Bild machen()Methode:

• Wenn wir die Erlaubnis haben, aufzeichnengehen das Video, voran und tun so

• Wenn wir das tunnicht, und wir sind nicht entscheidend für die breadcrust, aber wir sollten verschiedene Überlegungen zeigen, bevölkern und die breadcrust zeigen

• Andernfalls stellen Sie sicher,dasbreadcrustistWEGund fordern unsere Rechte

Endlich,ändernonRequestPermissionsResult ()imHauptaktivitätaufnehmendas Video, wenn wir jetzt die Erlaubnis, dies zu tun, durch die Zugabe vonsonstobBlock:

Wenn Sie laufendie App und tippen Sie auf die "Video aufnehmen" klicken, sollten Sie sofort für alle erforderlichen Berechtigungen gefragt werden, da wir noch nie Sie für RECORD_AUDIO
gefragt. Wenn Sie eine oder mehrere der Berechtigungen sinken, und tippen Sie auf "Video aufnehmen" ein zweites Mal, sollte die breadcrust erscheinen. Wenn Sie ein drittes Mal "Video aufnehmen" tippen, sollte die breadcrust verschwinden und Sie sollten wieder für die Berechtigungen aufgefordert. Und, wenn Sie alle Berechtigungen verweigern, während das Kontrollkästchen markieren, sollten Sie den Toast sagen, Sie sehen, dass wir nicht ein Video aufzeichnen kann. Dann deinstallieren Sie die App.

Schritt # 11: Unterstützung von Konfigurationsänderungen

Der fi
was wir tun müssen, ist die Konfigurationsänderungen zu berücksichtigen. Es
gibt zwei Dinge, die wir in Bezug auf die Konfigurationsänderungen zu verfolgen müssen: 1. Wirmüssen zu verfolgen, ob die breadcrust sichtbar ist, und wenn ja, welche Meldung angezeigt wird. Auf diese Weise, wenn unsere Tätigkeit zerstört und auf einer

Konfigurationsänderung neu erstellt, können wir die breadcrust seinen letzten Zustand als auch wiederherstellen.

2. Wir konnten verfolgen, wenn wir Berechtigungen gebetenonCreate () und warten immer noch auf die Ergebnisse, so dass, wenn der Benutzer den Bildschirm dreht oder löst eine andere Konfiguration zuändern, und der Benutzer verweigert eine der Berechtigungen, dass wir nicht sofort aus Versehen die Anfrage-Erlaubnis sofort wieder Dialog angezeigt werden .

Nun, da esstellt sich heraus, unsere On-First-Run-Logik, der zweite Grund, der oben wahrscheinlich gezeigt gegeben ist nicht erforderlich. Nach einer Konfigurationsänderung, isFirstRun () return false

sollte, da per Definition hätten wir einmal durch onCreate () bereits gegangen zu sein. Allerdings nur, um auf der sicheren Seite zu sein, werden wir verfolgen, ob unsere onCreate () - ausgelöst Berechtigungsanfrage ist noch im Gange.

Hinzufügendie folgenden KonstantenHauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Wir werden verwendenSTATE_BREADCRUSTwieder Schlüssel für dieBündelnWert dass wir in der gespeicherten Instanz Zustand speichert. Und wir
verwendenSTATE_IN_PERMISSIONverfolgendass wir in der Mitte der Erlaubnis-Anfrage-Flow ausonCreate ().

Als Nächstes fügendie folgenden fi
nachMainActivity, verwendet, ob diese aktuelle

Aktivitätsinstanz in der permission-Anforderungsablauf zu verfolgen:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dann füge hinzuMit dem folgenden Code zuonCreate (), direkt im AnschlusssetContentView (), Bevölkern dieisInPermissionfl
basierend auf unserer gespeicherten Instanz Zustand (wenn wir
welche haben):

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Dannänderndasobversuchen Sie es zuder Grund vononCreate ()nur gehen indasobblockieren, wenn wirnicht bereits in der Erlaubnis-Anfrage fließen, dann fl
dassisInPermissionfl
nachwahrvor dem AufrufrequestPermissions ():

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Als Nächstes fügenonSaveInstanceState ()undonRestoreInstanceState ()Methoden

Hauptaktivität:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Obdasbreadcrustwir sichtbar ist, sparendie Nachricht von derbreadcrustimdasBündeln.

ImonRestoreInstanceState ()Wir machen diebreadcrustsichtbar sein, wenn wireine Nachricht, wo wir diese Botschaft in die auch setzenbreadcrust.

HINWEIS: Das istein schlampiger Ansatz, nur weil diese App eine Sprache unterstützt nur funktioniert. Andernfalls wird im Falle einer locale Änderung, würden wir die Nachricht in der alten Sprache, die im Bundle zu sparen und das erneute Anwenden es, während der Rest unserer Benutzeroberfläche in der neuen Sprache ist. welche der beiden Botschaften, die wir benötigen (zB
über int String-Ressource-IDs) Eine bessere Implementierung würde verfolgen, damit wir die Ressourcen erneut anwenden, in den richtigen Übersetzungen ziehen. Das erfordert ein bisschen mehr Buchhaltung, und diese Probe ist schon nervend lang. Allerdings tragen nur daran, dass, wie wir den Zustand hier sparen ist roh und nur wirksam für diesen begrenzten Szenario.

Schließlich in onRequestPermissionsResult (), fl
dasisInPermissionfl

Zurück nach
falsch:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Wenn Sie laufendie App ein letztes Mal und bekommen die breadcrust zu erscheinen, das Gerät drehen oder auf andere Weise eine Konfigurationsänderung auslösenden die breadcrust nicht verlieren, auch wenn unsere Tätigkeit wird auf dem Weg zerstört und neu erstellt werden.

Auch, wenn Sie reproduzierender Test, den Sie (vielleicht) versucht, diesen Schritt zu Beginn (installieren und die Anwendung ausführen, das Gerät mit der Erlaubnis-Anfrage Dialog oben drehen, dann beide Berechtigungen verweigern), können Sie nicht ein Duplikat Dialog bekommen sollte.

Beimdieser Punkt, IhreHauptaktivitätsollteähnelnfolgende:

(von

Berechtigungen / tutorial / Ziel / RuntimePermTutorial / app / src / main / java / com /
commonsware / android / zul / tutorial /

MainActivity.java)

Und Ihre Tutorial ist nun abgeschlossen.

Assets, Dateien und Daten-Parsing

Android Angebotewenige strukturierte Möglichkeiten, Daten zu speichern,
insbesondereSharedPreferencesund lokale SQLite-Datenbanken. Und natürlich, Sie sind herzlich eingeladen, Ihre Daten zu speichern "indie Wolke "durch ein mitInternet-basierten Dienst. Wir werden auf alle erhalten vondiese Themen kurz.

Darüber hinausdass, obwohl, Android ermöglicht es Ihnen, mit einfachen alten gewöhnlichen fi arbeiten

Entweder diejenigen in Ihrer Anwendung ( "Assets") oder solche, auf sogenannten internen oder externen Speicher gebacken.

Um sicherzustellen,diejenigen fi

Arbeit- Und verbrauchen Daten aus der Internet - Sie müssen
wahrscheinlich einen Parser zu verwenden. Android wird mit mehreren Optionen für XML und JSON Parsen, zusätzlich zuBibliotheken von DrittanbieternSie können versuchen, zu verwenden.

Dieses Kapitel konzentriert sich auf die Vermögens-, fi

Und Parsern.

Verpackung Dateien mit Ihrer App

Nehmen wir an, Sie einige statische Daten, die Sie mit zu versenden wollen, müssendie Anwendung, wie zum Beispiel eine Liste von Wörtern für eine Rechtschreibprüfung. Irgendwie müssen Sie diese Daten mit der Anwendung zu bündeln, in einer Weise, die Sie später es von Java-Code zu bekommen, oder möglicherweise in einer Weise, die Sie an eine andere Komponente passieren können (zB WebView für gebündelte HTML fi

Es gibt drei Möglichkeiten hier: raw Ressourcen, XML-Ressourcen und Assets.

Raw Ressourcen

Eine Möglichkeit, zu implementiereneine fi
mögeneine Rechtschreibprüfung Katalog ist die
fi setzen
im die res / raw Verzeichnis, so dass es in der Android-Anwendung gestellt wird

APK fi
wie Teil von der Verpackungsprozess als Ausgangs Ressource.

Zugreifendieses fi

Sie brauchen, um sich eine zu bekommenRessourcenObjekt. Aus einer

Tätigkeit,das ist so einfach wie der AufrufGetResources (). EINRessourcenObjekt

AngeboteopenRawResource ()to erhalten einEingabestromOn die fi
you angeben. Anstatt
einen Pfad,openRawResource ()erwartet einen Integer-Kennung fürdie fi
wieverpackt. Dies
funktioniert genauso wie den Zugriff auf Widgets überfindViewById ()- Wenn Sie eine fi setzen genanntwords.xmlimres / rawDie Kennung zugänglich ist in Java alsR.raw.words.

Da kann man nur eine bekommenINPUTSTREAM- Sie haben keine Möglichkeit, diese fi

Daherändern, es ist eigentlich nur für statische Referenzdaten. Da es darüber hinaus ist unveränderlich, bis der Benutzer eine aktualisierte Version Ihrer Anwendung Paket installiert, entweder die Referenzdaten hat für die absehbare Zukunft gültig sein, oder Sie werden einige Mittel für die Aktualisierung der Daten zur Verfügung stellen müssen. Der einfachste Weg, das zu behandeln ist, um die Referenzdaten zu verwenden, eine andere modifizierbare Form von Speicher Bootstrap (zB eine Datenbank), aber dies ist für zwei Kopien der Daten im Speicher. Eine Alternative ist, die Referenzdaten zu halten, wie sie ist, sondernÄnderungen in einer fi halten oder Datenbank und merge sie zusammen, wenn Sie benötigen ein vollständiges Bild der Informationen. Zum Beispiel, wenn Ihre Anwendung Schiffe ein fi
von URLs, könnten Sie
haben eine zweite fi
dass Spuren URLs durch den Benutzer oder die Referenz-URLs
hinzugefügt, die vom Benutzer gelöscht wurden.

XML-Ressourcen

Wenn jedoch Ihre fi
ist in einem XML-Format, werden Sie besser bedient setzen sie nicht in res

/ raw /, sondern in res / xml /. Dies ist ein Verzeichnis für XML-Ressourcen - Ressourcen bekannt im XML-Format zu sein, aber ohne Annahmen darüber, was das XML darstellt.

Zugreifendass XML, erhalten Sie noch einmal einRessourcenObjekt durch den AufrufGetResources ()auf IhremAktivitätoder andereKontext. Dann rufengetXml ()aufdasRessourcenObjekt, Versorgungder ID-Wert Ihrer XML-Ressource (zBR.xml.words). Dies wird wieder
einXmlResourceParserUnd implementiert den AlgorithmusXmlPullParserSchnittstelle. Wir werden diskutieren, wie zu bedienenDieser Parser und der Performance-Vorteil von XML-Ressourcen,später imdieses Kapitel.

Wie bei den Rohmaterialien, sind XML-Ressourcen schreibgeschützt zur Laufzeit.

Vermögenswerte

Ihre dritte Option ist zu verpackendie Daten in der Form eines Asset. Sie können ein Vermögen /

Verzeichnis in Ihrem sourceSet (zB src / main / Vermögen) zu erstellen, dann platzieren, was fi Sie dort wollen. Das sind zugänglich zur Laufzeit durch getAssets () aufrufen

IhreAktivitätoder andereKontext, Dann ruftöffnen()mitder Pfad zum fi

(z.B,Aktiva / foo /
index.htmlwürde abgerufen werden überopen ( "foo / index.html")). Wie bei den Rohmaterialien,Dies liefert eineEingabestromaufdie fi 's Inhalt. Und, wie bei allen Arten von Ressourcen werden Vermögenswerte schreibgeschützt zur Laufzeit.

Ein Vorteil der Vermögenswerteüber die rohen Ressourcen istdasfile: /// android_asset / UriPräfix. Sie können verwendendies einen Vermögenswert in ein zu ladenWebView. Zum Beispiel für einen Vermögenswert liegt inAktiva / foo / index.htmlin Ihrem Projekt, rufenloadURL ( "file:

///android_asset/foo/index.html")wird geladendass HTML-Code in dieWebView.

Hinweisdass Vermögenswerte werden komprimiert, wenn die APK verpackt ist. Leider auf Android 1.x / 2.x diese Kompressionsmechanismus hat eine 1MB fi

Größenbeschränkung. Wenn Sie
es wünschen, einen Vermögenswert zu verpacken, die größer als 1 MB ist, müssen Sie entweder, um ihm eine fi

Erweiterung das wird nicht komprimiert werden (zB .mp3) oder speichern
tatsächlich eine ZIP-fi
von der Vermögenswert (die automatische Komprimierung zu
vermeiden) und es sich zur Laufzeit mit dem Standard-java.util.zip Klassen dekomprimieren. Diese Einschränkung wurde mit Android 3.0, angehoben und so, wenn Ihr minSdkVersion 11 oder höher ist, wird dies kein Problem für Sie sein.

Dateien und Android

Aufdas Ganze Android verwendet nur normale Java fi

I / O für lokale fi

. Sie erhalten
die gleiche Datei und Input und OutputWriter und anderen Klassen, die Sie sich immer wieder in Ihrer vorherigen Java Entwicklungsarbeit verwendet haben.

Was in Android unverwechselbar ist, wo man lesen und schreiben. Akin zum Schreibeneine Java-Web-Anwendung, Sie haben nicht lesen und den Zugang zu beliebigen Orten schreiben. Stattdessen gibt es nur eine Handvoll Verzeichnisse, mit denen Sie keinen Zugang haben, vor allem, wenn sie auf die Produktion Hardware.

Interne vs Externe

Interner Speicher bezieht sich auf die Anwendung des Teilsdie on-board, immer verfügbaren fl

Lagerung. Externer Speicher bezieht sich auf SpeicherplatzDies kann durch den Benutzer als Antrieb in Windows montiert werden (mit einigen Schwierigkeiten oder möglicherweise als ein Volumen in OS X oder Linux).

Historisch gesehen (dh Android 1.x / 2.x) wurde interner Speicher im Raum sehr begrenzt. Das ist viel weniger vonein Problem auf 3.0 und höher.

In ähnlicher Weise wird externer Speichernicht immer auf Android 1.x und 2.x - wenn sie als Laufwerk oder Volume auf einem Host-Desktop oder Notebook, Ihre Anwendung haben keinen Zugriff auf externe Speicher montiert ist. Wir werden diese Beschränkung in ein wenig genauer untersuchenspäter in diesem Kapitel. Das istnormalerweise kein Problem auf Android 3.0 und höher.

Standard vs. Cache

Auf den internen und externen Speicher, haben Siedie Möglichkeit des Sparens fi
wie ein

Cache oder auf eine dauerhaftere Grundlage. Dateien in einem Cache-Verzeichnis kann durch das Betriebssystem oder Anwendungen von Drittanbietern gelöscht werden, um Speicherplatz für den Benutzer freizugeben. Dateien außerhalb des Cache befinden, werden bleiben, bis sie manuell gelöscht werden.

Mit freundlichen Grüßen gegen jemand anderes

Interner Speicher ist aufeine pro Anwendung. Dateien, die Sie schreiben in Ihrem eigenen internen Speicher kann nicht von anderen Anwendungen gelesen oder geschrieben werden ... normalerweise.

Benutzer, die "root" ihre Telefone Anwendungen mit Root-Rechten ausführen können und in der Lage Ihre internen Speicher zugreifen. Die meisten Benutzer root nicht ihre Telefone und so nur Ihre App wird Ihre internen Speicher zugreifen fi können

.

Dateien, die auf externen Speicher, obwohl, sind sichtbar für alle Anwendungen undder Benutzer.

Jeder kann etwas dort gespeichert, und jede Anwendung zu lesen, die etwas schreiben oder zu löschen anfordert kann es will.

Arbeiten mit interner Speicher

Du hastein paar Optionen für den Inhalt Ihrer App Teil des internen Speichers zu manipulieren.

Eine Möglichkeit ist, zu verwenden,openFileInput ()undopenFileOutput ()auf IhremAktivitätoder andereKontexterhalten einEingabestromundOutput, beziehungsweise. Allerdings akzeptieren diese Methoden nicht fi

Pfade(z.B,path / to / file.txt), nur einfach
fi

.

Wenn Sie möchten, habenein bisschen mehr Flexibilität, getFilesDir () und getCacheDir () zurückgeben Objekt eine Datei an die Wurzeln Ihrer fi zeigen
undCache-Speicherplätze auf
internen Speicher auf. Gegebendie Datei, können Sie fi erstellen
und Unterverzeichnisse, wie

Sie fi sehen

Um zu sehen, wiedies funktioniert, werfen Sie einen Blick auf dieDateien / FilesEditorBeispielprojekt.

Diese Anwendung eine Tabbed-Editor implementiert, eine ViewPager mit und ein Drittanbieter Registerkarte Bibliothek. JederTab ist ein EditorFragment, ein großes EditText Widget, ähnlich Umsetzung dessen, was wir sahen, als Beispiele zurück indas Kapitel über ViewPager.

Aber,diese ViewPager Proben hatte keine Ausdauer. Was auch immer Sie schrieben in den Fragmenten blieb aber verloren, wenn der Prozess beendet wurde. FileEditor wird stattdessen speichern, was Sie in fi eingeben

, Ein fi
pro Tab.

Das Layout fürdie Aktivität erinnert an dieViewPagerProben, mit Ausnahmedass wir mit einio.karim.MaterialTabsWidget fürdie Laschen, anstatt etwas wie einPagerTabStrip: (von

Dateien / FilesEditor / app / src / main

/ res / Layout / main.xml)

Diese Bibliothek,io.karim: materialtabs, Ist eine der Abhängigkeiten sowie das
support-v13Bibliothek fürViewPagerselbst:

(von Dateien / FilesEditor / app / build.gradle)

Andereals einige leichte Verbesserungen für die Verwendung einerMaterialTabsfürdie Laschen, dieHauptaktivitätistnicht signifikant verschieden von der ursprünglichenViewPagerBeispiele. Es lädt bisdas Layout und füllt dieViewPagerundRegisterkarten:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / MainActivity.java)

WoherDinge beginnen, mehr wesentlich von den ursprünglichen Proben in SampleAdapter kommt abzuweichen. Anstatt 10 Seiten, begrenzen wir die Anzahl der Registerkarten auf 2 oder 3 in getCount (). Ob wir 2 oder 3 Seiten unterstützen hängt davon ab, welche Version von Android laufen wir auf - wir dieses Thema erforschen mehrspäter imdieses Kapitel.

Lieberals die Seitentitel an die EditorFragment delegieren, sieht ein String-Ressource Wert aus einem Array auf, auf der Grundlage der Position getPageTitle (), und verwendet diese für den Titel.

Und getItem () ... wird komplizierter:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / SampleAdapter.java)

Beyogen aufdie mitgeliefertePositionWir erstellenDateiObjekt darstellt, wosich die Daten für unsereEditorFragment. Im Moment konzentrieren wir uns auf dieTAB_INTERNALFall, wo wir verwendengetFilesDir ()erschaffeneinDateiObjekt zeigt aufeintest.txtfi
auf unsere internen

Speicher.

DasnewInstance ()Factory-Methode aufEditorFragmentjetzt nimmtdasDateiObjekt als Eingabe anstelledasPosition. EINDateiistSerializableUnd so können wir ein setzenDateiindie ArgumenteBündeln:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

ImonCreateView ()vonEditorFragmentAufblasen wir ein Layout, das unsere große enthält Text bearbeitenWidget und abrufen dassText bearbeitenWidget:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

Zusätzlich zu einerHerausgeberfi
fürunserText bearbeiten.EditorFragmenthat zwei
weitere fi

. Eines ist einLoadTextTask, einAsyncTaskUnterklasse dass wir Text zu laden
verwenden
von unserem fi
inunserText bearbeiten. Die andere ist,beladen, eine einfachebooleanzu
sehen, ob wir unseren Text noch geladen haben:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

ImonViewCreated ()wenn wir haben, noch nicht den Text geladen, kick off wir einLoadTextTask zu tun, nurdass, vorbei in die Datei, die wir in die Argumente Bundle setzen:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

LoadTextTask, imdoInBackground ()Geht durch eine typische Java fi

I / O Lese-all-the-

Linien Prozess in zu lesen ein Text fi
obEs existiert. Die resultierende Zeichenfolge wird
gegossen indasText bearbeiten. ImOnPostExecute ()Es aktualisiert dieText bearbeitenmitdie Einlese-Text sowie löscht derloadTaskfi
und Sets beladennachwahr:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

Da jedoch verwenden wir einAsyncTask, sollten wir dieses Fragment behalten:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

…und inonDestroy (), sollten wir aufheben (), um diese Aufgabe, wenn es noch läuft, da wir nicht mehr die Ergebnisse müssen:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

Liebereinige gewidmet "Speichern" Aktionsleiste Element oder ähnliches UI-Element als haben, können wir nur ordnen Sie die Daten zu speichern, wenn unser Fragment pausiert wird. Dies ist ein typischer Ansatz in Android-Anwendungen, wie die Benutzer nicht unbedingt eine Chance bekommen einige "Speichern" UI-Element zu klicken, wenn sie durch einen Anruf oder etwas unterbrochen bekommen. Also, in onPause (), treten wir ein SaveThread aus unseren EditText Inhalt in die gleiche Datei schreiben, noch einmal aus der Argumente Bundle gezogen:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

Beachten Sie jedoch,dass wir die Gabel die SaveThread nicht, wenn geladene noch falsch ist. In diesem Fall wissen wir, dass wir immer noch in dem Text laden, die den Text bedeutet, kann unmöglich durch den Anwender geändert worden sind, so gibt es nichts zu speichern.

SaveThread stellt sicher, dass das Verzeichnis, das wir schreiben wollen existiert (wie es kann oder nicht vorhanden sind, insbesondere auf Emulatoren), verwendet dann Objekte Java Writer unsere zu schreiben,

Text. Da esnichts, was wir mit dem UI tun wollen hier ein einfaches Thema, eher als ein AsyncTask, ist eine bessere Lösung:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

Der Grund für die VerwendungeinOutputstreamUnd das geheimnisvollegetFD (). sync ()Teil abgedeckt werdenspäter imdieses Kapitel.

Das Ergebnis isteine Reihe von Tabbed-Editoren, in denen die fi
eins ist unser ein für
internen Speicher:

Wenn duGeben Sie etwas in die "Intern" Registerkarte, drücken Sie BACK, um die Aktivität zu verlassen und wieder zurück in die App gehen, was auch immer Sie von der Festplatte werden wieder geladen eingegeben und im Editor angezeigt wird.

Der fi
in internen Speicher gespeichert sind nur für die Anwendung in der Standardeinstellung.

andere Anwendungenauf dem Gerät haben keine Rechte zu diesem Raum allein schreiben, zu lesen, zu lassen. Aber denken Sie daran, dass einige Benutzer "root" ihre Android-Handys, gewinnt Super-User-Zugang. Diese Benutzer werden in der Lage sein, zu lesen und zu schreiben, was fi Sie
wünschen. Als Ergebnis, beachten Sie bitte anwendungs lokalen fi
um sicher zu sein vor

Malware, aber nicht unbedingt sicher gegen interessierte Nutzer.

Arbeiten mit einem externen Speicher

Auf den meisten Android 1.x-Geräte und einige frühe Android 2.x-Geräte kamen externe Speicher indie Form einer Micro-SD-Karte oder das Äquivalent. Auf der restlichen Android

2.x

Geräte, externe Speicher
war Teildie On-Board-fl
aber untergebracht in eine separate Partition aus dem internen

Speicher. Auf den meisten Android 3.0+ Geräte, ist externe Speicher jetzt einfach ein spezielles Verzeichnis in der Partition, die internen Speicher hält.

Geräte werden mindestens 1 GB externen Speicher frei haben, wennsie liefern dem Benutzer.

Davon abgesehen, haben viele Geräte viel mehr als das, aber die verfügbare Größe an jedem Punkt könnte kleiner sein als 1 GB, je nachdem, wie viele Daten der Benutzer gespeichert hat.

Woher schreiben

Wenn Sie Fi
für Ihre Anwendung gebunden sind, die einfach zu groß sind, in den internen

Speicher zu gefährden, oder wenn der Benutzer sollte in der Lage sein, die fi herunterladen aus ihr Gerät nach Belieben können Sie getExternalFilesDir (), auf jede Aktivität oder anderen Kontext verwenden. Dadurch erhalten Sie ein File-Objekt verweist auf eine automatisch erstellte Verzeichnis auf externen Speicher, einzigartig für Ihre Anwendung. Obwohl es nicht gegen andere Anwendungen zu sichern, ist es ein großer Vorteil: wenn die Anwendung deinstalliert wird, diese fi
sind automatisch gelöscht, so wie die, die in der Anwendung lokalen fi

Bereich. Diese Methode wurde in API-Ebene hinzugefügt 8. Diese Methode nimmt einen Parameter - In der Regel null - die einen bestimmten Typ von fi zeigt

Sie sind Versuch (oder später, Last) zu
speichern.

ImSampleAdapter der Beispielanwendung, wenn der Benutzer die "Extern" Registerkarte wählt, verwenden wir
getExternalFilesDir ()erschaffen dasDateiverwendet werden, indem dasEditorFragment: (von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / SampleAdapter.java)

Es gibt auchgetExternalCacheDir (), die in einem Verzeichnis eine Datei zeigt zurückgibt, die fi enthält
dass Sie haben möchten, aber wenn Android oder ein Drittanbieter-App den Cache
löscht, wird Ihre App weiterhin normal funktionieren.

Android 4.4 (API Stufe 19) hinzugefügt zweineue Methoden, getExternalCacheDirs () und getExternalFilesDirs (), die mehreren Versionen der klassischen Methoden. Diese ein Array von File-Objekten, die eine oder mehrere Stellen, an denen Sie Ihre App mit externen Speicher arbeiten können. Der fi

Element im Array wird die gleiche Datei-Objekt durch den singulären

Versionen der Methoden (zB getExternalFilesDir ()) zurückgeführt werden. Die anderen Elemente in dem Array, wenn überhaupt, app-spezifische Verzeichnisse auf alternative externen Speicherstellen, wie herausnehmbare Karten darstellen. Das Android-Support-Paket hat eine ContextCompat Klasse mit statischen Versionen von getExternalCacheDirs () und
getExternalFilesDirs (), so dass Sie den gleichen Code auf API-Ebene 4 und höher verwendet werden können, obwohl die Rückportierung wird immer nur ein Verzeichnis, in dem Array zurück.

Wenn Sie Fi
die mehr dem Benutzer gehören, als zu Ihrer App - Bilder von der Kamera
aufgenommenen, heruntergeladen MP3 fi

Etc. - eine bessere Lösung zu verwenden
istgetExternalStoragePublicDirectory (), Verfügbar auf derUmweltKlasse. Dies wird IhneneinDateiObjekt zeigt aufein Verzeichnis zur Seite für eine bestimmte Art von fi basierend auf dem Typ, den Sie in gesetzt passierengetExternalStoragePublicDirectory (). Zum Beispiel kann man mehr verlangenDIRECTORY_MOVIES.DIRECTORY_MUSIC,
oderDIRECTORY_PICTURESzum Speichern von MP4, MP3 oder JPEG-fi

,
beziehungsweise. Diese fi
wird zurückgelassen, wenn die Anwendung deinstalliert wird. Diese Methodeauch wurde in API Ebene 8 hinzugefügt.

ImSampleAdaptervondie Beispielanwendung, wenn der Benutzer die "Public" Registerkarte wählt, verwenden wirgetExternalStoragePublicDirectory ()erschaffen dasDateiverwendet werden, indem dasEditorFragment, Setzen unsere fi
im
dasDIRECTORY_DOCUMENTSLage:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / SampleAdapter.java)

Sie werden auch fi
eingetExternalStorageDirectory ()Verfahren aufUmweltAuf die Wurzel des
externen Speichers zeigt. Dies ist nicht mehr der bevorzugte Ansatz

— die Methoden, die oben beschrieben Hilfe halten die fi des Benutzers
besser organisiert.

Wenn Sie jedoch sind ältere Android-Geräte unterstützen, können Sieverwenden müssen getExternalStorageDirectory (), einfach weil die neueren Optionen nicht zur Verfügung stehen kann.

Relevante Berechtigungen

Auf allen relevanten Android-Versionen vor Android 4.4 (API Stufe 19), wenn Sie auf externe Speicher schreiben möchten, können Siemüssen die WRITE_EXTERNAL_STORAGE Erlaubnis zu halten. Und auf diesen Versionen, Sie brauchen keine Erlaubnis von einem externen Speicher zu lesen.

Auf Android 4.4 und höher,die Regeln sind ein bisschen anders:

• Zum Lesen oder Schreiben indie Verzeichnisbäume verwurzelt aufgetExternalFilesDir ()und getExternalCacheDir ()Sie brauchen nicht eine Erlaubnis

• So schreiben Sie überallsonst auf externen Speicher, müssen Sie

WRITE_EXTERNAL_STORAGE

• Zum Lesen vonüberallsonst auf externen Speicher, müssen Sie
entwederWRITE_EXTERNAL_STORAGE(Wenn Sie bereitsdas)

oderREAD_EXTERNAL_STORAGE(obnicht)

Daher, so lange Ihrandroid: minSdkVersion ist weniger als 19, müssen Sie die meisten konservativen Ansatz:

• Wenn Sie irgendwo auf externen Speicher schreiben, Anfragedas

WRITE_EXTERNAL_STORAGEErlaubnis

• Wenn Sie nur lesen, sondern von überall auf externen Speicher, Anfragedas

READ_EXTERNAL_STORAGEErlaubnis

Hinweisdass Sie vielleicht Pfade zu externen Speicherstellen von Drittanbieter-Anwendungen bekommen, in der Regel in Form eines Uri. Wenn Sie Uri Werte von Drittanbieter-Anwendungen sind Handling, sollten Sie READ_EXTERNAL_STORAGE oder WRITE_EXTERNAL_STORAGE, falls
sich die Drittanbieter-App Hände fordern Sie ein Uri auf externe Speicher zeigt.

Zum Beispiel, hier istdie Beispielanwendung Manifest, komplett mit der

<Uses-permission>Element fürWRITE_EXTERNAL_STORAGE:

(von

Dateien / FilesEditor / app / src / main

/ AndroidManifest.xml)

Hinweisdie Verwendung von Android: maxSdkVersion. Dies sagt Android nur Wunsch, diese Erlaubnis an die angegebene API-Ebene. Danach, ignorieren Sie die Anfrage. In diesem Beispiel wird getExternalFilesDir () und daher nicht WRITE_EXTERNAL_STORAGE auf API-Ebene 19+

Geräte benötigt. Benutzer, die diese App auf solche Geräte zu installieren sind nicht für diese Erlaubnis gefragt, während die Benutzer, die diese App auf älteren Geräten installiert wird.

Diesdann rollt wieder, warum wir bedingt Bestimmung der Anzahl der Seiten auf der API-Ebene des Gerätes basieren. Wenn das Gerät API-Ebene 18 läuft oder unten, wir
fordernWRITE_EXTERNAL_STORAGEUnd deshalb können wir
verwendengetExternalStoragePublicDirectory (). Doch auf API-Ebene 19+ Geräte, sind wir nicht anfordertWRITE_EXTERNAL_STORAGEzu verwenden, und deshalb können wir

nichtgetExternalStoragePublicDirectory (). So unterdrücken wir das dritte Register, um uns zu fi

Speicherplätzedass wir verwenden dürfen.

Wannschreiben

Außerdem können externe Speicher seingebunden montiert durch den Benutzer, der es als USB-Speichergerät. Sie können getExternalStorageState () (eine statische Methode auf Environment) verwenden, um festzustellen, ob externe Speicher derzeit verfügbar ist oder nicht. Auf Android 3.0
und höher, dies ein Problem viel geringer sein sollte, wie sie sich verändert, wie der externe Speicher vom Host-PC verwendet wird - ursprünglich benutzten USB-Massenspeicher-Modus (man denke an USB-Sticks) und verwendet jetzt das USB-Media Transfer Protocol (man denke an MP3-Player).

Mit MTP, sowohl für die Android-Gerät und dem PC ist es verbunden kann der Zugriff auf die Fi
gleichzeitig; Massenspeicher-Modus würde nur erlauben der Host-PC Zugriff auf die fi haben
ob externer Speicher montiert.

Heutzutage kann man verwendengetStorageState ()aufdasEnvironmentCompatKlasse
ausdassupport-v4Bibliothek zu fi
aus der Zustand des externen Speichers, für die
jeweiligeDateigeben alsein Parameter.

Für VermieterSiehe die Benutzer von Dateien

Die Umstellung auf MTP hat einen Nebeneffekt für Android-Entwickler: fi
können Sie
schreiben, auf externe Speichernicht automatisch für den Benutzer sichtbar. Zum Zeitpunkt des Schreibens dieses Artikels, die nur fi
das wird auf dem PC des Benutzers angezeigt werden
diejenigen, die durch die Mediastore indiziert wurden. Während das Mediastore wird typischerweise als nur gedacht

Indizierung "Medien" (Bilder, Audio Fi, Video-fi, etc.) wurde die zusätzliche Rolle in Android 3.0 der Aufrechterhaltung eines Index aller fi für die Zwecke der MTP gegeben.

Ihre fidass Sie sich auf externen Speicher platzieren wird nicht automatisch einfach durch die Schaffung indiziert werden und darauf geschrieben werden. Letzten Endes wird es indiziert, obwohl es durchaus einige Zeit für eine automatische Indizierung Pass stattfinden kann.

Um zu erzwingen, Android zu indizieren Ihre fi Sie können Scanfile () verwenden, auf MediaScannerConnection:

Der dritte ParameterScanfile () ist ein Array von MIME-Typen, mit dem Array von Pfaden in dem zweiten Parameter, Line-Up. Wenn Ihr fi
ist irgendeine Form von Medien, und Sie wissen,
der MIME-Typ, dass Versorgung wird sichergestellt, dass Ihre Medien entsprechend zu den richtigen Apps (zB Bilder in der Galerie-App) sichtbar. Ansonsten versuchen Android wird einen MIME-Typ aus dem fi ableiten

Erweiterung.

Imdie Beispielanwendung, da die EditorFragment nicht weiß, ob der fi
ist auf externen

Speicher und deshalb ist erreichbar, es tut nicht wissen, ob diese Art von Indexierungs geeignet ist. In einem herkömmlichen Szenario, bei dem die EditorFragment konsequent auf externe Speicher schreiben würde, arrangieren SaveThread könnte MediaScannerConnection als Teil ihrer Arbeit zu berufen. Allerdings muss Scanfile () einen Zusammenhang, und so würde die SaveThread einer von denen brauchen. Sie würden ein bisschen wie mit etwas Wind-up:

Hier verwenden wirgetApplicationContext (), die einen Kontext zu uns zurückgibt, die ein prozessweiten Singleton ist. Auf diese Weise, wenn unsere Tätigkeit zerstört wird, während der Faden noch läuft, haben wir noch einen gültigen Kontext zu verwenden.

Limits auf einem externen Speicher Open Files

Viele Android-Geräte habenein pro-Prozess Grenze von 1024 offen fi

Auf jede Art von

Lagerung. Dies ist normalerweise kein Problem für Entwickler.

Bei einigen Geräten- Einschließlich wahrscheinlich alles, was Android 4.2 laufen und höher

— es gibtein Global-Limit von 1024 offen fi
aufexterner Speicher. Mit anderen Worten,
kombiniert alle laufenden Anwendungen können nur geöffnet 1024 fi
gleichzeitig auf externen

Speicher.

Das heisstdass es wichtig ist für Sie, wie viele offene fi zu minimieren auf externe Speicher

Sie haben bei eine Zeit. Nachdem ein paar offene fi
istdurchaus sinnvoll; mitein paar hundert
offene fi
ist nicht.

Mehrerer Benutzerkonten

Auf Android 4.1 und früherjedes Android-Gerät wurde angenommen, von nur einer Person verwendet werden.

Auf Android 4.2+Tabletten - und Telefone 5.0+ Android - es ist möglich, dass ein Besitzer des Geräts mehrere Benutzerkonten einzurichten. Jeder Benutzer erhält seinen eigenen Abschnitt der internen und externen Speicher für fi

, Datenbanken, SharedPreferences, und so weiter. Von

Ihrem Standpunkt aus, ist es, als ob die Benutzer wirklich auf verschiedenen Geräten, obwohl es in Wirklichkeit alle die gleiche Hardware.

Aber,dies bedeutet, dass die Pfade für interne und externe Speicher nun Benutzers variieren. Daher ist es sehr wichtig ist für Sie die entsprechenden Methoden verwenden, um skizzierte in dieses Kapitel, für fi

Standorteauf internen Speicher (zBgetFilesDir ()) Und externe

Speicher (zBgetExternalFilesDir ()).

Einige Blog-Posts, Stack-Überlauf Antworten undÄhnliches wird die Verwendung von hartkodierte Pfade für diese Orte (zB / sdcard oder / mnt / sdcard für den Stamm der externen Speicher) zeigen.

Hartcodierung solcher Wege war nie eine gute Idee. Und wie von Android 4.2, sind diese Pfade einfach falsch und wird nicht funktionieren.

Auf Android 4.2 und höher, fürder ursprüngliche Benutzer des Gerätes, werden interne Speicher an der gleichen Stelle eingereicht wie zuvor, aber externe Speicher wird einen anderen Pfad verwenden.

Für die zweite und die folgenden auf dem Gerät definierten Benutzer, sowohl interne als auch externe Speicher wird in verschiedenen Pfaden befinden. Die verschiedenen Methoden, wie getFilesDir (), wird dies für Sie transparent behandeln.

Hinweisdass zum Zeitpunkt des Schreibens dieses Artikels, sind mehrere Konten auf den Emulatoren nicht verfügbar ist, nur auf den tatsächlichen Tabletten. Handys werden in der Regel nicht mit mehreren Account-Support haben, unter der Prämisse, dass Tabletten sind häufiger als gibt Telefone gemeinsam genutzt werden.

Linux-Dateisysteme: Sie Sync, You Win

Android ist gebaut oben auf ein Linux-Kernel und nutzt Linux fi Stielen für seine fi halten.

Herkömmlicherweise verwendet Android YAFFS, optimiert für den Einsatz (Yet Another Flash File System) auf Low-Power-Geräte für Daten fl Speicher zu speichern.

YAFFS hat ein großes Problem: nur ein Prozess zu schreiben die fi

Stamm auf eine Zeit. Für
die von Ihnen in fi

Stengel, eherfi -Niveau Verriegelungs Anbietung und YAFFS hat

Partitionsebene Verriegelung. Dies kann ein bisschen ein Engpass werden, vor allem als Android-

Geräte in Kraft wachsen und beginnen wollen, um mehr Dinge zur gleichen Zeit wie ihre Desktop-und Notebook-Brüder zu tun.

Android 3.0 geschaltetext4, eine andere Linux-fi

Stammzellen sollen mehr auf Desktops /

Notebooks. Ihre Anwendungennicht direkt den Unterschied wahrnehmen. Allerdings ist ext4 ein gutes Stück von Puffern, und es kann Probleme für Anwendungen verursachen, die diese Pufferung Rechnung nicht nehmen. Linux-Anwendungsentwickler lief Hals über Kopf in diese in den Jahren 2008-2009, als ext4 begann, populär zu werden. Android-Entwickler müssen jetzt darüber nachdenken ... für Ihre eigenen fi

Lagerung.

Wenn Sie mit SQLite oderSharedPreferences, Sie brauchen sich nicht um dieses Problem zu kümmern. Android (und SQLite, im Fall von SQLite) behandeln alle Puffer-Probleme für Sie. Wenn aber schreiben Sie Ihre eigenen fi

, Möchten Sie vielleicht einen zusätzlichen

Schritt, wie Sie zu betrachten fl

Ihre Daten auf der Festplatte. Genauer gesagt, Siebrauchen
eine Linux-Systemaufruf als fsync bekannt auslösen (), die die fi erzählt
stammen alle

Puffer, um sicherzustellen, auf die Platte geschrieben.

Wenn Sie mitjava.io.RandomAccessFileimein Synchronmodus wird dieser Schritt für Sie als auch, behandelt, so müssen Sie sich nicht um sie kümmern. Allerdings Java-Entwickler neigen dazu, zu verwendenOutputstream, Das löst nicht einfsync ()Selbst, wenn Sie anrufenschließen()aufder Strom. Stattdessen rufen SiegetFD (). sync ()aufdasOutputstreamauslösendasfsync (). Beachten Sie, dass dies sehr zeitaufwändig sein kann, und so die Platte schreibt, sollte der

Hauptanwendungsthread, wo immer praktisch, wieüber ein getan werdenAsyncTask.

Deshalb ist, inEditorFragment, unserSaveThreadUmsetzung sieht aus wieDies:

(von

Dateien / FilesEditor / app / src / main / java / com / commonsware /
android / fileseditor / EditorFragment.java)

Während wir verwendeneinSchriftstellertundas Schreiben, ist es um ein eingewickeltOutputstream, So können wir den Zugriff auf das bekommenFileDescriptor(übergetFD ()) Und Callsync ()darauf.

StrictMode: Vermeiden von Janky-Code

Nutzer sind eher Ihre Anwendung zu mögen, wenn zusie, es fühlt sich reaktionsschnell. Hier wird durch "responsive", meinen wir, dass es schnell und genau auf Benutzeraktionen reagiert, wie Wasserhähne und klaut.

Im Gegensatz dazu sind die Nutzer weniger wahrscheinlich, dass mit Ihnen freuen, wennsie erkennen, dass die Benutzeroberfläche ist "janky" - träge auf ihre Wünsche reagieren zu können. Zum Beispiel, vielleicht Ihre Listen scrollen nicht so glatt, wie sie möchten, oder Antippen einer Taste nicht nachgibt, die unmittelbaren Ergebnisse, die sie suchen.

Während Fäden undAsyncTask und dergleichen können helfen, es ist nicht immer offensichtlich sein kann, wo man sie anwenden sollte. Eine umfassende Performance-Analyse, unter Verwendung vonTraceview oder ähnliche Android-Tools, ist durchaus möglich. Es gibt jedochein paar Standard möglichen Dinge, die Entwickler tun, manchmal ganz zufällig, auf der Hauptanwendungsthread, die Trägheit neigen dazu, zu verursachen:

1. Flash I / O, die beide für die interne und externe Speicher

2. Netzwerk-I / O

Aber auch hier, kann esnicht offensichtlich sein, dass Sie diese Vorgänge in der Hauptanwendungsthread ausführen. Dies gilt insbesondere, wenn die Operationen wirklich von Android Code getan, die man einfach anrufen werden.

Das ist woStrictMode kommt. Seine Aufgabe ist es, festzustellen, zu helfen, wenn Sie die Dinge auf der Hauptanwendungsthread tun, die eine janky Benutzererfahrung verursachen könnten.

StrictMode arbeitet an einer Reihe von Richtlinien. Derzeit gibt es zwei Kategorien von Maßnahmen: VM Richtlinien und Thread Politik. Erstere repräsentieren schlechte Programmierpraktiken, die auf Ihre gesamte Anwendung betreffen, insbesondere SQLite Cursor Objekte und kin leckt.

Letztere stellenDinge, die schlecht sind, wenn sie auf der Hauptanwendungsthread durchgeführt, insbesondere fl

I / O und Netzwerk-I / O.

Jede Politik diktiert, wasStrictMode sollte (zB fl beobachten
liest OK, aber fl

Schreiben sindnicht) und wie StrictMode reagieren soll, wenn Sie die Regeln verletzen, wie zB: 1. Melden Sie eine Nachricht an Logcat

2. Anzeigenein Dialog

3. Absturz der Anwendung (ernsthaft!)

Das einfachstewas zu tun ist, um die statische enableDefaults nennen () -Methode auf StrictMode von onCreate () Ihres fi

Aktivität. Dies wird eingerichtetNormalbetrieb, alle Verletzungen

Berichterstattung durch die einfach zu LogCat anmelden. Allerdings können Sie Ihre eigenen benutzerdefinierten Richtlinien über Builder-Objekte festgelegt, wenn Sie dies wünschen.

Allerdings tunverwenden StrictMode im Produktionscode nicht. Es ist für den Einsatz, wenn Sie das Erstellen, Testen und Debuggen einer Anwendung. Es ist nicht in der fi verwendet zu werden So zum Beispiel, haben Sie vielleicht so etwas wiedies in Launchers Aktivität:

BuildConfig.DEBUG wird wahr sein für debug baut, sonst false. Also, im Falle einer Debug-Build, wollen wir alle Fehler zu erkennen und die App sofort abstürzen, wenn wir ihnen begegnen, aber in der Produktion, wollen wir nur Informationenüber den Fehler zu LogCat loggt sein.

Sie werden feststellen,dass die Beispielanwendung enthalten diesen Code nicht. Das liegt daran, dass das Aufrufen von Methoden wiegetFilesDir ()undgetExternalFilesDir ()sollte wirklich auf

Hintergrund-Threads zu sein, wieStrikter Modusbeschwert sichüberSie. Daher würde dieser Code verursachenSampleAdapterzum Absturz zu bringen, wenn esGebäude versucht, dieDateiObjekt zu verwenden.

Dies könnte dadurch behoben werden, dieSampleAdapterpassieren einfach inein fl
anzeigt,
der Lagerort und mitLoadThreadTaskundSaveThreadZurecht kommendasDateiObjekte.

Hinweisdass StrictMode auch offen fi durchgesickerten Bericht

. Zum Beispiel, wenn Sie
einen Outputstream auf einer Datei erstellen und nicht später zu schließen (), wenn die Outputstream (und verwandte Objekte) Garbage Collection sind, werden StrictMode Sie berichten über die Tatsache, dass Sie den Stream zu schließen fehlgeschlagen. Dies ist sehr nützlich, stellen Sie sicher, zu helfen, dass Sie nicht offen fi undicht werden
das kann dazu beitragen,Auslassen des 1.024
offene fi Grenze auf externen Speicher.

Dateien und Ihre EntwicklungMaschine

Alledies Lesen und Schreiben von Daten ist schön, aber für die Fehlersuche und diagnostische Zwecke, ist es oft nützlich für Sie in der Lage zu sein, bei dem fi aussehen

, Anders als
durch Ihre App.

Dies ist etwas schwierig, aufgrundder Mangel an Werkzeugen und aufgrund von

Sicherheitsbeschränkungen in Fertigungseinrichtungen (im Vergleich zu Emulatoren).

Davon abgesehen,In den folgenden Abschnitten werden einige Optionen skizzieren, die Sie Ihrer App fi zugreifen müssen
unabhängig Ihrer Anwendung.

Montage als Antrieb

Wenn Sie eine aktuelle Android-Gerät haben, wenn Sie es anschließen überein USB-Kabel, in der Regel werden Sie externe Speicher als Laufwerksbuchstaben (Windows) oder ein bereitgestelltes Volume (OS X und Linux) zur Verfügung zu bekommen. In Abhängigkeit von dem Gerät, Hersteller und Konfiguration können Sie auch Zugriff auf Wechselspeicher haben auch auf diese Weise.

Imdiese Fälle können Sie Ihre Entwicklung Maschine OS verwenden, um diese fi
stecken

Standorte und Blick auf Ihre fi

(oder jemand anderen).

Es gibt jedoch einige Falten:

• Auf Android6.0+, standardmäßig eine USB-Verbindung ist nur zum Aufladen verwendet.

Sie müssen sich für den USB-Anschluss auf dem Notification Öffnen Sie die

Benachrichtigungsleiste und tippen Sie gleiten, um es umzuschalten fi teilen

Verwendung MTP.

• Einige Versionen von OSX und Linux benötigen Sie zusätzliche Software
installieren fi anzuzeigen
over MTP.

• ichf Sie sehen ein Volume-Namen "Interner Speicher" bezeichnet, dass wirklich externen Speicher ist, weil die Menschen zu verwirren Spaß ist, anscheinend.

• Man kann nicht zu dem, wasdas Android SDK bezieht sich auf als interne Speicher kann durch das bedeutet.

Drücken und Ziehenfür externe Speicher

Sie können an externen Speicher (und möglicherweise Wechselspeicher) von Geräten und Emulatoren erhalten überdie Befehlszeilen adb-Tool. Dieses Programm ist in der Plattform-Tools / Ihres Android-SDK-Installation, und es ist eine gute Idee, das Verzeichnis für Ihr Betriebssystem Umgebungsvariablen PATH hinzuzufügen, so können Sie adb von überall laufen.

adbPush und Pull adb können Sie fi hoch- und herunterladen

, beziehungsweise. Beide
nehmen den lokalen Pfad und die Fernbedienung (Gerät / Emulator) Pfad als

Befehlszeilenargumente, wenn auch in unterschiedlichem Reihenfolge:

• adb Push localpathremotePathwird hochladendie fi
repräsentiert durch
localpathnachder Standort vertreten durchremotePath

• adb Pull remotePathlocalpathwird heruntergeladendie fi
repräsentiert durch
remotePathnachder Standort vertreten durchlocalpath

Für externe Speicherdas Root-Verzeichnis Name variiert von Android OS-Version:

• androide1.x / 2.x: Verwendung/SD-Karte/

• Android 4.x / 5.x: Verwendung/ Mnt / Schale / emulierten / 0 /

• androide 6.0+: Verwendung/ Storage / emulierten / 0 /.

So, zum Beispiel,Mit dem folgenden Befehl würde schieben einindex.htmlfi
nachdasgetExternalFilesDir ()Standort fürdas primäre Gerät Konto, für eine App, deren Anwendungyour.package.name.here:

Wenn Sie versuchen,ein lokales Verzeichnis schieben, oder ein Remote-Verzeichnis ziehen, wird der Inhalt dieser Verzeichnisse hochgeladen und heruntergeladen werden, respectively. Doch selbst das Verzeichnis ist nicht, was zu Verwirrung führen kann.

Angenommen, wir habenein Verzeichnis auf unserem Entwicklungs-PC namensfoo /. Es enthält vier PNG fi, mit dem Namen1.png.2.png.3.png, undParallelität-is-boring.png. Wir führen Sie dann den folgenden Befehl auf der Kommandozeile:

Sie wind up mit:

• /storage/emulated/0/Android/data/your.package.name.here/files/ 1.png

• /storage/emulated/0/Android/data/your.package.name.here/files/

2.png

• /storage/emulated/0/Android/data/your.package.name.here/files/ 3.png

• /storage/emulated/0/Android/data/your.package.name.here/files/

Parallelität-is-boring.png

Beachten Sie jedoch,dass die foo Verzeichnisnamen nicht enthalten ist. In anderen Worten, die Inhalt vonfoo /übertragen werden, abernichtfoo /selbst.

Rennen wiefür Interner Speicher
adbdrückenundadbziehendirekt für die interne Speicherung arbeiten auch ... auf Emulatoren.

Bei der Herstellung Hardware, haben aber Sie einige zusätzliche Arbeit zu tun. Genauer gesagt, Siemüssen externe Speicher als Vermittler zu verwenden und adb Lauf als verwenden, um sich die temporäre Fähigkeit, mit internen Speicher zu arbeiten, um zu geben.

Zum Beispiel auf einem Emulator, könnten Sie schiebenindex.htmlnachdas Verzeichnis zurückgegeben durchgetFilesDir (), Für eine App mit einem Anwendungs-IDyour.package.name.here, Für das primäre Gerät Konto,über:

Wenn du es versuchstdass auf Produktionshardware, wird es scheitern. Während das Stück, das mit auf dem Emulator läuft mit Superuser-Privilegien adb in Verbindung steht, tut das Äquivalent Stück auf Produktionshardware nicht. Die gleiche Sicherheit, die andere Anwendungen verhindert, dass der App Teil des internen Speichers Zugriff verhindert adb aus, um gut zu tun.

Aber,adb auf Produktionshardware kann die Lauf als Befehl zu verwenden, einen Linux-Befehl auszuführen, als ob es durch den Linux-Benutzer mit der App, die dem Benutzer zugeordnet ausgeführt wurden, die alle Ihre fi besitzt
und die hat Lese- / Schreibzugriff auf diejenigen
fi

.

Damit,das Äquivalent Skript die fi kopieren

In den internen Speicher aufeine Produktion

Android 4.x / 5.x-Gerät wäre:

(Hinweisdass der zweite Befehl sollte in einer Zeile erscheinen alle, auch wenn sie als Wort-wrapped kann zeigen sich hier aufgrund der Länge der Leitung und der zur Verfügung stehende Breite des Buches)

Dies wird nur für debug Anwendungen arbeiten, das istder normale Zustand von Anwendungen, die Sie von Ihrem IDE ausführen. Dieses Skript:

• schiebtdie fi
nach die Wurzel des externen Speicher

• VerwendungenLauf wie die Linux-Befehl cp ausführen, um die fi kopieren von externen Speicher auf der App-internen Speicher

• LäuftDer Linux-Befehl rm die fi entfernen
dass wir auf externe Speicher
platziert

(Wenn Sie sich fragen, warum wir tunverwenden mv statt cp und rm nicht erzeugt mv Fehler im Zusammenhang mit dem Versuch, das Eigentum an der verschobene fi ändern

XML-Parsing-Optionen

Android unterstützteine ziemlich Standard-Implementierung der Java DOM und SAX-APIs. Wenn Sie Erfahrung mit diesen bestehenden, oder wenn Sie einen Code, der sie bereits nutzt, fühlen Sie sich frei, sie zu benutzen.

Android backt auch indie XmlPullParser ausdie xmlpull.org Website. Wie SAX,die XmlPullParser ist eine ereignisgesteuerte Schnittstelle, verglichen mit dem DOM, der eine komplette Datenstruktur und Hände, die Sie dieses Ergebnis aufbaut. Im Gegensatz zu SAX, die auf einem Hörer und Callback-Methoden beruht, hat die XmlPullParser ziehen Sie Ereignisse aus einer Warteschlange, diejenigen zu ignorieren Sie nicht brauchen, und den Versand der Rest, wie Sie fi auf den Rest des Codes zu sehen.

Der Hauptgrunddie XmlPullParser in Android gesetzt wurde, war für XML-kodierten Ressourcen.

Während Sie Klartext-XML während der Entwicklung zu schreiben, was in Ihrer APK fi verpackt
ist eine sogenannte "binäre XML" -Format, in dem spitzen Klammern und

Anführungszeichen und solche durch bitfields ersetzt werden. Dies hilft, eine Bit-Komprimierung, aber meistens wird diese Umwandlung zu beschleunigen Parsing getan. Android XML-Ressource-Parser können die "binäre XML" analysieren etwa zehnmal schneller als es die entsprechende Klartext-XML analysieren kann. Daher werden in einer XML-Ressource alles, was Sie (res / xml /) setzen ähnlich schnell analysiert.

Für Klartext-XML-Inhalte,die XmlPullParser entspricht in etwa, der Geschwindigkeit her zu SAX.

Unter sonst gleichen Bedingungen, neigen zu SAX, einfach weil mehr Entwickler damit von der klassischen Java-Entwicklung vertraut sein wird. Allerdings, wenn Sie wirklich die XmlPullParser Schnittstelle, fühlen Sie sich frei, es zu verwenden.

Sie sind willkommen, um zu versuchen,ein Drittanbieter-XML-Parser JAR, aber denken Sie daran,das da können Probleme sein, wenn es in Android zum Laufen zu bringen versucht,.

JSON Parsing-Optionen

Android hat gebündeltdie org.json Klassen in das SDK seit Anfang an für den Einsatz in Parsing JSON. Diese Klassen haben einen DOM-Stil-Schnittstelle: Sie können ein großes Stück von JSON

Hand JSONObject, und es gibt Ihnen eine In-Memory-Darstellung des vollständig analysiert Ergebnis. Das ist praktisch, aber, wie die DOM, ein bisschen wie ein Performance Schwein.

API Stufe 11 hinzugefügtJSONReader, basierend auf Googles Gson Parser, als "Streaming" Parser Alternative. JSONReader ist viel mehr erinnert an die XmlPullParser, dass Sie Ereignisse aus dem

"Leser" ziehen und sie verarbeiten. Dies kann erhebliche Performance-Vorteile haben, insbesondere in Bezug auf Speicherverbrauch, wenn Sie die gesamte JSON-Datenstruktur nicht brauchen. Dies ist jedoch nur auf API-Ebene 11 und höher.

because JSONReader ist ein bisschen "spät, um die Partei", hat es auf Android umfangreiche Arbeit gewesen auf immer andere JSON-Parser arbeiten.Googles Gsonwie beliebt ist Jackson.

Jackson Angeboteeinige APIs, und die Streaming-API arbeitet angeblich sehr gut auf Android mit erstklassigen Leistung.

Besuchdie Spuren!

In Ergänzung zu diesem Kapitel, können Sie mehr über den Zugriff auf Multimedia-fi lernen
über das Mediastoreund erfahren Sie mehr überdie Auswirkungen mehrerer

Benutzerkonten auf Tabletten.

Tutorial # 11Hinzufügen einfacher Inhalt -

Jetztdass wir haben gesehen, wie mit einem Vermögen zu arbeiten, können wir beginnen, sie zu verwenden setzen, durch einige "Hilfe" und "über" HTML fi definieren und sie in ihre jeweiligen Aktivitäten angezeigt werden.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository des Buches.

Schritt 1: Hinzufügen einiger Inhalt

Ihr Projekt kann bereits einassets / Ordner. Wenn nicht, erstellen. In Android Studio mit der rechten Maustaste auf das Haupt sourceSet Verzeichnisüber, wählen Sie Neu> Verzeichnis aus dem Kontextmenü, fi im Namen Vermögenswerte im Dialog, und klicken Sie auf OK. Dies sollte Ihnen eine app / Modul geben, die wie folgt aussieht:

ImVermögenswerte / erstellen Sie eine misc / Unterordner, durch einen Rechtsklick auf das Vermögen / Ordner und ein neues Verzeichnis mit dem Namen misc (zB Neu> Verzeichnis aus dem Android Studio Kontextmenü) hinzufügen Auswahl, so dass Sie so etwas wie:

Imassets / misc /, erstellen Sie zwei fi

, About.html und help.html. In Android Studio mit
der rechten Maustaste auf das Vermögen / misc / Ordner im Projekt-Explorer, wählen Sie Neu> Datei aus dem Kontextmenü, fi in der gewünschten fi
im der Dialog, und klicken Sie auf

OK.

die eigentlicheHTML-Inhalt dieser beiden fi
tut egal, so lange, wie Sie sie auseinander,
wenn Blick auf sie zu berichten. Wenn Sie möchten, können Sie Beispiel
herunterladenabout.htmlundhelp.htmlfi
vondie GitHub-Repository der Anwendung, über
die Links.

Schritt 2: Mit SimpleContentFragment

Nun eröffnenSimpleContentActivity und ersetzen die Stub-Implementierung, die wir jetzt mit dem folgenden Java haben:

(von

EmPubLite-Android Studio / T11-Helpabout / EmPubLite / app / src / main / java / com /
commonsware / empublite /

SimpleContentActivity.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

ImonCreate (), folgen wir dem Standardrezept für die Definition unserer Fragment, wenn (und nur dann) wir neu gestartet wurden, und nicht neu gestartet nach einer Konfigurationsänderung, durch zu sehen, ob das Fragment ist bereits vorhanden. Wenn wir das Fragment hinzuzufügen brauchen, rufen wir einen String Extra aus der Absicht, uns zu starten verwendet (identifi
wieEXTRA_FILE), erstellen Sie eine Instanz mit diesen Wert aus dem zusätzlichen

SimpleContentFragment, und führen Sie einen FragmentTransaction die SimpleContentFragment unserer UI hinzuzufügen.

Schritt 3: Unsere Aktivitäten starten, diesmal wirklich

Nun, was bleibt, ist tatsächlich lieferndassEXTRA_FILEWert, die wirderzeit nicht tun, wenn wir oben anfangenSimpleContentActivityvonEmPubLiteActivity.

ÄndernonOptionsItemSelected ()vonEmPubLiteActivityaussehenDies:

(von

EmPubLite-Android Studio / T11-Helpabout / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Sie fügendie ZweiputExtra ()Anrufe indasR.id.aboutundR.id.helpZweigedasSchalterErklärung. In beiden Fällen sind wir miteine quasi-URL mit dem Präfixfile: /// android_asset /. Dies weist auf die Wurzel unseres ProjektsVermögenswerte/Mappe.

WebView weiß, wie diese URLs, zu interpretieren fi zu laden
aus unseres Vermögens direkt.

Schritt # 4: Ersteein bisschen mehr Werkstoff

Gerade jetzt, unsere Aktionsleiste auf Android 5.0 Gerätederjenige von

Theme.Holo.Light.DarkActionBar definiert. Das funktioniert sicher. Allerdings sieht es ein wenig fehl am Platz, da die meisten der integrierten Apps wird ein Material Thema werden. Also, lassen Sie uns einige kleinere Anpassungen vornehmen, um unsere App Mischung in ein bisschen besser zu machen.

Als erstes werden wirbrauchen eine res / Werte-v21 / Verzeichnis hinzuzufügen, was Ressourcen, die ausschließlich auf API-Ebene verwendet werden 21+ Geräte. In Android Studio mit der rechten Maustaste auf die res / Verzeichnis in Ihrem Haupt / sourceSet über und Neu> "Android Ressourcenverzeichnis" aus dem Kontextmenü wählen. Wählen Sie "Werte" als "Ressourcentyp".

Dann wird in der Liste der verfügbaren Qualifier auf der linken Seite, klicken Sie auf "Version" und dann auf die Schaltfläche ">>" nach rechts von dieser Liste. Dies kann Ihnen eine ziemlich verkorksten Dialog, zumindest in der aktuellen Version von Android Studio:

Ergänze21 in der "Platform API-Ebene" fi
dann auf OK klicken. Dies sollte Ihnen eine
leere res / Werte-v21 / Verzeichnis, wie gewünscht.

Kopieren Sie danndasstyles.xmlfi ausres / Werte /inres / Werte-v21 /. Windows / Linux-Benutzer können per Dragstyles.xmlvonres / Werte /bei gedrückterdie Strg-Taste, um eine Kopie zu machen. OS

X-Benutzer wahrscheinlich eineähnliche Konvention haben.

Öffnenres / Werte-v21 / styles.xmlund VeränderungdasElternteilAttribut unserer einStilElement zu seinandroid: Theme.Material.Light.DarkActionBar. Fügen Sie außerdem drei untergeordneten Elemente der<Style>Element:

(von

EmPubLite-Android Studio / T11-Helpabout / EmPubLite / app / src

/ main / res / Werte-v21 / styles.xml)

Diese teilenTheme.Material (und deren Nachkommen) bestehenden Farbschema auf das Thema anzuwenden.

Schritt # 5: Sehendie Ergebnisse

Nun, wenn Sie laufendie Anwendung und wählen Sie "Hilfe" in der Aktionsleiste Überlauf, werden Sie Ihre Hilfe Inhalt auf dem Bildschirm sehen:

Durch Drücken von BACK und wählen Sie "Über"In der Aktionsleiste Überlauf wird Ihre über Inhalt bringen:

Allerdings auf einem Android 5.0 oder höher Gerät oder Emulator, unsere Aktionsleiste wird nun unsere bezeichneten Farbschema Sport:

In unserer nächsten Folge ...

… wir werdenanzeigender eigentliche Inhalt unseres Buchesin unserem Tutorial-Projekt.

Tutorial # 12- Anzeige der Buch

Beimdiesem Punkt sind Sie wahrscheinlich fragen, wenn wir jemals werden unsere digitalen Book-Reader lassen Sie uns ein digitales Buch gelesen zu haben.

Jetzt inDieses Tutorial wird Ihre Geduld belohnt.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository des Buches.

Hinweisdass in diesem Tutorial beginnen, wird angenommen, dass Sie wissen, wie Import-Anweisungen nach Bedarf hinzufügen, wie wir neue Klassen in vorhandenen Code beziehen, und so werden die erforderlichen Importe nicht immer angegeben sein wird.

Schritt 1: Hinzufügenein Buch

Als erstes werden wirbrauchen ein Buch. Erwarten Sie ein Buch als Teil dieses Tutorial zu schreiben, scheint etwas übertrieben zu sein. Anstatt also werden wir ein bereits geschriebenes Buch verwenden:Der Krieg vonDer Welt, durchHG Wells, wie vertrieben vonProject Gutenberg.

ANMERKUNG DER REDAKTION: Wir realisierendass diese Wahl von Buch als beleidigend gesehen von Marsianer werden können, wie es ihnen als kriegerischen Eindringlinge mit begrenzten Immunsystem darstellt.

Bitte verstehedass dieses Buch ist ein Klassiker der westlichen Literatur und spiegelt die Haltung der Zeit. Wenn Sie irgendwelche Bedenken zu diesem Material haben, kontaktieren Sie uns bitte unter martians-so-do-not-exist@commonsware.com.

Herunterladenhttp://misc.commonsware.com/WarOfTheWorlds.zipund entpacken Sie seinen Inhalt (aBuch / Verzeichnis fi
inIhreassets / Ordner Ihres Projekts.

Windows und Linux Android Studio Benutzer können per Dragdieses Buch / Verzeichnis in das Projekt und legen Sie es in Vermögen / die fi kopieren
nach die richtige Position. Sie
sollten mit einem Vermögen / Buch / und fi eingereicht
innen von dort:

Imdas Verzeichnis, werden Sie fi
etwas HTML und CSS fi
mit die Prosa des Buches,
sowie eine contents.json fi
mitMetadaten. Wir werden prüfen,Diese Metadaten in größerem

Detail im nächsten Abschnitt.

Schritt 2: Erstellenein ModelFragment

Dieses Beispielprojekt verwendendas "Modell Fragment" Musteran etwas festhaltendie Daten über das Buch betrachtet werden. Das "Modell Fragment" Muster funktioniert gut für die Fälle, in denen:

• die Daten werden nur von einer Aktivität, nicht mehrere Komponenten benötigt wird, und

• wollen wir festhaltendie Daten, die während einer Konfigurationsänderung (zB

Bildschirm-Rotation), so dass wir die Daten nicht wieder etwas Arbeit verrichten müssen, um zu erhalten

Es muss etwas zu ladendass BOOK, idealerweise im Hintergrund, ein Asset und Parsen der JSON, da das Lesen wird einige Zeit dauern. Auch etwas hat auf diesem BOOK zu halten, so dass es von EmPubLiteActivity und die verschiedenen Kapitel Fragmente im ViewPager verwendet werden.

NachDafür werden wir eine neue Klasse, listig namens ModelFragment erstellen.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie

Neu>

Java-Klasse
aus
dem

Kontextmenü.

ErgänzeModelFragmentwieder

Name,android.app.Fragmentwiedieübergeordnete Klasse, und klicken Sie auf OK, um die leere Klasse zu erstellen.

Schritt 3: Definieren UnsereModell

Dasscontents.json fi
enthältein bisschen von Metadaten über den Inhalt des Buches: der

Titel des Buches und einer Liste seiner "Kapitel":

Imder Fall dieses Buches von Project Gutenberg, das Vermögen / Buch / Verzeichnis enthält sechs HTML-fi
which EmPubLite wird als "Kapitel", betrachten, auch wenn
jedes dieser HTML-fi
enthält mehrere Kapitel aus das Ausgangsmaterial. Sie sind herzlich
eingeladen, die HTML neu zu organisieren, wenn Sie möchten, die Aktualisierung contents.json übereinstimmen.

Wirmüssen in den Speicher laden contents.json, so EmPubLite weiß, wie viele Kapitel angezeigt werden und wo können diese Kapiteln. Wir werden contents.json in ein BOOKModellObjekt gießen, die Gson Bibliothek nutzen, die wir zu unserem Projekt hinzugefügtin einem früheren Tutorial.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeBOOKwieden Namen und klicken Sie auf OK
die leere Klasse zu erstellen.

Dann ersetzender Inhalt dieser Klasse mit den folgenden:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / BookContents.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt # 4: Untersuchen UnsereModell

BOOKisteine Gson Interpretation der JSON Strukturcontents.json.BOOKhält sich andasKapitel, als einListevonBookContents.ChapterObjekte,von denen jeder hält sich an seine fi

BOOKliefert auch drei Zugriffsmethoden:

• getChapterCount (), Die Anzahl der Kapitel (dh die Größe des zu identifizieren KapitelArray indie JSON)

• getChapterFile (), Den relativen Pfad zurückzukehren innerhalbAktiva / Buch /dass in unserem Besitz "Kapitel" von HTML

• getChapterTitle (), Den Titel dieses "Kapitel" des Buches zurückkehren Schritt # 5: Definition unserer Veranstaltung

Wir laden möchtendie JSON und erstellen Sie die BOOK auf einem Hintergrund-Thread, da wir genug I / O und Parsen auftreten werden, dass wir unsere UI etwas träge machen können, wenn wir die Arbeit an der Hauptanwendungsthread tun. Allerdings müssen wir die UI-Ebene

(EmPubLiteActivity und seine ViewPager) wissen zu lassen, wenn das Buch geladen ist, so kann es in die Benutzeroberfläche gegossen werden.

Wir könnten ein verwendenAsyncTask dafür, die Aktivität in OnPostExecute Benachrichtigung ().

Allerdings werden wir mehr fl brauchen

Zwischenkomponenten Kommunikation überZeit,

Dinge, die nicht durch eine einfache AsyncTask behandelt werden. Daher werden wir hier mit dem Eventbus Muster beginnen, unter Verwendung von EventBus Bibliothek greenrobot, die wir für unser Projekt hinzugefügtimeine vorherige Tutorial.

Mit EventBus schaffen wir unsere eigene Ereignisklassen. Die eine Veranstaltungdass wir vorne haben, ist ein, um anzuzeigen, dass unser Buch Metadaten geladen wurde und einsatzbereit ist, in Form eines BOOK Objekt. Daher wird in diesem Schritt des Tutorials werden wir eine BookLoadedEvent definieren, die gebucht wird, wenn das Buch geladen wird. Und, haben wir die Veranstaltung auf die BOOK halten, leicht zu vereinfachen später auf die UI-bevölkern.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeBookLoadedEventwieden Namen und klicken Sie auf OK die leere Klasse zu erstellen.

Dann ersetzender Inhalt dieser Klasse mit den folgenden:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / BookLoadedEvent.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt 6: Laden UnserModell

Jetzt wirmüssen tatsächlich arrangieren das Buch auf einem Hintergrund-Thread zu laden und nach unseren neu geschaffenen BookLoadedEvent. Dies ist eine der wichtigsten Arbeitsplätze unserer ModelFragment: die Belastung unserer Tätigkeit des Modells, mit Hintergrund-Threads zu verwalten.

Mitin diesem Sinne, unsere Stub ModelFragment Implementierung mit dem folgenden ersetzen:

(from

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

ImonCreate (), rufen wir setRetainInstance (true), den Rahmen zu sagen, dieses Fragment zu halten trotz einer Konfigurationsänderung,übergeben Sie einfach auf die neue Tätigkeit als Ergebnis dieser Konfigurationsänderung erstellt.

ImonAttach ()Wenn wir nicht bereits haben unsereBOOKObjekt, wir Gabel ein

LoadThreadzu füllen, und wir können auf eine nicht leicht zu bekommenVermögensverwalterbis wir sind andie Hosting-Aktivität. Aus diesem Grund sind wir nicht LoadThread in onCreate Forking ().

Sie können diese Methode Namen mit durchgestrichener Formatierung erscheinen sehen. onAttach

() nimmt einen Kontext als ein Parameter in API Stufe 23 hinzugefügt wurde, und onAttach () nimmt eine Aktivität als ein Parameter veraltet war. Allerdings ist unser minSdkVersion niedriger ist als 23, also müssen wir die ältere Callback-Methode zu verwenden.

LoadThreadnimmtdasVermögensverwalterwieein Parameter ist, ist es in einer fi stashing im das

LoadThreadKonstruktor.

Dann indasLauf()Methodedas ist auf dem Hintergrund-Thread aufgerufen, nennen
wirSetThreadPriority ()fallen lassendie Priorität des Threads zu dem eines Hintergrund-Thread.

Dadurch verringert sich, wie viel wir mit dem Hauptanwendungsthread für CPU-Zeit konkurrieren.

Dann lesen wir im JSON Gson mit der zu erstellenBOOKBeispiel. Gson automatisch de-serialisiert unsere JSON indasBOOKundBookContents.ChapterFällen gegebenendass wir sagen diefromJson ()Methodedass es eine Instanz eines zu ladenBOOKObjekt. Schließlich haben
wirPost()einBookLoadedEventnach der StandardEventBus.

DasBOOKwird in eine gewickeltAtomicReferencein Fall versucht der Hauptanwendungsthread das zu bekommenBOOKbeimdie gleiche Zeit, um unsere Hintergrund-Thread versucht, dass fi einstellen

Wert. Mit Hilfe einesAtomicReferenceGriffe unsere Thread-Synchronisation für
uns.

Dasopen () -Methode auf Assetmanager könnte eine IOException werfen. Normalerweise ist dies eine Entwicklung Zeit Fehler anzeigt (zB haben wir versagt, um tatsächlich das Buch / contents.json fi einrichten
welche warum wir log die Nachricht an LogCat. Ein Produktions-Klasse Buch

Leser sollte auch post () eine EventBus Ereignis der UI-Ebene zu ermöglichen es dem Benutzer zu informieren, dass wir das Buch nicht laden konnte. Wie es aussieht, wird das Book-Reader auf dem ProgressBar für immer bei dieser Art von Problem stecken bleiben. Als Erweiterung der Anleitung auf diese Weise wird für den Leser als Übung.

Hinweisdass dieLoadThreadUmsetzung hatein Paar von Referenzen aufVerarbeiten. In diesem Fall, das istandroid.os.Processnichtjava.lang.Process. Schon seitjava.lang.Processwenn Sie automatisch importiert wird, nicht importiertandroid.os.Process, Sehen Sie Fehler,
wieTHREAD_PRIORITY_BACKGROUNDundSetThreadPriority ()sindnicht definiert. Da wir nicht verwendenjava.lang.Processimdiese Klasse, mit dem Importandroid.os.Process(wie gezeigt inder Codeliste oben) löst diesen Konflikt.

Schritt 7: Registrierenfür Events

Gerade jetzt, unsereBookLoadedEvent gepostet werden ... und ignoriert, da nichts in der Anwendung eingerichtet ist für solche Ereignisse zu beobachten. Unsere EmPubLiteActivity muss über diese Ereignisse zu erkennen, und die fi

Schritt zu erreichen das heißt, um es
für Veranstaltungen im Allgemeinen mit dem EventBus registrieren.

Hinzufügendie folgenden zwei MethodenEmPubLiteActivity:

Diese einfach registrierendie Aktivität mit der EventBus während es in den Vordergrund.

Schritt 8: Anpassungder Inhalt

Bevor wir verwendendasBOOKMüssen wir aktualisierenContentsAdapteranzuzeigendie Prosa auf dem Bildschirm.

Zuerst fügeneinBOOKDatenelementnachContentsAdapter:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Dann füge hinzudie BOOK Parameter an den Konstruktor, es auf das neue Datenelement zuweisen: (von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Als nächstes UpdategetCount ()benutzen dasgetChapterCount ()unsererBOOK:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Dann,änderngetItem ()abrufender relative Pfad für ein bestimmtes Kapitel aus derBOOKund erstelleneinSimpleContentFragmentaufdas Ganzefile: /// android_assetWeg nachdie fi im

Frage:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Hinweisdass Sie den Parameternamen in der getItem () Erklärung eventuell ändern müssen Position zu sein, da sie einen anderen Wert (zB arg0) sein kann.

Schließlich fügengetPageTitle (), unsere Reiter-Titel aus dem Kapiteltitel ziehen: (von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Schritt # 9: Zeigeder Inhalt Wenn Loaded

Nun, wir können tatsächlich hinzufügendie Logik das Buch angezeigt werden, sobald es geladen wird. Ein ... kreierensetupPager ()Verfahren aufEmPubLiteActivitywie folgt: (von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Die Inhaltediese Methode sind einige Linien in onCreate fast identisch () - wir haben gerade bewegt, sie zu einem separaten Verfahren. So entfernen Sie diese doppelte Zeilen aus onCreate (), so haben Sie:

Dann füge hinzufolgendeonBookLoaded ()MethodeEmPubLiteActivity:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Dies sagtEventBus, dass, wenn ein BookLoadedEvent gebucht wird, sind wir daran interessiert, und es sollte auf dem Hauptanwendungsthread zu unserem onBookLoaded () Methode geliefert werden. Diese Methode sieht aus wie er nicht benutzt wird, weil es Reflexion durch die EventBus genannt verwenden werden, und die IDE nicht weiß, dass. Das

@SuppressWarnings ( "Ungenutzt")Anmerkung zeigtdaß dieses Verfahren verwendet wird.

Schritt # 10: Anbringen unsererModelFragment

Wir auchmüssen einige Code zu addieren zu setzen dieModelFragment- Es ist nicht auf magische Weise wird auf ihrer eigenen erscheinen. Also, die fi

Zeit, die wir erstellen
einEmPubLiteActivityWollen wir schaffenModelFragment. Um dies zu erreichen, definieren Sie ein statisches Datenelement namensMODELLimEmPubLiteActivity:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Dann aktualisierendasonStart ()Verfahren inEmPubLiteActivityzu sehen, ob wir bereits habendas Fragment, bevor man zu erstellen:

Wenn Sie laufendas Ergebnis in einem Gerät oder Emulator, werden Sie den Buchinhalt sehen erscheinen:

Streichen nach links und rechts bringt Sie zumdie anderen Abschnitte des Buches.

Schritt # 11: Zeigeder Inhalt nach einer Konfigurationsänderung

Während Sie können sehen,die Buchinhalte jetzt, wenn Sie den Bildschirm versuchen zu drehen, erscheint nicht die Buchinhalte. Das ist, weil die ModelFragment hat bereits den Inhalt geladen (so die BookLoadedEvent bestanden hat), aber wir haben keine Logik in EmPubLiteActivity das Buch zu füllen, mit anderen Mitteln.

Tundass, fügen Sie einfach einesonstobKlauseldasobimonStart (), Die Buchinhalte zu bekommenübersetupPager ()obSie sind bereit:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Nun, wenn Sie laufendie Probe und drehen Sie den Bildschirm (zB Linux-Emulator), wird das Buch in jedem Fall erscheinen.

Schritt # 12: Einrichten StrictMode
aufdie Fenster/

Da wir jetzt tun ich Platte beginnen / O, vor allem dem Ziel, sie auf Hintergrund-Threads getan zu haben, wäre eseine gute Idee StrictMode zu konfigurieren, wird es so beschweren, wenn wir in unserem Streben scheitern und aus Versehen auf dem Hauptanwendungsthread diese I / O tun.

Hinzufügendie folgende MethodeEmPubLiteActivity:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Hier schaffen wirein StrictMode.ThreadPolicy.Builder, konfiguriert, um alle Verletzungen an der Hauptanwendungsthread zu erkennen, zu LogCat anmelden. Darüber hinaus, wenn wir in einem Debug-Build sind, werden wir fl
ein roter Rand um den Bildschirm.

Beachten Sie jedoch,dass diese rote Grenze wird angezeigt, auch wenn wir keine Fehler nicht machen. Leider keine Google-Ingenieure für diese Art von Verletzungen den Framework-Code zu überprüfen, zu einigen Fehlern führen, die wir als App-Entwickler können nicht lösen. Diese werden als StrictMode Verletzungen gemeldet werden, so als ob wir die Fehler selbst gemacht hatte.

Dann, nach nursuper.onCreate ()imdasonCreate ()Verfahren inEmPubLiteActivityFügen Sie auf den neuen in einem AufrufsetupStrictMode ()Methode. Dies wird Ihnen einonCreate ()Methodedas sieht aus wie:

(von

EmPubLite-Android Studio / T12-Buch / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

In unserer nächsten Folge ...

... Wir werden dem Benutzer erlauben,manipulieren einige Einstellungenin unserem Tutorial-Projekt.

Mit Voreinstellungen

Android hat viele verschiedene Möglichkeiten für Sie, um Daten zu speichern für die langfristige Nutzung durch Ihre Tätigkeit. Die einfachsten zu bedienen sindSharedPreferences und einfache fi

.

Android erlaubt Aktivitäten und Anwendungenzu halten Präferenzen in Form von Schlüssel / Wert-Paare (ähnlich einer Map), die zwischen Anrufungen einer Aktivität hängt herum. Wie der Name schon sagt, ist der primäre Zweck für Sie vom Benutzer angegebenen Konfigurationsdetails, wie die letzten Feed speichern die Benutzer an in Ihren Feed-Reader sah, oder welche Sortierreihenfolge standardmäßig auf einer Liste zu verwenden, oder was auch immer. Natürlich können Sie in den Einstellungen speichern, was Sie wollen, so lange, wie es durch einen String eingegeben wird und einen Grundwert (boolean, String, etc.)

Präferenzen könnenentweder für eine einzelne Aktivität oder bei allen Aktivitäten in einer Anwendung gemeinsam genutzt. Andere Komponenten, wie Dienstleistungen, können auch mit gemeinsamen Einstellungen arbeiten.

Erste, was Sie wollen

Um den Zugang zudie Präferenzen, haben Sie drei APIs zur Auswahl:

• getPreferences ()aus IhrerAktivität, Auf tätigkeitsspezifische Präferenzen zugreifen

• getSharedPreferences ()aus IhrerAktivität(Oder eine andere Anwendung

Context), Application-Level-Einstellungen zugreifen

• getDefaultSharedPreferences (), aufPreferenceManager, Um die gemeinsamen

Vorlieben erhalten, die mit Android Gesamtpräferenz Rahmen gemeinsam arbeiten

Der fi
zwei nehmenein Sicherheitsmodus Parameter. Die richtige Antwort ist
hierMODE_PRIVATE, So können keine anderen Anwendungen, die die fi zugreifen

Das
getSharedPreferences ()Verfahren nimmt auchein Name einer Reihe von Präferenzen;getPreferences

()effektiv ruftgetSharedPreferences ()mitden Klassennamen des Tätigkeit als Präferenz Satzname.

DasgetDefaultSharedPreferences ()Methode nimmtdasKontextfürdie Präferenzen (zB IhreAktivität).

Allediese Methoden geben eine Instanz von SharedPreferences, die eine Reihe von Getter bietet preferences zuzugreifen, ein entsprechend typisierte Ergebnis zurück (zB getBoolean () eine boolean Präferenz zurückzukehren). Die Getter auch einen Standardwert, der zurückgegeben wird, wenn es keine Präferenz ist unter der spezifi gesetzt

Schlüssel.

Es sei denn, Sie habenein guter Grund, es anders zu machen, werden Sie am besten gedient, über die dritte Option -getDefaultSharedPreferences ()- Wie das wird Ihnen dieSharedPreferencesObjektdas funktioniert mit einemPreferenceActivityStandardmäßig wird wie beschriebenspäter imdieses Kapitel.

Unter Angabe Ihrer Präferenz

Gegebendie entsprechenden SharedPreferences Objekt, können Sie bearbeiten () verwenden, um einen "Editor" für die Einstellungen zu bekommen. Dieses Objekt hat eine Reihe von Setter, der die Getter auf der übergeordneten SharedPreferences Objekt spiegeln. Es hat auch:

1. remove () wird man von einem einzigen Namen Präferenz befreien

2. klar()wird man von allen Präferenzen befreien

3. apply ()oderverpflichten()bestehen bleibenüber IhreÄnderungen vorgenommender Editor Der letzte ist wichtig- Wenn Sie Einstellungen über den Editor ändern und nicht die Änderungen zu speichern, verdampfen diese Änderungen, wenn der Editor den Gültigkeitsbereich verlässt. commit () ist ein blockierender Aufruf, während apply () arbeitet asynchron. Idealerweise verwenden apply (), wo möglich, auch wenn es nur in Android 2.3 hinzugefügt wurde, so dass es für Sie möglicherweise nicht verfügbar, wenn Sie als die früheren Versionen von Android unterstützen wollen zu.

Da umgekehrtdie Vorlieben Objekt unterstützt Live-Änderungen, wenn ein Teil der Anwendung (zum Beispiel eine Aktivität) modifiziert gemeinsamen Vorlieben, ein anderer Teil der Anwendung (zum Beispiel ein Dienst) sofort Zugriff auf den geänderten Wert haben wird.

Sammeln Einstellungen mit PreferenceFragment

Einige "Einstellungen" wird im Rahmen gesammelt werden vondie natürliche Nutzung Ihrer Benutzeroberfläche. Zum Beispiel, wenn Sie eine SeekBar haben eine Zoom-Ebene zu steuern, können Sie wählen, um die SeekBar Position in SharedPreferences aufnehmen, so können Sie die Benutzer letzten Zoom-Ebene später wiederherstellen.

Jedoch in vielen Fällen haben wir verschiedene Einstellungendass wir den Benutzer konfigurieren möchten in der Lage sein, aber nicht etwas, das der Benutzer an anderer Stelle in unserem UI konfigurieren würde. Sie könnten Ihre eigenen UI rollen Präferenzen in der Masse von dem Benutzer zu sammeln. Im Großen und Ganzen ist dies eine schlechte Idee. Verwenden Sie stattdessen bevorzugt XML-Ressourcen und eine PreferenceFragment.

Warum?

Einer vondie gemeinsamen Beschwerden über Android-Entwickler ist, dass sie Disziplin fehlt, nicht nach etwaigen Normen oder Konventionen, die mit der Plattform. Bei anderen Betriebssystemen kann der Gerätehersteller verhindern, dass Sie Anwendungen verteilen, die ihre menschliche Schnittstelle Richtlinien verstoßen. Mit Android, das ist nicht der Fall ist - aber das ist nicht eine Decke Erlaubnis zu tun, was Sie wollen.

Wo da istein Standard oder Konvention, folgen sie bitte, wenn Sie einen klaren Grund, nicht zu haben, so dass die Benutzer mehr Komfort mit Ihrer Anwendung und ihr Gerät fühlen.

MiteinPreferenceFragmentfür Präferenzen zu sammeln ist eine solche Konvention.

Dreh- und Angelpunkt zudie Vorlieben Rahmen und PreferenceFragment ist noch eine weitere Gruppe von XML-Datenstrukturen. Sie können Ihre Anwendung-Einstellungen im XML-fi beschreiben
in Ihrem Projekt gespeichertres / xml / Verzeichnis. In Anbetracht, dass

Android eine Benutzeroberfläche für die Manipulation dieser Präferenzen darstellen kann, eine, die dem entspricht, was man in der App Einstellungen zu sehen. Die Auswahl des Benutzers werden dann in den SharedPreferences gespeichert, die Sie von getDefaultSharedPreferences zurück ().

Dies kann gesehen werden,dasPrefs / FragmentBeispielprojekt.

ZeigeDie aktuellen Werte

Dieser Haupttätigkeit des Projektrechnerein Tablelayout, in dem wir die Werte von fünf Voreinstellungen laden werden:

(from

Prefs / Fragment / app / src / main /
res / Layout / content.xml)

Die obige Layout wird vonPreferenceContentsFragment, Die füllt die rechte Spalte vonTextviewWidgets zur Laufzeit inauf Wiederaufnahme()Und zieht die Werte aus der StandardSharedPreferencesfür unsere Anwendung:

(von

Prefs / Fragment / app / src / main / java / com / commonsware / android /
preffrag / PreferenceContentsFragment.java)

Die Haupttätigkeit,FragmentsDemo, Lädt einfachres / Layout / main.xmlGeht, die
eine<Fragment>Element zeigt aufPreferenceContentsFragment. Es definiert auch ein Optionsmenü, die wir später in diesem Abschnitt untersuchen wird.

Das Ergebnis ist eine Aktivität zeigt,die Standardwerte der Präferenzen, wenn es fi laufen, da wir alle Werte noch nicht festgelegt haben:

Definieren von Voreinstellungen

Du zuerstmüssen Android zu sagen, welche Vorlieben Sie versuchen, von dem Benutzer zu sammeln.

Um dies zu tun, werden Siebrauchen eine res / xml / Verzeichnis zu einem Projekt hinzuzufügen, wenn man nicht bereits vorhanden ist. Dann wird für Ihre PreferenceFragment, werden Sie eines dieser XML-Ressource fi definieren. Das Wurzelelement dieser XML-fi wird <PreferenceScreen>, und es wird untergeordneten Elemente enthalten, eine pro Präferenz.

Imdas Beispielprojekt haben wir eine solche fires / xml / preferences.xml:

(von

Prefs / Fragment / app / src / main / res /
xml / preferences.xml)

Jede PräferenzElement hat zwei Attribute auf Minimum:

1. android: Schlüssel, die der Schlüssel ist, dass Sie den Wert in der nachschlagen verwenden, um

SharedPreferencesObjektüber Methoden wiegetInt ()

2. android: Titel, die ein paar Worte ist diese Einstellung für den Benutzer zu identifizieren Sie können auch zu prüfen, dieandroid: Zusammenfassung, die einen kurzen Satz zu erklären, was der Benutzer für diese Präferenz zu liefern ist.

Es gibt viele andere Attribute, die gemeinsam für alle Vorzugselemente, und es gibt mehrere Arten von Vorzugs Elemente als diejenigen, die wir in der Präferenz XML verwendet oben gezeigt. Wir werden mehr bevorzugt Elemente untersuchenspäter im dieses Kapitel.

Erstellen Sie Ihre PreferenceFragment

Bevorzugt XML, auf API-Ebene 11 und höher, geladen wird durch eine Implementierung vonPreferenceFragment. Die MissionPreferenceFragmentist zu
nennenaddPreferencesFromResource ()imonCreate ()Und liefert die Ressourcen-ID des Präferenz XML zu laden (zBR.xml.preference2). Das Fragment, inwiederum kann durch eine einfache belastet werdenAktivität.

Eigentlich,das Fragment so kurz ist, könnte man es sogar eine statische Klasse in der Aktivität zu machen, wie in der Beispielanwendung durchgeführt wird. Die Aktivität, die die Vorlieben sammelt, EditPreferences, hat eine Prefs statische Unterklasse von PreferenceFragment:

(von

Prefs / Fragment / app / src / main / java / com / commonsware /
android / preffrag / EditPreferences.java)

Das einzigeSache diePrefstut, ist Aufrufdie geerbteaddPreferencesFromResource ()in seinemonCreate ()Verfahren, Versorgungdie ID des Vorzugs XML. AlleEinstellungen bearbeitenhat sich arrangieren zu zeigen,das Fragment, in diesem Fall ein mitFragmentTransaction.

Die Ergebnisse

Eine HandlungBar Artikel inHauptaktivitätstartetdasEinstellungen bearbeitenAktivität. Wenn Sie aufdass aus demÜberlauf, erhalten Sie die Benutzeroberfläche sehen von Ihrem XML durch die erstelltPreferenceFragment:

Wenn Sie macheneine Änderung, wie auf das Kontrollkästchen tippen, und drücken Sie wieder auf die ursprüngliche Tätigkeit zurückkehren, werden Sie die resultierende Änderung in der Präferenzwerte selbst sehen:

Android Studio Profileditor

Wenn Sie eröffneneine Präferenz XML Ressource in Android Studio, werden Sie einen Editor, erinnert an die Layout-Ressource-Editor ist gegeben. Sie werden zwei Unterregister haben: "Text"

mit dem XML und "Design" mit einem Drag-and-Drop-Benutzeroberfläche:

Die Drag-and-Drop-Editor UI arbeitet an seinem Layout Ressource-Editor Pendant verwandt. Sie können per Drageine Präferenz aus der Palette entweder in den Vorschaubereich oder in den Komponentenbaum es auf die Ressource hinzuzufügen. Für jede ausgewählte Präferenz ermöglicht der Bereich Eigenschaften Sie Attribute zu ändern, entweder aus der Standard-Kurz Liste der beliebtesten Eigenschaften oder die vollständige Liste der Eigenschaften, die Sie von einem Klick auf "Alle Eigenschaften" erhalten.

Arten Präferenz

Es gibteine Vielzahl von Unterklassen von Bevorzugt im Android SDK für die Verwendung mit PreferenceActivity. In diesem Abschnitt werden die wichtigsten auf skizzieren.Später imdas BuchWir werden untersuchen, wie Sie eigene zu erstellenBevorzugt Klassen.

CheckBoxPreference und SwitchPreference

Die Beispielanwendung oben gezeigt hatein Paar CheckBoxPreference Elemente, ein je Vorzugs XML fi

Ein CheckBoxPreference ist eine "Inline" bevorzugt, dass das Widget der Benutzer interagiert mit (in diesem Fall ein CheckBox) ist Teil der Präferenz Bildschirm selbst, anstatt in einem separaten Dialog enthalten.

SwitchPreferenceist funktional äquivalent zuCheckBoxPreference, Sofern beide
sammelnbooleanWerte vonder Benutzer. Der Unterschied ist,

dassSwitchPreferenceAnwendungeneinSchalterWidgetdass die Benutzer gleitet nach links und rechts zwischen "Ein" und "Aus" -Zuständen umzuschalten. Beachten Sie auch, dassSwitchPreferencewird in API-Ebene 14 und damit hinzugefügtnicht auf älteren Android-Versionen verfügbar sein.

EditTextPreference

EditTextPreference, Wenn sie vom Benutzer abgehört, erscheint ein Dialog, dass ein enthält EditText Widget. Sie können das Widgetüber Attribute auf die Konfiguration

<EditTextPreference>Element - neben Standardpräferenzattribute wieandroid: keySie können jedes Attribut verstanden sind durchText bearbeiten, sowieandroid: input.

Der Wert gespeichert indasSharedPreferencesistein Faden. Die

Beispielanwendung hat eineEditTextPreference:

(von

Prefs / Fragment / app / src / main / res /
xml / preferences.xml)

Wannder Benutzer tippt darauf im PreferenceFragment, einen Dialog der Benutzer sehen, wo sie in einem Wert, oder bearbeiten Sie einen vorhandenen Wert fi nden können, wenn sie zu einem früheren Zeitpunkt zur Verfügung gestellt:

RingtonePreference

RingtonePreferenceöffnet sich ein Dialog mit einer Liste der Klingeltöne auf dem Gerät oder Emulator installiert werden. Aber bedenken Sie, dassältere Emulator Bilder keine vorinstallierten Klingeltöne haben.

In ErgänzungshowDefault, was darauf hinweist, dass die Liste eine "Standard-Klingelton" Option enthalten sollte: auf die Standardpräferenzattribute können Sie android umfassen. Wenn der Benutzer diese Klingelton wählt, entscheiden sie effektiv den gleichen Klingelton, die sie für eingehende Anrufe eingerichtet haben.

Sie können auch verwendenandroid: showSilent, die dem Benutzer erlaubt, eine "Silence" Pseudo-Klingelton zu wählen, um anzuzeigen, keinen Klingelton zu spielen.

Die Beispielanwendung hateinRingtonePreference:

(von

Prefs / Fragment / app / src / main / res /
xml / preferences.xml)

Wannder Benutzer Abgriffe in der PreferenceFragment, wird der Benutzer eine Liste von Klingeltönen, zusammen mit "Standard" und "None" Optionen zu sehen, da wir in solche entschieden:

Der Wert gespeichert indie SharedPreferences ist eine Zeichenfolge, insbesondere die String-Darstellung eines Uri zeigte auf eine Contentprovider, die den Klingelton für die Wiedergabe dienen kann. Die Verwendung von Contentprovider abgedeckt werdenimein späteres Kapitelabgedeckt werden, und Medien wie Klingeltöne wird wieder spielenin einem anderen späteren Kapitel.

ListPreference undMultiSelectListPreference

Visuell,einListPreferencesieht genauso aus wieRingtonePreference, Mit der Ausnahme, dass Sie kontrollieren, was in die Liste geht. Sie tun dies, indem ein Paar AngabeString-ArrayRessourcen in Ihrer Präferenz XML.

String-Ressourcen halten einzelnen Strings; String-Array-Ressourcen halteneine Sammlung von Strings. Typischerweise werden Sie fi

Schnur Array-Ressourcen inres / Werte / arrays.xml
und damit verbundene Ressourcengruppen für dieÜbersetzung. Die <string-Array> Element hat den Namen
zuschreibenidentifizieren die Ressource, zusammen mit Kind <item> Elemente für die einzelnen Strings im Array.

Also, unsere Beispielanwendung hatein Paar<String-array>Ressourcen inres / Werte / arrays.xml:

(von

Prefs / Fragment / app / src / main / res

/ Werte / arrays.xml)

Hier,die tatsächlichen Strings werden in-line geschrieben. Sie könnten genauso gut Verweise auf String-Ressource sein (zB <item> @ Zeichenfolge / philly </ item>). Für Benutzer gerichtete Strings, wie diejenigen, die in den Städten Array, so dass sie als String-Ressourcen hat, kann es einfacher für Sie, Ihre Übersetzungen zu verwalten.

Die Beispielanwendungdann verwendet diese Arrays in einListPreference:

(von

Prefs / Fragment / app / src / main / res /
xml / preferences.xml)

Diesdann ermöglicht es dem Benutzer, eine Stadt zu wählen, wenn der Benutzer auf diese Präferenz im PreferenceFragment tippt:

Wenn jedochder Benutzer wählt eine Stadt mit Namen (zB Philadelphia), was in der gespeichert wirdSharedPreferencesistdie entsprechenden Flughafencode (zB PHL).

MultiSelectListPreferencefunktioniertähnlichdie gleiche Art und Weise, mit der Ausnahme:

• Die Liste enthält Kontrollkästchen,nicht Radio-Buttons

• Der Benutzer kann mehrere Artikel überprüfen

• Das Ergebnis wird gespeichert inein "String-Set" in derSharedPreferences, Abgerufen über getStringSet ()

• Es ist nur auf API-Ebene 11 und höher

Wir werden sehenMultiSelectListPreferencein Aktionspäter imdas Buch.

Tutorial # 13- Mit einigen Einstellungen

Jetztdass wir die Kernlese Funktionalität Arbeits haben, können wir beginnen, für den Benutzer andere Funktionen hinzuzufügen.

Ein gemeinsameswas in Android-Anwendungen ist Präferenzen vom Benutzer zu sammeln, Schneiderei, wie die App verhält. Im Falle von EmPubLite, werden wir zunächst zwei Vorlieben verfolgen:

• Obder Nutzer will, um das Buch auf dem gleichen Kapitel (Seite im ViewPager)

zurückzukehren, dass sie auf, als sie zuletzt das Buch gelesen haben

• Obder Benutzer möchte, dass wir auf dem Bildschirm zu halten, so dass sie müssen nicht halten den Bildschirm tippen Android automatische Sleep-Modus von Tritte in zu verhindern

ImIn diesem Tutorial werden wir diese beiden Vorlieben sammeln und zu
nutzen. Dies ist eine Fortsetzung der Arbeit, die wir haben indie vorherigen

Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Definierendie Präferenz von XML-Dateien

Wirbenötigen eine XML-Ressource fi
zu definieren, welche Vorlieben wir sammeln
möchten. Fügen Sie zunächst vierneu<String>Elementeres / Werte / strings.xml: Als nächstes Rechtsklick überres / in Ihr Projekt und Neu> "Android Ressourcenverzeichnis"

aus dem Kontextmenü wählen. Ändern Sie den "Ressourcentyp" drop-down "xml" zu sein, dann klicken Sie auf OK um das Verzeichnis zu erstellen.

Dann mit der rechten Maustaste auf Ihreneue res / xml / Verzeichnis und wählen Sie Neu>

"XML-Ressource fi" aus dem Kontextmenü. Füllen Sie pref_display.xml in der "New XML

Resource File" Dialog, dann auf OK klicken Sie auf die fi erstellen

Dies eröffnet inEditor eine Präferenz Bildschirm mit "Design" und "Text" Unterregister:

ZieheneinCheckBoxPreferencevondie Palette in den Vorschaubereich. Dann wird in dem Bereich Eigenschaften den Schlüssel aufsaveLastPosition, Stellen Sie den Titel@ Zeichenfolge /
lastposition_titleund setzen, um die Zusammenfassung@ Zeichenfolge / lastposition_summary:

Als nächstes ziehen andereCheckBoxPreferencevondie Palette in den Vorschaubereich. Dann wird im Bereich Eigenschaften für diese neu hinzugekommenen Präferenz, den Schlüssel
aufkeepScreenOn, Stellen Sie den Titel@ Zeichenfolge / keepscreenon_titleund setzen, um die Zusammenfassung@ Zeichenfolge / keepscreenon_summary:

Wenn man sichsiehe die XML in der "Text" Unterregister, sollten Sie, dass es ähnelt: (von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src /
main / res / xml / pref_display.xml)

Schritt 2: Erstellen Unsere Präferenz Aktivität

Wir werden schließlich ladendass Präferenz XML in einen PreferenceFragment. Wir könnten eine PreferenceActivity dafür verwenden, aber wir haben nicht genug Vorlieben ein volles Master /

Detail-Setup zu rechtfertigen. Stattdessen können wir nur das Display

PreferenceFragmentim ein StammkundeAktivität, genanntVoreinstellungenUnter Verwendung einer statischen inneren Klasse Implementierung einesPreferenceFragment, genanntAnzeigen.

Rechtsklicken Sie aufdie com.commonsware.empublite Paket in Ihrem java / und Neu> Aktivität> Leere Aktivität aus dem Kontextmenü wählen. Legen Sie den Namen der Aktivität Einstellungen und deaktivieren Sie alle Kontrollkästchen zu sein. Dann klicken Sie auf Fertig um die Aktivität zu dem Projekt hinzuzufügen.

Imdie Vorlieben Klasse, die erstellt wird, ersetzen Sie die aktuelle Implementierung mit den folgenden:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / Preferences.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt 3: Hinzufügen zu unserem Aktionsleiste

Natürlich, mitdiese Aktivität tut uns nicht gut, wenn wir es nicht starten können, so müssen wir einen anderen Haken an unsere Aktionsleiste Konfiguration für das hinzuzufügen.

Zuerst fügeneinEinstellungenString-Ressource, mit ein Wert vonEinstellungen:

Als nächstes herunterladendas Symbol "Einstellungen" aus dem offi

Material Design-

Ikonenals SVG fi

Dann mit der rechten Maustaste aufdie res / Verzeichnis Ihrer app / Modul und New> Vector Inventar aus dem Kontextmenü wählen. Klicken Sie auf den "Local fi" Radio-Button, dann wählen Sie die SVG-fi
dass Sie auf den Pfad heruntergeladen

Klicken Sie auf Weiter,Beenden Sie dann.

Schließlich fügendas folgende XML-Elementres / menu / options.xmlwiedie fi

Kind von
das<Menü>WurzelElement:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app /
src / main / res / menu / options.xml)

Schritt 4: Startendie Präferenz Aktivität

Das einzigeSache noch der Benutzer auf die Präferenzen zu erhalten, damit wir brauchen, ist eine neue hinzufügenFallnachdasSchalter()Aussage inonOptionsItemSelected

()vonEmPubLiteActivity:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Nun, wenn Sie laufendies in einem Emulator oder Gerät, werden Sie die neue Option in der Aktionsleiste Überlauf sehen:

Die Wahldie Option "Einstellungen" bringt unsere beiden Einstellungen auf: Schritt # 5: Ladendie Voreinstellungen

Jetzt wirmüssen tatsächlich arrangieren, um die Einstellungen auf einem Hintergrund-Thread zu laden.

Wie erwähnt, wird dies durch unsere ModelFragment gehandhabt werden, so wie es das Laden der Buchinhalt verarbeitet.

Zuerst fügen ein privates Daten Mitglied mit dem Namenprefs, Dass einAtomicReferencenach ein SharedPreferences, nachModelFragment:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Dann füge hinzueingetPrefs ()MethodeModelFragmentdass kehrt dieprefsWert:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Als nächstes reviseLoadThreadnach:

• ErsetzendasVermögenswerteDaten-MitgliedeinctxtDatenelementArtKontext

• aufnehmenein Kontext im Konstruktor (sein diese Weise, auch wenn aus irgendeinem seltsamen Grund unserer ursprünglichen Aktivität zerstört und neu erstellt, während wir die Vorlieben geladen werden, werden wir nicht die ursprüngliche Aktivität undicht) anstelle eines Assetmanager

• Speichernder Anwendungskontext (ausgetApplicationContext ()aufKontext) In einem Datenelement anstelle einesVermögensverwalter

• AnrufgetAssets ()aufdassKontextimLauf(), Anstatt die erstere mit

Vermögensverwalter

• auch abrufendasSharedPreferencesimLauf()

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Dies hat unsereLoadThreadladen beidedasSharedPreferencesunddasBOOK, Und zwar in einer bekannten Reihenfolge (SharedPreferencesfi

Du wirständern müssenonAttach ()passieren nur indasAktivitätnach dasLoadThread

Konstruktor:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

die sich ergebendeModelFragmentaussehen sollte:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Schritt 6: Speicherndie Last-Position lesen

Eine Präferenz ist unsere aktuelle Seite zur Wiederherstellung indie ViewPager, wenn der Benutzer später wieder öffnet die App. Um diese Arbeit zu machen, müssen wir beginnen, die aktuelle Seite zu speichern, wenn der Benutzer die Anwendung verlässt. Und können wir auch unsere frisch gebackenen SharedPreferences verwenden Sie diesen Wert zu speichern.

Wirbenötigen einen Schlüssel, mit dem speichern wir diesen Wert in derSharedPreferencesso fügen Sie ein neues statisches Datenelement zuEmPubLiteActivity:

Wir werden auch aufbrauchen Zugang zu unseremModelFragmentvon außerhalbauf Wiederaufnahme() imEmPubLiteActivity. Füge hinzu einModelFragmentDatenelement genanntmfrag:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Dann,ändernonStart ()zu beziehendasmfragDatenelement, ersetztdas Vorherige

mfraglokale Variable:

Als nächstes UpdateOnStop ()aufEmPubLiteActivityverfolgendie Seite derViewPager
dass der Benutzer an dem Punkt in der Zeit, wenn OnStop () aufgerufen wird:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Hier prüfen wir,dass wir dieSharedPreferencesbeladen- Chancen sind, dass wir das tun, aber wir können nicht sicher sein. Wenn wir uns den Zugang zu den habenSharedPreferencesWir fi nden
ausdie aktuelle Position innerhalb derViewPagerübergetCurrentItem ()(z.B,0fürdie fi

Seite). Wirerhalten dann eineSharedPreferences.Editorund es verwenden, zu
speicherndieser Positionswert in derSharedPreferencesVerkeilt alsPREF_LAST_POSITIONunter Verwendung vonapply ()anhaltendie Veränderungen.

Schritt 7: Wiederherstellendie Last-Position lesen

Jetztdass wir diese Positionsdaten speichern, können wir es in Betrieb nehmen.

Unsere Präferenz XML hat unser Schlüssel zum"Save Last Position" Präferenz, aber wir müssen es in Java-Code als auch, so fügen Sie ein anderes statisches Datenelement zu EmPubLiteActivity:

Hinzufügendie folgenden Zeilen bis zum Ende dersetupPager ()imEmPubLiteActivity: Hier prüfen wir, obder Benutzer hat es uns ermöglicht, die zuletzt gespeicherte Position wiederhergestellt werden muss (auf false angenommen wird). Wenn der Benutzer hat, rufen wir die zuletzt gespeicherte Position (standardmäßig auf 0, oder die fi

Seite),und

CallsetCurrentItem () auf dem ViewPager auf die jeweilige Seite zu verschieben.

Wenn Sie laufendies in einem Gerät oder Emulator, überprüfen Sie die "Save Last Position"

markieren bevorzugt, fl
voraus ein paar Kapitel, verlassen Sie die App über die BACK-

Taste, und zurück in die App gehen, werden Sie sehen, dass Sie zurück in das Kapitel entnommen werden Sie zuletzt gelesene.

Schritt 8: Haltender Bildschirm auf

Unsere anderen Präferenz ist, obnicht sollte der Bildschirm bleiben, ohne Benutzereingabe, während wir das Buch lesen. Die nackten Knochen Umsetzung dieser erfordert nur zwei Zeilen mit zusätzlichem Code.

Als erstes werden wirbrauchen eine andere statische Daten Mitglied auf EmPubLiteActivity, diesmal mit dem Schlüssel für unsere Keep-Bildschirm-on Präferenz zu definieren: Dann fügen Sie eine weitere Zeile zusetupPager ()imEmPubLiteActivityInnerhalb derob Block:

Dies gibt Ihnen:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

setKeepScreenOn (), auf einer beliebigen View genannt, halten den Bildschirm beleuchtet und aktiv ohne kontinuierliche Benutzereingabe, solange die Ansicht auf dem Bildschirm ist.

Dieser Ansatz ist etwas eingeschränkt, indass wir (nur Einstellung dieser während des Anrufs setupPager werden). Wenn der Benutzer den Präferenzwert ändert, nur diese Änderung in Kraft treten soll, wenn die Aktivität neu gestartet wurde (zB Benutzer dreht den Bildschirm verlässt Benutzer die App über BACK und kehrt später).

Der einfachste Weg für uns zu habendiese nehmen mehr sofortiger Wirkung zu erkennen, dass EmPubLiteActivity pausiert werden und gestoppt, wenn die Einstellungen Aktivität auf dem Bildschirm ist, und gestartet wird und wieder aufgenommen, wenn die Benutzereinstellungen durchgeführt wird eingestellt. So können wir einfach onStart () erweitern auch den Bildschirm-on Einstellung zu aktualisieren:

(von

EmPubLite-Android Studio / T13-Prefs / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Natürlich können wirhaben nicht die SharedPreferences noch, wenn die App fi beginnen, so wir vermeiden, dass Änderungen in diesem Fall.

Wenn Sie laufendiese auf einem Gerät (Anmerkung: kein Emulator), können Sie mit dieser Einstellung spielen und die Veränderungen in den Bildschirm des Verhaltens sehen.

In unserer nächsten Folge ...

... Wir werden dem Benutzer erlauben,Schreiben, Speichern und Löschen von Notizenfürdie aktuell betrachtete Kapitel, eine Datenbank zu verwenden.

SQLite-Datenbanken

AußerdemSharedPreferences und Ihre eigenen fi Strukturen, die dritte primäre Mittel der auf Android Daten lokal persistierenden ist über SQLite. Für viele Anwendungen ist SQLite das Rückgrat der App, ob sie direkt verwendet wird, oder über einen Drittanbieter-Wrapper.

Dieses Kapitel konzentriert sich auf, wie Sie mit SQLite direkt arbeiten können relationale Daten zu speichern.

Einführung in SQLite

SQLiteisteine sehr beliebte eingebettete Datenbank, wie es kombiniert eine saubere SQL-Schnittstelle mit einem sehr geringen Speicherbedarf und akzeptabler Geschwindigkeit. Darüber hinaus ist es public domain, so dass jeder sie verwenden können. Viele fi

(Adobe, Apple,

Google, Symbian) und offene sourcE-Projekte (Mozilla, PHP, Python) alle Produkte des Schiffs mit SQLite.

Für Android, SQLite ist "gebacken in"die Android Runtime, so dass jedes Android-Anwendung kann SQLite-Datenbanken erstellen. Da SQLite eine SQL-Schnittstelle verwendet, ist es relativ einfach für die Menschen in anderen SQL-basierten Datenbanken mit Erfahrung zu verwenden.

Allerdings ist seine native API ist nicht JDBC und JDBC könnte zu viel Aufwand für eine Speicher begrenzte Gerät wie ein Telefon, sowieso. Daher haben Android-Programmierer eine andere API zu lernen - die gute Nachricht dafür ist, dass es nicht so schwierig ist.

Dieses Kapitel decktdie Grundlagen der SQLite im Zusammenhang auf Android zu arbeiten. Es ist keineswegs eine gründliche Abdeckung von SQLite als Ganzes. Wenn Sie mehr über SQLite zu lernen, dieSQLite WebsiteVielleicht hilft das.

Denken an Schemen

SQLite isteine typische relationale Datenbank, Tabellen, die (sich bestehend aus Zeilen und Spalten), Indizes und so weiter. Ihre Bewerbung wird seinen eigenen Satz von Tabellen müssen und so weiter zu halten alle Daten, die Sie halten möchten. Diese Struktur wird im Allgemeinen als ein "Schema"

bezeichnet.

Es ist wahrscheinlichdass Ihr Schema müssen im Laufe der Zeit ändern. Sie könnten neue Tabellen oder Spalten unterstützen neue Funktionen hinzuzufügen. Oder könnten Sie deutlich Ihre Datenstruktur reorganisieren und einige Tische fallen eingereicht, während die Daten in neue zu bewegen.

Wieein Ergebnis, wenn Sie ein Update für Ihre Anwendung an die Benutzer versendet, wird Ihr Java-Code ändern, nicht nur, aber die Erwartungen des Java-Code wird auch in Bezug auf das, was Ihr Datenbankschema aussehen wird, ändern. Version 1 der App wird Ihre ursprüngliche Schema verwenden, sondern durch die Zeit, die Sie versenden, sagen wir, die Version 5 der App, könnten Sie eine angepasste Schema benötigen.

Android hat Einrichtungen, die Sie unterstützen mit wechselnden Datenbankschemata Handhabung, meist zentriert umdie SQLiteOpenHelper Klasse.

Beginnen mitein Helfer

SQLiteOpenHelper ist entworfen, um Ihren Code im Zusammenhang mit zwei sehr häufig auftretende Probleme zu konsolidieren:

1. Was geschiehtdie sehr fi Zeit, wenn Ihre Anwendung auf einem Gerät ausgeführt wird, nachdem es installiert ist? Zu diesem Zeitpunkt haben wir noch nicht eine Datenbank, und so müssen Sie Ihre Tabellen, Indizes, Starter-Daten, usw. zu erstellen.

2. Was geschiehtdie sehr fi

Zeit, wenn eine aktualisierte Version der App auf einem

Gerät ausgeführt wird, wo die aktualisierte Version eine neuere Datenbankschema
erwartet? Ihre Datenbank wird immer noch auf dem alten Schema von der älteren Version der App. Sie müssen eine Chance zu haben, das Datenbankschema zu ändern, um die

Bedürfnisse der Rest Ihrer Anwendung anzupassen.

SQLiteOpenHelper wickelt die Logik bis zu erstellen und eine Datenbank zu aktualisieren, nach Ihren Vorgaben, wie von der Anwendung benötigt werden. Sie müssen eine benutzerdefinierte Unterklasse von SQLiteOpenHelper, Implementierung drei Methoden bei Minimum zu erstellen: 1. Der Konstruktor, Verkettungs nach obender SQLiteOpenHelper Konstruktor. Dies
geschieht durch die Context (zB eine Aktivität), den Namen der Datenbank, eine optionale Cursor-Fabrik (in der Regel nur null übergeben), und eine ganze Zahl, die Version des

Datenbankschemas darstellt, die Sie verwenden (beginnen in der Regel bei 1 und Zuwachs von Dort).

2. onCreate () aufgerufen wird, wenn es keine Datenbank und Ihre Anwendung benötigt man, was passiert Sie ein SQLiteDatabase-Objekt, zeigt auf eine neu erstellte Datenbank, die Sie mit Tabellen und Ausgangsdaten, gegebenenfalls auffüllen verwenden.

3. ONUPGRADE () aufgerufen, wenn die Schemaversion Sie suchen nicht die

Schemaversion der Datenbankübereinstimmt, die Sieübergibt ein SQLiteDatabase

Objekt und die alten und neuen Versionsnummern, so können Sie
fi
e, wie am besten die Datenbank aus dem alten Schema auf die neue zu
konvertieren.

Um zu sehen, wie allediese SQLite Sachen in der Praxis funktioniert, werden wir untersuchen, dieDatenbank/ ConstantsROWIDBeispielanwendung. Diese Anwendung ziehtein Bündel von Gravitationskonstanten von der Sensormanager Klasse, legt sie in einer Datenbank-Tabelle, zeigt sie in einer ListFragment, und ermöglicht es dem Benutzer neue über die Aktionsleiste hinzuzufügen.

Als erstes werden wirbraucheSQLiteOpenHelperUnterklasse, hiergenanntDatabaseHelper.

DasDatabaseHelper Konstruktor Ketten an dieübergeordnete Klasse und liefert den Namen der Datenbank (gehalten in einem DATABASE_NAME statisches Datenelement) und die

Versionsnummer der Datenbank-Schema (statt in SCHEMA):

(von

Datenbank / ConstantsROWID / src / com / commonsware /
android / Konstanten / DatabaseHelper.java)

Wir auchbrauchen einonCreate ()Methode, die aufgerufen wird,
undübergebeneinSQLiteDatabaseObjekt, wennmuss eine Datenbank neu erstellt werden.

Nachfolgend erhalten Sie dieDatabaseHelperImplementierung vononCreate (), Erhalten wir jedoch darüber, wie es mit derSQLiteDatabaseObjekt später mehr indieses Kapitel:

(von

Datenbank / ConstantsROWID / src / com / commonsware /
android / Konstanten / DatabaseHelper.java)

Es genügt zu sagen fürder Moment, es ist eine Konstanten-Tabelle erstellen und mehrere Reihen hinein, die alle in einer Transaktion eingewickelt einlegen.

Wir auchmüssen ONUPGRADE () ... obwohl es sollte nie im Augenblick aufgerufen werden:

(von

Datenbank / ConstantsROWID / src / com / commonsware /
android / Konstanten / DatabaseHelper.java)

Schließlich, gerade jetzt, haben wir nur eine Version unseres Schemas(1) und daher keine Notwendigkeit, zu aktualisieren. Wenn in der Zukunft, wir SCHEMA auf einen höheren Wert zu ändern (zB 2), und wir unsere App auf einem Gerät zu aktualisieren, die zuvor mit unserem früheren Schema ausgeführt worden war, dann werden wir mit ONUPGRADE () aufgerufen werden. Wir sind die alten und neuen Schemaversionen übergeben, so dass wir wissen, was aktualisiert werden muss.

Berücksichtigendass die Nutzer müssen auf jedem Ihrer Anwendungs-Updates nicht unbedingt nehmen, und so könnten Sie fi
dass ein Benutzer eine Schema-Version übersprungen:

• Sie geben eine App am Montag, mit Schema-Version1

• Ein Benutzer installiert die App am Dienstag und läuft es, die Schaffung einer Datenbank über
onCreate ()

• Sie geben eine aktualisierte App am Mittwoch, mit Schema-Version2

• Sie geben noch ein weiteres Upgrade am Donnerstag, mit Schema-Version3

• Der Benutzer installiert das Upgrade, jetztein Schema Version 3-Datenbank
benötigen, anstatt die Version 1 derzeit auf dem Gerät, um einen Anruf zu Auslösen ONUPGRADE ()

Es gibt zwei andere Methoden können Sieelect in Ihrem SQLiteOpenHelper außer Kraft zu setzen, wenn Sie das Bedürfnis verspüren:

• Sie können außer Kraft setzenonOpen (), die Kontrolle zu bekommen, wenn
jemand diese Datenbanköffnet. Normalerweise ist dies nicht erforderlich.

• Android 3.0 eingeführtonDowngrade (), die aufgerufen wird, wenn der Code anfordert eine ältere Schema als das, was gegenwärtig in der Datenbank ist. Dies ist das Gegenteil von ONUPGRADE () - wenn Ihre Versionsnummern unterscheiden, eine dieser beiden

Methoden aufgerufen werden. Da in der Regel bewegen Sie sich vorwärts mit Updates, können Sie in der Regel onDowngrade überspringen ().

Der Einsatz der Helfer

So verwenden Sie IhreSQLiteOpenHelperUnterklasse, zu erstellen und auf eine Instanz davon halten.

Dann, wenn SiebraucheSQLiteDatabaseObjektabfragen oder Datenänderungen zu tun, fragen Sie IhrenSQLiteOpenHelpernachgetReadableDatabase ()odergetWritableDatabase ()Abhängig davon, ob oder nicht, werden Sie dessen Inhalt sichändern.

Beispielsweise,dasConstantsFragmentvondie Beispielanwendung erstellt einDatabaseHelper B. inonViewCreated ()und hält sich an sie inein Datenelement:

(von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

Wenn Sie fertig sind mitdie Datenbank (zB Ihre Aktivität geschlossen wird), rufen Sie einfachschließen()auf IhremSQLiteOpenHelperveröffentlichen Sie Ihre Verbindung,
wieConstantsFragment(unter anderenDinge) inonDestroy ():

(von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

(Wir erkundendiese "andere Dinge" in einem Bit)

Woherzu Halten Sie einen Helfer

Für triviale Anwendungen, wiedie ein Profi
imdieses Kapitel ist eine SQLiteOpenHelper in
einem Daten Mitglied Ihrer one-and-only Holding fi

Wenn jedoch haben Sie mehrere Komponenten- Wie mehrere Aktivitäten - alle benötigen die Datenbank zu nutzen, sind Sie viel besser bedient eine einzelne Instanz Ihrer SQLiteOpenHelper mit, im Vergleich zu jeder Aktivität eine eigene Instanz haben.

Der Grund ist Threading.

Sie sollten wirklich Ihre Datenbank I / O auf Hintergrund-Threads zu tun. Öffnungeine Datenbank ist billig, aber die Arbeit mit ihm (Abfragen, Beilagen, etc.) ist es nicht. Das SQLiteDatabase Objekt von SQLiteOpenHelper verwaltet ist Thread-sicher ... so lange, wie alle Fäden die gleiche Instanz verwenden.

Für Singleton-Objektedas hängt davon ab, eineKontext, mögenSQLiteOpenHelper, Anstatt das Objekt mit einer Garten-Sorte erstellenKontextwie einAktivität, Sollten Sie wirklich es mit einem erstellenAnwendung. Es gibt eine einzelne Instanz einesKontextIn Form
desAnwendungUnterklasse, in Ihrem Prozess Momente erstellt, nachdem er gestartet wird. Sie können abrufendiese Singleton durch den AufrufgetApplicationContext ()auf einer anderenKontext.

Der Vorteil der VerwendungAnwendungistSpeicherlecks: Wenn Sie ein
setzenSQLiteOpenHelperimein Singleton, und zu verwenden, sagen, einAktivitätschaffen es,dann ist

dieAktivitätMachtnicht in der Lage sein, Garbage Collection zu sein, weil
dieSQLiteOpenHelperhältein starker Hinweis auf sie. Schon seitAnwendungselbstein Singleton (und daher ist "pre-durchgesickerten" sozusagen), signifikant die Risiken einer Speicherverlust verringern.

Anstatt also:

imein Fragment, mit db als Datenelement, könnten Sie haben:

mitdb als statisches Datenelement, geteilt durch mehrere Aktivitäten oder andere Komponenten.

Abrufen von Daten Out

Ein beliebteswas mit einer Datenbank zu tun ist, Daten aus ihm heraus zu bekommen. Android hat ein paar Möglichkeiten, wie Sie eine Abfrage auf einem SQLiteDatabase ausführen können (von Ihrem SQLiteOpenHelper), zusammen mit einigen Klassen, wie Cursor, können Sie die Ergebnisse, die Sie zurückbekommen verwenden, um zu helfen.

Abfrageoptionen

In den meisten Fällen Ihre einfachste Möglichkeit für die Ausführungeine Abfrage rawQuery () auf dem SQLiteDatabase zu nennen. Dies hat zwei Parameter:

• Eine SQL-Anweisung SELECT (oder irgendetwas anderes, die eine

Ergebnismenge zurückgibt), gegebenenfalls mit? Zeichen in der WHERE-Klausel

(oder ORDER BY oder ähnliche Klauseln), die Parameter zur Laufzeit gebunden zu
sein

• Eine optionaleString Array der Parameter verwendet werden, die zu ersetzen?

Zeichen indie Abfrage

Wenn Sie tunVerwenden Sie das nicht? Positionsparameter Syntax in der Abfrage, Sie sind willkommen, null als zweiten Parameter zu rawQuery () übergeben.

Der netteSache über rawQuery () ist, dass jede gültige SQL-Syntax funktioniert, solange es eine Ergebnismenge zurückgibt. Sie sind willkommen, beitritt, Unter wählt zu verwenden, und so weiter, ohne Frage.

Es gibt zwei andereAbfrageoptionen - query () und SQLiteQueryBuilder. Diese beiden Aufbau einer SQL SELECT-Anweisung aus seinen Bestandteilen (zB Name der Tabelle abzufragen, WHERE-Klausel und Positionsparameter). Diese sind umständlich zu bedienen, vor allem bei komplexen SELECT-Anweisungen. Meistens würden sie in Fällen eingesetzt werden, wo zum einen oder anderen Grund, dass Sie nicht die genaue Abfrage bei der Kompilierung und fi wissen es

einfacher, diese Einrichtungen zu verwenden, um die Abfrage von Teilen zur Laufzeit zu konstruieren. Einige Entwickler werden dies tun zu vermeiden Werte Duplizieren von Konstanten für Dinge wie Tabellennamen und Spaltennamen definieren.

Beispielsweise,ConstantsFragmenthateine private innere Klasse mit dem NamenBaseTaskwas hateindoQuery ()Methodedass AnwendungenAbfrage():

(von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

Machen, Wenn auch nicht Ihre eigene WHERE-Klausel verketten. Lassen Sie die ?

Positionsparameter behandeln, die für Sie als Arbeit, die sie tun, um Ihre Apostrophe zu entkommen, Zitat

Marken unddergleichen hilft auch gegen SQL-Injection-Angriffe zu verteidigen. In diesem speziellen Fall haben wir nicht eine WHERE-Klausel.

Obdass ROWID AS _id Stück sieht ein wenig seltsam, wir werden sehen, warum das in der Abfrage ein bisschen später in diesem Kapitel ist.

Was istein Cursor?

Alle dreidiese geben Ihnen einen Cursor, wenn Sie fertig sind. In Android, stellt ein Cursor auf die gesamte Ergebnismenge der Abfrage - alle Zeilen und alle Spalten, die die Abfrage zurückgegeben.

In dieser Hinsicht ist es erinnert an einen "Client-Cursor" von Toolkits wie ODBC, JDBC, usw.

(obder Cursor-Ergebnismenge über 1 MB ist, hält es eigentlich nur ein "Fenster" auf den Daten, und die Geschichte wird wirklich wirklich kompliziert ...)

So wie,ein Cursor kann durchaus der Speicher Schwein sein. Bitte schließen Sie (), um den Cursor, wenn Sie mit ihm fertig sind, den Heap-Speicherplatz freizugeben es verbraucht und dass der Speicher auf den Rest der Anwendung zur Verfügung zu stellen.

Mitder Cursor manuell

MitdasMauszeiger, Sie können:

1. Finden Sie heraus, wie viele Zeilen sind indas Ergebnis gesetzt über getCount () 2. iterierendie ReihenübermoveToFirst ().MoveToNext (), undisAfterLast ()

3. Rausfindendie Namen der SpaltenübergetColumnNames (), Diejenigen in

Spaltennummern umwandelnübergetColumnIndex ()Und für eine bestimmte Spalteüber

Methoden Werte für die aktuelle Zeile erhalten wiegetString ().getInt (), etc.

Zum Beispiel, hier iterieren wir übereine fi

Widgets Tabellenzeilen:

Die Einführung Cursor

Ein anderer Weg, zu verwenden,einMauszeigerzu wickeln ist es ineinCursor. Genauso wieArrayAdapteranpaßt Arrays,Cursorpasst sich anMauszeigerObjekte, so dassihre Daten zur Verfügung einAdapterViewmögen einListenansicht.

Daseinfachste Weg, eine davon bis zu setzen, ist zu verwenden,SimpleCursorAdapter, Der sichCursorund bietet einige vorformulierten Logik fürwobei Werte aus Spalten und in Zeile setzenAussichtObjekteeinListenansicht(oder andereAdapterView). Die Beispiel-App funktioniert einfachdass:

(von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

Hier sind wir zu sagenSimpleCursorAdapternehmen Reihen auseinMauszeigergenanntStrom, Die jeweils in einem aufgeblasenen DrehR.layout.row Viewgroupin diesem Fall,
einRelativeLayoutFesthaltenein PaarTextviewWidgets:

(von

Datenbank / ConstantsROWID /
res / layout / row.xml)

FürJede Zeile in derMauszeiger, Die Spalten mit den NamenTitelundWert(vertreten
durchTITELundWERTKonstantenDatabaseHelper) Sind gegossen werden in ihre
jeweiligeTextviewWidgets (R.id.titleundR.id.value).

Beachten Sie jedoch,dass, wenn Sie Adapter Cursor oder ihrer Unterklassen werden (wie SimpleCursorAdapter) zu verwenden, Ihre Ergebnismenge der Abfrage muss eine Integer-Spalte enthält den Namen _id dass einzigartig für die Ergebnismenge ist. Dieses "id" Wert wird dann auf Methoden wie onListItemClick () geliefert wird, zu ermitteln, welche Artikel der Benutzer auf der AdapterView geklickt. Beachten Sie, dass diese Forderung auf das Ergebnis ist in der Cursor gesetzt, so dass, wenn Sie eine passende Spalte in einer Tabelle, die nicht genannt _id ist, können Sie es in Ihrer Abfrage umbenennen (zB SELECT-Taste AS _id, ...).

Allerdings, wenn Sie möchten, können Sie verwendendie eingebaute in ROWID

Zitiertdie SQLite-Dokumentation:

In SQLite, jeder jede Zeile vonTabelle hat eine 64-Bit-Ganzzahl mit Vorzeichen ROWID.

Die ROWID für jede Zeile ist einzigartig unter allen Zeilen in der gleichen Tabelle. Sie können die ROWID einer SQLite-Tabelle zugreifen man die speziellen Spaltennamen mit ROWID, _ROWID_ oder OID ... Wenn eine Tabelle eine Spalte vom Typ INTEGER

Primärschlüssel enthält, dann wird diese Spalte wird ein Alias für die ROWID. Sie können dann auf den ROWID einer von vier verschiedenen Namen verwenden, die ursprünglichen drei Namen oben oder Namen in die INTEGER PRIMARY KEY-Spalte angegeben

beschrieben. Alle diese Namen sind Aliase für einander und arbeiten gleich gut in jedem Kontext.

Mitwenn man das im Auge, wollen SQLite abzufragen und die Ergebnisse in einer

GebrauchsCursor, Aber Sie haben keine eigeneINTEGER PRIMARYSCHLÜSSELSpalte, können Sie einfach schließenROWIDin deinemAbfrage, Umbenennung zu_Ich würdenach erfüllenCursor.

Aus diesem Grund haben wirdasROWID AS_Ich würdeimdasdoQuery ()Verfahren:erfüllen diese_Ich würde

Anforderung vonCursor.

beachten Sie auch,dass man nichtschließen()dasMauszeigerbenutzt voneinCursorbismüssen nicht mehr dieCursor. Deshalb haben wir das nicht schließenMauszeigerbisonDestroy ()vondas Fragment: (von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

Wir abrufendasMauszeigervondasCursor, Die erhalten wir durch den Aufruf
getListAdapter ()aufdas Fragment.

Data Out bekommen, Asynchron

Idealerweise werden Abfragen erfolgen aufein Hintergrund-Thread, da sie einige Zeit in Anspruch nehmen. Ein Ansatz für das zu tun ist, ein AsyncTask zu verwenden. In der Beispielanwendung, ConstantsFragmentanstoßeneinLoadCursorTaskimonViewCreated ()(oben
gezeigt).LoadCursorTaskerweitertdasBaseTaskKlasse zuvor erwähnt, wodasdoQuery ()Verfahren befindet.LoadCursorTaskist verantwortlich für das Tundie Abfrage (über diedoQuery ()Verfahren siehe oben) und setzenDie Ergebnisse in derListenansichtinnendas Fragment (mit
demSimpleCursorAdapteroben gezeigt):

(von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

Wir führendie eigentliche Abfrage in doInBackground () und rufen getCount () auf dem Cursor, um es zu zwingen, um die Abfrage tatsächlich auszuführen - Abfrage () gibt den Cursor, aber die Abfrage nicht tatsächlich ausgeführt, bis wir etwas tun, dass die Ergebnismenge benötigt. Dies gilt auch für rawQuery (), weshalb müssen wir "berühren", um den Cursor stellen Sie sicher, während wir auf dem Hintergrund-Thread sind.

OnPostExecute ()dann verwendetchangeCursor

()ersetzendasMauszeigerimdasSimpleCursorAdaptermitdie Ergebnisse. da
unsereSimpleCursorAdapterwurde erstellt miteinnull Cursor.changeCursor ()nur gleitet indas neueMauszeiger, Erzählt dieListenansichtdass die Daten geändert. Dies bewirkt, dass unsereListenansichtwerden aufgefüllt.

Diesen Weg,die Benutzeroberfläche wird nicht eingefroren werden, während die Abfrage ausgeführt wird, aber wir nur die Benutzeroberfläche aus dem Hauptanwendungsthread aktualisieren.

Hinweisdass die fi

Mal, wenn wir versuchen, die Verwendung vonSQLiteOpenHelperist
in unserem Hintergrund-Thread.SQLiteOpenHelperwerdennicht versuchen, unsere Datenbank (zB
für eine neue App installieren) zu schaffen, bis wir rufengetReadableDatabase

()odergetWritableDatabase (). Daher,onCreate ()(oder später,ONUPGRADE ())

unsererSQLiteOpenHelperWind-up wird dazu aufgerufen, aufals auch der Hintergrund-Thread, was bedeutet, dass die Zeit der Erstellung ausgegeben (oder ein Upgrade) die Datenbank auch nicht die Benutzeroberfläche nicht einfrieren.

beachten Sie auch,dass inonDestroy ()wie zuvor gezeigt, nennen
wirstornieren()aufdasAsyncTaskwenn es sich umnichtNull. Wenn die Task noch läuft, ruftstornieren()wird verhindert,OnPostExecute ()aus wird aufgerufen, und wir werdennicht um die Aktualisierung unserer UI Sorgen machen müssen, nachdem das Fragment zerstört wurde.

Der Rest vondie CRUD

Um Daten auseine Datenbank, ist es in der Regel nützliche Daten in sie in der fi Stelle zu setzen.

Die Beispielanwendung startet durch das Laden von Daten, wenn die Datenbank erstellt wird (in onCreate ()vonDatabaseHelper), Plus hat eine Aktionsleiste Element zu ermöglichen,der Benutzer andere Konstanten nach Bedarf hinzufügen.

ImIn diesem Abschnitt werden wir weiter im Detail zu prüfen, wie wir die Datenbank, sowohl für die Schreib Aspekte der CRUD (Create-Lese-update-delete) und für die Datendefinitionssprache (DDL) Operationen (Erstellen von Tabellen, Erstellen von Indizes, etc.) zu manipulieren .

Die primäre Option: ExecSQL ()

Für die Erstellung IhrerTabellen und Indizes, müssen Sie ExecSQL () auf Ihrem

SQLiteDatabase, die Bereitstellung der DDL-Anweisung Sie gegen die Datenbank zu
übernehmen anrufen möchten. Außer im Falle der Datenbankfehler, gibt diese Methode nichts.

So zum Beispiel, können Sie anrufenExecSQL ()erschaffendasKonstantenTisch, wie in der gezeigtenDatabaseHelper onCreate ()Methode:

(von

Datenbank / ConstantsROWID / src / com / commonsware /
android / Konstanten / DatabaseHelper.java)

Dies erzeugteine Tabelle, benannte Konstanten, mit zwei Datenspalten: Titel (Text) und Wert (a fl
oder "Real" in SQLite Begriffe).

Höchstwahrscheinlich werden Sie erstellenTabellen und Indizes, wenn Sie fi
erstellen die

Datenbank, oder möglicherweise, wenn die Datenbank muss aktualisiert werden eine neue Version der Anwendung gerecht zu werden. Wenn Sie nicht Ihre Tabellenschemata ändern, könnten Sie nie Ihre Tabellen oder Indizes fallen, aber wenn Sie das tun, nur ExecSQL () verwenden, um DROP

INDEX aufrufen und TABLE-Anweisungen DROP nach Bedarf.

Alternative Optionen

Für Einfügungen, Aktualisierungen und Löschungen von Daten, haben Sie zwei Möglichkeiten. Sie können jederzeit verwendenExecSQL (), wie Sie es getan haben, die Tabellen für die Erstellung. Die ExecSQL () Methode funktioniert für jede SQL, dass die Ergebnisse nicht zurückgibt, kann also INSERT behandeln, UPDATE, DELETE usw. nur fi

Eine gute Alternative ist die Verwendungdaseinfügen().aktualisieren(), undlöschen()Methoden aufdasSQLiteDatabaseObjekt, das viel eliminierendie SQL-Syntax erforderlich grundlegenden Operationen zu tun.

Zum Beispiel, hier sind wireinfügen()eine neue Zeile in unsereKonstantenTisch, wieder aus onCreate ()vonDatabaseHelper:

(von

Datenbank / ConstantsROWID / src / com / commonsware /
android / Konstanten / DatabaseHelper.java)

Diese Methoden nutzenContent Objekte, die eine Map-artige Schnittstelle implementieren, wenn auch eine, die für die Arbeit mit SQLite-Typen zusätzliche Methoden hat. Beispielsweise, zusätzlich zu get () einen Wert, der durch seinen Schlüssel abzurufen, haben Sie GetAsInteger (), getAsString (), und so weiter.

Das() Einfügen Methode nimmt den Namen der Tabelle, der Name einer Spalte als "Null-Spalte Hack", und ein content mit den Anfangswerten möchten, dass Sie in dieser Zeile setzen. Die "Null-Spalten Hack" ist für den Fall, dass die content Instanz leer ist - die Spalte als Namen "Null-Spalte Hack" wird den Wert NULL explizit in der SQL-Anweisung INSERT durch Insert () erzeugt zugeordnet werden. Dies ist erforderlich, an Merkwürdigkeiten in SQLite Unterstützung für die SQL-Anweisung INSERT.

Dasupdate () -Methode nimmt den Namen der Tabelle, ein content die Spalten und Ersatzwerte darstellen zu verwenden, eine optionale WHERE-Klausel und eine optionale Liste von Parametern in der WHERE-Klausel zu fi nden, eingebettete Fragezeichen zu ersetzen (?). Da nur Spalten ersetzt mit fi zierten Werte update (), im Vergleich zu berechneten diejenigen, basierend auf anderen Informationen, müssen Sie ExecSQL () zu verwenden, um einige Enden erreichen. Die WHERE-Klausel und die Parameterliste arbeitet mit den Positions SQL-Parameter verwandt Sie von anderen SQL-APIs verwendet werden.

Das() Löschen Methode funktioniertähnlich zu aktualisieren (), den Namen der Tabelle nehmen, die optionale WHERE-Klausel und die entsprechenden Parameter zu fi nden in der WHERE-Klausel.

Asynchrone CRUD und UI-Updates

So wie die Abfrageeine Datenbank sollte auf einem Hintergrund-Thread ausgeführt werden, so sollte eine Datenbank zu modifizieren. Aus diesem Grund ist es wichtig, die fi machen

Zeit, die

Sie fordern einSQLiteDatabasevon einSQLiteOpenHelpersein aufein Hintergrund-Thread, fallsonCreate ()oderONUPGRADE ()sind erforderlich.

Das Gleichewas gilt, wenn Sie die Datenbank während des normalen Betriebs der App aktualisieren müssen. Zum Beispiel hat die Beispielanwendung eine Aktionsleiste Element in der rechten oberen Ecke des Bildschirms "add":

Durch Klicken aufdas bringt einen Dialog - eine Technik, die wir später in diesem Buch besprechen werden:

Obder Benutzer fi
im eine Konstante und klickt auf die Schaltfläche "OK", brauchen wir
einen neuen Datensatz in der Datenbank einzufügen. Dies wird über eine InsertTask behandelt: (von

Datenbank / ConstantsROWID / src / com / commonsware / android /

Konstanten / ConstantsFragment.java)

DasInsertTaskist versorgteincontentObjekt mit unserenTitelundWert, So wie wir früher inonCreate ()vonDatabaseHelper. ImdoInBackground (), Erhalten wir eine beschreibbare Datenbank ausDatabaseHelperund ausführendaseinfügen()rufen, sodie Datenbank I / O binden nicht die Hauptanwendungsthread.

Jedoch indoInBackground (), Rufen wir auchdoQuery ()aufs Neue. Dies ruftein
frischesMauszeigermitdie neue Liste von Konstanten ... einschließlich der, die wir gerade eingefügt.

Wie beiLoadCursorTaskWir ausführendoQuery ()imdoInBackground ()behalten die Datenbank I / O
an der Hauptanwendungsthread. Dies löst die gleicheOnPostExecute ()wie
vor, geerbt vonBaseTask, Die verwendetchangeCursor ()zu ersetzen jedevorhandenen Ergebnisse mit den neuen Ergebnissen.

Einstellen Transaktion Bounds

In der Standardeinstellungjede SQL-Anweisung ausführt, in einer eigenen Transaktion - das recht typisches Verhalten für eine SQL-Datenbank ist, und SQLite ist keine Ausnahme.

Es gibt zwei Gründe, warum Sie möchten Ihre eigene Transaktions Grenzen zu haben, größerals eine einzige Erklärung:

1. Die klassische "wir habeneine Reihe von Operationen, die als Ganzes "Rationale erfolgreich sein oder fehlschlagen müssen, um die Datenintegrität beibehalten

2. Performance, wiejede Datenbank-Transaktion umfasst Disk-I / O und eine große

Transaktion wird viel schneller als viele kleine Transaktionen sein

Das Grundrezept für Ihre eigenen Transaktionen ist:

begintransaction ()Markierungendie Tatsache, dass Sie eine Transaktion
wollen.setTransactionSuccessful ()zeigt andass Sie wollen, dass die Transaktion zu begehen.

Allerdings ist die tatsächlicheVERPFLICHTENoderROLLBACKtuttreten nicht auf,
bisendTransaction (). Im Normalfall,setTransactionSuccessful ()genannt bekommt,
undendTransaction ()führteinVERPFLICHTEN. Wenn jedoch fehlschlägt eine Ihrer SQL-Anweisungen (zum Beispiel gegen eine Fremdschlüssel), diesetTransactionSuccessful ()rufen Sieübersprungen wird, soendTransaction ()Wird besorgteinROLLBACK.

Sie fragen sich vielleicht, warum wir das gemacht habennicht mit einer Transaktion Mühe inonCreate ()Methode vonDatabaseHelper, Letztere Grund gegeben. Das ist, weilonCreate ()heißt innerhalbeine Transaktion einrichten, indem SieSQLiteOpenHelperselbst, so tun Sienicht selbst benötigen.

Hey, was Hibernate?

Diejenigen von euch, mit signifi

Java Hintergründe außerhalb von Android sind vermutlich
mit dem Kopf gegen den Schreibtisch Stampfen jetzt recht. Außerhalbein paar Annehmlichkeiten wie SQLiteOpenHelper und Cursor, Android Ansatz zur Datenbank I / O fühlt sich ein bisschen wie klassische JDBC. Java-Entwickler, haben die Schmerzen von rohen JDBC erfahren, erstellt verschiedene Wrapper um ihn herum, der prominenteste davon ist ein ORM (Object-Relational-Mapper) genannt Hibernate.

Ach, ist Hibernate für Server entwickelt,nicht mobile Geräte. Es ist ein bisschen Schwergewicht, und es ist für den Einsatz mit JDBC, nicht Androids SQLite-Klassen.

Android tat enthalten keine Art von ORM am Anfang aus zwei Gründen:

1. Behaltendie fi
ware Größe so klein wie möglich, da kleinere fi

Ware kann
zu weniger teure Geräte führen

2. Eliminierendie ORM-Overhead (zB Reflexion), die für die frühe Android-Versionen auf frühen Android-Geräte zu viel gewesen wäre

Das Android-Ökosystem hat sich mit Alternativen kommen, wie zum BeispielORMLiteund greenDAO. Also, wenn Sie mit Hilfe eines ORM verwendet werden, möchten Sie vielleicht zu untersuchendiese Art von Lösungen - sie sind einfach nicht in Android selbst gebaut.

Besuchdie Spuren!

Wenn Sie in die Offenlegung Ihrer Datenbankinhalte sind daran interessiert,eine Drittanbieter-Anwendung, können Sie möchten auf zu lesen,Inhalt Anbieter.

Die Wege haben auch Kapitel überverschlüsselte Datenbanken mit SQLCipherundVersand abgepackte Datenbanken mit Ihrer App.

Tutorial # 14- Speichern Hinweise

Es wäre schön, wennkönnte der Benutzer einige persönliche Anmerkungen zu dem Kapitel hinzufügen, die sie liest, sei es als Kommentar dient, erforscht werden Punkte, Beschwerden über den Autor Haar (oder deren Fehlen), oder was auch immer.

Also, inIn diesem Kapitel werden wir die Benutzer zu erlauben, Notizen hinzufügen pro Kapitel, über ein großes EditText Widget ein neues Fragment und neue Aktivität hinzuzufügen. Diese Noten werden in einer SQLite-Datenbank gespeichert werden.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Hinzufügenein DatabaseHelper

Der fi

Schritt für mit SQLite arbeiten, ist eine Implementierung hinzufügen

SQLiteOpenHelper, Was wir hier tun werden, mit dem NamenDatabaseHelper.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeDatabaseHelperwieden Namen und dieandroid.database.sqlite.SQLiteOpenHelperwiedieübergeordnete Klasse. Klicken Sie dann auf OK, um die leere Klasse zu erstellen.

Dann ersetzender Inhalt dieser Klasse mit den folgenden:

Schritt 2: Untersuchen DatabaseHelper

Unsere erste VersionDatabaseHelperhatein paar Dinge:

• Es hatder Konstruktor, den Namen der Datenbank fi auf die übergeordnete

Versorgung

(DATABASE_NAME) und die Revisionsnummer unseres Schemas

(SCHEMA_VERSION). Beachten Sie, dass der Konstruktor privat ist, wie wir die

Singletonmuster verwenden, so dass nur DatabaseHelper sollten DatabaseHelper

Instanzen erstellen können.

• Es hatdie onCreate () -Methode aufgerufen, um die fi

Zeit, dass wir die App auf
einem Gerät oder Emulator laufen, um uns auf die Datenbank zu füllen. Hier verwenden wir ExecSQL () einen Anmerkungen Tabelle mit einer Positionsspalte (unter Angabe unserer Kapitel) und eine Prosa-Säule (was der Benutzer sich als Anmerkung) zu
definieren.

• Es hatdie ONUPGRADE () -Methode, benötigt, da SQLiteOpenHelper ist abstrakt, so dass unsere App ohne eine Implementierung nicht kompiliert werden. Bis wir unsere Schema revidieren, allerdings sollte diese Methode nie aufgerufen werden, so heben wir eine Runtime in den unwahrscheinlichen Fall, dass es unerwartet aufgerufen wird.

• Es hat eine statischeDatabaseHelperSingleton-Instanz undeingetInstance ()

Verfahren zu faul initialisieren es.

Wie bereits indas Kapitel über Datenbanken, es ist darauf zu achtendass alle Threads die gleiche SQLiteDatabase Objekt, für Thread-Sicherheit zugreifen. Das in der Regel bedeutet, dass Sie auf ein einzelnes Objekt SQLiteOpenHelper halten. Und in unserem Fall könnten wir aus mehr als eine Tätigkeit in dieser Datenbank erhalten möchten. Daher gehen wir mit dem Singleton-Ansatz, so dass jeder mit dem gleichen DatabaseHelper Instanz funktioniert.

Schritt 3: Erstellenein NoteFragment

Nachdemeine Datenbank ist schön und alle, aber wir müssen auf der Benutzeroberfläche arbeiten Benutzer zur Eingabe von Noten zu ermöglichen. Um das zu tun, werden wir mit einem NoteFragment starten.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeNoteFragmentwieden Namen und dieandroid.app.Fragmentwiedieübergeordnete Klasse. Klicken Sie dann auf OK, um die leere Klasse zu erstellen.

Als nächstes ersetzender Inhalt dieser Klasse mit den folgenden:

Hinweisdaß dieses Fragment verwendet dasres / Layout / editor.xmlRessourcedass wir geschaffen zurück inLernprogramm# 5.

Schritt # 4: Untersuchung NoteFragment

UnserNoteFragment ist recht einfach und erinnert an die

SimpleContentFragmentwir erstellt inTutorial # 11.

NoteFragmenthateinnewInstance ()statische Factory-Methode. Diese Methode erstellt eine InstanzNoteFragment, Nimmt einübergebenes inint(Identifizierungdas Kapitel, für die wir eine Notiz) erstellen, legt es in einBündelnerkannt alsKEY_POSITION, Hände, welche
dieBündelnnachdas Fragment als Argumente und gibt die neu erstellteNoteFragment.

ImonCreateView ()Wir aufblasen dieR.layout.editorRessourcedass wir definiert und unsere Hände auf unsere erhaltenText bearbeitenWidget für die spätere Verwendung.

Schritt # 5: Erstellendie NoteActivity

Nachdemein Fragment, ohne es anzuzeigen ist ziemlich sinnlos, also müssen wir etwas ein zu ladenNoteFragment. Insbesondere für Telefone, ist die einfachste Antwort ein zu
schaffenNoteActivityfürdass parallel zu der Beziehung
zwischenSimpleContentFragmentundSimpleContentActivity.

Rechtsklicken Sie aufdie com.commonsware.empublite Paket in Ihrem java / und Neu> Aktivität> Leere Aktivität aus dem Kontextmenü wählen. Füllen Sie NoteActivity wie der Name, deaktivieren Sie alle Kontrollkästchen, und klicken Sie auf OK, um die leere Klasse zu erstellen.

Imdie NoteActivity Klasse, die erstellt wird, ersetzen Sie die aktuelle Implementierung mit den folgenden:

Schritt # 6: Untersuchen NoteActivity

Wie du siehst,Dies ist eine ziemlich trivial Aktivität. ImonCreate ()Wenn wir neu geschaffen werden, führen wir einFragmentTransactionhinzufügen einNoteFragmentzu unsererAktivität, es in den Vollbild-Gießen (android.R.id.content). Hier,android.R.id.contentidentifiziertder Behälter in die die Ergebnisse dersetContentView ()würde gehen - Es ist ein Behälter, der durch Aktivität selbst gelieferten und dient als obersten Container für unsere Inhalte.

Aber wir erwartendass wirübergeben werden einAbsichtExtra mitdie Position

(EXTRA_POSITION), Die wir entlang zu passierendasNoteFragmentFactory-Methode.

Schritt 7: Notizen hinzufügenauf der Aktionsleiste

Na sicher,nichts davon ist nützlich, wenn wir auf die NoteActivity bekommen den Anwender nicht einen Weg geben. Insbesondere können wir einen Notizen Eintritt in unsere res / Menü / options.xml Ressource hinzufügen, wird eine neue Schaltfläche in der Symbolleiste auf unsere Haupttätigkeit der Aktionsleiste erscheinen zu lassen.

Rechtsklicken Sie aufdie res / Verzeichnis und wählen Sie Neu> Vector Inventar aus dem Kontextmenü. Klicken Sie auf die Schaltfläche Symbol und wählen Sie die "Create" Symbol:

Klicken Sie auf OK, um zu schließendas Symbol Picker. Dann klicken Sie auf Weiter und Fertig stellen diese drawable Ressource zu speichern.

Unglücklicherweise,Dieses Symbol wird in schwarz machen, wenn wir sie brauchen in Weiß gegeben unser Thema zu machen. Rechtsklick aufres / ziehbar /
ic_create_black_24dp.xmlwählen, Umgestalten> aus dem Kontextmenü auf Umbenennen, undändern Sie den Namen zuic_create_white_24dp.xml. Dannöffnenres / ziehbar /
ic_create_white_24dp.xmlund Veränderungdasandroid: fillColorimdas<Pfad>Element zu sein#FFFFFFFFAnstatt von # FF000000:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main /
res / ziehbar / ic_create_white_24dp.xml)

Als Nächstes fügeneine neue String-Ressource namens Notizen, mit einem Wert wie Noten.

Dann,ändernres / menu / options.xmlaussehen:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app /
src / main / res / menu / options.xml)

Schließlich inEmPubLiteActivityFügen Sie den folgendenFallnachdasSchalterAussage in onOptionsItemSelected ():

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Hier erhalten wirdie aktuell betrachtete Position vom ViewPager und passieren, dass als die EXTRA_POSITIONextraNoteActivity.

Schritt 8: Definierenein NoteLoadedEvent

Wir wollen Notizen zu laden vondie Datenbank auf einem Hintergrund-Thread. Daher können wir die gleichen grundlegenden Ansatz anwenden, wie wir mit ModelFragment verwendet wird, ein Ereignis veröffentlichen
aufdie greenrobot EventBus, wenn die Last abgeschlossen ist, die Ergebnisse der zu liefern NoteFragment. Dieser Schritt wird erstellenNoteLoadedEventzu handhabendieser Fall.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeNoteLoadedEventwieden Namen und klicken Sie auf OK die leere Klasse zu erstellen.

Dann ersetzender Inhalt dieser Klasse mit den folgenden:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteLoadedEvent.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt # 9: Ladenein Hinweis aus der Datenbank

Nächsten wirmüssen Code irgendwo hinzufügen, die tatsächlich die Datenbank (auf einem Hintergrund-Thread) abgefragt wird die Note für eine gegebene ViewPager Position zu laden. Ein übliches Muster ist diese Art von Datenbank-Zugriffslogik auf Ihrer SQLiteOpenHelper Unterklasse zu setzen, so dass alle Ihre Datenbank-spezifischen Code befindet sich an einem Ort. Das ist der Ansatz, den wir hier zu nehmen, eine loadNote () -Methode hinzufügen, die einen Thread gabelt, die Datenbank abfragen und Posten NoteLoadedEvent als Ergebnis.

bearbeiten Sie IhreDatabaseHelperhinzuzufügen, seine eigeneLoadThreadinnere Klasse, erinnert anderjenige vonModelFragment:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / DatabaseHelper.java)

Hier verwenden wirrawQuery () die Notiz auf einer mitgelieferten Position basierend abzurufen.

Wenn es keinen solchen Hinweis ist, wird unser Cursor keine Zeilen haben, und wir sind fertig.

Wenn jedoch haben wir die Ergebnisse wieder auf die Abfrage erhalten, geben wir dann eine NoteLoadedEvent mit der Position und der Prosa (der Text aus der Datenbank).

Du wirstbenötigen einen Import manuell hinzuzufügenandroid.os.ProcessZu können, die zu lösenSetThreadPriority ()Methode und deren Parameter.

Fügen Sie außerdemeinloadNote ()MethodeDatabaseHelperdass Gabeln dieseLoadThread: (von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / DatabaseHelper.java)

Schritt # 10: Ladender Hinweis in den Splitter

Jetzt dass wir eine Notiz, die Datenbank und zurück (falls vorhanden) abfragen können, können wir das in der KrawatteNoteFragmentLadendie Note für das Fragment desPositionwanndas Fragment wird geöffnet. Wir werden nicht nur anrufen müssenloadNote ()aufdasDatabaseHelper, Sondern können auch auf die antwortenNoteLoadedEventwenn es ankommt.

HinzufügenfolgendeonStart ()MethodeNoteFragment:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Hier registrieren wir fürdie EventBus. Wenn wir dann Widget keinen Text in der EditText haben, rufen wir loadNote () auf unsere Singleton-Instanz der DatabaseHelper, in der Position vorbei, die unser Fragment verwalten ist. Der Grund für die Überprüfung, ob die EditText leer ist Konfigurationsänderungen zu handhaben. Dieses Fragment ist nicht beibehalten Fragment, und so wird es zerstört und neu erstellt werden. Der Standard onSaveInstanceState () Logik der EditText wird unsere Kenntnis behalten, obwohl, so dass wir nicht wollen, sie aus der Datenbank neu zu laden. Dieser Ansatz ist nicht optimal, dass wir loadNote () in den Fällen Aufruf eingereicht werden, wo wir wissen konnte, dass es keinen Hinweis ist.

Diese Optimierung ist komplex genug, ummachen es für eine Reihe von Buch-Tutorials nicht lohnt, auch wenn es etwas, das Sie sich wünschen kann in einem handelsüblichen Anwendung zu erkunden.

Als Nächstes fügendie entsprechendeOnStop ()nachNoteFragment, Um von der deregistrieren EventBus:

Schließlich fügen ein onNoteLoaded (NoteLoadedEvent)MethodeNoteFragment, So erhalten wir dieNoteLoadedEventaufHauptanwendungsthread:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Hier stellen wir Konfi
dass das Ereignis unserer Fragment Position ist für, wie es denkbar
ist, dass diese Veranstaltung für eine andere Note, obwohl das eher unwahrscheinlich gegeben ist,

wie der Benutzer Notizen anzeigen würde. Davon abgesehen, wenn die Note für unsere Position ist, dass wir die EditText mit dem Hinweis Prosa füllen.

Schritt # 11: Aktualisierungdie Datenbank

Natürlich Laden Notizen auseine Datenbank alle fi
und gut ... außer dass wir keine Hinweise
in der Datenbank nicht. Wir sollten wirklich, dass fi.

Fügen Sie einUpdateThreadInnenklasseDatabaseHelper:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / DatabaseHelper.java)

Hier verwenden wirExecSQL () eine INSERT auszuführen oder SQL-Anweisung ERSETZEN.

Wie der Name schon sagt, wird dies eine neue Zeile einzufügen, wenn es keineÜbereinstimmung auf unserer Primärschlüssel (Position) ist. Andernfalls wird er die anderen Spalten zu aktualisieren, wenn es eineÜbereinstimmung gibt.

Hinweisdass wir eine Veranstaltung nicht hier posten. Wir könnten, wenn es etwas in der App war, die wissen musste, wenn eine Note aktualisiert wurde.

Fügen Sie außerdem einupdateNote ()MethodeDatabaseHelperdass Gabeln dieseUpdateThread: (von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / DatabaseHelper.java)

Schritt # 12: Speicherndie Notiz

Irgendwo, wiranrufen müssen updateNote (). Ein klassisches "Desktop" Ansatz wäre, einen "save"

Artikel Aktionsleiste zu haben, in der NoteFragment, die der Benutzer benötigen würde die Notiz klicken auf zu speichern. Allerdings befasst sich nicht mit dem Interrupt-gesteuerte Art von Telefonen alles gut. Zum Beispiel könnte der Benutzer starten in einer Notiz eingeben, dann eingereicht einen Anruf nehmen. Wenn unser Prozess beendet wird, je nachdem, wie der Benutzer versucht, zurück in unsere App bekommen, könnten wir die Notiz von unserem gespeicherten Instanz Zustand nicht haben.

Ein besserer Ansatz, in vielen Fällen ist, Daten in OnStop () zu speichern, wenn die Aktivität in den Hintergrund bewegt. Wenn es eine Chance ist, dass der Benutzer die teilweise eingegebener Informationen wünschen könnte, könnten Sie es in einer "Seite" Bereich, wie zum Beispiel eine temporäre fi speichern
und mit ihr umgehen, wennder Benutzer wieder in Ihre Anwendung.

Oder könnten Sie aktualisieren nur die reale Datenspeicher ... das ist, was wir hier tun.

BearbeitendasOnStop ()Verfahren inNoteFragmentaussehenfolgende:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Hier aktualisieren wirdie Notiz. Das ist ein bisschen ineffizient, da wir die Datenbank selbst zu aktualisieren, wenn der Benutzer, nicht den Text der Notiz ändern oder auch wenn der Ton ist leer.

Das ist eine weitere Optimierung, die eine Produktionsqualität App zu verfolgen könnte, wollen aber übersprungen hier im Interesse der Einfachheit.

Wenn Sie erstellen und ausführendie App auf einem Gerät oder Emulator, werden Sie die neue

"Notizen" Symbolleiste auf die Schaltfläche in der Aktionsleiste sehen:

Tappingdas wird die Noten für was auch immer ViewPager Position bringen, die Sie auf sind. Die Eingabe in einigen Notizen und drücken BACK, um die Aktivität zu beenden werden diese Notizen speichern, die Sie wieder zu sehen, wenn Sie die Aktionsleiste Symbolleiste auf die Schaltfläche wieder tippen. Wenn Sie die Hinweise zu ändern, BACK drücken, werden die geänderten Noten in der Datenbank zu speichern, zu einem späteren Zeitpunkt erneut angezeigt, wenn Sie wieder in die Noten für die ViewPager Position gehen.

Schritt # 13: Hinzufügeneine Aktion löschen Leiste Element

Das einzige Problem mitDiese Lösung ist, dass die Noten nie verlassen. Während der Benutzer manuell alles im EditText löschen könnte, wäre es schön, dass vielleicht ein bisschen einfacher zu machen. In diesem Schritt werden wir eine Aktionsleiste Element hinzufügen, die die EditText für den Benutzer klar wird.

Rechtsklicken Sie aufdie res / Verzeichnis und wählen Sie Neu> Vector Inventar aus dem Kontextmenü. Klicken Sie auf die Schaltfläche Symbol und wählen Sie das Symbol "Löschen":

Klicken Sie auf OK, um zu schließendas Symbol Picker.Ändern Sie den Namen der

Ressourceic_delete_white_24dp. Dann klicken Sie auf Weiter und Fertig stellen diese drawable Ressource zu speichern. Dannöffnenres / ziehbar / ic_delete_white_24dp.xmlund

Veränderungdasandroid: fillColorimdas<Pfad>Element zu sein#FFFFFFFFAnstatt von# FF000000: (von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main /
res / ziehbar / ic_delete_white_24dp.xml)

Als Nächstes fügeneine neue String-Ressource, mit dem Namen löschen, mit einem Wert wie Löschen.

Dann erstelleneine neue Ressource,res / menu / notes.xmlZu konfigurieren, unsere die Aktionsleiste für die Aktivität HostingNoteFragment:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app

/ src / main / res / menu / notes.xml)

Dieses einfach definierteine Aktionsleiste Element, mit der ID löschen.

Um dies zu tun, können Android Studio Benutzer der rechten Maustaste aufdie res / Menü / Verzeichnis und Neu> "Menü Ressource fi" aus dem Kontextmenü wählen. Füllen Sie notes.xml im "New Menu Resource File" Dialog und klicken Sie auf OK. Fügen Sie in der XML-oben in das fi gezeigt Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Um lassen Android kennendass unsereNoteFragmentWünsche für die Teilnahme an die Aktionsleiste, müssen wir nennensetHasOptionsMenu (true)an einem gewissen Punkt. Fügen Sie einonCreate ()MethodeNoteFragmentzu handhabendies, wenn das Fragment erstellt:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Das wird auslösenein AufrufonCreateOptionsMenu (), Die wir hinzufügen müssen, wird NoteFragment:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Dies bläht nur unsereneue Ressource für die Verwendung in dem Optionsmenü.

Obder Benutzer tippt auf dieser Symbolleiste auf die Schaltfläche,onOptionsItemSelected ()aufgerufen wird, so werden wirhinzufügen müssen, dass auch zuNoteFragment:

Hier wird, wennder Benutzer auf unserer Löschaktion bar Element angezapft, deaktivieren wir die EditText

Widget.

Schritt # 14: Schließendie NoteFragment Wenn Gelöschte

Aber,an diesem Aktionsleiste Artikel Klopfen hält den NoteFragment auf dem Bildschirm. Es wäre schön, sondern automatisch auf das Buch zurück. Doch die NoteFragment selbst nicht weiß, wie das zu tun, als etwas anderes (in diesem Fall NoteActivity) die NoteFragment auf dem Bildschirm platzieren. Daher müssen wir die Anforderung übergeben Sie die NoteFragment entlang auf die richtige Partei zu schließen.

Wir könnten eine andere verwendenEvent-Objekt und unsere EventBus. In diesem Fall werden wir einen anderen Ansatz demonstrieren: Mit dem Vertragsmuster das Hosting-Aktivität zu warnen, dass die Noten geschlossen werden sollte.

Defi
eine innere Schnittstelle imdasNoteFragment, genanntVertrag, wie folgt:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Sie könnten setzendie Zeilen unmittelbar nach dempublic classNoteFragment ...

Linie vordie Erklärung von einem der Datenelemente oder Methoden, zum Beispiel.

Dann füge hinzueine privategetContract ()Methode,dass wirft das HostingAktivitätnachdas VertragSchnittstelle:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Was wir hier tun, ist die Durchsetzungdass die Aktivität, die unsere NoteFragment Gastgeber muss implementierendasNoteFragment.ContractSchnittstelle.

Dann füge hinzuein AufrufcloseNotes ()aufdasVertragzu unserer Logik in
onOptionsItemSelected ():

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Nun, wennder Benutzer klickt auf die Löschaktion bar Artikel, löschen wir die EditText und das Hosting Aktivität fragen loswerden von uns zu bekommen. Auf dem Weg, unsere onPause () aufgerufen werden, was uns den Inhalt der Prosa Spalte in unserer Datenbank Zeile als auch zu löschen.

Beimdieser Punkt,NoteFragmentsollte folgendermaßen aussehen:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

NoteActivityJetzt muss implementierenNoteFragment.Contractund implementieren
closeNotes ().ÄndernNoteActivityaussehen:

(von

EmPubLite-Android Studio / T14-Datenbank / EmPubLite / app / src / main / java / com

/ commonsware / empublite / NoteActivity.java)

Dies fügtdasArbeitsgeräteStichwort unddascloseNotes ()Implementierung, die nur fi dasNoteActivity, Kontrolle der RückkehrEmPubLiteActivity.

Wenn Sie laufendies in einem Gerät oder Emulator, und Sie gehen in die Noten, werden Sie unsere löschen Symbolleiste auf die Schaltfläche sehen:

Tappingdass Symbolleiste auf die Schaltfläche wird die Notiz löschen und die Aktivität schließen, Sie auf das Buch zurück.

In unserer nächsten Folge ...

... Wir werden dem Benutzer erlauben,Aktienotes des Kapitelsmit jemandemsonst.

Internet Zugang

Die Erwartung ist,dass die meisten, wenn nicht alle, werden Android-Geräte verfügen über eine integrierte in Internetzugang. Das könnte WiFi, mobile Datendienste sein (EDGE, 3G, etc.), oder vielleicht etwas ganz anderes. Egal, die meisten Menschen - oder zumindest die mit einem Datentarif oder WiFi-Zugang - wird das Internet von ihrem Android-Telefon zu bekommen können.

Nicht überraschend,die Android-Plattform bietet eine breite Palette von Möglichkeiten, Entwickler Nutzung dieses Internetzugang zu machen. Einige bieten High-Level-Zugriff, wie zB die integrierte

WebKit-Browser-Komponente (WebView) wir in eine Sägefrüheren Kapitel. Wenn Sie möchten, können Sie alle fallenWeg hinunter Raw Sockets zu verwenden. Oder zwischendurch, können Sie APIs nutzen - sowohl auf dem Gerät und von 3rd-Party-JAR-Dateien - das geben Ihnen Zugriff auf bestimmte Protokolle: HTTP, XMPP, SMTP, und so weiter.

DasSchwerpunkt dieses Buches auf den höheren Ebenen Zugangsformen: dieWebKit

Komponente und Internet-Zugang APIs, so beschäftigt Programmierer solltenRoll die eigene on-the-Wire-Protokoll, wo immer möglich, versuchen, im Vergleich zu bestehenden Komponenten wieder zu verwenden.

DIY HTTP

In vielen Fällen ist die einzige praktikable Option einige Web-Service oder einem anderen HTTP-basierten Ressource für den Zugriff zu tunDer Antrag selbst. Die Google-endorsed API für Android in dieser heute tun, ist die klassische java.net-Klassen für HTTP-Operation zu verwenden, zentriert um HttpURLConnection. Es ist ziemlich viel Material auf diese bereits veröffentlicht, da diese Klassen für eine lange Zeit in Java gewesen sein. Der Fokus liegt dabei in die zeigen, wie diese in einem Android-Kontext funktioniert.

Beachten Sie jedoch,dass Sie kann es fi einfacher beschrieben werden, wie für Sie, einige HTTP-Client-Bibliotheken zu verwenden, die verschiedene Aspekte des Internetzugangs Griffspäter im dieses Kapitel.

Ein Verwendungsbeispiel von HttpURLConnection

In diesem Kapitel geht durch mehrere Implementierungen voneinen Stapelüberlauf-Client-Anwendung. Die App hat eine einzige Tätigkeit, mit einem einzigen ListFragment. Die App wird die neueste Block von Stack Overflow Fragen mit Android getaggt laden, die Stapel öffentliche Exchange-API. Diese Fragen werden in der Liste angezeigt werden, und auf eine Frage tippen wird die Webseite für diese Frage in der Benutzer-Standard-Web-Browser aufzurufen.

Alle Implementierungendie App den gleichen Kern UI-Logik. Was unterscheidet, ist, wie jeder behandelt den Internetzugang. In diesem Abschnitt werden wir einen Blick auf dieInternet/

SCHLEUDERNBeispielprojekt, das verwendetHttpURLConnection die Fragen aus dem Stapel Exchange Web-Service-API abgerufen werden.

Um Erlaubnis fragen

Um etwas mitdas Internet (oder ein lokales Netzwerk) aus Ihrer Anwendung, benötigen Sie die INTERNET Erlaubnis zu halten. Dazu gehören Fälle, in denen Sie Dinge wie WebView verwenden

— wenn Ihr Prozessbenötigt Netzwerkzugriff, müssen Sie dieINTERNETErlaubnis.

Daher,das Manifest für unser Beispielprojekt enthält die erforderliche

<Uses-permission>Erklärung:

Erstellen Sie Ihre DatenModell

Der Stapel Exchange Web Service API gibt JSON in Reaktion auf verschiedene Abfragen. Daher wirmüssen Java-Klassen erstellen, die die JSON-Struktur spiegeln. mit Googles Gson Insbesondere werden viele der Beispiele sein, um diese Datenmodelle automatisch auf der Grundlage seiner Analyse der JSON füllen, die wir aus dem Web-Service erhalten.

In unserem Fall werden wir verwendenein spezifi Endpunkt der Stapel Exchange-API, wie /

Fragen nach dem Scheidungs Teil des Weges bezeichnet. Die Dokumentation für diesen Endpunkt zu finden inder Stack Exchange-API Dokumentation.

Wir werden prüfen,die URL für den Endpunkt ein bisschen später in diesem Abschnitt.

Die Ergebnisse, die wir erhalten für die Ausstellungeine GET-Anforderung für die URL ist ein JSON-Struktur (hier nur eine einzige Frage zeigt, die Auflistung kurz zu halten): HINWEIS: Einigedie längeren URLs werden in dem Buch Wort wickeln, aber sie sind auf einer einzigen Zeile in der aktuellen JSON. Ehrlich.

Wir bekommen wiederein JSON-Objekt, in dem unsere Fragen werden unter dem Namen der gefundenen Artikel. Artikel ist ein JSON-Array von JSON Objekten, wobei jedes JSON-Objekt nur eine einzige Frage stellt, mit fi
mögenTitel und Link. Die Frage JSON-Objekt verfügtüber
einen integrierten Besitzer JSON-Objekt mit zusätzlichen Informationen.

Wir tunnicht unbedingt alle diese Informationen benötigen. In der Tat, für diese fi Version von
die Probe, alle sind wir den Titel und Link von jedem Eintrag im Element-Array wirklich brauchen.

Der Schlüssel ist,dass standardmäßig, müssen die Datenelemente in unseren Java-Datenmodell genau Spieldie JSON Schlüssel für die JSON-Objekte.

So haben wir einItem-Klasse, was die Informationen von einem einzelnen Eintrag im Element-Array: (von

Internet / Hurl / app / src / main / java / com /
commonsware / android / schleudern / Item.java)

Allerdings ist unser Web-Service tutnicht wieder direkt dem Array Items. Artikel ist der Schlüssel in einem JSON-Objekt, das die tatsächliche JSON durch Stapel von Exchange zurückgegeben wird.

Also brauchen wir eine andere Java-Klasse, die die Datenelemente enthält, stellen wir von diesem äußeren JSON-Objekt benötigen, hier genannt SOQuestions (mangels einer besseren Idee für einen Namen ...):

(von

Internet / Hurl / app / src / main / java / com / commonsware /
android / schleudern / SOQuestions.java)

Nachdem einArtikel Datenelement, das eine Liste der Artikel ist erzählt Gson, dass wir das JSON-Objekt erwarten für SOQuestions verwendet werden, um ein JSON-Array zu haben, benannte Elemente, wobei jedes Element in diesem Array sollte auf Item-Objekte abgebildet erhalten.

Ein Thema für das Laden

Wirmüssen die Netzwerk-I / O auf einem Hintergrund-Thread zu tun, so dass wir binden nicht den Hauptanwendungsthread. Zu diesem Zweck hat die Beispielanwendung eine LoadThread, die unsere Fragen lädt:

(von

Internet / Hurl / app / src / main / java / com / commonsware /
android / schleudern / LoadThread.java)

LoadThread:

• Erstellt einHttpURLConnectiondurch ErstelleneinURLfür unsere Stapel Exchange-

APIEndpunkt undÖffnen einer Verbindung

• erzeugteinBufferedReaderumwickeltdasEingabestromvondie HTTP-Verbindung

• Analysiertdie JSON wir zurück von dieser HTTP-Anforderung über eine Gson

Instanz, die Daten in eine Instanz unserer SOQuestions Laden

• SchließendasBufferedReader(unddasEingabestromdurch Erweiterung)

• PosteinQuestionsLoadedEventzu greenrobot desEventBus, Lassen jemand wissen,
dass unsere Fragen bestehen

• Log-Meldungen zu LogCat bei Fehlern

QuestionsLoadedEventistein einfacher Wrapper um einSOQuestionsSo dient als Event-Klasse für die Verwendung mitEventBus:

(von

Internet / Hurl / app / src / main / java / com / commonsware / android

/ schleudern / QuestionsLoadedEvent.java)

Ein Fragment für Fragen

Die Beispielanwendung hateinQuestionsFragmentdas sollte diese geladen Fragen an:

(von

Internet / Hurl / app / src / main / java / com / commonsware /
android / schleudern / QuestionsFragment.java)

ImonCreate (), markieren wir, dass dieses Fragment sollte beibehalten werden und die LoadThread Gabel. Daher, wenn wir unsere Fragen haben, unser beibehalten Fragment auf diesem Modelldaten für uns halten, und wir vermeiden Duplizieren der LoadThread wenn eine Konfigurationsänderung wurde irgendwann nach unserem Fragment erfolgt zunächst erstellt.

Imauf Wiederaufnahme()undonPause ()Wir registrieren und deregistrieren aus derEventBus.

UnseronEventMainThread ()Methode wird aufgerufen, wenndasQuestionsLoadedEventangehoben durchLoadThreadUnd dort halten wir auf die geladenen Fragen und füllen Sie dasListenansicht. Wir verwenden einItemsAdapter, Die weiß, wie man ein zu machenArtikelwieeine
einfacheListenansichtReihe zeigtdie Frage Titel. DasItemsAdapterAnwendungenHtml.fromHtml ()bevölkerndasListenansichtReihen,nicht weil Stack-Überlauf Hände zurück Titel mit HTML-Tags, sondern weil Stack-Überlauf Hände Titel mit HTML-Entity-Referenzen zurück, undHtml.fromHtml ()Griff sollte vielejene.

Und inonListItemClick ()Wir fi nden
dasArtikelverknüpft mitdie Zeile, die der Benutzer
geklickt auf, dann heben einQuestionClickedEventzu lassen jemanden kennendass der Benutzer auf dieser Zeile angeklickt. DasQuestionClickedEventKlasseein einfacher Wrapper um einArtikelals Event-Klasse für den Einsatz zu dienen mit EventBus:

(von

Internet / Hurl / app / src / main / java / com / commonsware / android

/ schleudern / QuestionClickedEvent.java)

Eine Aktivität für Orchestrierung

Hauptaktivitäteinrichtetdas Fragment inonCreate (), Register und hebt die Registrierung für die Veranstaltung Bus inauf Wiederaufnahme()undonPause ()Und behandelt die Click-Ereignisse inonEventMainThread ():

(von

Internet / Hurl / app / src / main / java / com / commonsware /
android / schleudern / MainActivity.java)

Daher,HauptaktivitätistServieren in einer Orchestrierung Rolle.QuestionsFragmentisteine lokale Steuerung, Handhabung direkt durch seine Widgets ausgelösten Ereignisse (aListenansicht).

MainActivity verantwortlich ist Ereignisse für den Umgang mit, die eine einzelne Fragment überschreiten - in diesem Fall beginnt sie einen Browser auf das geklickt-upon Frage anzuzeigen.

Das Ergebnis isteine einfache Listview-Fragen zeigt:

Was Android bringtan den Tisch

Google hat AugmentedHttpURLConnectionzu tun Entwickler mehr Sachen zu helfen. Vor allem:

• Es verwendet automatisch GZIP-Komprimierung auf Anfragen, das Hinzufügendie
entsprechenden HTTP-Header und automatisch alle komprimierten Antworten

(hinzugefügt in Android 2.3) Dekomprimieren

• Es benutztServer Name Indicationzu helfen, die Arbeit mit mehrerenHTTPS

Rechner eine IP-Adresse teilen

• API-Ebene 13 (Android 4.0) hinzugefügt einHttpResponseCacheImplementierung
vondasjava.net.ResponseCacheBasisklasse,das kann transparentes Caching Ihrer HTTP-Anforderungen zu bieten installiert werden.

Auch mit freundlicher Genehmigung von einigen Code von Drittanbietern (OkHttp)dass wir in Kürze besprechen werden, unterstützt HttpURLConnection auchdas SPDY-Protokollzur Beschleunigung der Web-Content-Verteilung über SSL ab Android 4.4.

Testen mit StrictMode

StrictMode, erwähnt indas Kapitel über die fi
zu melden, können auch Netzwerk-I / O auf
der Hauptanwendungsthread auf Ausführen. Noch wichtiger ist, auf Android 3.0 und höher, standardmäßig wird Android App mit einem NetworkOnMainThreadException abstürzen, wenn Sie versuchen, Netzwerk-I / O auf dem Hauptanwendungsthread auszuführen.

Daher ist es im Allgemeineneine gute Idee, Ihre Anwendung zu testen, entweder mit StrictMode selbst oder einen geeigneten Emulator verwenden, um sicherzustellen, dass Sie nicht Netzwerk ausführen E / A auf dem Hauptanwendungsthread.

Was über Httpclient?

Android enthält auch- Oder verwendet enthalten - die eine meist-vollständige Kopie der Version 4.0.2beta vonApache Httpclient-Bibliothek. Viele Entwickler verwenden diese, wiesie bevorzugen die reicheren API dieser Bibliothek über den etwas klobigen Ansatz von java.net verwendet angeboten. Und, ehrlich gesagt, war dies die stabilere Option vor Android 2.3.

Es gibtein paar Gründe, warum dies wird nicht mehr empfohlen, für Android 2.3 und darüber hinaus:

• Das Core-Android-Team ist besser in der Lage neue Funktionen hinzuzufügen, zudie java.net Implementierung, während die Abwärtskompatibilität beibehalten wird, weil seine API schmaler ist.

• Die Probleme, die zuvor auf Android erlebt mitdie java.net

Umsetzung weitgehend gewesen fied.

• Der Apache Httpclient-Projekt entwickelt kontinuierlich seine API. Das heisstdass Android wird weiterhin mehr und mehr hinter der neuesten und- größte von Apache zu fallen, wie Android können die am besten auf die Aufrechterhaltung möglich

Rückwärtskompatibilität und daher nicht nehmen auf neueren-but-verschiedene Httpclient-Versionen besteht.

• Google offiziell als veraltetdiese API in Android 5.1.

• Google offiziell entferntdiese API in Android 6.0.

Wenn Sie Legacy-Code habendass verwendet die Httpclient-API, beachten Sie bitte Apache eigenständige Version der VerwendungHttpclient für Android.

Und, können, wenn Sie nicht tun alledas, und Sie Gradle für Android verwenden für Ihre Builds (zB

Sie Android Studio Standardeinstellungen verwenden), können Sie useLibrary

'org.apache.http.legacy' auf den Android-Verschluss addieren Sie Android-Aktie zugreifen zu geben Httpclient-API :

Jedoch in der Regel unter Verwendung voneine eigenständige Version sollte vernünftigerweise praktikabel sein.

Beispielsweise,dasInternet / HttpclientBeispielprojektein Klon desHttpURLConnectionProbe von früher indieses Kapitelüberarbeitet Httpclient zu verwenden. Genauer gesagt, es verwendet dascz.msebera.androidVerpackung von Apache Httpclient für Android:

(von Internet / Httpclient / app / build.gradle)

Die Klassen sind alledie gleichen wie in dem Ersatzcode Apache Httpclient, mit der Ausnahme, dass org.apachewird ersetzt durchcz.msebera.android.

Der Codedass Sie mit Android verwendet haben eingebaute in Httpclient wird nicht direkt auf neuere Versionen von Apache Httpclient arbeiten, aufgrund API Unterschiede. Allerdings ist es ziemlich nah an häufigsten Orte ist, geringfügige Änderungen erfordern, in der Regel die API zu verbessern.

Zum Beispiel, hier istdie LoadThread Klasse aus der Zeit vor, überarbeitet Httpclient verwenden:

(von

Internet / Httpclient / app / src / main / java / com / commonsware /
android / Httpclient / LoadThread.java)

Wir beginnen mit einem immerHttpclientBeispiel von einemHttpClientBuilder. Vor allem, wenn Sie die VerwendungPoolingHttpClientConnectionManager, Wie hier gezeigt, dieHttpclientBeispiel soll unter mehreren Threads gemeinsam genutzt werden, und so verwendet werden könnte, wieein Singleton.

Hier haben wir es nur einmal zu verwenden, so ist es lediglich eine lokale Variable in derLauf()Methode.

Von dort aus können wir:

• Erstelle einHttpGet Objekt der Stapel Exchange-API-GET-Anforderung darstellen

• SagendasHttpclientnachausführen()dasHttpGet, Vorbei an der Reaktion durch
eineBasicResponseHandlerWerden, welches einSchnurenthält unsere JSON (vorausgesetzt, es ist kein Server-Fehler)

• BestehendassSchnurdurch Gson, um unsereSOQuestions, So wie zuvor

HTTP über Download

Wenn Ihr Ziel ist es, einige große fi herunterladen

Sie besser, indem Sie bedient werden
können,Downloadmanager hinzugefügt, um Android 2.3, da es eine Menge von Low-Level-Komplexität für Sie übernimmt. Zum Beispiel, wenn Sie einen Download auf WiFi zu starten, und der Benutzer das Gebäude verlässt und das Gerät versagt zu irgendeiner Form von mobilen Daten über, müssen Sie den Server und entweder starten Sie den Download erneut oder verwenden Sie einige Inhalte Verhandlung zu holen wieder zu verbinden von wo Sie aufgehört haben. Download Griffe dass.

Aber,Download-Managerist auf irgendeine Sendung abhängigAbsichtObjekte,eine Technik, die wir diskutiert haben noch nicht, so decken wir verzögernDownload-Managerbisspäter imdas Buch.

Unter Verwendung von Drittanbietern JARs

Zu einem gewissen Grad,die beste Antwort ist, nicht den Code selbst schreiben, sondern einige bestehende JAR verwenden, die sowohl die Internet-E / A und alle erforderlichen Daten Parsing.

Dies ist an der Tagesordnung, wenn die öffentliche Web-Dienste zugreifen - entweder weil die fi hinter dem Web-Dienst hat einen JAR freigegeben, oder weil jemand in der Gemeinde hat eine JAR
für die Web-Service veröffentlicht.

Beispiele beinhalten:

• MitJTwitterTwitters API zugreifen

• MitAmazon JARverschiedene AWS-APIs, einschließlich S3, SimpleDB und SQS
zugreifen

• MitdasDropbox SDKfür den Zugriff auf DropBox Ordner und fi

Jedoch außerhalbdasklassische Potenzial JAR Probleme, Können Sie eine andere Begegnung, wenn es JAR-Dateien zu verwenden für den Zugriff auf Internet-Dienste kommt: Versionierung.

Beispielsweise:

• JTwitter Bündeldie org.json Klassen in seiner JAR, die von Android eigene Kopie ersetzt wird, und wenn die JTwitter Version der Klassen eine andere API haben, könnten JTwitter abstürzen.

• Bibliotheken abhängig von Httpclient könnte sein, abhängig voneine Version mit einer anderen API (zB 4.1.1) als im Android (4.0.2 Beta).

Versuchen Sie, fi

JAR-Dateien das gewesen auf Android getestet und sind als solche von
ihrem Verfasser unterstützt. Ohne dass, versuchen zu fi

JAR-Dateien , die Open-Source, so
dass Sie ihre Implementierung optimieren, wenn nötig, um Android-Unterstützung hinzuzufügen.

Später imdieses KapitelWerden wir eine andere Klasse von Drittanbietern JAR-Dateien, diejenigen überprüfenDas sind mehr für allgemeine Zwecke als Dinge wie JTwitter, bieten aber immer noch HTTP-Verarbeitung zu vereinfachen.

SSL

Of Natürlich, wenn Sie über HTTP zu denken sind, sollten Sie wirklich über HTTPS denken -

SSL-verschlüsselte HTTP-Operationen.

Normalerweise, SSL "einfach funktioniert", durch eine https: // URL. Daher, in der Regel gibt es nur wenig, dass Sie tun müssen, um eine einfache Verschlüsselung zu aktivieren.

Es gibt jedoch andere Aspekte der SSL zu berücksichtigen, einschließlich:

• Was wäre wennder Server mit einem SSL-Zertifikat nicht, dass Android wird ehren, wie ein selbst signiertes Zertifikat?

• Was man-in-the-Middle-Angriffe, gehackt Zertifizierungsstellen, unddergleichen?

Die Pfade enthaltenein Kapitel über SSL gewidmetdass Sie werden ermutigt, zu lesen, so dass dieses Kapitel nicht verrückt-lange dauert bekommen.

Mit HTTP-Client-Bibliotheken

Oft schreiben Internet Zugangscode istein Schmerz in verschiedenen Körperteilen.

Es überrascht nicht, gibt eseine Vielzahl von Bibliotheken von Drittanbietern mit diesem zu helfen konzipiert. Einige sind so ausgelegt, Zugriff auf eine spezifi API bereitzustellen, wie die, die in diesem Kapitel bereits erwähnt. Aber andere sind eher für allgemeine Zwecke, entworfen, um Schreiben HTTP-Operationen ein bisschen einfacher machen, indem Sie Dinge wie Handhabung:

• Wiederholungen (zB ausgefallene Gerät von WiFi auf mobile Daten über Mid-Transaktion)

• Threading (zB Handhabung zu tundas Internet Arbeit auf einem Hintergrund-Thread für Sie)

• Daten-Analyse und Serialisieren, für bekannte Formate (zB JSON)

ImIn diesem Abschnitt werden wir uns drei Bibliotheken suchen, die diesen Ansatz verdeutlichen: OkHttp, Retrofi
und Picasso. Später werden wir anderen Bibliotheken sehendass Sie
untersuchen könnte wünschen, einschließlich Google-eigenen Volley HTTP-Client-API.

OkHttp

OkHttpAnwendungenein modifizierter Klon des Standard HttpURLConnection viele Performance-Verbesserungen zu bieten. Am bemerkenswertesten ist die Unterstützung fürSPDY.eine Google gesponserten Version von HTTP erweitert, über die der klassischen HTTP "Keep-alive"

Unterstützung für viele Anfragen und Antworten zu ermöglichen, gehen über den gleichen Socket-Verbindung geliefert werden. Viele Google-APIs werden von SPDY-fähigen Servern zur Verfügung gestellt, und SPDY-Support ist für andere als gut zu verwenden.

Darüber hinausdass, Wraps OkHttp gemeinsame HTTP Performance-Verbesserung Muster, wie GZIP-Kompression, Reaktion Caching und Connection-Pooling auf. Es ist auch bekannt, "realen Welt" Verbindungsprobleme, wie falsch konfigurierte Proxy-Server und dergleichen.

Hinweisdass eine Version von OkHttp hinter der Standard-Implementierung von

HttpURLConnection in Android liegt 4.4 und höher - das ist, wo Android SPDY Unterstützung kommt.

OkHttp hat sich verändert überdie Jahre. OkHttp kam zum Vorsprung in seiner 1.x und 2.x-Versionen, mit einem einigermaßen stabilen API. OkHttp 3.x ist die aktuelle Generation, mit einem reicheren, aber etwas andere API.

OkHttp 2.x

DasInternet / OkHttpBeispielprojektein Klon des Stack-Überlauf Beispiel weiter oben in diesem Kapitel gezeigt. Die ursprüngliche Probe verwendet HttpURLConnection der Stapel Exchange Web Service-Daten zum Download bereit. Diese überarbeitete Probe ersetzt, dass mit OkHttp.

Als erstes werden wirbrauchen eine Abhängigkeit von OkHttp unseren hinzufügenapp

/Modulbuild.gradle
fi

(von Internet / OkHttp / app / build.gradle)

OkHttp bietet zwei grundlegende Varianten vonHTTP API: synchron und asynchron. Mit einem synchronen Aufruf der Anruf blockiert, bis der HTTP-E / A abgeschlossen ist (oder zumindest die Header heruntergeladen werden). Bei einem asynchronen Aufruf, dass Anfangsimpuls von Netzwerk-I / O wird auf einem Hintergrund-Thread behandelt. Die Faustregel ist:

• Wenn Sie arbeiten mitdie rohe HTTP-Antwort, und es kurz ist, verwenden Sie die asynchrone API, wie es Sie davon ab, spart mit dem eigenen Thread zu fuss

• Obdie Antwort lang sein kann oder erfordert signifi

Post-Retrieval-Arbeit (zB

Parsing), verwenden Sie Ihren eigenen Hintergrund-Thread und Verwendungdie synchrone API

In unserem Fall haben wirmüssen die JSON mit Gson, so dass der zweite Ansatz ist die bessere Antwort zu analysieren. Dies hat den Nebeneffekt unserer Java Änderungen der Beschränkung auf nur in LoadThread sein:

(von

Internet / OkHttp / app / src / main / java / com / commonsware /
android / okhttp / LoadThread.java)

Unsere überarbeitetrun () Methode erstellt eine Instanz von OkHttpClient. Dies ist Ihr Gateway für HTTP-Anfragen durchführen.

Eine individuelle Anfrage,nicht überraschend, wird durch ein Request-Objekt dargestellt wird, in der Regel eine Request.Builder erstellt. Die URL () -Methode auf dem Builder ist, wo Sie die URL liefern über eine GET-Anforderung abgerufen werden. Es gibt andere Methoden auf Builder, wie Post (), die zusätzliche Daten für die Anforderung liefert und wandelt sie in eine POST-Anfrage. DasOkHttp Rezepte SeiteUmrisseeine Reihe von gemeinsamen Szenarien.

Um tatsächlich durchführendie synchrone Anforderung, CallNEWCALL (). execute

()aufdasOkHttpClient, Vorbei in dieAnfordernnachdasneuer Anruf()Methode. Dies gibt IhneneinAntwortObjekt, das zurückgeben sollwahrvonist erfolgreich().falschanzeigen würde irgendeine Art vonein Problem, wie eine HTTP-Antwortcode 404.

GegebenEine erfolgreiche Antwort, können Sie auf dem Körper der Reaktion über einen Körper ()

-Methode erhalten. Dies gibt eine Response, die drei Möglichkeiten bietet an der Reaktion Körper zu bekommen selbst:

• string () liefert die gesamte Antwort als String, der nur wirklich geeignet für kurze Textantworten ist

• ByteStream ()gibt einEingabestromaufdie rohen Bytes der Antwort

• CharStream (), trotz seines Namens, gibt einen Reader auf die Zeichen der Antwort, unter Berücksichtigung der Zeichencodierung Antwort (zB UTF-8)

Hier verwenden wirCharStream ()bekommeneinLeser, Die wir dann in eine wickelnBufferedReader.

Der Rest desLauf()Methode ist ziemlich vieldas gleiche wie das Original, fragen Gson die Antwort und veröffentlichen ein zu analysierenQuestionsLoadedEventbekommendie Fragenüber unseren Fragment auf dem Hauptanwendungsthread.

OkHttp3

Für einfache Projekte wiediese, gibt es keine wesentliche Veränderung für OkHttp3 erforderlich.

DasInternet / OkHttp3Beispielprojektein Klon des Internet / OkHttp Projekt, angepasst mit OkHttp3 zu arbeiten. Es gibt nur zwei solche Anpassungen:

1. Aktualisierenbuild.gradleauf etwas zeigendascom.squareup.okhttp3Artefakt:

(von Internet / OkHttp3 / app / build.gradle)

1. aktualisieren Sie dieeinführenAussagen zu verwenden,okhttp3wieein Paket, anstelle von com.squareup.okhttp
weildas Artefakt und Importe sind beide anders, es technisch möglich ist, sowohl OkHttp 2.x und 3.x in einem Projekt zu einer Zeit zu haben. Das ist keine große langfristige Lösung, aber es kann nützlich sein, vor allem, wenn Sie andere Bibliotheken verwenden, die auf verschiedenen Generationen von OkHttp passieren abhängen.

OkHttp 1.x und 2.x unterstützt Kompatibilität Schichtendaß modelliertHttpURLConnection und ApacheHttpclient. Diese wurden mit OkHttp3 eingestellt.

Retrofit

Viele Male, wenn die Arbeit mitHTTP-Anfragen, unsere Bedürfnisse sind ziemlich einfach: nur einige JSON abrufen (oder andere strukturierte Daten, wie zB XML) von einem Web-Service, oder vielleicht eine JSON zu diesem Web-Service hochladen.

Retrofitwurde entwickelt, umvereinfachen dies, indem die Daten-Analyse der Handhabung und für uns Marshalling, zusammen mit den HTTP-Operationen und (optional) Hintergrund Threading. Wir sind mit einer ziemlich natürlich aussehende Java API links nach / von dem Web-Service zum Senden / Empfangen Java-Objekte. Retrofi erreicht dies durch die List Verwendung von Annotationen, Reflexion und, soweit verfügbar, OkHttp selbst.

Es gibt zwei Hauptgenerationendie Retrofi API: 1.x und 2.x. Beide teilen die gleichen Ziele und allgemeinen Fähigkeiten. Retrofi 1.x war ziemlich beliebt, und so werden Sie ein gutes Stück von Code noch sehen, dass die Verwendung, auch wenn neue Entwicklung stark die neuere 2.x Generation in Betracht ziehen sollten. In diesem Abschnitt werden wir beide, suchen fi überprüfen
beim 1.x und Sehen Sie dann, was in 2.x. geändert

Retrofit 1.x

Um zu demonstrieren, Retrofi 1.x (und die Bühne für Retrofi 2.x), lassen Sie uns die BewertungHTTP

/ RetrofitBeispielprojekt. Dieses Projekt istein Klon des vorhergehenden, diesmal Retrofi zum Abrufen und Analysieren von unserem Stack Overflow Fragen verwenden.

Hinweisdass Stack-Überlauf geschieht JSON als Datenformat zu verwenden, die gut mit Retrofi arbeitet
als JSON ist die Standarddatenformat. Allerdings können Sie Ihre eigene

Konvertierungslogik liefern, um Daten zu / von anderen Formaten zu konvertieren, wie XML
oderProtocol Buffers.

Abhängigkeiten

Dascom.squareup.retrofit: Nachrüst-Artefakt ist für Retrofi 1.x verwendet Die letzte veröffentlichte Version von Retrofi 1.x war 1.9.0, und dieses Projekt beinhaltet, dass, zusammen mit einer 2.x-Generation von greenrobot des EventBus:

(von HTTP / Retrofit / app / build.gradle)

Standardmäßig Retrofi Anwendungen Googles Gsonfür seine JSON Parsen.

Dascom.squareup.retrofit: NachrüstungArtefakthat Gson als Abhängigkeit, so
erfordertcom.squareup.retrofit: Nachrüstungwird auch ziehen ineine kompatible Version von Gson.

Erstellen Sie Ihre Dienstleistung Schnittstelle

Der fi
was wir brauchen, ist Retrofi mehr darüber, wo unsere JSON herkommt zu
erzählen. Um dies zu tun, müssen wir eine Java-Schnittstelle mit einigen spezifi zu erstellen Nachrüs- Anmerkungen geliefert, dokumentieren:

• die HTTP-Operationen, die wir durchführen möchten

• der Weg (und, falls erforderlich, Abfrageparameter), um eine HTTP-Operation
anzuwenden, um

• die per-Anforderungsdaten den HTTP-Betrieb, beispielsweise die dynamischen Bereiche des Wegs für einen REST-style API oder zusätzliche Abfrageparameter zu konfigurieren, um die URL zu befestigen

• welches Objekt sollte verwendet werden,zum Gießen der HTTP-Antwort in

Zum Beispiel, nehmen wirein an StackOverflowInterface, unsere Schnittstelle sehen eine Abfrage von Stack-Exchange-API für die Herstellung von Fragen von Stack-Überlauf zu erhalten: (von

HTTP / Retrofit / app / src / main / java / com / commonsware / android /

Retrofit / StackOverflowInterface.java)

Jede Methode inDie Schnittstelle sollte eine Anmerkung Identifizierung des HTTP-Operation müssen, wie @ abrufen oder @POST auszuführen. Der Parameter für die Anmerkung ist der Weg für die Anforderung und alle fi zierten Abfrageparameter. In unserem Fall verwenden wir das durch Stapel von Exchange dokumentiert Pfad für Fragen (/2.1/questions) abrufen, sowie einige fi zierten Query-Parameter:

• Damit, ob die Ergebnisse werden aufsteigend sollte (auf) oder absteigend (ab)

• sortieren, um anzuzeigen, wie die Fragen sortiert werden sollen, wie zum Beispiel die Schaffung von Zeit zu sortieren, wenn die Frage gestellt wurde,

• Website, um anzuzeigen, was Stapel Exchange-Standort wir (zB abfragen,

Paketüberfluss)

Die MethodeName kann alles sein, was Sie wollen.

Wenn Sie zusätzlicheAbfrageparameter, die dynamisch variieren, können Sie mit dem

@query Anmerkung auf String-Parameter zu haben, um sie zu dem Ende der URL hinzugefügt werden. In unserem Fall wird der markierte Abfrageparameter mit dem, was Parameter die Tags hinzugefügt werden soll, auf unsere Fragen () -Methode.

Ebenso können Sie verwenden{Name} Platzhalter für Pfadsegmente und via @ Pfad kommentierte Parameter an die Methode diejenigen zur Laufzeit zu ersetzen.

Um Ergebnisse zurück, und geben Sieder Datentyp für diese Ergebnisse, haben Sie zwei Möglichkeiten:

1. Habendie Methode gibt den Datentyp, den Sie möchten, in welchem Fall, wenn
wir schließlich diese Methode aufrufen, wird der HTTP-Operation synchron
ausgeführt werden, unsere Verfahren zur Anrufblockierung

2. Bestehen ein Callback-Parameter, mit dem gewünschten Datentyp deklariert (zB

SOQuestions), in dem Fall, wenn wir diese Methode schließlich nennen, wird der HTTP-Operation auf einem Hintergrund-Thread ausgeführt werden, wobei die Ergebnisse uns asynchron über eine benutzerdefinierte Callback-Implementierung ausgeliefert, wir stellen ImIm vorliegenden Fall sind die Wahl wir Retrofi behandeln das Einfädeln für uns, so dass wir liefern einen Rückruf und haben die Methode Rückkehr nichtig zu lassen.

Merkwürdigerweise werden wir nie eine Implementierung erstellendie StackOverflowInterface uns.

Stattdessen erzeugt Retrofi für uns, mit Code, der von uns gewünschte Verhalten implementiert.

Erstellen die RestAdapter

Benutzendies erzeugtStackOverflowInterfaceUnd führen tatsächlich diese Operationen müssen wir eine Instanz eines erstellenRestAdapter. Normalerweise werden Sie tun diesüber
eineRestAdapter.BuilderZu konfigurieren, was geschehen soll.

Der Größtewas Sie RestAdapter.Builder ist der Server gebunden an diese HTTP-Operationen zur Verfügung stellt. Der Aufruf setEndpoint () erlaubt es das System, Host und Port angeben, um den Rest der URL angehängt werden, von Ihrer Schnittstelle kommen. Zum Beispiel müssen wir unsere Wünsche des https://api.stackexchange.com Server machen, so haben wir:

(von

HTTP / Retrofit / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

Andere Methoden, die aufRestAdapter.Buildereinschließen:

• setConverter (), wenn Sie Ihre Nutzlasten sind nicht im JSON-Format, aber noch etwas anderes

• setExecutors (), bereitstellenTestamentsvollstreckerObjekte (zB Instanzen

ThreadPoolExecutor) Werden für Anfragen und Rückrufe verwendet

• setlog ()undsetDebug ()zur Steuerung Protokollausgabe

Wenn Sie fertig sind Konfi
dasRestAdapter.Builder, Anrufbauen()bekommendie sich
ergebRestAdapter.

Anfragen machen

Gegebeneine konfigurierte RestAdapter, können Sie durch den Aufruf der create () Methode, um eine Umsetzung Ihrer API-Schnittstelle abgerufen werden:

(von

HTTP / Retrofit / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

Sie könnendann verwenden Sie die resultierende Schnittstelle typisierte Objekt nicht anders, als Sie würde jede andere Java-Objekt, trotz der Tatsache, dass Sie nie eine Implementierung dieser Schnittstelle selbst geschrieben.

In unserem Fall können wir nennendie Fragen () -Methode, die Tag (oder Tags) liefern, aus denen wir den letzten Fragen erhalten möchten:

(von

HTTP / Retrofit / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

Der zweite ParameterFragen () ist eine Implementierung von Callback, asynchrone Ergebnisse aus unseren HTTP-GET-Anfrage zu empfangen. Rückruf erfordert zwei Methoden, Erfolg () und einen Fehler (). Erfolg () nimmt zwei Parameter: der Datentyp in der Benutzeroberfläche angezeigt (zB

SOQuestions) die analysierten Ergebnisse der HTTP-Anforderung, und ein Response-Objekt enthält weitere Informationen aus dem HTTP-Antwort, wie Header darstellt:

(von

HTTP / Retrofit / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

Hier aktualisieren wir unsereListenansichtmit einemItemsAdapterbasierend aufdie empfangenen Fragen.

Ausfall () nimmt einen einzigen Parameter, eine Instanz von RetrofitError, das ist eine Ausnahme Details von etwas bietet, die falsch in der HTTP-Anforderung ging (zum Beispiel wurde Zulassung verweigert). Sie können damit umgehen, dass nicht anders, als Sie andere Ausnahmen von anderswo in der App kann der Benutzer wissen zu lassen, dass etwas schief gelaufen ist. In diesem Fall nehmen wir die rohe-but-einfache Annäherung eines Toast zeigt und die Details LogCat Anmeldung:

(von

HTTP / Retrofit / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

Retrofit 2.x

DasHTTP / Retrofit2Beispielprojektein Klon des vorhergehenden, aktualisiert Retrofi 2.x zu verwenden (zusammen mit 3.x von greenrobot des EventBus).

Dort gab eseine Anzahl von Änderungen in Retrofi 2.x hergestellt, beginnend mit der Abhängigkeit.

Mit Retrofi 1.x würde Retrofi automatisch in eine kompatible Version von Gson ziehen, und es tun würde, so die ganze Zeit (es sei denn, Sie spezifi Schritte in Gradle nahm, dass zu blockieren). In Retrofi 2.x wird der Parsing-Logik nun durch Plugins behandelt, als Retrofi 2.x direkte Unterstützung für eine breite Palette von Parsern hat, für JSON (zB Gson, Jackson), XML (zB

SimpleXML) und Protocol Buffers . Wenn Sie das Artefakt für eines dieser Plugins anfordern, wird das Artefakt in einer kompatiblen Version von sowohl 2.x Retrofi ziehen und die damit verbundene

"Konverter" Code (zB Gson). Damit Anwendungen sowohl Retrofi 1.x und 2.x im selben Projekt zu unterstützen, bewegte Retrofi 2.x auf die com.squareup.retrofit2 Gruppen-ID, mit verschiedenen Artefakte drin. Also, zieht diese überarbeitete Beispielanwendung in dem Konverter-Gson Artefakt, Retrofi mit Gson Unterstützung zu erhalten:

(von HTTP / Retrofit2 / app / build.gradle)

Auch zu ermöglichen Projekte sowohl Retrofi haben 1.x und 2.x, die alle die Retrofi 2.x-Klassen sind in einem retrofit2 Java-Paket, die sich von dem Paket Nachrüstung verwendet für Retrofi 1.x Mit Retrofi 1.x, unsere Service-Schnittstelle verwenden würde zwei verschiedene

Methodensignaturen für synchrone und asynchrone Operation. Synchrone Methoden würde die gewünschte Objekttyp zurückgeben (zB SOQuestions), während die asynchrone Methoden void zurückgeben würde und einen Rückruf als Parameter. Retrofi 2.x simplifi
diese, mit allen

Service-Schnittstelle Methodensignaturen eines Anrufs Objekt des gewünschten Typs:

(von

HTTP / Retrofit2 / app / src / main / java / com / commonsware / android /

Retrofit / StackOverflowInterface.java)

Für synchrone Arbeiten Sieexecute () den Anruf; für asynchrone Arbeit, Sie
enqueue ()dasAnrufUnd bietet eineRückrufenObjekt alsein Parameterenqueue ().

Retrofi 1.x eine RestAdapter hatte, die Sie verwenden würden die allgemeine Retrofit Verhalten zu konfigurieren, dann () verwenden, erstellen Implementierungen der Service-Schnittstelle zu erhalten.

Retrofi 2.x verwendet ein ähnliches System, aber es ist jetzt ein Retrofit-Objekt über eine erstellt Retrofit.Builder:

(von

HTTP / Retrofit2 / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

Hinweisder Anruf anaddConverterFactory ()aufdasRetrofit.Builder. da Retrofit

2.x
nicht mehr davon aus, dass Sie einen bestimmten Parser verwenden möchten, müssen Sie speziell eine Instanz einer VersorgungsKonverter.GsonConverterFactoryist indasWandler-GsonArtefakt und gibt unseinGsonConverterdass wirüber erstellenerstellen()aufdie Fabrik.

DasRückrufenSchnittstelle ist auch etwas anders, mitonResponse ()und
onFailure ()Methoden zu ersetzendie Retrofi 1.xErfolg()undFehler()Methoden:

(von

HTTP / Retrofit2 / app / src / main / java / com / commonsware /
android / Retrofit / QuestionsFragment.java)

ImonResponse (), Um die Ergebnisse der Retrofi Anfrage, Anruf erhaltenKörper()aufdie mitgelieferteAntwortObjekt.

Also, insgesamt, Retrofi 2.x hat die gleiche Art von Arbeit wie auch Retrofi 1.x, nur mit einem etwas veränderten Satz von Artefakten und APIs.

Picasso

Manchmal, was Sie herunterladen möchten, istnicht JSON oder XML, oder jede Art von strukturierten Daten.

Manchmal ist es ein Bild.

Zum Beispiel haben Stack Overflow Benutzer Avatare. In unserem Beispiel-App, könnte es schön, angezeigt werdender Avatar des Benutzers, der die Frage gestellt.

Picassoisteine Bibliothek von Square, das entworfen ist, mit asynchron Laden von Bildern zu helfen, ob diese Bilder von HTTP-Anfragen kommen, lokale fi

Ein Contentprovider, etc. Zusätzlich
zu den Lade asynchron tun, Picasso Simplifi
viele Operationen aufdiese Bilder, wie zum

Beispiel:

• CachingDie Ergebnisse im Speicher (oder HTTP-Anforderungen wahlweise auf der

Festplatte)

• Anzeigen Platzhalter Bilder währenddie realen Bilder werden geladen, und Anzeige von Fehlerbildern, wenn ein Problem beim Laden des Bildes war (zB ungültige URL)

• Transformingdas Bild, wie Ändern der Größe oder zerteilen eine bestimmte

Menge an Speicherplatz zu fi nden

• Ladendie Bilder direkt in eine Image Ihrer Wahl, Handhabung auch Fälle, in denen das Image recycelt wird (zum Beispiel Teil einer Reihe in einem Listview, in dem der Benutzer gescrollt, während ein Bild für das Image noch geladen wurde, und nun ein weiteres Bild ist dazu bestimmt, für dass gleiche Image, wenn die Zeile wurde wiederverwendet) DasHTTP / PicassoBeispielanwendung erweitertdie Retrofi man den Avatar-Bild der Person, die Frage zu stellen herunterladen, es in der Listview zusammen mit der Frage Titel angezeigt wird.

Das Herunterladen und Installieren von Picasso

Picasso kann heruntergeladen werdenein kleines Glas ausdie oben genannten Website. Android Studio picasso: ... für einige Version bezeichnet mit ..., und es werden alle anderen Abhängigkeiten von Picasso benötigt Pull-Down-Benutzer können nur eine Abhängigkeit für com.squareup.picasso hinzufügen.

Aktualisierungdas Model

Unsere ursprüngliche Datenmodell tatkeine Informationen über den Eigentümer gehören. Daher müssen wir unsere Datenmodell erweitern, so Retrofi, dass die Informationen aus dem Stapel von Exchange JSON zieht und macht es uns zur Verfügung.

NachDafür haben wir jetzt eine Besitzer-Klasse, auf die eine Information halten wir über den Besitzer brauchen: die URL zum Avatar (aka, "profi

Image"):

(von

HTTP / Picasso / app / src / main / java / com /
commonsware / android / picasso / Owner.java)

Die JSON Schlüssel fürDiese in der Stapelaustausch API ist Profile_image und Unterstrichen sind nicht die herkömmliche Art der Wörter in einem Java-Datenelement zu trennen. Java Samples verwenden "Camelcase" in der Regel statt. Das Standardverhalten von Retrofi würde uns bedürfen unserer Datenelement Profile_image zu nennen die JSON zu entsprechen.

Jedoch unterdie Abdeckungen, Retrofi wird mit Googles Gson die Zuordnung von JSON Objekten zu tun. Gson unterstützt eine @SerializedName Anmerkung, die JSON-Taste, um anzuzeigen, für dieses Datenelement zu verwenden. Dies ermöglicht es uns, die Daten Mitglied der mehr natürliche Namen Profilbild zu geben, durch @SerializedName ( "Profile_image") mit Gson zu lehren, wie man es richtig zu füllen.

(Der Autor möchteAlec Holmes für seine Unterstützung bei der Gson Unterstützung danken) UnserArtikelKlasse hat jetzt ein Eigentümer, genanntEigentümerDa der Besitzer Daten ist in derEigentümer

Schlüssel eines JSON-Objekts Artikel:

(von

HTTP / Picasso / app / src / main / java / com /
commonsware / android / picasso / Item.java)

Diese beiden Änderungen sind ausrei
für Retrofi geben uns unsere URL in der Lage
sein, das Bild zum Download bereit.

Anforderndie Bilder

Mit Picasso ist äußerst einfach, da es bietetein fl

Schnittstelledass ermöglicht es uns, eine

Anforderung in einer einzigen Java-Anweisung einzurichten.

Die Erklärung beginnt mitein Aufruf der statischen mit () -Methode auf dem Picasso-Klasse, wo wir einen Kontext (wie unsere Tätigkeit) für Picasso liefern zu verwenden. Die Erklärung endet mit einem Aufruf in (), was auf die Imageview, in die Picasso ein Bild geladen werden soll. Zwischen diesen ruft, können wir die Kette andere Anrufe, wie mit () und die meisten anderen Methoden auf einem Picasso-Objekt zurückgeben das Picasso-Objekt selbst.

So können wir etwas tun, wie:

(von

HTTP / Picasso / app / src / main / java / com / commonsware /
android / picasso / QuestionsFragment.java)

Hier haben wir:

• Zeigendass wir wollenBelastung()ein Bild gefunden beieine bestimmte URL, durch die identifiziertenProfilbildDatenelementdasEigentümerinnen einArtikelbezeichnet alsArtikel

• Sagendass wir wollenpassen()das Bild auf unser ZielImage

• Geben Sie das sollte sich das Bild mit centerCrop () Regeln der Größe verändert werden, um das Bild in der gewünschten Größe auf die Mitte (wenn sie kleiner auf einer oder beiden Achsen ist) und das Bild zuzuschneiden (wenn es größer auf einer oder beiden Achsen ist)

• Zeigendass wir wollen, eine gewisse drawable Ressource als Platzhalter () Bild zu setzen in der Image zu zeigen, während das Laden im Hintergrund los ist

• Bundeslanddass wir eine bestimmte drawable Ressource in der Image im Falle eines Fehlers (), wenn das Bild geladen zeigen wollen, wurde

Und das ist es. Picasso gehen wird, herunterladendas Bild, und gießen Sie sie in die Image wenn es fertig ist (und Größe angepasst).

Der Rest vondie Geschichte

Das Bit von Picasso-Code ist inein neuergetView ()Verfahren Sie auf unsererItemsAdapter:

(von

HTTP / Picasso / app / src / main / java / com / commonsware /
android / picasso / QuestionsFragment.java)

Wir haben unsere eigene Reihe Layout (res / layout / row.xml) erstellt, bestehend aus einemImage und ein Textview. Wir haben ArrayAdapter unsere Reihe aufblasen oder recyceln, rufen Sie den Artikel für diese Zeile, rufen Sie den Image aus der Reihe, verwenden Picasso beginnen das reale Bild laden, fi in der HTML-Entity-aware Text in das Textview, und dann unsere Rückkehr aktualisierte Zeile. Als wir die Zeile zurückkehren, wird Picasso haben bereits den Platzhalter Bild geladen, das, was der Benutzer sehen zunächst, während wir das reale Bild herunterladen.

Das Ergebnis istdass wir jetzt Symbole für jeden unserer Frage Titel weiter:

Volley

Beimdie Google I | O 2013 Konferenz gab eseine Sitzungüber Volley, einHTTP-Client-Bibliothek von Google erstellt und durch interne Anwendungen, wie zB die Play Store verwendet. Volley kann als eine Obermenge von Retrofi und Picasso gedacht werden, minus Nicht-HTTP-Bild Verladeanlagen Picassos.

AufDie Plus-Seite, Volley ist so ein Obermenge und daher eine einzige Code-Basis verwendet werden, können mehrere Bibliotheken zu ersetzen. Auch angesichts Volley die Nutzung von Google, stellt man sich, dass dieser Code hat eine große Auswahl von möglichen Geräten angewendet. Und im Frühjahr 2016, Volley fi
y begann als ein Artefakt verteilt werden, die wir unseren

Android Studio-Projekte über eine einfache Kompilierung Anweisung hinzufügen.

Jedoch gibt eskeine Dokumentation darüber hinaus, dass I | O Video undein Trainingsmodul. Es gibtkeine Unterstützung Mechanismus, außer vielleicht über Ad-hoc-Social-Media-Anfragen und allgemeine Support-Seiten (zBPaketüberfluss).

Alledass gesagt wird, ist Volley noch recht beliebt, so wollen wir mal sehen, wie man es in einem Android-Projekt verwenden können. Insbesondere ist dieHTTP / VolleyBeispielanwendung basiert weg vondas

Picasso Probe wanderten über Volley zu verwenden, anstattdie Kombination von Picasso und Retrofit.

Erste Volley

Ich war Hälfte, dass der Kampf war gerade dabei Volley in der fi

Ort. Seit Jahren gab

Google uns nur ein Dump des Quellcodes im Android Open Source Project, anstatt eine richtige Artefakt.

Doch Anfang 2016 Google leise veröffentlichtein Volley Artefakt, so dass Sie es zu Ihrem Abhängigkeiten hinzufügen:

Anfragen und Warteschlangen

Volley primäre API ist übereine Klasse namens Request. Wie der Name schon sagt, reiht es Anfragen, ob diese Anfragen für Bilder sind, Strings, JSON Strukturen, oder was auch immer. Eine Anfrage -
in Form einer Anforderungsinstanz - verkörpert die URL abgerufen werden, zusätzliche Informationen (zB zusätzliche HTTP-Header), und die Regeln für die Antwort vom Server empfangen zu interpretieren.

Unterdie Abdeckungen, unterhält einen Request Thread-Pool für diese Anfragen zu verarbeiten. Sie können diesen Thread-Pool optional konfiguriert werden, die angibt, wie viele Threads es haben und so sollte. Sie können auch optional konfigurieren, wie Antworten zwischengespeichert werden

soll und die tatsächliche HTTP-Stack für das Erledigen der Netzwerk-I / O verwendet werden.

Standardmäßig auf moderne Versionen von Android, Volley Delegierten HttpURLConnection.

Einen Manager-

Retrofi und Picasso verwalten Application-Level-Thread-Pools und Caches für Sie, über die mitgelieferten Singletons. Ach, Volley nicht. Während diese Flexibilität bietet, bedeutet es, dass Sie um einen Request Ihre eigenen Singleton-Wrapper müssen. Im Beispielprojekt haben wir VolleyManager dafür:

(von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / VolleyManager.java)

VolleyManagerhältdie Singleton-Instanz in einstatischfi
genanntBEISPIEL. Das ist faul
initialisierteüber diebekommen()Verfahren zum Abrufendie Instanz, wie wir brauchen, ist einKontextfürein bisschen unserer Arbeit.

DasPrivatgeländeKonstruktor erstelltein neuerRequestüberdasstatische newRequestQueue ()Helfer-Methode aufdasVolleyKlasse. Wenn Sie mehr Kontrolle zu haben (zB Ihre eigene Antwort Cache liefern) bevorzugen, können Sie auch erstelleneinRequestüberein Konstruktor, dann rufenAnfang()aufdasRequestKick-offder Thread-Pool.

Wir werden diskutierender Rest von VolleyManager, einschließlich der mysteriösen Imageloader wir im Konstruktor, ein bisschen später in unserer Untersuchung der Probe App erstellen.

Anfordern von JSON

Volley hat eine eingebaute Unterstützung für Streicher und Abrufen von Bildern ausein Web-Service.

Wenn der Web-Service-JSON dient, auch Volley hat eine integrierte Unterstützung für das JSON

Parsen.

Jedoch verwendet esdie Legacy-org.json Klassen aus dem Android SDK, die arbeiten, aber sind langsam und klobig.

Retrofi integrierte Unterstützung hat eine JSON-Nutzlast von einem Webdienst über eine HTTP-Anforderung zum Abrufen, mit Gson dass Nutzlast in die gewünschte POJOs zu analysieren. Ach, Volley bietet nicht Gson Unterstützung aus dem Kasten heraus.

Der Autor von Volley, Ficus Kirkpatrick, schriebeine GsonRequest Klasse, die diese und veröffentlicht es Griffe überein GitHub Kern. Das hat sich seit repliziert wurden indie Android-Dokumentation. Da diese Spiele näher, was wir in Retrofi hatte

Das Beispielprojekt
verwendet diese GsonRequest:

(von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / GsonRequest.java)

Eine benutzerdefinierte Anfrage Implementierung wie diese braucht vier Dinge:

1. Versorgender HTTP-Methode, URL, und einerResponse.ErrorListenernachder

Oberklassenkonstruktors

2. ÜberschreibengetHeaders (), eine Karte von HTTP-Headern in die Anfrage zu injizieren, oder null, wenn es keine gibt

3. ÜberschreibenparseNetworkResponse (), die Rohdaten vom Server zu nehmen und in eine Antwort dreht sich um die eigentlichen Daten zu verpackenden an die App
zurückgegeben werden (in diesem Fall die individuelle POJO von Gson analysiert)

4. ÜberschreibendeliverResponse (), Die nur eine Frage der Berufung sein kann
onResponse ()aufeinResponse.Listener
viele Entwickler können jedoch weg mit der Verwendung von nur einer vondie integrierten anfordern Implementierungen oder vielleicht auch andere vordefinierte Implementierungen, wie diese GsonRequest.

UnserQuestionsFragmentkönnen jetzt erstelleneinGsonRequestfür unsere Stack Overflow Fragen Abrufen undDrehen sie in eineSOQuestionsObjekt. Imdiese Version der Probe, zum Auffüllen der Arbeit derListenansichtwurde verschoben ausonCreateView ()nachonViewCreated ():

(von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / QuestionsFragment.java)

DasR.string.url Wert weist auf einen String-Ressource die vollständige URL enthält, wie es ein bisschen zu lang für einen Java-Code Auflistung ist oder sogar leicht in diesem Buch hier zu reproduzieren.

Beachten Sie jedoch, zweiDinge über sie:

1. ImDie Nachrüstbetriebenen Beispielen haben wir die markierten Abfrageparameter über einen @Query kommentierte Parameter auf unserer StackOverflowInterface. Das war vor allem mit solchen Parametern zu zeigen, wie wir es immer waren die Android-Fragen anfordern. Da wir URL Konstruktion haben Retrofit ist nicht mehr, enthält die URL in der String-Ressource der markierte = android Abfrageparameter.

2. Da Werte Ressource fi

XML-fi sind
müssen alle & Zeichen in der

URL maskiert werden als & amp ;, um XML-Parsing-Regeln erfüllen.

Der Rest vondasGsonRequestParameterdie Klasse für die Antwort (SOQuestions.class), Unser extraHTTP-Header (Null), Und unsere ImplementierungenHörerundErrorListener(beidedas Fragment selbst).

Wirdann abrufen unsereVolleyManagerSingleton und Callenqueue ()auf sie, die indrehen Anrufehinzufügen()aufdasRequest, Einer der Volley des Threads zu bewirken, dass der HTTP-Arbeit und verarbeiten das Ergebnis zu gehen tun.

ErrorListenererfordert einonErrorResponse ()Verfahren, dieähnlich wie seine Retrofi arbeitet Gegenstück:

(von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / QuestionsFragment.java)

Listener erfordert eine onResponse () Methode, die die Art der Daten dauert wir versuchen, als Parameter (SOQuestions) zu laden. Noch einmal, das funktioniert wie sein Retrofit Gegenstück: (von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / QuestionsFragment.java)

Anfordern von Images

Volley hat einImageRequest, eine, die wie GsonRequest arbeitet, mit der Ausnahme, dass es Sie gibt einen Bitmap zurück. Sie sind herzlich eingeladen, diese zu verwenden, vor allem für gelegentliche einmalige Anfragen für Bilder.

Allerdings, wenn Sie gehen zu holenviele Bilder - vor allem in so etwas wie ein Listview, wie die Beispielanwendung tut - Sie brauchen etwas mehr Köpfchen als das.

Picasso liefert diese Smarts Ihnen automatisch. Mit Volley verwenden Sie eine Imageloader. Ein Imageloader-Koordinaten laden viele Bilder, Umgang mit Dingen wie:

• Cancelling-Anforderungen, wenn Ansichten recycelt erhalten

• mitein Speicher-Cache für Bilder, die Disk-Cache, der Volley verwendet für Antworten zu ergänzen

• versucht redraws der Benutzeroberfläche zu minimieren, wenn mehrere Bilder in
etwa gleichzeitig dekodiert werden

• und so weiter

Jetzt aus Gründendie nicht ganz klar sind, während Imageloader einen Speicher-Cache muss richtig funktioniert, ist es nicht ein. Auch nicht Volley selbst. Stattdessen müssen Sie eine eigene Implementierung von ImageLoader.ImageCache machen.

Die Android-Dokumentation liefert eine LruBitmapCachedas tut dies, auf der Rückseite des AndroidLRUCache:

(von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / LruBitmapCache.java)

Der Schlüssel für jeden Cache, insbesondereein Speicher-Cache, ist seine maximale Größe.

LruBitmapCache können Sie das direkt angeben, wenn Sie es wünschen. Alternativ können Sie es mit einem Kontext zu machen, und es wird eine Größe der Cache die Größe von drei Vollbildern zu sein. Dies ist kein großer Cache Sizing-Algorithmus - es besser ist, die Größe auf die maximale Speichergröße der App zu binden - aber es ist das, was Google verwendet.

VolleyManagerschafft eineImageloaderin seinem Konstruktor, die Bereitstellunges mit einemLruBitmapCache.VolleyManagerhat aucheinloadimage ()Methodedas funktioniert ein bisschen wie der Generator-Methoden auf Picasso. Es dauert vier Parameter:

• Die URLdas Bild zu laden

• DasImagein die zu ladendas Bild

• Eine drawable Ressource-ID für einen Bild-Platzhalter

• Eine drawable Ressource-ID für ein Bild zu zeigen, ob es ein Fehler ist das reale Bild Abrufen (zB 404 von dem Web-Server, wenn die URL anfordert)

loadimage ()imRunde geht diejenigen auf dieImageloaderWird handhaben, die das Bild Abrufen, Caching, und es in der mitgelieferten setzenImage.

DasgetView ()Verfahren aufItemsAdapterkanndann seine Picasso ersetzen Code mit einem Aufruf anloadimage ():

(von

HTTP / Volley / app / src / main / java / com / commonsware /
android / Volley / QuestionsFragment.java)

Der Vergleich mit Retrofit+ Picasso

Volley des großen Anspruch auf Ruhm istdass es in der Play Store App und an anderer Stelle in Google-eigenen Apps, die angeblich verwendet.

Doch seinen Mangel an offi

Verpackung und Unterstützung macht esetwas schwieriger für die
durchschnittliche Entwickler zu verwenden. Es fehlt auch einige der "Kreatur Komfort" von Retrofit und Picasso, ein paar zusätzliche Klassen erfordern Bibliotheken zu tun, was Platz direkt zur Verfügung stellen.

Andere Kandidaten Bibliotheken

Es gibt viele andere Bibliothekenversuchen, dass in ähnlicher Weise zu helfen, Android HTTP-Operationen zu vereinfachen, einschließlich:

• AndroidAsync

• android-JSON-RPC

• Universal-Image Loader (UIL), Die in einigen Proben verwendet werden später
indieses Buch

Wenn Sie geschehen, zu verwendensupport-v4 oder Support-v13 aus dem Android-Support-Paket in Ihrer Anwendung, Sie auch interessieren könntenIon.

Die Android-Arsenal hat Kategorien fürGeneralHTTP-Clients / networking Bibliotheken für REST-Client-Bibliotheken, und fürBild das Laden von Bibliotheken.

Besuchdie Trails

Wie bereits erwähnt, gibt eseinKapitel über SSLdass Sie sollten lesen, wenn Sie Probleme bei der Verwendung von SSL in Android laufen oder möchten Ihre Sicherheit weiter zu verbessern, als Sie mit nur Lager SSL Handhabung zu bekommen.

Es gibt aucheinKapitel über verschiedene Netzwerkfunktionen- Die Berichterstattung über Download-ManagerDort finden.

Intents, Intent-Filter

Wir haben gesehenIntent Objekte kurz, in unserer Diskussionübermit mehreren Aktivitäten in unsere Anwendung. Allerdings haben wir wirklichTauchen Sie nicht in zu viel von den Details über diese Absicht Objekte, und sie können auch auf andere Weise außer Anfahren eine Aktivität verwendet werden. In diesem Kapitel werden wir Intent und ihre gatoren untersuchen.

Was ist Ihre Absicht?

Als Sir TimBerners-Lee kochte das Hypertext Transfer Protocol up - HTTP - er stellte ein System von Verben und Adressen in Form von URLs auf. Die angegebene Adresse eine Ressource, wie zum Beispiel eine Webseite, eine Grafik oder serverseitige Programm. Das Verb angegeben, was getan werden sollte: GET, um es abzurufen, POST Formulardaten, um es für die Verarbeitung zu schicken, usw.

EinAbsicht istähnlich, dass sie eine Aktion und Rahmen darstellt. Es gibt mehrere Aktionen und mehr Komponenten auf den Kontext mit der Absicht, als es mit HTTP Verben und Ressourcen, aber das Konzept ist immer noch die gleichen.

Genauso wieeinen Web-Browser weiß, wie ein Verb + URL Paar zu verarbeiten, weiß Android, wie man fi

Aktivitäten oder andere Anwendungslogik das wird eine gegebene Absicht
behandeln.

Pieces of Intents

Die zwei wichtigsten Teile einesIntent sind die Aktion und was Android bezieht sich auf die

"Daten". Diese sind fast genau analog zu HTTP-Verben und URLs - die Aktion ist das Verb und die

"Daten" ist ein Uri, wie https://commonsware.com repräsentiert eine HTTP-URL, um einige Website des Balding Kerl. Aktionen sind Konstanten, wie ACTION_VIEW (um einen Betrachter für die Ressource bringen) oder ACTION_EDIT (die Ressource zu bearbeiten).

Wenn Sie waren eine zu erstellenAbsichtVereinigungACTION_VIEWmitein

GehaltUrivonhttps://commonsware.comUndübergeben,Absichtauf AndroidüberstartActivity ()Android, würde wissen, zu fi nden
und öffnen Sie eine Aktivität der Lage Betrachtungs dass

Ressource.

Es gibt noch andere Kriterien, die Sie innerhalb eines platzieren Absicht, neben der Aktion und "Daten"

Uri, sowie:

1. Kategorien. Ihre "Haupt" Aktivität wird inDie Abschußvorrichtung Kategorie, was anzeigt, sollte es auf dem Startmenü angezeigt. Andere Aktivitäten werden wahrscheinlich in der Standard-Kategorie sein, obwohl andere Kategorien vorhanden sind und gelegentlich verwendet.

2. Ein MIME-Typ, unter Angabe der Art der Ressource, die Sie arbeiten möchten.

3. Eine Komponente, die die Klasse der Aktivität zu sagen ist, die angeblich diese Absicht zu empfangen.

4. "Extras", das ein Bündel von anderen Informationen, die Sie zusammen mit dem Empfänger mit der Absicht übergeben wollen, dass der Empfänger Anspruch nehmen
möchten. Welche Stücke von Informationen einen bestimmten Empfänger verwenden
können, bis zum Empfänger ist und (hoffentlich) ist gut dokumentiert.

Sie fi

Roster vondie Standard-Aktionen, Kategorien und Extras im Android SDK-

Dokumentation für die Intent-Klasse.

Intent Routing

Wie oben erwähnt, wenn Siegeben Sie die Zielkomponente in Ihrer Absicht, hat Android keinen Zweifel daran, wo die Absicht soll geroutet werden - es wird die genannte Aktivität starten. Dies könnte in Ordnung sein, wenn der Zielempfänger (zB auf die Aktivität gestartet werden) in der Anwendung ist. Es ist auf jeden Fall nicht für den Aufruf Funktionalität in andere Anwendungen empfohlen. Komponentennamen, im Großen und Ganzen, werden als private auf die Anwendung und Änderungen vorbehalten. Aktionen, Uri Vorlagen und MIME-Typen sind die bevorzugten Wege zur Identifizierung von Funktionen, die Sie Code von Drittanbietern wollen zu liefern.

Wenn Sie tungeben Sie die Zielkomponente nicht, dann hat Android zu fi nden
e heraus, was
die Empfänger sind berechtigt, die Absicht zu erhalten. Zum Beispiel nehmen Android die Absicht Sie zu startActivity liefern () und fi
die Aktivitäten, die sie unterstützen könnten. Beachten

Sie die Verwendung der mehreren "Aktivitäten", wie ein im Großen und Ganzen geschriebene Absicht gut auf mehrere Aktivitäten lösen könnten. Das ist die ... ähm ... Absicht (verzeihen Sie das Wortspiel), wie Sie sehen werdenspäter imdieses Kapitel. Diese Routing-Ansatz wird als implizite Routing bezeichnet.

Grundsätzlich gibt es drei Regeln, von denen alle sein mußgilt für eine bestimmte Tätigkeit für eine bestimmte Absicht in Frage zu kommen:

• Die Tätigkeit muss unterstützendie spezifi

Aktion

• Die Tätigkeit muss unterstützendie angegebenen MIME-Typ (falls vorhanden)

• Die Tätigkeit muss unterstützen alledie Kategorien in der Intent-Namen

Das Ergebnis ist,dass Sie möchten, dass Ihre Absicht spezifi genug, um fi zu machen die
richtigen Empfänger, und nicht mehr spezifi als das.

Dies wird klarer, wenn wir durch einige Beispiele arbeiten in ganzdieses Kapitel.

Unter Angabe Ihrer Intent (Ionen)

Alle Android-Komponentendieser Wunsch über eine Absicht gestartet werden muss Intent gatoren erklären, so Android weiß, welche Absichten auf diese Komponente zu gehen. Ein gemeinsamer Ansatz dafür ist, ein oder mehrere <Intent-Filter> Elemente AndroidManifest.xml fi hinzufügen
innen das Element für die Komponente, die auf die Intent reagieren soll.

Zum Beispiel werden alle vonDie Beispielprojekte in diesem Buch haben ein <Intent-Filter> auf ein

<Aktivität>das sieht wie folgt aus:

Hier erklären wir,dass diese Aktivität:

1. istdie Haupttätigkeit für diese Anwendung

2. Es ist in Die Abschußvorrichtung Kategorie, es bedeutet, bekommt ein Symbol in irgendetwas, das von sich selbst als "Launcher", wie der Startbildschirm denkt

Sie sind herzlich eingeladen, mehr zu habenals eine Aktion oder mehr als eine Kategorie in der Intent-Emulgatoren. Das zeigt an, dass die zugehörige Komponente (zB Aktivität), um mehrere verschiedene Arten von Intent Muster verarbeitet.

Reagierenauf Implizit Intents

Wir sahen indas Kapitel über die vielfältigen Aktivitäten, wie eine Aktivität eine andere über einen expliziten Absicht beginnen können, die bestimmte Aktivität zu identifizieren gestartet werden: Imdiesem Fall muss OTHERACTIVITY keine <Intent-Filter> im Manifest müssen. Es wird automatisch reagieren, wenn jemand explizit als die gewünschte Aktivität identifiziert.

Was aber, wenn Sie wollen eine implizite reagierenIntent, eine, die auf einer Aktionszeichenfolge und andere Werte konzentriert? Dann werden Sie ein <Intent-Filter> müssen im Manifest.

Nehmen wir zum Beispielein Blick auf dieIntents / FauxSenderBeispielprojekt.

Hier haben wir eine Aktivität,FauxSender, Eingerichtet, um eine zu antwortenACTION_SEND

Intent, Die speziell für Inhalte, die den MIME-Typtext / plain:

(von

Intents / FauxSender / app / src / main /

AndroidManifest.xml)

Der AufrufstartActivity ()wird immer hinzufügendasSTANDARDKategorie, wennkeine andere Kategorie ist spezifi
welcheDeshalb sind unsere<Intent-Filter>auch fi ers auf diese

Kategorie.

Wenn also jemand aufDas System ruftstartActivity ()auf einACTION_SEND Intentmitein MIME-Typtext / plain, unserFauxSenderAktivität könnte Kontrolle geraten. Wir erklärendie Verwendung des Begriffs "Macht" im nächsten Abschnitt.

DasDokumentation ACTION_SENDzeigt an dass ein Standard-Extra auf dem Intent EXTRA_TEXT
ist, den Text darstellt, gesendet werden. Es könnte auch ein EXTRA_SUBJECT, was eine

Betreffzeile, wenn die "Senden" Betrieb ein solches Konzept haben könnte, wie zum Beispiel eine E-Mail-Client.

FauxSender können diese Extras abrufen und von ihnen Gebrauch machen:

(von

Intents / FauxSender / app / src / main / java / com / commonsware /
android / fsender / FauxSender.java)

Hier verwenden wirTextUtils.isEmpty ()zu erkennen, ob ein extra entwederNulloder hat einleere Zeichenkette als Wert. ObEXTRA_TEXTgeliefert wird, zeigen wir es ineinToast.

Andernfalls wir benutzenEXTRA_SUBJECT wenn es zugeführt wird, und wenn das auch fehlt, zeigen wir eine Lager-Nachricht von einem String-Ressource.

Die Aktivitätdann ruft sofortFertig()vononCreate ()loszuwerden, sich zu bekommen. Dies, gepaart mitandroid: theme = "@ android: style / Theme.NoDisplay"imdas

<Aktivität> Element, bedeutet, dassdie Aktivität wird keine Benutzeroberfläche, darüber hinausdas Toast. Wenn von der Trägerrakete starten, werden Sie immer noch die Trägerrakete hinter dem Toast zu sehen:

Anfordern von Implicit Intents

Senden Sie etwasüberACTION_SENDSie fi nden

Set oben dasAbsicht, Enthält, was

Informationen Sie wollen in schickenEXTRA_TEXTWie dieser Code aus
demFauxSenderTestAktivität:

(von

Intents / FauxSender / app / src / main / java / com / commonsware /
android / fsender / FauxSenderTest.java)

(woherthemes ist einübergebene in Parameter an die Methode mit diesem Codefragment) Wenn wir nennenstartActivity () zu diesem Intent direkt, gibt es drei mögliche Ergebnisse, in den folgenden Abschnitten beschrieben.

NullStreichhölzer

Es ist möglich, wenn auch unwahrscheinlich,dass es überhaupt auf dem Gerät keine Aktivitäten, die diese Absicht in den Griff bekommen können. In diesem Fall werden wir mit einem

ActivityNotFoundException abstürzen. Dies ist ein Runtime, weshalb wir alle unsere startActivity nicht halten müssen Einwickeln () ruft in try / catch-Blöcke. Allerdings, wenn wir etwas anfangen könnten, die nicht existiert, sollten wir wirklich diese Ausnahme zu fangen ... oder den Anruf im fi

vermeiden

Ort. Erkennen von vorne, ob wird es Begegnungen sein für unsere Tätigkeit ist ein Thema, das später in diesem Buch diskutiert werden.

Hinweisdass die Chancen eines ActivityNotFoundException klettern im Wesentlichen auf Android 4.3+ Tabletten, wenn eine eingeschränkte Profi
in Gebrauch ist, wird wie erörtertspäter im
dieses Buch.

EinsSpiel

Es ist möglich, dass es genau eine Anpassungs Aktivität sein. In diesem Fall beginnt die betreffende Tätigkeit und Vordergrund übernimmt. Dies ist, was wir mit der ausdrücklichen Absicht zu sehen.

Viele Spiele, Standardverhalten

Es ist möglich, dass es mehr als eine passende Tätigkeit sein. In diesem Fall wird standardmäßig wird der Benutzer präsentiert werden mit einem so genannten "Chooser" Dialogfeld: Der Benutzer kannTippen Sie auf einen Eintrag in der Liste, die bestimmte Aktivität zu haben, derjenige sein, dieses Ereignis zu verarbeiten. Und wenn der Benutzer klickt auf "Always", und wir rufen die gleichen grundlegenden Intent wieder (gleiche Aktion, denselben MIME-Typ, gleiche Kategorien, gleiche Uri Schema), was auch immer der Benutzer nun automatisch wieder verwendet werden wählt, die Auswahl umgangen wird. Die "Always" Button im Auswahldialog stellt die Standard-Aktivität für die besondere Absicht Struktur der Handhabung, die den Chooser ausgelöst.

Die Auswahl außer Kraft setzen

Für vieleIntent Muster, macht die Vorstellung des Benutzers ein Standard Auswahl durchaus Sinn.

Wenn Sie beispielsweise, wenn der Benutzer einen anderen Web-Browser, bis sie eine Standard-Aktivität gesetzt, jedes Mal, wenn sie gehen, um eine Webseite anzuzeigen, werden sie mit einem chooser präsentiert werden, unter den installierten Browser zu wählen. Das kannärgerlich schnell.

Aber,ACTION_SEND ist einer jener Fälle, in denen eine Standard-Aktivität in der Regel ungeeignet ist. Nur weil der Benutzer am Montag wählte etwas über Bluetooth zu senden und klickte aus Versehen "Always" bedeutet nicht, dass jeden Tag danach, sie immer wollen, dass jeder ACTION_SEND gehen über Bluetooth, anstelle von Google Mail oder E-Mail oder Facebook oder Twitter oder anderen ACTION_SEND-fähigen Anwendungen sie installiert haben.

Sie könnenwählen, um eine Chooser zwingen anzuzeigen, unabhängig davon, ob der Benutzer eine Standard-Aktivität oder nicht gesetzt hat. Um dies zu tun, anstelle des AufrufsstartActivity ()aufdasAbsichtdirekt, Sie wickelndasAbsichtin einem anderenAbsichtkehrte nachdascreateChooser ()statische Methode aufAbsichtselbst:

(von

Intents / FauxSender / app / src / main / java / com / commonsware /
android / fsender / FauxSenderTest.java)

Der zweite ParametercreateChooser () ist eine Meldung oben im Dialogfeld angezeigt werden soll:

Beachtendas Fehlen der "Always" Taste - müssen nicht nur eine Wahl zu treffen der Benutzer jetzt, aber auch sie können nicht die erste Wahl für die Zukunft, entweder machen.

Direkter Anteil Ziele

Auf Android6.0 ist es möglich, für eine App nicht nur eine Tätigkeit in der Auswahl erscheinen zu lassen, sondern auch "direkte Anteilsziele" zur Verfügung zu stellen. Diese Elemente in der Auswahl werden von der App lieferte eine ACTION_SEND Implementierung anbieten, sondern als eine einfache Tätigkeit darstellt, können sie auch zusätzliche Daten in den Extras Bundle in der Absicht verwendet, um diese Tätigkeit beginnen. Die Idee ist, dass die App ein paar Symbole bieten könnte Sharing bis zu einem gewissen fi zu ermöglichen

-grained Ziel, wie zum Beispiel einen
bestimmten Kontakt oder einen bestimmten Ordner oder so etwas.

Direkter Anteil Ziele werden abgedecktspäter imdieses Buch.

ShareActionProvider

Oben sahen wir, wie Sie bringen könnenein Chooser bei der Verwendung vonstartActivity ()auf einer implizitenAbsichtAktion, wie beispielsweiseACTION_SEND.

Es gibt einen anderenOption, wenn Sie die Aktionsleiste verwenden:ShareActionProvider.

Konzipiert für den Einsatz mitACTION_SEND.ShareActionProviderVorräteein Drop-Down-Menü in der Aktionsleiste der Benutzer zu lassen einige Implementierung eines
aufrufenAbsichtdass Sie konfigurieren und Versorgung.

Um zu sehen, wie Sie hinzufügen können,einShareActionProviderauf Ihre Aktivität oder ein Fragment, lassen Sie unsein Blick auf dieActionBar / ShareNativeBeispielprojekt.

Unsere Tätigkeit-Hauptaktivität- Wird die Aktionsleiste nutzen. Die Aktionsleiste Elemente sind in einem enthalten sindres / menu / actions.xmlfi

(von

ActionBar / ShareNative / app / src / main /
res / menu / actions.xml)

Zusätzlich zueine ID und angibt, die Angabe, dass die Ware in der Aktionsleiste angezeigt, wenn es Raum, sind wir auch die Android-Version: actionProviderClass Attribut. Dies deutet auf eine konkrete Umsetzung des ActionProvider abstrakt

Basisklasse, die für Rendering verantwortlich istIn der Aktionsleiste Element. In unserem Fall verwenden wir ShareActionProvider.

Unsere Tätigkeit UI ist einfachein großes EditText widget:

(from

ActionBar / ShareNative / app / src / main / res

/ Layout / activity_main.xml)

Wir ladendass das Layout inonCreate ()vonHauptaktivitätSowie ein mit der Initialisierung Absichtverwendet werden, wenn wir beschäftigendasShareActionProvider:

(von

ActionBar / ShareNative / app / src / main / java / com /
commonsware / android / sap / MainActivity.java)

Wir auch registrierendie Tätigkeit selbst ein TextWatcher, zu fi sein
aus wann der Benutzer
etwas in das EditText Widget.

onCreateOptionsMenu ()ist, wo wir konfigurierendasShareActionProvider, Die so erhalten wir durch den AufruffindItem ()auf unseremMenübekommenDer Artikel mit dem Anbieter verbunden sind, dann rufengetActionProvider ()aufdie mitgelieferteMenuItem. Speziell:

• Wir liefern einAbsicht- Konfiguriert mit der Aktion, MIME-Typ, usw., die wir aufrufen wollen - zusetShareIntent ()

• Wir liefernHauptaktivitätselbst als

ImplementierungOnShareTargetSelectedListenerübersetOnShareTargetSelectedListener ()

ImdasafterTextChanged ()Methodeindem die benötigtenTextWatcherSchnittstelle, wir aktualisierendasEXTRA_TEXTExtra indasAbsichtseinDie aktuellen Inhalte derText bearbeiten. Auf diese Weise, während der Benutzer tippt, halten wir dieAbsicht"Frisch" in Bezug auf das, was gemeinsam genutzt werden soll. Viele Verbraucher voneinShareActionProviderhaben weniger dynamischen Inhalten, in welchem Fall Sie gerade eingestellt haben können bisdasAbsichtvorne, bevor Sie registrieren es mitdasShareActionProvider.

Obder Benutzer wählt ein Element aus derShareActionProviderWerden wir über einen Anruf informiert zu unseremonShareTargetSelected ()Methode. Registrierung
alsdasOnShareTargetSelectedListenerist optional- Android wird automatisch die gewählte Aktion ohne unsere Beteiligung starten.onShareTargetSelected ()wenn Sie ist es wissen wollen,die Mittel teilen, dass der Benutzer wählen. In unserem Fall haben wir nur fl
einToastum
anzuzeigendass der Rückruf gearbeitet.

Praxis-Safe-Inhalt Auflösung

HINWEIS:Folgendes basiert aufein Blog-Beitrag des Autors.

Dominik Schürmann und Lars Wolf, in einer ausgezeichnetenBlogeintragundPre-pub Papier, Weist darauf hin,eine Sicherheitslücke in vielen Aktivitäten, die eine ACTION_SEND haben

<Intent-Filter>.

VieleACTION_SEND Implementierungen akzeptieren EXTRA_STREAM als Eingabe. Das soll zu Uri repräsentiert einen Strom von Sachen zu zeigen irgendwo gesendet werden. E-Mail-Anwendungen könnte es als eine Anlage, zum Beispiel zu senden. Also, Sie fi nden eine ContentResolver e up, rufen openInputStream () auf den Inhalt von diesem Uri gesichert zu bekommen (weildas ist, wie echte Entwickler es tun), unddann tun Sie etwas mit diesem Inhalt. Sie könnten nicht einmal wirklich, was der Inhalt ist ... bis dass der Inhalt etwas von Ihrer eigenen App ist. Wie, sagen, Ihr Benutzerkonto-Datenbank.

Das Problem bei der Herr Schürmann Post und Papier skizziert istUri zu Ihrer eigenen: dass eine böswillige Partei könnten Sie mit einer Datei zur Verfügung stellen interne Speicher. Währenddie von Drittanbietern App kann nicht Ihre internen Speicher zugreifen, können Sie. Also, im Falle einer E-Mail-App, fragt der Angreifer Sie einen Ihrer App eigenen fi per E-Mail
nachdie E-Mail-

Adresse des Angreifers. Der Benutzer kann in dieser (zB mit tatsächlich etwas klicken zu senden, um die E-Mail) beteiligt sein, aber mitein bisschen von Phishing oder Social EngineeringKann das Problem, zumindest einen Teil der Zeit behandelt werden. Immerhin, mit freundlicher Genehmigung von der Absicht: Schema, einige Web-Browser und dergleichen wird ein einfacher Link klicken, um auslösen den bösen ACTION_SEND Anfrage ermöglichen.

Um dabei zu helfen, cketti (von K-9 Mail Ruhm) schriebein SafeContentResolverdas hat seine eigeneopenInputStream ()Methode. Aber,diese wird fehlschlagen, wenn dieUriverweist aufeine fi
dass Ihre App besitzt oder einInhalt Anbietervon Ihrer App. Wenn du benutztdies statt deropenInputStream ()aufContentResolver, IhreACTION_SENDImplementierung werden sicherer ausdieser Angriff.

wenn Sie von außen eingegeben Parteien Allgemeiner akzeptieren, zu validieren. Haben Sie Regeln für welche Arten vonUri Werte, die Sie und wird für Dinge wie EXTRA_STREAM nicht akzeptieren, und Laufzeitprüfungen bieten zu Konfi
dass die Werte erhalten Sie die Regeln
befolgen.

Broadcasts und Broadcast-Receiver

Ein KanalDie Absicht Message-Bus wird verwendet, Aktivitäten zu starten. Ein zweiter Kanal des Intent Message-Bus wird verwendet, Broadcasts zu senden. Wie der Name schon sagt, ist eine Broadcast-Intent ein, dass - in der Standardeinstellung - ist auf dem Gerät zu irgendwelchen und alle Anwendungen veröffentlicht, die in stimmen wollen.

Versendungeinfache Broadcast

Der einfachste Weg zu schickeneine BroadcastAbsichtist zu schaffendasAbsichtSie wollen,dann rufensendBroadcast ().

Das ist es.

Beimdieser Punkt wird Android durch alles scannen, tune in einer Sendung für Ihre Absicht eingerichtet, in der Regel fi Ering nur auf die Aktion String. Jeder eingerichtet, um diese Sendung zu erhalten, in der Tat, es zu erhalten, eine BroadcastReceiver verwenden.

Empfangein Broadcast: In einer Aktivität

Für den Empfang solchereine Sendung in einer Aktivität (oder ein Fragment), müssen Sie vier Dinge zu tun.

Als erstes müssen Siebrauchen eine Instanz Ihrer eigenen Unterklasse von BroadcastReceiver zu erstellen. Die einzige Methode, die Sie brauchen, um (oder sollte) implementieren ist OnReceive

(), die die Absicht übergeben wird, die ausgestrahlt wurde, zusammen mit einem Context-Objekt, das in diesem Fall, Sie werden in der Regel ignorieren.

Zweitens werden Sie brauchen eine Instanz eines IntentFilter-Objekt zu erstellen, beschreibt die Arten von Sendungen Sie erhalten möchten. Die meisten dieser gatoren eingerichtet sind für eine einzige Sendung Intent Aktion zu sehen, in welchem Fall der einfachen Konstruktor genügt: Drittens werden Sieanrufen müssenregisterReceiver (), Typischerweise vonauf

Wiederaufnahme()Ihrer Tätigkeit oder ein Fragment, liefert IhreRundfunkempfängerund deinIntentFilter.

Viertens werden Sieanrufen müssenunregisterReceiver (), Typischerweise vononPause ()Ihrer Tätigkeit oder ein Fragment, Versorgungdas GleicheRundfunkempfängerInstanz, die Sie zur Verfügung gestellt zuregisterReceiver ().

Zwischendie Anrufe anregisterReceiver ()undunregisterReceiver (), Erhalten Sie alle Sendungen die passendeIntentFilter.

Der größte Nachteil andieser Ansatz ist, dass einige Aktivität um den Empfänger zu registrieren hat. Manchmal wollen Sie Sendungen zu empfangen, auch wenn keine Aktivität dort herum ist.

Um das zu tun, müssen Sie eine andere Technik verwenden: den Empfänger im Manifest Registrierung.

Empfangein Broadcast: Über das Manifest

Sie können auch Android über Sendungen erzählen Sie erhalten möchten durch Hinzufügenein

<Empfänger>Element zu Ihrem Manifest, die Klasse zu identifizieren, die Ihre implementiertRundfunkempfänger(überdasandroid: nameAttribut), plus eine<Intent-Filter>das beschreibt die Sendung (en), die Sie erhalten möchten:

Das guteNachricht ist, dass diese BroadcastReceiver für Sendungen verfügbar sein wird, jederzeit auftreten. Es gibt keine Annahme, dass Sie eine Aktivität haben bereits entschieden, dass genannt registerReceiver läuft ().

Das SchlechteNachricht ist, dass die Instanz der BroadcastReceiver von Android verwendet, um eine Sendung zu verarbeiten wird nur so lange leben, wie es dauert, die OnReceive () -Methode auszuführen. An diesem Punkt wird die BroadcastReceiver verworfen. Daher ist es nicht sicher für eine manifest registriert BroadcastReceiver, alles zu tun, die nach OnReceive ausgeführt werden muss () selbst abgeschlossen ist, wie ein Gewinde gabeln. Immerhin kann Android gut
beendender Prozess innerhalb von Millisekunden, wenn es keine andere in den Prozess laufende Komponente.

Schlechternews: - der gleichen Hauptanwendungsthread, die die Benutzeroberfläche aller Ihrer Aktivitäten Griffe OnReceive () auf der Hauptanwendung Thread aufgerufen. Und, sind Sie unterliegen den gleichen Einschränkungen wie Ihre Aktivität Lifecycle-Methoden und alles, was genannt auf der Hauptanwendungsthread sind:

• Irgendeinverbrachte Zeit in OnReceive () friert die Benutzeroberfläche, wenn Sie eine Vordergrund-Aktivität passieren zu haben

• Wenn Sie verbringen zu lange inOnReceive (), wird Android beenden Ihre

Rundfunkempfängerohne zu warten,OnReceive ()fertigstellen

Dies macht mitein manifest registriertRundfunkempfängerein bisschen schwierig. Wenn die Arbeit getan werden, sehr schnell ist, implementieren es nur inOnReceive (). Andernfalls werden Sie wahrscheinlich benötigen, dies zu koppelnRundfunkempfängermiteine Komponente als ein bekannterIntentService, Die wir untersuchen,imdas nächste Kapitel.

Gestoppten Zustand

Auf Android 3.1 und höher, wenn Ihre Anwendung ist fi
installiert auf das Gerät ist es in
einem Zustand "Stopped". Das hat nichts mit OnStop () von jeder Aktivität zu tun. Während in dem gestoppten Zustand, Ihrem Manifest registrierten BroadcastReceivers werden alle Sendungen nicht empfangen.

Aussteigen vongestoppten Zustand

Aus etwas herauskommender gestoppten Zustand, etwas auf dem Gerät, wie zB eine andere app (die sich nicht in dem gestoppten Zustand ist), muss eine explizite Absicht verwenden eines Ihrer Komponenten aufzurufen.

Der gebräuchlichste Weg,dies geschieht, ist für den Benutzer auf einem Launcher-Symbol mit dem Launcher-Aktivität assoziiert zu erschließen. Unter den Abdeckungen wird die Trägerrakete Startbildschirm eine explizite Absicht erstellen, Ihre Aktivität zu identifizieren, und verwenden, die mit startActivity (). Dadurch wird man aus dem gestoppten Zustand.

Einstieg ingestoppten Zustand

Wie oben erwähnt, beginnen Sie ab inder gestoppten Zustand. Sobald Sie aus dem gestoppten Zustand bewegt werden, über die ausdrückliche Absicht, Sie, bis eines von zwei Dingen geschieht aus dem gestoppten Zustand bleiben:

1. Der Benutzer deinstalliert Ihre App

2. Der Benutzer "Kraft-stoppt" Ihre App

Letztere normalerweise auftritt, wennder Benutzer klickt auf die "Kraft Stop" Taste auf dem Bildschirm der App in den App Einstellungen (Settings> Apps). Es gibt einige Hinweise, dass
einige Gerätehersteller ihre eigenen Geräts Task-Manager gebunden haben eine "Kraft stop" zu tun, wenn der Benutzer eine Task entfernt - das war keine besonders kluge Wahl auf der betreffenden Hersteller.

Hinweisdass ein Neustart Sie nicht in den gestoppten Zustand zurückversetzen. Sie bleiben im Normalzustand durch einen Neustart.

Beispiel System-Broadcasts

Es gibt viele, viele Sendungen, die von Android selbst verschickt, wo Dutune in, wenn Sie fi sehen

Viele, abervon diesen nicht alle, sind auf der Intent Klasse dokumentiert. Die Werte in der "Konstanten" Tabelle, die "Broadcast Aktion" abgeht ihrer Beschreibung sind Aktion Strings für System Sendungen haben. Es gibt noch andere solche Sendung Aktionen rund um das SDK
verstreut, obwohl, also nicht davon ausgehen, dass sie alle auf Intent dokumentiert sind.

In den folgenden Abschnitten wird untersucht, zweidiese Sendungen, um zu sehen, wie die Rundfunkempfängerarbeitet in Aktion.

Beim Systemstart

Eine beliebte Anforderung ist, um Code get Kontrolle haben, wenn das Gerät eingeschaltet ist. Das ist machbar, aber etwas gefährlich, dass zu viele Anfragen auf starten Sie den Gerätestart verlangsamen und kann träge machen Dinge für den Anwender.

Sein, umbenachrichtigt, wenn das Gerät seine System-Boot-Vorgang abgeschlossen ist, müssen Sie die RECEIVE_BOOT_COMPLETED Erlaubnis zu beantragen. Ohne diese, auch wenn Sie die Boot-Broadcast Intent erhalten arrangieren, wird es nicht an Ihren Empfänger versendet werden.

Wiedie Android-Dokumentation beschreibt es:

obwohl Halteist diese Erlaubnis keine Auswirkungen auf die Sicherheit haben, kann es einen negativen Einfluss auf die User Experience haben durch die Höhe der Zeit zu erhöhen sie die System-Anwendungen zu starten und damit nimmt zu haben, selbst ohne dass der Benutzer ausgeführt wird bewusst von ihnen. Als solche müssen Sie explizit die Nutzung dieser Einrichtung erklären, dass für den Benutzer sichtbar zu machen.

Wir auchmüssen sich registrieren, unsereRundfunkempfängerimdas Manifest - durch die Zeit, würde eine Tätigkeit nennenregisterReceiver ()Wird sich die Boot längst aufgetreten.

Zum Beispiel, lassen Sie uns untersuchendasIntents / ONBOOTBeispielprojekt. In
unserem Manifest, bitten wirdie erforderliche Erlaubnis und registrieren unsere

RundfunkempfängerZusammen mit einer Aktivität:

(von

Intents / ONBOOT / app / src / main /

AndroidManifest.xml)

OnBootReceivereinfach protokollierteine Nachricht an LogCat:

(from

Intents / ONBOOT / app / src / main / java / com / commonsware /
android / sysevents / boot / OnBootReceiver.java)

Zu testendiese auf Android 3.0 und früher, einfach die Anwendung zu installieren und das Gerät neu starten - die Meldung in LogCat erscheinen sehen.

Doch auf Android 3.1 und höher,der Benutzer muss fi
manuellstarten eine gewisse Aktivität
vor einem offensichtlichen registriertBroadcastReceiver Objekte verwendet werden, wie oben erwähnt, inder Teil mit dem gestoppten Zustand abdeckt. Wenn Sie also waren nur installierendie Anwendung und starten Sie das Gerät, würde nichts passieren. Der kleine BootstrapActivity ist nur dort für den Benutzer zu starten, so dass die ACTION_BOOT_COMPLETED

BroadcastReceiver beginnt zu arbeiten.

Auf Batteriestatus Änderungen

EinsThema mit Systemereignisse, sie zu benutzen, um Ihre Benutzer glücklicher machen, indem Sie Ihre Auswirkungen auf das Gerät zu reduzieren, während das Gerät nicht in einem großen Staat ist. Die meisten Anwendungen werden durch die Batterielebensdauer beeinflusst.

Verbrauchte Batterien laufen keine Anwendungen. Daher kann die Batterieniveau zu wissen, für Ihre Anwendung wichtig sein.

Da ist einACTION_BATTERY_CHANGED Intent, die als die

Batteriestatusänderungenübertragen wird, sowohl in Bezug auf die Ladung (zB 80% geladen) und die Aufladung (zB wird das Gerät nun das Stromnetz angeschlossen). Sie müssen einfach registrieren diese Absicht zu empfangen, wenn es ausgestrahlt wird, entsprechende Schritte ergreifen.

Einer vondie BeschränkungenACTION_BATTERY_CHANGEDistdass Sie
verwendenregisterReceiver ()einrichteneinRundfunkempfängerbekommenDiesAbsichtwenn ausgestrahlt. Sie können nicht verwendenein Manifest deklarierten Empfänger. Es gibt separateACTION_BATTERY_LOWundACTION_BATTERY_OKSendungendass Sie von einem

Manifest registrierten Empfänger empfangen können, aber sie sind weit weniger häufig übertragen, nur dann, wenn die Akkuladung unter oder steigt über einige undokumentierte "low" Schwellenwert fällt.

DemonstrierenACTION_BATTERY_CHANGED, Werfen Sie einen Blick auf dieIntents / OnBattery Beispielprojekt.

Dort werden Sie fi
einres / Layout / batt.xmlRessource enthält,einFortschrittsanzeige, ein

Textview, und einImageAls Batteriemonitor zu dienen:

(von

Intents / OnBattery / app / src / main /
res / Layout / batt.xml)

Dieses Layout wird voneinBatteryFragment, Welche Register die erhalten

ACTION_BATTERY_CHANGED Intentimauf Wiederaufnahme()undhebt die Registrierung
inonPause ():

(von

Intents / OnBattery / app / src / main / java / com / commonsware /
android / battmon / BatteryFragment.java)

the-Taste zuACTION_BATTERY_CHANGEDichs in den "Extras". Viele Extras sind in der verpackteAbsicht, Den aktuellen Zustand der Batterie, beispielsweise die folgenden Konstanten beschreiben auf die definierteBatteryManagerKlasse:

• EXTRA_HEALTHsein, die im Allgemeinen sollteBATTERY_HEALTH_GOOD

• EXTRA_LEVEL, die der Anteil der Lebensdauer der Batterie ist als eine ganze Zahl bleibt, spezifi
aufdie Skala von der EXTRA_SCALE Wert beschrieben

• EXTRA_PLUGGED, Zeigt an, welche, wenn das Gerät an das Stromnetz
angeschlossen ist (BATTERY_PLUGGED_AC) Oder USB-Stromversorgung

(BATTERY_PLUGGED_USB)

• EXTRA_SCALE, die den maximal möglichen Wert der Pegel anzeigt (zB 100, das

Niveau anzeigt, ist ein Prozentsatz der verbleibenden Ladung)

• EXTRA_STATUS, Die Ihnen sagen, wenn der Akku geladen ist

(BATTERY_STATUS_CHARGING), Voll(BATTERY_STATUS_FULL) Oder

Entladen (BATTERY_STATUS_DISCHARGING)

• EXTRA_TECHNOLOGY, Die angibt, welche Art von Batterie installiert ist (zB

"Li-Ion")

• EXTRA_TEMPERATURE, die Ihnen sagt, wie warm die Batterie, in Zehntel Grad

Celsius (zB 213 beträgt 21,3 Grad Celsius)

• EXTRA_VOLTAGE, was anzeigt, die aktuelle Spannung von der Batterie geliefert wird, in Millivolt

Imder Fall vonBatteryFragmentWenn wir eine EmpfangsACTION_BATTERY_CHANGED

IntentWir drei Dinge tun:

1. Wir berechnender Prozentsatz der verbleibende Batterielebensdauer, indem der Pegel durch den Skalenteilung

2. Wir aktualisierendasFortschrittsanzeigeundTextviewanzuzeigendie Lebensdauer der Batterie als Prozentsatz

3. Wir zeigen ein Symbol, mitdas Symbol Auswahl je nachdem, ob wir aufladen (Status istBATTERY_STATUS_CHARGING), Voll, aber aufdas Ladegerät (Status
istBATTERY_STATUS_FULLund eingesteckt
istBATTERY_PLUGGED_ACoderBATTERY_PLUGGED_USB), oder sindnicht
eingesteckt

Wenn Sie steckendies in einem Gerät, wird es zeigen Ihnen den Ladezustand der Einrichtung: Sticky Broadcasts unddie Batterie

HINWEIS: Klebrige Sendungen in Android 5.0 sind veraltet, unddie Dokumentation deutet an, dass sie in der Zukunft ganz aufgegeben werden.

Android einen Begriff der "Dauerhaften Broadcast Intents". Normalerweise wird eine Broadcast-Intent an Interessenten und dann verworfen geliefert werden. Eine klebrige Broadcast Intent wird an Interessenten abgegeben und zurückgehalten, bis die nächste passende Intent ausgestrahlt wird.

Anwendungen können registerReceiver () mit einem IntentFilter nennen das

Streichhölzerdie klebrige Sendung, aber mitnull BroadcastReceiverUnd bekommen die klebrige AbsichtzurückEin Ergebnis derregisterReceiver ()Anruf.

Dies kann verwirrend klingen. Schauen wir uns anDies im Zusammenhang mit der Batterie.

ZuvorIn diesem Abschnitt haben Sie gesehen, wie für
registrierenACTION_BATTERY_CHANGEDum Informationen zu erhaltendie Batterie an Sie
geliefert. Sie können auch, obwohl, erhalten Sie die neueste Batterieinformationen ohne einen Empfänger zu registrieren. Erstellen Sie einfach
eineIntentFilterpassenACTION_BATTERY_CHANGED(Wie oben gezeigt) und

AnrufregisterReceiver ()mitdass fi er und einnull BroadcastReceiver. DasAbsichtSie wieder ausregisterReceiver ()istdas LetzteACTION_BATTERY_CHANGED Intentdass ausgestrahlt wurde, mit den gleichen Extras. Daher können Sie diese verwenden, um die aktuellen (oder in der Nähe von Strom) Batteriestatus zu erhalten, anstatt eine tatsächliche kümmern zu müssen

RegistrierungRundfunkempfänger.

Aus diesem Grunddie Beispielanwendung zeigt die Ergebnisse sofort - es war die letzt Broadcast-Ausgabe des GegebenenACTION_BATTERY_CHANGEDübertragen, sobald wir
genanntregisterReceiver ().

Batterie undder Emulator

Ihr Emulator tutnicht wirklich eine Batterie haben. Wenn Sie diese Beispielanwendung auf einem Emulator laufen, sehen Sie in der Standardeinstellung, dass das Gerät 50% gefälschte Ladung bleiben und dass es geladen wird. Jedoch ist es unendlich langsam geladen, da es nicht über 50% steigen wird

... zumindest nicht ohne Hilfe.

HINWEIS: Beimdie Zeit des Schreibens dieses Artikels, wird die Linux-Emulator nicht richtig die Batterie für AVDS emulieren von bestimmten Geräte Profi erstellt

(ZB Nexus S), zeigt 0% der

Akkuladung undnicht reagiert unten beschrieben auf die Telnet-Befehle. Wie wird festgestellt, indieses ProblemWenn Sie dies auftritt, gehen indie config.ini fi
fürIhre AVD (gefunden in~ /

.android / AVD /.../, wo ~ / ist Ihr Home-Verzeichnis und ... ist der Name des AVD) und fügen Sie hw.battery = yes als Eigenschaft. Wenn das Objekt vorhanden ist, aber auf keine festgelegt ist,ändern Sie ihn auf ja.

Währendder Emulator nur fi zierten Batterieeigenschaften zeigen, können Sie ändern, was diese Werte sind, durch die hochentwickelte Benutzeroberfläche als Telnet bekannt.

Sie haben vielleicht bemerktdass Ihr Emulator Titelleiste des Namens Ihres AVD besteht und einer Zahl, häufig 5554. Diese Zahl ist nicht nur einige der beliebtesten Nummer des Ingenieurs. Es ist auch ein offener Port, auf dem Emulator, zu dem Sie in Telnet kann, auf localhost (127.0.0.1) auf Ihrer Entwicklungsmaschine.

Es gibt viele Befehle, die Sie ausgeben könnender Emulator durch Telnet. Um den Ladezustand der Batterie zu ändern, verwenden Energiekapazität NN, NN steht der Prozentsatz der Lebensdauer der Batterie ist noch, dass Sie den Emulator zurückkehren wollen. Wenn Sie das tun, während Sie ein ACTION_BATTERY_CHANGED BroadcastReceiver registriert haben, wird der Empfänger eine Broadcast-Intent erhalten Sie über die Änderung informiert.

Sie können auch mit einigen experimentierendie anderen Strom Subbefehle (zB Netz oder Netz aus), oder andere Befehle (zB geo, simulierte GPS fi es zu senden, wie Sie es von DDMS tun können).

Batterie-Daten auf Android 5.0+

Wie bereits erwähnt, Android 5.0 deprecates dauerhafte Broadcasts. Dasbestehenden Sendungen arbeiten immer noch, obwohl. Und selbst wenn eines Tages Android ganz von klebrigen Sendungen entledigt, sendet wie ACTION_BATTERY_CHANGED höchstwahrscheinlich immer noch
funktionieren wird, wenn auch nur als eine regelmäßige Sendung.

Um aktuelle Informationen zur Batterie auf Android 5.0 erhalten und höher,BatteryManagerbietet angetIntProperty ()undgetLongProperty (), Wo die Schlüssel für die "Eigenschaften"

sindBATTERY_PROPERTY_ *Konstanten definiert aufBatteryManager,
sowieBATTERY_PROPERTY_CAPACITYbestimmender Prozentsatz der Batteriekapazität zu
bleiben.

Die Ordnung der Dinge

Eine weitere Variationdie Sendung Intent ist die bestellte Sendung. Normalerweise, wenn Sie eine Intent ausgestrahlt, und es gibt 10 registrierte

BroadcastReceivers, die diese Absicht entsprechen, alle 10 die Sendung, in unbestimmter Reihenfolge und möglicherweise auch parallel (insbesondere auf Multi-Core-Geräte) erhalten.

Mit einer geordneten Sendung,das Verhalten verschiebt ein wenig:

• EinzigerRundfunkempfängerbeimes wird eine Zeit der Sendung erhalten

• Die Reihenfolge, in derdie BroadcastReceivers erhalten die Sendung (etwas)

gesteuert von ihren Entwicklern ist

• Ein BroadcastReceiver "aussteigen" kann die Sendung, verhindern, dass andere Empfänger in der Kette vom Erhalt

Senden eine geordnete Übertragung bloßeine Frage der Aufruf
sendOrderedBroadcast ().

Empfangen einer geordneten Sendung, in seinem Kern ist identisch mit Empfangseine regelmäßige Sendung: Sie schreiben einRundfunkempfängerund registrieren sieüberdas Manifest
oderregisterReceiver (). Sie haben jedoch zwei zusätzliche Optionen bei der Registrierung, dassRundfunkempfänger.

Erstens können Siegeben Sie eine Priorität, entweder über setPriority () auf dem IntentFilter oder Android: Priorität auf dem <Intent-Filter> Element. Die Priorität ist eine positive ganze Zahl ist, mit höheren Nummern anzeigt, höhere Priorität. Höhere Priorität Empfänger wird die Sendung früher als mit niedrigerer Priorität Empfänger erhalten.

Zweitens, IhreRundfunkempfängerkann anrufenabortBroadcast ()KonsumierenDie Veranstaltung, die alle mit niedrigerer Priorität Empfänger von selbst zu sehen, die Sendung zu verhindern.

Keeping It Lokale

Eine Broadcast-Intent, die standardmäßig und fast per Definition ausgestrahlt wird. Alles, was auf dem Gerät könnte einen Empfänger "abgestimmt" haben für diese Sendungen zu hören. Während Sie setPackage () auf Intent verwenden können, um die Verteilung zu beschränken, geht die Sendung noch über die Standard-Broadcast-Mechanismus, der die Absicht zu einem OS-Prozess beinhaltet

die Übertragung, die dann die eigentliche Ausstrahlung tut. Daher hat eine Broadcast-Intent einigen Aufwand.

Dennoch gibt esZeiten bei der Verwendung von Sendungen innerhalb einer App ist praktisch, aber es wäre schön, den Aufwand zu vermeiden. Damit hinzugefügt mit diesem Kern Android-Team LocalBroadcastManager zum Android-Support-Paket, ein in-Verfahren bereitzustellen Weg von Sendungen mit dem Standard-Intent tun, IntentFilter und BroadcastReceiver Klassen, aber mit weniger Aufwand.

LocalBroadcastManagerwird von beiden geliefertendasandroid-support-v4.jarundandroid-support-v13.jarBibliotheken. Generell, wenn Ihrandroid: minSdkVersionist wenigerals 13 ist, sollten Sie wahrscheinlich wählen
android-support-v4.jar.

Der einzige wirkliche Unterschied auseine Codierung Standpunkt, bei der

VerwendungLocalBroadcastManageristdass Sie anrufenregisterReceiver ().unregisterReceiver (), undsendBroadcast ()auf einer Instanz vonLocalBroadcastManagerStatt auf einer InstanzKontext. Sie bekommendasLocalBroadcastManagerSingletons für Ihren Prozessübereine statische
getInstance ()Verfahren aufLocalBroadcastManagerselbst.

Wir werden sehenLocalBroadcastManagerim Einsatz in einem derdie Proben inDie Dienste Kapitel.

Besuchdie Spuren!

Wir untersuchenLocalBroadcastManagergenauer, zusammen mit anderen Eventbus

Alternativen,später imdas Buch.

Tutorial # 15- Gemeinsame Nutzung Ihre Notizen

Vielleicht möchten Sie Ihre Notizen wie aus App unseres Book-Reader zu bekommen und in irgendwosonst, oder vielleicht würden Sie sie mit jemandem zu teilen, sonst mögen. So oder so, können wir tun, dass ein ACTION_SEND Betrieb verwenden, dem Benutzer zu ermöglichen zu entscheiden, wie zu "senden", um die Noten, wie sie per E-Mail zu senden oder sie zu einem gewissen Dritt Note Service hochladen.

Um sicherzustellen,Diese Arbeit wird fügen wir einShareActionProviderzu unserem Aktionsleiste aufdas NoteFragment.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Hinzufügenein ShareActionProvider

Als erstes werden wirmüssen, damit der Benutzer, um anzuzeigen, dass sie die Notiz in der aktuellen NoteFragment angezeigt zu "teilen" wollen. Indem eine Aktionsleiste Element auf die Aktivität in dem die NoteFragment angezeigt wird, brauchen wir nicht über das Lassen der Benutzer wählen, sich Sorgen zu machen, welche Note zu schicken - wir schicken Sie einfach je nachdem, was beachten sie passieren anzeigen oder bearbeiten werden.

Durch die Nutzungein ShareActionProvider, wird das Aktionselement die meiste Arbeit handhaben für so dass der Benutzer in dem zu wählen, die Notiz zu senden. Wir brauchen nur eine Absicht zu schaffen, das identifiziert, was gemeinsam genutzt werden soll.

Ändernres / menu / notes.xmlhinzuzufügen, indas neueAktieSchaltfläche in der Symbolleiste: (von

EmPubLite-Android Studio / T15-Share / EmPubLite / app /
src / main / res / menu / notes.xml)

Hinweisdass dieses Menü Definition erfordert eine neue String-Ressource namens Aktie mit einem Wert wie Teilen.

Schritt 2: Teilendie Notiz

Jetzt wirmüssen die ShareActionProvider zu konfigurieren, insbesondere mit einem ständig aktualisierten Intent liefert, basierend auf dem, was der Benutzer in die EditText getippt hat.

HinzufügeneinShareActionProviderDaten MitgliedNoteFragment, genanntAktieZusammen mit einemAbsichtDatenelementgenanntshareIntentkonfiguriert verwendenACTION_SENDvonein MIME-Typtext / plain:

(von

EmPubLite-Android Studio / T15-Share / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Dann inonCreateView (), Sagen dieText bearbeitenlassen Sie uns wissen, wennDer Benutzerändert den Text, dieüberaddTextChangedListener ():

(von

EmPubLite-Android Studio / T15-Share / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Dies
wird
nicht
kompiliert,
da
unsereNoteFragmentistnicht
die

Umsetzung
derTextWatcherSchnittstelle.

Damit,ändern
dieNoteFragmentKlassendeklaration
enthaltendasTextWatcherSchnittstelle:

(von

EmPubLite-Android Studio / T15-Share / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Das, indrehen, wird von uns verlangen drei Methoden zu implementieren:

1. afterTextChanged ()

2. beforeTextChanged ()

3. OnTextChanged ()

In unserem Fall kümmern wir uns umafterTextChanged (). So fügen Sie die folgenden drei MethodenNoteFragment:

(von

EmPubLite-Android Studio / T15-Share / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Hier aktualisieren wirdie shareIntent mit der neuesten Text geteilt werden, ist es in EXTRA_TEXT, gemäß den Anweisungen in der Android-Entwickler-Dokumentation für die Arbeit mit ACTION_SEND speichern.

Allerdings haben wirnicht initialisiertAktienoch. Wir können tun,dass inonCreateOptionsMenu ()Und fügte hinzu, um einen Anruf zufindItem ()zu fi
unser R.id.shareMenüpunkt,dann
ruftgetActionProvider ()bekommendasShareActionProviderausder Menüpunkt:

(von

EmPubLite-Android Studio / T15-Share / EmPubLite / app / src / main / java / com /
commonsware / empublite / NoteFragment.java)

Hier haben wir auch anhängendasshareIntentnachdasShareActionProvider, So dass, wenn es darum geht, Zeit, um den Text zu teilen, dieShareActionProviderweiß, wie zu tundass.

Schritt 3: Testendas Ergebnis

Wenn Sie laufendiese auf einem Gerät und navigieren Sie zu einem fi

Hinweis, du
wirst sehen die neue Aktionsleiste Artikel:

Wenn duTippen Sie darauf erhalten Sie eine Liste von Möglichkeiten, erhalten Sie den Text zu teilen:

Die genauen Optionen, die Sie sehen wollenvariieren je nach Gerät oder Emulator, und welche Anwendungen darauf installiert sind, die wissen, wie Klartext zu teilen. Wenn Sie nur eine Wahl haben (zB Messenger), wird es neben der Freigabe-Symbol angezeigt wird, und Sie werden nur auf, dass eine Wahl zu tippen können.

Leider kann Ihr Emulatornichts, was diese Absicht umgehen kann. Wenn das der Fall ist, werden Sie mit einem ActivityNotFoundException abstürzen. Um diese Vergangenheit, wenn Sie
eingebenhttp://goo.gl/w113ein Ihrem Emulator im Browser,dass sollte Ihnen ermöglichen, eine Kopie der APK von der zum Herunterladen und InstallierenIntents / FauxSenderBeispielprojektdass wir bedecktfrüherdieses Buch. Wannder Download abgeschlossen ist (was sehr schnell sein sollte), öffnen Sie die Meldung Schublade und tippen Sie auf den "Download abgeschlossen" Meldung. Dies sollte mit der Installation beginnen. Je nach Ihrer Android-Version, müssen Sie möglicherweise auch auf

"Installation von Nicht-Market-Anwendungen zulassen"

— nach fi

Dies, Sie verwenden können, die Downloads-App auf dem Emulator zu versuchen

Sie es erneut die APK installieren. Sobald FauxSender installiert ist, wird es auf Ihre Versuche reagieren, um eine Notiz zu teilen.

In unserer nächsten Folge ...

... Wir werden dem Benutzer erlauben,aktualisierenden Inhalt des Bucheszu Endedas Internet.

Dienstleistungen unddas Command-Muster

Wie bereits erwähnt, sind Android Dienste für lang laufende Prozessedas kann am Laufen zu halten brauchen, auch wenn von jeder Aktivität entkoppelt. Beispiele dafür sind der Wiedergabe von

Musik, auch wenn die "Spieler" Aktivität zerstört wird, zur Abfrage des Internet für RSS / Atom-Feed-Updates und einen Online-Chat-Verbindung aufrechterhalten, auch wenn der Chat-Client aufgrund eines eingehenden Telefonanruf den Fokus verliert.

Services erstellt werden, wenn manuell gestartet (über einen API-Aufruf), oder wenn eine gewisse Aktivitätversucht, den Dienst über Interprozesskommunikation (IPC) verbindet. Services wird leben, bis sie explizit heruntergefahren oder bis Android ist verzweifelt für RAM und beendet den Prozess. Laufen für eine lange Zeit hat seine Kosten, obwohl, so dass Dienstleistungen müssen vorsichtig sein, nicht zu viel CPU zu verwenden oder Radios halten aktiv zu viel von der Zeit, damit der Dienst des Geräts Batterie führen schnell zu verbraucht zu werden.

In diesem Kapitel werdendie grundlegende Theorie hinter der Erstellung und raubend Dienstleistungen, darunter ein Blick auf die "Befehlsmuster" für Dienstleistungen.

Warum Services?

Dienstleistungen sindein "Schweizer Taschenmesser" für eine breite Palette von Funktionen, die wie keinen direkten Zugriff auf eine Aktivität der Benutzeroberfläche erfordert: 1. Ausführen von Funktionendass müssen weiterhin selbst wenn der Benutzer die

Aktivitäten der Anwendung lässt, wie ein langer Download (wie mit dem Play Store zu sehen) oder Musik zu spielen (wie bei Android Musik-Apps zu sehen)

2. Ausführen von Funktionendass Bedarf bestehen, unabhängig von Aktivitäten kommen und gehen, wie eine Chat-Verbindung zur Unterstützung einer Chat-Anwendung
beibehalten

3. Bereitstellung eine lokale API Remote-APIs, wie vielleicht von einem Web-Service zur Verfügung gestellt werden

4. Durchführen von periodischen Arbeiten ohne Benutzereingriff, ähnlich wie

Arbeitsplätze oder Windows cron geplantAufgaben

SogarDinge wie App Startbildschirm Widgets beinhalten oft einen Dienst mit Langlauf Arbeit zu unterstützen.

Die primäre Rolle vonein Dienst ist als fl
nach das Betriebssystem, lässt sie wissen, dass Ihr

Prozess immer noch Arbeit zu tun, trotz der Tatsache, dass es im Hintergrund ist. Das macht es etwas weniger wahrscheinlich, dass Android Ihr Prozess wegen niedrigen Speicherbedingungen beendet.

Viele Anwendungen werdenbrauchen keine Dienste. Nur sehr wenige Anwendungen werden mehr als eine brauchen. Allerdings ist der Service ein leistungsfähiges Instrument für eine Toolbox Android-Entwickler und ist ein Thema, mit dem jede qualifizierte Android-Entwickler vertraut sein sollte.

EinrichtenEin Dienst

Erstelleneine Service-Implementierung teilt viele Eigenschaften mit einer Aktivität zu bauen. Sie erben von einem Android-gelieferten Basisklasse, einige Lifecycle-Methoden außer Kraft setzen und den Service in das System über den offensichtlichen Haken.

Der Service Klasse

So wie eine Tätigkeit in Ihrer Anwendung erstrecktentweder Aktivität oder ein Android- gelieferten Aktivität Unterklasse erstreckt sich ein Service in Ihrer Anwendung entweder Dienst oder ein Android-supplied Serviceunterklasse. Die häufigste Serviceunterklasse ist IntentService, in erster Linie für den Befehl Muster verwendet wird, beschriebenspäter imDies Kapitel. Davon abgesehen, einfach viele Dienste erweiternBedienung.

LebenszyklusMethoden

So wie AktivitätenhabenonCreate ().auf Wiederaufnahme().onPause ()und Verwandten, Bedienung Implementierungenihre eigenen Lebenszyklus Methoden, wie zum Beispiel:

• onCreate (), die, wie bei Aktivitäten, wird aufgerufen, wenn der Dienst erstellt wird, mit allen Mitteln

• onStartCommand (), Die jedes Mal aufgerufen wird, der Dienst einen Befehlüber
gesendet wirdDienst starten()

• onBind (), die aufgerufen wird, wenn ein Client zum Dienst bindet via
bindService ()

• onDestroy (), die aufgerufen wird, wenn der Dienst nach unten wird geschlossen ist Wie bei den Aktivitäten, initialisieren Dienstleistungen, was auch immersie müssen in onCreate () und die Elemente in onDestroy aufzuräumen (). Und wie bei Aktivitäten, die onDestroy () -Methode eines Dienstes kann nicht aufgerufen werden, wenn Android den gesamten Bewerbungsprozess, wie für den Notfall RAM Rekultivierung beendet.

DasonStartCommand () und onBind () Lifecycle Methoden der Kommunikation an den Client auf der Grundlage Ihrer Wahl durchgeführt werden, wie erläutert werden wirdspäter imDies Kapitel.

Hinweis dassBedienungist einabstraktKlasse undonBind ()ist einabstraktVerfahren, so dass selbst wenn Sie sindnicht mitbindService (), Müssen Sie implementierenonBind ()um erfolgreich zu kompilieren.Ein gemeinsamer Ansatz ist hier zu habenonBind ()einfach zurückgebenNull.

Manifest Eintrag

Schließlich Siemüssen den Dienst Ihres AndroidManifest.xml fi hinzufügen
füres werden
als verfügbare Service für den Einsatz anerkannt. Das ist einfacheine Angelegenheit eine der Zugabe

<Service>Element als Kind von derAnwendungElement, Bereitstellenandroid: name Ihre Serviceklasse zu verweisen.

Schon seitdie Service-Klasse ist in der gleichen Java Namespace als alles andere in dieser Anwendung haben wir die Kurzschreibweise verwenden können (zB "PlayerService") unserer Klasse zu verweisen.

Zum Beispiel, hier istein Manifest mit der <service> -Element zeigt:

(von

Service / FakePlayer / app / src / main /

AndroidManifest.xml)

Die Kommunikation zu Dienstleistungen

Die Kunden von Dienstleistungen- Häufig Aktivitäten, wenn auch nicht notwendigerweise - haben zwei Möglichkeiten, Anfragen oder Informationen zu einem Dienst zu senden. Ein Ansatz ist es, einen Befehl zu senden, die auf den Dienst keine dauerhafte Verbindung schafft. Der andere Ansatz besteht darin, auf den Dienst zu binden, um einen Kommunikationskanal, der zur Festlegung solange der Kunde braucht es dauert.

Senden von Befehlen mit den Start ()

Der einfachste Weg, mit dem Sie arbeitenist ein Service anrufenDienst starten(). DasDienst starten()Verfahren nimmt einAbsichtParameter, so wiestartActivity ()tut.

Eigentlich,dasAbsichtzuzuführendenDienst starten()hatdie gleiche zweiteilige Rolle wie sie mitstartActivity ():

1. Identifizierender Dienst zur Kommunikation mit

2. Versorgungsparameter,die Form der Intent Extras, um den Dienst zu sagen, was es tun soll

Fürein lokaler Dienst - im Mittelpunkt dieses Kapitels - die einfachste Form derAbsichtist eindass identifiziert die Klasse, die implementiertBedienung(z.B,neuIntent (this, MyService.class);).

Der AufrufStartservice () ist asynchron, so wird der Kunde nicht blockieren. Der Dienst wird erstellt, wenn es nicht bereits ausgeführt wird, und es wird die Intentüber einen Aufruf der onStartCommand () Lifecycle-Methode erhalten. Der Service kann alles tun, was es braucht, um in onStartCommand (), aber da onStartCommand () auf der Hauptanwendung Thread aufgerufen wird, sollte er seine Arbeit sehr schnell tun. Alles, was mehr als eine Handvoll von Millisekunden dauern könnten, sollten zu einem Hintergrund-Thread delegiert werden.

DasonStartCommand () -Methode kann eine von mehreren Werten zurückkehren, vor allem, um anzuzeigen, zu Android, was passieren soll, wenn der Prozess des Service sollte getötet werden, während es ausgeführt wird. Die wahrscheinlichsten Rückgabewerte sind:

1. START_STICKYDies bedeutet, dass der Dienst wieder in den gestarteten Zustand
bewegt werden (als obonStartCommand ()war genannt worden), aber tunnicht wieder
liefern dieAbsichtnachonStartCommand ()

2. START_REDELIVER_INTENTDies bedeutet, dass der Dienstüber einen Aufruf
gestartet werdenonStartCommand ()Und liefert die gleicheAbsichtwie geliefert
wurdediesmal

3. START_NOT_STICKY, was bedeutet, dass der Dienst, bis sie explizit von

Anwendungscode gestartet gestoppt bleiben

Standardmäßig ruftStartservice () sendet nicht nur den Befehl, sondern erzählt Android den Dienst am Laufen zu halten, bis er etwas sagt zu stoppen. Eine Möglichkeit, einen Dienst zu beenden ist Stopservice () zu nennen, die gleiche Absicht mit Startservice verwendet Versorgung () oder zumindest eine, dieäquivalent ist (zB identifiziert die gleiche Klasse). An diesem Punkt wird der Dienst zu beenden und werden vernichtet. Beachten Sie, dass Stopservice () verwendet nicht jede Art von Referenzzählung, also drei Anrufe an den Start () wird in einem einzigen Dienst ausgeführt wird zur Folge haben, die durch einen Aufruf von Stopservice () gestoppt.

Eine andere Möglichkeit zum Anhaltenein Dienst ist, den Service-Aufruf stopSelf () auf sich selbst zu haben. Sie könnten dies tun, wenn Sie den Start () verwenden, um einen Dienst zu haben, beginnen laufen und einige Arbeit auf einem Hintergrund-Thread zu tun, dann beenden Sie den Dienst mit sich selbst, wenn die Hintergrundarbeit abgeschlossen ist.

Bindungzu Dienstleistungen

Ein weiterer Ansatz zur Kommunikation mitein Dienst ist die Bindungsmuster zu verwenden. Hier kann anstelle von Verpackungs-Befehle über eine Absicht gesendet werden, können Sie eine tatsächliche API aus dem Dienst, mit dem, was Datentypen, Rückgabewerte, erhalten und so auf, dass Sie es wünschen. Sie rufen dann diese API nicht anders, als würden Sie auf einem lokalen Objekt.

Der Vorteil ist,die reicheren API. Die Kosten ist, dass die Bindung komplexer einzurichten und komplexer zu halten, vor allem über Konfigurationsänderungen.

Wir werden diskutierendas Bindungsmusterspäter imdieses Buch.

Szenario: DieMusikspieler

Die meisten Audio-Player-Anwendungenin Android - für Musik, Hörbücher, oder was auch immer -
erfordern nicht die Benutzer in der Player-Anwendung bleiben selbst. Vielmehr kann der Benutzer gehen und andere Dinge tun, mit ihrem Gerät, mit dem Audio-Wiedergabe im Hintergrund.

Das Beispielprojektüberprüft inDieser Abschnitt istService / FakePlayer.

Das Design

Wir werden verwendenStartservice (), da wir den Service wollen sogar zu laufen, wenn die Aufnahme der Tätigkeit zerstört wurde. Allerdings werden wir einen regelmäßigen Service, anstatt eine IntentService verwenden. Ein IntentService ist so konzipiert, Arbeit zu tun und aufhören sich selbst, während sie in diesem Fall soll der Benutzer die Musikwiedergabe zu können zu stoppen, wenn der Benutzer will.

Da die Musikwiedergabe ist außerhalbDer Umfang dieses Kapitels Stummel der Dienst einfach, diese bestimmte Operationen aus.

Der Service-Implementierung

Hier istBei der Implementierung dieserBedienung, genanntPlayerService:

(von

Service / FakePlayer / app / src / main / java / com / commonsware /
android / fakeplayer / PlayerService.java)

Imdieser Fall, wir müssen nichts für onCreate wirklich (), so dass Lifecycle-Methode übersprungen.

Auf der anderen Seite müssen wir onBind () implementieren, denn das ist eine abstrakte Methode zum Service ist.

Wanndie Client-AnrufeDienst starten().onStartCommand ()heißt inPlayerService. Hier bekommen wir dieAbsichtund ein paar Extras herausgreifen, uns zu sagen, was wieder zu
spielen(EXTRA_PLAYLIST) Und andere Konfigurationsdetails

(zBEXTRA_SHUFFLE).onStartCommand ()Anrufespielen(), Die einfach fl
dass wir spielen
und eine Nachricht an LogCat anmeldet - ein echter Musik-Player verwenden würdeMedia Playerzu spielen beginnendie fi

Song indie Wiedergabeliste.onStartCommand ()kehrt

zurückSTART_NOT_STICKY, Was darauf hinweist, dass, wenn Android den Prozess (zB Low-Memory) beendet wird, es nicht wieder ein sollte einmal Bedingungen zu verbessern.

onDestroy () stoppt die Musik zu spielen - theoretisch jedenfalls - durch einen Anschlag () -Methode aufrufen. Auch dies protokolliert einfach eine Nachricht an LogCat plus aktualisiert unsere interne sind-wir-Spielen Flagge.

Imdas kommende Kapitel über MeldungenWerden wir diese Probe und diskutieren die Verwendung von startForeground () erneut, um es einfacher für die Benutzer zu den Musik-Player zu kommen, und lassen Sie Android wissen, dass der Service-Teil der Vordergrund Erfahrung liefert und daher nicht heruntergefahren werden sollte .

Mitder Service

DasPlayerFragmentdemonstrierendie Verwendung vonPlayerServicehateine sehr aufwendige UI, bestehend aus zwei großen Tasten:

(from
service / FakePlayer / app / src / main

/ res / Layout / main.xml)

Das Fragment selbst istnicht viel komplexer:

(von

Service / FakePlayer / app / src / main / java / com / commonsware /
android / fakeplayer / PlayerFragment.java)

DasonCreateView () Methode lädt lediglich die Benutzeroberfläche. Das OnClick () -Methode eine Intent mit gefälschten Werte für EXTRA_PLAYLIST und EXTRA_SHUFFLE konstruiert, ruft dann den Start (). Nachdem Sie die Schaltfläche "Start" drücken, wird die entsprechende Meldung in LogCat sehen. In ähnlicher Weise stopPlayer () ruft Stopservice (), die zweite LogCat Meldung auslöst. Bemerkenswert ist, brauchen Sie nicht, die Aktivität zu halten zwischen diesen Tastenklicks zu verwenden - Sie die Aktivität über BACK verlassen kann und kommen später wieder den Dienst zu beenden.

Kommunizieren von Dienstleistungen

Senden von Befehlen anein Service, standardmäßig ist eine Einbahnstraße. Häufig aber müssen wir Ergebnisse unserer Service zurück zu unserer Tätigkeit zu erhalten. Es gibt ein paar Ansätze dafür, wie dies zu erreichen.

Broadcast-Intents

Ein Ansatz, fi
erwähnt in das Kapitel überAbsichtfi ers, Der Service ist eine Broadcast-Intent
haben senden, die durch die Tätigkeit aufgenommen werden kann ... die Aktivität unter der Annahme, noch um und machte eine Pause nicht. Der Dienst kann sendBroadcast () aufgerufen werden, eine Intent Versorgung, die die Sendung identifiziert, entworfen von einem BroadcastReceiver abgeholt werden. Dies könnte eine bauteilspezifische Broadcast (zB neue Intent (this, MyReceiver.class)), wenn der BroadcastReceiver im manifesten registriert ist. Oder es kann auf eine Aktion Zeichenfolge basieren, vielleicht ein selbst dokumentiert und für Anwendungen von Drittanbietern zu hören für.

Die Aktivität indrehen, kann eine BroadcastReceiver über registerReceiver () registrieren, wenn auch nur dieser Ansatz für Intent Objekte festlegen, einige Maßnahmen arbeiten, nicht diejenigen eine bestimmte Komponente zu identifizieren. Aber, wenn die Aktivität des BroadcastReceiver die Sendung empfängt, kann er das tun, was er will, um den Benutzer zu informieren oder auf andere Weise selbst zu aktualisieren.

Doch für lokale Dienste,Dies ist keine gute Wahl. System-Sendungen wie diese sind an sich systemweit; für einen lokalen Service, sollten Sie einen Kommunikationskanal verwenden, der für Ihren Prozess privat ist.

Ausstehende Ergebnisse

Ihre Aktivität kann anrufen createPendingResult (). Dies gibt einPendingIntent- Ein Objekt, das bedeutet einAbsichtunddie entsprechende Aktion, die bei, dass durchgeführtAbsicht(ZB verwenden sie eine Aktivität zu starten). Imdiesem Fall ist diePendingIntentwird verursachenein Ergebnis auf Ihre Aktivität der Implementierung geliefert werden vononActivityResult (), So als ob eine andere Tätigkeit hatte mit genanntstartActivityForResult ()und indrehen, die so genanntesetResult ()zurück zu senden ein Ergebnis.

Schon seiteinPendingIntentistParcelUnd kann daher setzen in eine werdenAbsichtExtra können Sie Ihre Aktivität passierenDiesPendingIntentnachder Service. Der Service, die wiederum kann eine von mehreren Varianten des Aufrufssenden()Verfahren aufdasPendingIntent, Um die Aktivität zu benachrichtigen (viaonActivityResult ()) Eines Ereignisses, liefert möglicherweise sogar Daten (in Form einesAbsicht) Dieses Ereignis darstellt.

Wir werden sehen,PendingIntentverwendet, um viele Orte später indieses Buch, wie mit Meldungen undAlarmmanager.

Event-Busse

Event-Bus-Implementierungen- mögenLocalBroadcastManageroder greenrobot des EventBus-Eine große Lösung, einen Service für mit mit Objekten an anderer Stelle in Ihrem Prozess zu kommunizieren. Sie können die Service-Raise Ereignisse (zB
haben,NewEmailEvent.UploadCompletedEvent.MartiansHaveLandedEvent), Die Fragmente oder Aktivitäten für hören und darauf zu reagieren.

Bote

Noch eine andere Möglichkeit ist, zu verwenden,ein Messenger-Objekt. Ein Messenger sendet Nachrichten an eine Tätigkeit des Handler. Innerhalb einer einzelnen Tätigkeit kann ein Handler verwendet werden, um Nachrichten an sich selbst senden, wie kurz in die erwähnteKapitel über die Themen. Jedoch zwischen den Komponenten- Wie zum Beispiel zwischen einer Aktivität und einem Service - Sie erhalten eine Messenger benötigen als Brücke zu dienen.

Wie beieinPendingIntent, einBoteistParcelUnd so kann setzen in eine werden

Absichtextra. Die Aktivität Aufruf Dienst starten()oderbindService ()würde befestigen ein Messenger als Extra auf der Intent. Der Dienst würde, dass Messenger aus der Intent erhalten. Wenn es Zeit ist die Aktivität eines Ereignisses, würde der Dienst zu warnen:

1. AnrufMessage.obtain ()erhalten ein leerNachrichtObjekt

2. Bevölkerndass Message-Objekt nach Bedarf, mit welchem Daten der Dienst auf
die Aktivität passieren will

3. Anrufsenden()aufdasBoteUnd liefert dieNachrichtwieein Parameter

DasHandler wird dann die Nachrichtüber handle () erhalten, auf dem Hauptanwendungsthread, und so die Benutzeroberfläche aktualisiert werden kann oder was auch immer notwendig ist.

Benachrichtigungen

Ein weiterer Ansatz ist fürder Dienst der Benutzer lassen sich direkt über die Arbeit wissen, die abgeschlossen wurde. Um das zu tun, kann ein Dienst eine Benachrichtigung zu erhöhen - ein Symbol in der Statusleiste setzen und optional oder Piepsen oder etwas schütteln. Diese Technik wird in abgedecktein kommender Kapitel.

Wir können auch kombinierenDiese Techniken, wie zum Beispiel ein Ereignis Bus-Ereignis mit und Erkennen, wenn nichts in der UI-Ebene das Ereignis empfängt, so wissen wir, dass wir eine Benachrichtigung angezeigt werden müssen. Wir werden dieses Muster später auch in dem Buch werden untersuchen.

Szenario: Der Downloader

Wenn duwählen etwas aus dem Play Store zum Download, können Sie gerne ganz aus dem Play Store-Anwendung wieder heraus. Dies gilt Abbrechen nicht den Download - den Download und die Installation laufen bis zur Fertigstellung, obwohl es keine Aktivität Play Store auf dem Bildschirm zu sein.

Sie haben ähnliche Umstände in Ihrer Anwendung von Downloadein gekauftes E-Book-Karte für ein Spiel das Herunterladen eines fi auf das Herunterladen von
von eine Art von "Drop Box"

fi -Sharing Service. Und vielleicht Downloadmanager ist nicht eine gute Wahl sein würde, für eine beliebige Anzahl von Gründen (zB möchten Sie die fi herunterladen

In den internen

Speicher).

Das Beispielprojekt überprüft inDieser Abschnitt istService / Downloader, Die einen solchen Download-Dienst implementiert.

Das Design

Diese Art von Situationist eine perfekte Anwendung für die Befehlsmuster und einem IntentService. Die IntentService hat einen Hintergrund-Thread, so Downloads nach Bedarf so lange dauern kann. Ein IntentService schaltet sich automatisch ab, wenn die Arbeit getan ist, so dass der Dienst nicht verweilen und Sie brauchen nicht zu befürchten sie heruntergefahren selbst.

Ihre Aktivität kann einfach einen Befehl über den Start () an die IntentService senden es zu sagen, um die Arbeit zu gehen tun.

Freilich,die Dinge ein bisschen schwieriger, wenn Sie die Aktivität fi haben wollen aus
wannder Download abgeschlossen ist. In diesem Beispiel wird die Verwendung von

LocalBroadcastManager für diese Show.

Mitder Service

DasDownloadFragmentdemonstrierendie Verwendung vonDownloaderhattriviale UI, bestehend aus einem großen Knopf:

(von

Service / Downloader / app / src / main /
res / Layout / main.xml)

Das UI wird initialisiert inonCreateView (), wie gewöhnlich:

(von

Service / Downloader / app / src / main / java / com / commonsware / android

/ Downloader / DownloadFragment.java)

Wannder Benutzer auf die Schaltfläche klickt, onClick () aufgerufen, um die Taste (zur Vermeidung von versehentlichen doppelten Downloads) und rufen Sie den Start () zu deaktivieren, um einen Befehl zu senden über:

(von

Service / Downloader / app / src / main / java / com / commonsware / android

/ Downloader / DownloadFragment.java)

Hier,Die Absicht wir übergehen hat die URL der fi
zum Download (in diesem Fall eine

URL zu einem PDF zeigen).

Der Service-Implementierung

Hier istBei der Implementierung dieserIntentService, genanntDownloader:

(von

Service / Downloader / app / src / main / java / com / commonsware /
android / Downloader / Downloader.java)

Unsere Business-Logik ist in onHandleIntent (), Die auf einem Android-supplied Hintergrund-Thread aufgerufen wird, so können wir nehmen, was Zeit, die wir brauchen. Auch wird, wennonHandleIntent ()Ende, dasIntentServicewill Anschlag selbst automatisch ... sofern keine anderen Anforderungen für Downloads während aufgetretenonHandleIntent ()lief. Imdieser Fall,onHandleIntent ()genannt wird wiederder nächste Download, und so weiter.

ImonHandleIntent ()Wir fi nden

Set oben einDateiObjekt zeigt auf, wo wir herunterladen
möchtendie fi

Wir gebrauchengetExternalStoragePublicDirectory ()zu fi
derÖffentliche Ordner für Downloads. Da dieses Verzeichnis nicht existieren kann, müssen wir es schaffen, mitmkdirs (). Wir verwenden dann diegetLastPathSegment ()bequeme Methode aufUri, Die uns gibt den fi

Portion von ein Weg-StilUri. Das Ergebnis ist, daß
unsereAusgabedateiObjektpunkte eine fi
die gleiche wie die fi benannt
wir
herunterladen, in einenöffentlichen Ordner.

Wirgehen dann durch einen typischen HttpURLConnection Prozess zur URL für die Verbindung über die Uri in der Intent geliefert, Streaming, die Ergebnisse aus der Verbindung (8 KB
beimeine Zeit) an unsere benannten fi

Dann, wir folgen Die angeforderte Rezept unsere fi,
um sicherzustellen,
ist Gerettet:

• spülen()der Strom

• sync ()dasFileDescriptor(vongetFD ())

• schließen()der Strom

Dieses Rezept wurde erklärt, wieder indas Kapitel über die fi I / O.

Schließlich wäre es schön, jemanden wissen zu lassen,dass der Download abgeschlossen ist. Also, schicken wir eine lokale BroadcastAbsicht, Mit unseren eigenen benutzerdefinierten Aktion (ACTION_COMPLETE) Unter Verwendung vonLocalBroadcastManager.

Empfang die Sendung

UnserDownloadFragmentzu hören ist eingerichtet fürdass lokale BroadcastAbsicht, Durch eine lokale RegistrierungRundfunkempfängerimauf Wiederaufnahme()und Aufheben der Registrierung inonPause ():

(von

Service / Downloader / app / src / main / java / com / commonsware / android

/ Downloader / DownloadFragment.java)

DasRundfunkempfängerselbst wieder aktiviert unsere Taste, sowie DisplayseinToastanzeigt,dass der Download abgeschlossen ist:

(von

Service / Downloader / app / src / main / java / com / commonsware / android

/ Downloader / DownloadFragment.java)

Hinweisdass, wenn der Benutzer die Aktivität (zB BACK, HOME) verlässt, wird die Sendung nicht durch die Aktivität empfangen werden. Es gibt auch andere Möglichkeiten, um dies anzugehen,

insbesondere eine geordnete Sendung mit einer Mitteilung kombiniert, die wir untersucht werdenspäter in diesem Buch.

Dienstleistungen und Konfigurationsänderungen

Dienstleistungen sindnicht direkt von Konfiguration betroffen ändert sich die Art und Weise, die Aktivitäten sind. Während Aktivitäten zerstört und wird standardmäßig neu erstellt werden, wird weiterhin Dienste ausgeführt werden, wenn sie erstellt wurden.

Normalerweise Dienste tunnicht wirklich über Konfigurationsänderungen. Wenn Sie jedoch eine Dienstleistung, die Pflege der Fall ist, können Sie onConfigurationChanged () im Dienste außer Kraft setzen.

Das heisstdass Sie haben zwei Möglichkeiten, mit Konfigurationsänderungen zu tun: Überschreibung onConfigurationChanged () oder einfach in der Konfigurationsinformationen neu zu lesen, wie gebraucht. Angenommen, dass die vom Benutzer gewählte locale müssen wissen, wie Informationen in einem Web-Service-Aufruf enthalten. Wenn Sie das Gebietsschema auf jedem Web-Service-Aufruf prüfen, wird Ihr Service muss sich nicht um

Konfigurationsänderungen zu kennen. Wenn auf der anderen Seite bevorzugen Sie die Locale-Daten zu cachen, es in der Locale-Klasse zu lesen, wenn der Dienst erstellt wird, werden Sie onConfigurationChanged () und zu aktualisieren, dass die Cache, falls die

Konfigurationsänderung außer Kraft zu setzen war eine locale Änderung .

Tutorial # 16- Aktualisierung des Buches

Die App ist so konzipiert, zu versendeneine Kopie der als Vermögenswerte Kapiteln des Buches, so kann ein Benutzer eine Sache und bekommen einfach herunterladen alles, was sie brauchen: Buch und Leser.

Allerdings werden die manchmal Bücher aktualisiert. Das istein bisschen weniger wahrscheinlich mit dem Material in diesem Tutorial verwendet werden, da es eher unwahrscheinlich ist, dass HG Wells aus dem Grab steigen Der Krieg der Welten zu ändern. Jedoch können auch andere Bücher, wie Android-Entwickler-Guides von Balding Jungs geschrieben, könnten häufig aktualisiert mehr werden.

Höchstwahrscheinlich,die Art, wie Sie die Updates erhalten würde, ist durch die gesamte App zu aktualisieren, so dass Sie auch Verbesserungen an den Leser zu bekommen. Allerdings würde ein anderer Ansatz in der Lage sein, ein Update für das Buch als separate ZIP fi herunterladen Das Leser würde verwenden der Inhalt dieser ZIP fi
ob ein heruntergeladen wurde, sonst wird
es "zurückfallen" zu die Kopie des Vermögens. Das ist der Ansatz, den wir in diesem Tutorial zu nehmen, ein wenig mit Internetzugang und Dienstleistungen zu experimentieren. Auf dem Weg dorthin werden wir verwendenRetrofitanrufenein Web-Service (von Sorten) zu fi nden aus

Wenn ein Update verfügbar ist.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Hinzufügenein Stub DownloadCheckService

Es gibtein paar Stücke in unserem Download-the-Buch-Update-Puzzle:

• Wirbenötigen, um festzustellen, ob es eine Aktualisierung verfügbar ist, und wenn ja, wo wir fi
die ZIP-fi
das ist die Aktualisierungs

• Wirmüssen, um die Aktualisierung des ZIP fi herunterladen
welche könnte sein eine
ziemlich große fi

• Wirmüssen, dass die ZIP-fi auspacken
in interne oder externe Speicher, so dass sie
leichter durch den Rest unseres Code verwendet wird, und führt schneller als dynamisch die Inhalte aus dem ZIP-on the fly lesen würde

• Alledas muss im Hintergrund von einem Einfädeln Standpunkt geschehen

• Idealerweise alledas könnte passieren, entweder im Vordergrund oder im Hintergrund von einem UI-Sicht (dh Benutzer fordert manuell eine Update-Prüfung oder eine Update-Prüfung wird automatisch nach einem Zeitplan durchgeführt)

Zur Bewältigungdie fi

Puzzle Stück - Bestimmen, ob ein Update verfügbar ist - wir können
eine IntentService verwenden. Das macht es einfach für uns, nicht nur die Arbeit im Hintergrund von einem Einfädeln Standpunkt zu tun, sondern auch in der Lage sein, es zu benutzen entweder von der Benutzeroberfläche oder von irgendeiner Art von Hintergrund-Arbeit Scheduler. Also, lassen Sie uns einen DownloadCheckService zu unserem Projekt hinzufügen.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Service> "Service (IntentService)" aus dem Kontextmenü.

ErgänzeDownloadCheckServicewieder Klassenname und deaktivieren Sie die "Hilfsmethoden verwenden". Klicken Sie auf Fertig stellen, um erzeugen dieDownloadCheckServiceKlasse und fügen Sie einen Eintragdas Manifest.

Dann ersetzendie erzeugte UmsetzungDownloadCheckServicemit:

Schritt # 2: Bindungder Service geht in der Aktionsleiste

Erlaubender Benutzer manuell anfordern, dass wir das Buch zu aktualisieren (wenn ein Update verfügbar ist), sollten wir eine neue Aktionsleiste Element EmPubLiteActivity hinzufügen.

Rechtsklicken Sie aufdie res / Verzeichnis und wählen Sie Neu> Vector Inventar aus dem Kontextmenü. Klicken Sie auf die Schaltfläche Symbol und wählen Sie das Symbol "Aktualisieren": Klicken Sie auf OK, um zu schließendas Symbol Picker. Ändern Sie den Ressourcennamen ic_refresh_white_24dp. Dann klicken Sie auf Weiter und Fertig stellen diese drawable Ressource zu speichern.

Noch einmal,Dieses Symbol wird in schwarz machen, wenn wir sie brauchen in Weiß gegeben unser Thema zu machen.Öffnenres / ziehbar / ic_refresh_white_24dp.xmlund Veränderungdasandroid: fillColorimdas<Pfad>Element zu sein#FFFFFFFFAnstatt von# FF000000:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / res

/ ziehbar / ic_refresh_white_24dp.xml)

Dann,ändern dieres / menu / options.xmlfi
einschließenfolgende<Item>

Element:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app /
src / main / res / menu / options.xml)

Hinweisdass dieses Menü Definition erfordert eine neue String-Ressource, mit dem Namen Aktualisierung herunterladenMit einem Wert wieHerunterladenAktualisieren.

Das erlaubt uns, hinzufügenein neuerFallnachdasSchalterAussage in
onOptionsItemSelected ()im EmPubLiteActivity:

(from

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / EmPubLiteActivity.java)

Alles, was wir hier tun, ist sendenein Befehl an unsereDownloadCheckServicezu sehen, wenn ein Download zur Verfügung.

Schritt 3: Definieren unserer Veranstaltung

UnserIntentService wird im Hintergrund die Arbeit der Aktualisierung des Buches zu tun. Allerdings wollen wir den Rest der App wissen zu lassen, wenn das Buch aktualisiert wird. Insbesondere die ModelFragment, muss, wenn es vorhanden ist, zu wissen, dass es eine neue Reihe von Buchinhalten ist anzuzeigen. Um dies zu erreichen, können wir ein weiteres Ereignis auf unserem EventBus, ein BookUpdatedEvent in diesem Fall verwendet werden.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeBookUpdatedEventwieden Namen und klicken Sie auf OK die leere Klasse zu erstellen.

Schritt 4: Definieren Unsere JSON

Unterdie Abdeckungen verwendet Retrofi Gson für das Parsen von JSON es aus dem Web-Dienst ruft (oder eine andere URL). Daher, so wie wir eine Java-Klasse, die Modelle unserer JSON für die Buchinhalte zu definieren, benötigt, brauchen wir eine Java-Klasse die Daten, die Modelle, die wir von unserem Server, ob nicht ein Buch Update verfügbar ist erhalten.

Das JSON sieht so aus:

Wir können erstelleneinBookUpdateInfoKlassedass ahmt diese Struktur.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeBookUpdateInfowieden Namen und klicken Sie auf OK die leere Klasse zu erstellen.

Dann, mitBookUpdateInfoöffnen im Editor, Einfügen in der folgenden Klassendefinition: (von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / BookUpdateInfo.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Schritt # 5: Unser Retrofit-Schnittstelle definieren

Retrofi dann muss eine Java-Schnittstelle, die die meisten Details für liefert, wie unsere JSON zu holen und sie in ein Java-Objekt konvertieren. In unserem Fall werden wir einen HTTP-GET-Operation, um die JSON abrufen, und so werden wir die Retrofit @ abrufen Anmerkung verwenden werden mit einem Pfad auf einem Server zeigen auf, dass JSON zeigen.

Rechtsklicken Sie aufdascom.commonsware.empublitePaket in IhremJava/Verzeichnis und wählen Sie Neu> Java-Klasse aus dem Kontextmenü. ErgänzeBookUpdateInterfacewieder Name, schalten Sie das "Kind" "Interface", und klicken Sie auf OK, um die leere Schnittstelle zu erstellen.

Dann, mitBookUpdateInterfaceöffnender Editor, fügen Sie in der folgenden SchnittstellenDefinition:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / BookUpdateInterface.java)

Wenn Sie möchten, können Sie sehen,dieses fi 's Inhalte in Ihrem Webbrowser überdiese GitHub Link.

Hier definieren wir die Schnittstelle als eine mitupdate () -Methode, eine Instanz unserer BookUpdateInfo Struktur zurückkehren, mit der @ abrufen Anmerkung auf einen Pfad zeigt, wo das entsprechende JSON kann auf einem Server gefunden werden später benannt werden.

Schritt 6: Suchen Unsere JSON Via Retrofit

Nun, wir können tatsächlich nutzen Retrofi unsere BookUpdateInfo abrufen und sehen, ob wir ein Buch Update haben.

Als erstes werden wirhinzufügen müssen dieINTERNETdie Erlaubnis, unsere App, wie wir Materialien aus werden gehen auf das Herunterladen dasINTERNET. Fügen Sie den
folgenden<Uses-permission>Element als ein Kind der Wurzel<Manifest>Element inAndroidManifest.xml:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app /
src / main / AndroidManifest.xml)

Als nächstes wird in DownloadCheckService, Fügen Sie einOUR_BOOK_DATEstatisches

Datenelement, wasdas Bearbeitungsdatum des Buches in unsere APK gebacken, in YYYYMMDD

Format:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Dann füge hinzueingetUpdateUrl ()MethodeDownloadCheckService:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Hier schaffen wireine Retrofit-Instanz, indem er auf dem Server, auf unsere "Web-Service"

(wirklich eine statische JSON fi
aber das nicht vom Standpunkt des Kunden Code Rolle).

Wir verwenden dann die Retrofit-Instanz eine Instanz einer BookUpdateInterface

Implementierung zu erstellen, mit dem Code erzeugt durch Retrofi

Wirdann rufen Sie
update () für das Objekt unserer BookUpdateInfo zu bekommen. Wenn das Datum in der updatedOn
fi
unsererBookUpdateInfoist neueralsOUR_BOOK_DATEKehren wir
dieupdateURLfi
vondasBookUpdateInfo, Das wird eine URL zu einem ZIP-Archiv enthält
das aktualisierte Buch verweist. wenn deraktualisiert amWert istälteralsOUR_BOOK_DATE, wir kehren zurückNullnachbedeuten, dass keine Updates verfügbar sind.

Das istnicht besonders gut optimierte Ansatz. Insbesondere nehmen wir nie in Betracht, dass, sobald wir ein Update heruntergeladen haben, die wir in Updates neuer als die nur daran interessiert sind wir heruntergeladen. Wie es aussieht, vergleichen wir immer den updatedOn Wert OUR_BOOK_DATE, nicht der letzte updatedOn Wert, den wir verwendet. Ein produktions- Grad App würde darauf abzielen, diese, wie zu behandeln, indem die zuletzt verwendete updatedOn Wert in einem SharedPreferences Speichern und Vergleichen dagegen, sofern verfügbar.

Schließlich aktualisierenonHandleIntent ()anrufengetUpdateUrl ():

Schritt 7: Das Herunterladendas Update

WährendDer obige Code uns die URL des ZIP-Archivs wird, ist es nicht tatsächlich herunterladen. Wir brauchen mehr Code, zu erreichen.

HinzufügeneinPrivatgeländestatic final StringDatenelement
genanntUPDATE_FILENAMEnachDownloadCheckService, Die den Namen des fi
für
die heruntergeladene ZIP-fi

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Dann inDownloadCheckServiceFügen Sie den folgendenherunterladen()Methode:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Diese Methode löschtdie vorhandenen Ausgabe fi
ob es vorhanden ist, verwendet dann

OkHttp (und seine Okio transitive Abhängigkeit) das Buch zum Download, um die Ergebnisse zu der vorgesehenen Ausgang fi Schreiben

Dann aktualisierenonHandleIntent ()imDownloadCheckServiceanrufenherunterladen()wenn wir etwas herunterladen:

Hier löschen wirdie fi
nach Herunterladen es, so tun wir nicht unsere internen Speicher mit
der heruntergeladenen ZIP verunstalteten. Dies scheint den Zweck, den Download der ZIP-fi zu besiegen
im die fi

Ort, aber wir werden einige Code hinzufügen zu verwenden
die ZIP-fi
imder nächste Schritt des Tutorials.

Schritt 8: Auspackendas Update

Der letzte Schritt indas Buch-Download-Prozess ist das ZIP-Archiv auf den internen Speicher zu entpacken, so können wir mit Hilfe der heruntergeladenen Inhalte zu starten.

Hinzufügeneinstatischfinal StringDatenelementgenanntUPDATE_BASEDIRnach

DownloadCheckService:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Dies wird zeigen aufdas Verzeichnis auf internen Speicher, in dem das neueste Buch Update befinden wird.

Dann aktualisierenonHandleIntent ()aufDownloadCheckServiceNoch einmal,dieses Mal in einem Aufruf in denZipUtils.unzip ()und einige anderenotwendigenÄnderungen:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Hier haben wir:

• ErstellendasUPDATE_BASEDIRVerzeichnis, wenn es tutnicht vorhanden

• AnrufZipUtils.unzip ()zum entpackendie ZIP-fi
in das Verzeichnis

• PosteinBookUpdatedEventnachbedeuten, dass ein Buch Update ist fertig

ZipUtils ist eine Klasse aus der CWAC-Sicherheitsbibliothek, die wir für unser Projekt hinzugefügt zurück inLernprogramm# 6. Seine unzip () Methode behandelt eine Vielzahl von möglichen Fehlern in der ZIP-Archiv, das von einem Angreifer injiziert werden könnten, die unsere Kommunikation mit dem Buch-Update-Server abfängt.

Trotzdass dieses Update-Logik ist ein bisschen schlampig. Es ist möglich, dass verschiedene Buchaktualisierungen unterschiedliche fi haben

Und unsere UPDATE_BASEDIR werden
einige zusätzliche fi als Ergebnis haben. Im Idealfall sollten wir UPDATE_BASEDIR reinigen, bevor Sie das ZIP Auspacken

Archiv. Hinzufügen in einigen rekursive löschen-all-the-files-in-a-Verzeichnis-Logik wird als Übung fürder Leser.

Beimdieser Punkt,DownloadCheckServicesollte folgendermaßen aussehen:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite /

DownloadCheckService.java)

Schritt # 9: Verwendendas Update

AlleDiese Arbeit ist schön. Doch nichts anderes in der App kennt diese

UPDATE_BASEDIR Kopie des Buches tatsächlich anzuzeigen.

In der Tat haben wir zwei Szenarien zu berücksichtigen:

• Der Benutzergreift das Update Aktionsleiste Element, und wir laden Sie das Update und möchten sich jetzt die aktualisierte Buch dem Benutzer zu zeigen,

• Später, wennDer Benutzer öffnet das Buch, müssen wir erkennen, dass wir bereits ein Update haben und es verwenden, anstatt die Kopie unter Verwendung von in die APK
gebacken

Das wird einige Änderungen an unseren Datenmodell benötigen, wie wir füllen es aus ModelFragmentUnd wie wir verwenden, um die Ergebnisse in unsererContentsAdapter.

Zuerst fügeneinDateibaseDirDaten MitgliedBOOKZusammen mit einem begleitenden Setter-Methode:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / BookContents.java)

Dann füge hinzueingetChapterPath ()MethodeBOOKdass AnwendungengetChapterFile ()für immerder relative Pfad vom JSON Buch, verwendet dann, dass in Verbindung
mitbaseDiroderdasandroid_assetPfad zu kommen mitein vollerWebView-friendly Pfaddie fi ob es ist in Vermögenswerte oder eine lokale fi

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / BookContents.java)

Als nächstesänderndasgetItem ()Verfahren aufContentsAdapterbenutzendiese neue
getChapterPath ()Verfahren aufBOOK:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / ContentsAdapter.java)

Dann,ändern dieLauf()Methode vondasLoadThreadimModelFragmentum zu versuchen, zu
verwenden,das Update:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Hier stellen wir tundie folgenden, zusätzlich zu unserer ursprünglichen Logik:

• Sehen obdasUPDATE_BASEDIRVerzeichnisvorhanden ist oder nicht

• Ist dies der Fall, verwenden wirdascontents.jsondrin; andernfalls fallen wir zurück zuder inVermögenswerte/wie vorher

• Aktualisierendie BOOK mit dem Update-Verzeichnis, wenn wir benutzt, dass der

Inhalt für das Laden

Dies wird Griffder Fall, wenn ein Update vorhanden ist, wenn wir die App e und gehen zu sehen, das Buch fi. Allerdings müssen wir noch einige Code, der auf die BookUpdatedEvent reagiert und ordnet die aktualisierten Inhalte zu diesem Zeitpunkt zu verwenden.

Mitdass im Sinn, zu ergänzenonAttach ()aufModelFragmentzu registrierendas

EventBus:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Wir haben auch jetztbenötigen eine entsprechendeonDetach ()Verfahren
aufModelFragmentAufheben der Registrierung vondasEventBus:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

Schließlich können wir reagieren aufdasBookUpdatedEventÜber eine neue
onEventBackgroundThread ()Verfahren aufModelFragment:

(von

EmPubLite-Android Studio / T16-Update / EmPubLite / app / src / main / java / com /
commonsware / empublite / ModelFragment.java)

DasNamethreadMode= ThreadMode.BACKGROUNDSignaledasEventBusdass wir wollen dieses Ereignis auf einem Hintergrund-Thread zu empfangen. In unserem Fall wird das Ereignis auf einem Hintergrund-Thread (der einen aus der entsandteIntentService). Daher unsere onBookUpdated ()Methode wird aufgerufen, aufdieser Thread. Wenn jedoch waren wir zu postenBookUpdatedEventvonHauptanwendungsthread,EventBuswürde liefern
unsereBookUpdatedEventnachonBookUpdated ()auf einEventBus-supplied Hintergrund-Thread, um sicherzustellen,dass wir die Hauptanwendungsthread binden nicht.

Hier stellen wir treten gerade wegein frischer LoadThread die BOOK neu zu laden, unter der Annahme, dass der Benutzer BACK nicht nur gedrückt oder anderweitig unsere Aktivität zerstört.

Die neue LoadThread sehen, dass das Update verfügbar ist und es verwenden, seine eigene Veranstaltung veröffentlichen unsere UI-Ebene auf dem Bildschirm, um das Update installieren zu lassen.

Beimwenn Sie diesen Punkt, den Bau und die App starten, werden Sie die Update-Aktionsleiste Artikel finden Sie unter:

Swiping zurück zudie fi Seite im ViewPager, dass die Aktionsleiste Element tippen und ein paar Momente warten, sollte dazu führen, dass Buch mit neuen Inhalten aus dem Internet heruntergeladen aktualisiert werden:

In unserer nächsten Folge ...

… wir werdenbewegen einige Fragmente ineine Sidebarauf Großbild-Geräte, wie Tabletten.

Großbild-Strategien und Taktiken

Bisher wurden wir in der Regel ignoriert Bildschirmgröße. Mitdie überwiegende Mehrheit der Android-Geräte in einem ziemlich engen Bereich von Größen (3 "auf knapp 5"), ignorieren Größe ist, während das Lernen ist kein schlechter Ansatz. Allerdings, wenn es Zeit kommt eine Produktions App zu erstellen, gehen zu wollen, dringend zu prüfen, wie Sie andere Größen zu handhaben werden, meist größere (zB Tabletten).

Objektiv:Maximale Verstärkung, Minimum Schmerz

Was Sie wollen, ist in der Lage zu sein, zu schaffen,Benutzererfahrung ein hochwertiges ohne Ihre Entwicklung Budget zu sprengen - Zeit und Geld - in den Prozess.

Eine App entwickelt, umein Telefon in der Standardeinstellung kann auf einem Tablet ziemlich mies aussehen. Das ist, weil Android ist einfach dabei zu versuchen, Ihre Layouts und so zu strecken, um den verfügbaren Platz zu fi nden. Während das funktionieren wird, technisch gesehen, können die Ergebnisse unangenehm sein, oder zumindest unwirksam. Wenn wir den zusätzlichen Raum haben, wäre es schön, dem Benutzer zu ermöglichen, etwas mit dem Raum zu tun.

BeimZur gleichen Zeit, wenn Sie nicht unendlich viel Zeit haben, mit all dies zu tun haben.

Schließlich gibt es eine Vielzahl von Tablettengrößen. Während ~ 7 "und ~ 10" Bildschirme die am

häufigsten sind, gibt es sicherlich andere, die ziemlich beliebt sind (zB Amazon Kindle Fire HD 8.9

").

Die Fragment-Strategie

Einige Anwendungen verwendender zusätzliche Speicherplatz von einem großen Bildschirm direkt.

Zum Beispiel würde ein Gemälde App diesen Raum nutzen meist eine größere Zeichenfläche zur Verfügung zu stellen, auf die der Benutzer kann versuchen, die nächste Rembrandt, Picasso oder Pollock zu werden. Das

App Machtwählen, um mehr Werkzeuge zur Verfügung zu stellen direkt auf dem Bildschirm als auch gegenüber eine Art von Pop-up erfordert der Benutzer erscheinen zu lassen Pinselstile zu ändern, eine andere Farbe wählen, und so weiter.

Aber,dies kann eine Menge Arbeit.

Einige Anwendungen können macheneine vereinfachende Annahme: Die UI-Tablette ist wirklich ein Haufen von Telefon-Größe Layouts zusammengenäht. Zum Beispiel, wenn Sie eine "Tablette 10 in der Landschaft zu nehmen, ist es etwa die gleiche Größe wie zwei oder drei Telefone Side-by-Side.

Daher könnte man sich vorstellen, die Smarts aus wenigen Aktivitäten nehmen ist und diese miteinander auf einem Tablett benachbart sein, im Vergleich zu nur einer zu einer Zeit sichtbar sein, wie sie sich auf Telefone sind.

Betrachten wir zum Beispieldie Original-Ausgabe von der Google Mail-App für Android.

Aufein Telefon, würden Sie Gespräche in einem bestimmten Etikett auf einem Bildschirm sehen:

... Und die Liste von Etiketten auf einem anderen Bildschirm:

... Und die Liste der Nachrichten in einigen ausgewählten Gespräch in einem dritten Bildschirm:

Während aufein 7 "Tablet, würden Sie die Liste der Labels und die Gespräche in einem ausgewählten Etikett zur gleichen Zeit zu sehen:

Aufdass "Tablette 7, auf einem spezifi Gespräch tippen bringt die Liste der Nachrichten für dieses Gespräch in einem neuen Bildschirm. Aber auf einem 10 "Tablet, auf einem bestimmten Gespräch Klopfen zeigte das Gespräch, und die Liste der Gespräche, Side-by-Side:

Doch alldas wurde mit einer App mit sehr wenig redundante Logik getan, durch Fragmente.

Die Liste-of-Etiketten, list-of-Gespräche, und list-of-Nachrichten Bitsdie Benutzeroberfläche wurden als Fragmente umgesetzt. Auf einem kleineren Bildschirm (beispielsweise einem Telefon), die jeweils durch eine einzelne Aktivität angezeigt. Noch auf einem größeren Bildschirm (zB eine Tablette), mehr als ein Fragment wird durch eine einzelne Aktivität angezeigt. In der Tat - auf der

"Tablette 10 zeigte die Aktivität aller drei Fragmente, animierte Effekte mit der Liste von Etiketten Off-Screen und die Liste der Gespräche über auf den linken Schlitz gleiten kann, wenn - wenn es nicht aus den statischen Screenshots ersichtlich sind der Benutzer tippt auf ein Gespräch, die Nachrichten zu zeigen.

Die Vision ist es daher, die Benutzeroberfläche in Fragmente zu organisieren,und wählen Sie dann, welche Fragmente, in dem basierend auf den verfügbaren Platz auf dem Bildschirm Umstände zu zeigen:

Ändern des Layouts

Eine Lösung ist, zu sagen,dass Sie die gleichen Fragmente für alle Geräte und alle Konfigurationen, sondern dass die Dimensionierung und Positionierung dieser Fragmente variiert. Dies wird durch verschiedene Layouts für die Aktivität durchgeführt, diejenigen, die die Format- und Positionierungsregeln für die Fragmente bereitzustellen.

Bisher haben die meisten unserer Fragment Beispiele wurden auf Aktivitäten konzentriert mitein einzelnes Fragment, wie Sie auf kleineren Bildschirmen (zB Handys) verwenden können.

Allerdings können Aktivitäten sicherlich mehr als ein Fragment haben, obwohl Sie die "Slots", in die zu stecken, diese Fragmente bereitstellen müssen.

Zum Beispiel könnten Sie habendie folgenden inres / Layout-w720dp / main.xml:

(von

LargeScreen / EU4You / app / src / main / res /

Layout-w720dp / main.xml)

Hier haben wireine horizontaleLinearlayoutFesthaltenein PaarFrameLayoutBehälter.

jeweilsjeneFrameLayoutBehälter sindein Schlitz in einem Fragment zu laden, wie unter Verwendung von Code:

Im Prinzip könnte man auch habeneinres / Layout-h720dp / main.xmldas gilt sowohl des gleichenFrameLayoutContainer, aber nur ineinvertikale Linearlayout:

Wieder Benutzer das Gerät dreht, werden die Fragmente in ihre entsprechenden Schlitze gehen.

Ändern FragmentMischen

Doch für größere Veränderungen in der Bildschirmgröße, werden Sie wahrscheinlichmüssen, um größere Veränderungen in Ihrem Fragmente haben. Die häufigste Muster ist weniger Fragmente auf dem Bildschirm für eine Aktivität auf einem kleineren Bildschirmgerät (zB ein Fragment zu einem Zeitpunkt auf einem Telefon) und Fragmente auf dem Bildschirm für eine Aktivität in einem größeren Bildschirmgerät (zB zwei Fragmente zu einem Zeitpunkt auf einem Tablett).

So, beispielsweise alsdas Pendant zumres / Layout-w720dp / main.xmlgezeigt inder vorigen Abschnitt haben Sie vielleicht einres / Layout / main.xmldas sieht wie folgt aus: (von

LargeScreen / EU4You / app / src / main /
res / Layout / main.xml)

Dies liefertein Single-Slot, R.id.countries, für ein Fragment, eine, die fi
der Bildschirm. Für
eine größere Bildschirmgerät, in der Landschaft gehalten, würden Sie die Zwei-Fragment-Layout verwenden; für etwas anderes (zB Tabletten im Hoch- oder Telefon in jeder Ausrichtung), würden Sie das ein Fragment-Layout verwenden.

Na sicher,der Inhalt, der in dem zweiten Fragment gehört hätte zu zeigen,
irgendwo.

Manchmal, wenn fügen Sie ein weiteres Fragment fürein großer Bildschirm, wollen es nur dort einen Teil der Zeit zu sein. Zum Beispiel kann ein digitales Buch-Leser (wie die, die wir sind in den Tutorials Aufbau) könnte normalerweise nehmen Sie die Vollbild mit dem Lese Fragment, sondern könnte eine Sidebar Fragment auf einer Aktionsleiste Element klicken oder dergleichen basierend anzuzeigen. Wenn Sie die Taste BACK möchten Ihre FragmentTransaction umkehren, die das zweite Fragment hinzugefügt - so BACK drücken entfernt das Fragment und kehrt zum Single-Fragment Setup - Sie addToBackStack () als Teil Ihrer FragmentTransaction Konstruktion hinzufügen:

Wir werden sehendas indas nächste Tutorial.

Die Rolle vondie Aktivität

Also was istdie Aktivität zu tun?

Zuerst,die Aktivität ist die, das gesamte Layout laden, die eine angibt, welche Fragmente sollten (beispielsweise die Proben oben gezeigt) geladen werden. Die Aktivität ist verantwortlich für diese

"Slots" mit den entsprechenden Fragmente bevölkern. Es kann feststellen, welche Basis zu schaffen, Fragmente, auf denen Slots vorhanden sind, so dass es versuchen würde, nur um ein Fragment zu schaffen, in R.id.details zu gehen, wenn es tatsächlich ein R.id.details Slot zu verwenden ist.

Nächster,die Aktivität ist verantwortlich für alle Ereignisse der Handhabung von UI-Arbeit in einem Fragment (zB Benutzer durch Klick auf ein Listview-Element) ausgelöst werden, deren Ergebnisse sollten andere Fragmente beeinflussen (zB Einzelheiten der geklickten auf Listview-Element angezeigt wird). Die Aktivität weiß, welche Fragmente in der heutigen Zeit existieren. So kann die Aktivität entweder eine Methode auf dem zweiten Fragment nennen, wenn es vorhanden ist, oder es kann anrufen
startActivity () Steuerung auf eine andere Tätigkeit zuübergeben, die für das zweite Fragment verantwortlich sein wird, wenn es nicht in der aktuellen Aktivität vorhanden ist.

Endlich,die Aktivität ist in der Regel verantwortlich für alle Modelldaten, die mehrere Fragmente umfasst. Ob das Modelldaten werden in einem "Modell-Fragment" gehalten (wie skizziertim das Kapitel über die Fragmente) Oder irgendwosonst ist Ihnen überlassen.

Fragment Beispiel: Die List-and-Detailmuster

Dadurch wirdein bisschen mehr Sinn, als wir durch ein anderes Beispiel arbeiten, konzentrierte sich diesmal auf einem gemeinsamen Muster: eine Liste von etwas, wo auf der Liste klicken bringt Details zu dem Element, das auf geklickt wurde. Auf einer größeren Bildschirmgerät, Landschaft, sind beide Stücke typischerweise bei gleichzeitig Seite an Seite angezeigt. Auf kleineren Bildschirmgeräte, und manchmal sogar auf größeren Bildschirm-Geräte im Portrait, nur ist die Liste zunächst sichtbar - auf einem Listenelement Antippen eine andere Aktivität bringt die Details anzuzeigen.

beschreibendie App

Die Beispielanwendung fürDieser Abschnitt istLargeScreen / EU4You. Diese App hat eine Liste der Mitgliedsstaaten der Europäischen Union (EU). Durch Tippen auf ein Mitglied Nation wird die mobile Wikipedia-Seite für das Volk in einem WebView-Widget anzuzeigen.

Das Datenmodell- Wie es ist und was es davon - besteht aus einem Land-Klasse, die auf den Namen des Landes (als String-Ressource-ID) gilt, fl

(wie eine drawable Ressourcen-ID)

und mobile Wikipedia URL (als eine andere Zeichenfolge-Ressource-ID):

DasLand-Klasse verfügtüber eine statische Arraylist von Land Objekte, die die gesamte EU
initialisiert, in einem statischen Initialisierungsbaustein:

(von

LargeScreen / EU4You / app / src / main / java / com /
commonsware / android / eu4you / Country.java)

CountriesFragment

Das Fragment verantwortlich für die Darstellungdie Liste der EU-Staaten istCountriesFragment.

Es isteinListFragment, Verwendung einerCountryAdapterbevölkernDie Liste:

(von

LargeScreen / EU4You / app / src / main / java / com / commonsware /
android / eu4you / CountriesFragment.java)

Dieser Adapter ist etwas komplexerals die, haben wir gezeigt, in derKapitel Auswahl-Widgets. Wir werden uns in das, wasCountryAdapter tut, und die CountryViewHolder es verweist, inein späteres Kapitel dieses Buches. Es genügt für jetzt zu sagen,enthalten, dass die Zeilen in der Liste sowohl den Namen des Landes und seiner Flagge.

Wannder Benutzer Hähne auf einer Reihe in unserem Listview, muss etwas geschehen -
insbesondere die Details dieses Landes angezeigt werden müssen. Allerdings ist diese Details die Anzeige nicht in der Verantwortung von CountriesFragment, da es einfach die Liste der Länder und nichts anderes anzeigt. Daher müssen wir bis zum Hosting-Aktivität zu handhaben das Ereignis übergeben.

Wir konnten erreichendies ein Ereignis-Bus, wie in den anderen Beispielen früher im Buch gesehen.

Die EU4You Reihe von Proben, verwenden Sie jedoch einen anderen Ansatz, als Vertragsmuster bezeichnet. In diesem Muster definiert das Fragment eine Schnittstelle, das ist der "Vertrag", die alle Hosting-Aktivitäten dieses Fragments implementieren müssen. Diese Anforderung wird von der übergeordneten Klasse, ContractListFragment erzwungen:

(von

LargeScreen / EU4You / app / src / main / java / com / commonsware /
android / eu4you / ContractListFragment.java)

onAttach () wird aufgerufen, wenn das Fragment wurde auf eine Aktivität angebracht worden ist, ob das aus, wenn die Aktivität ursprünglich erstellt wurde, nach einer Konfigurationsänderung, oder wann immer. In diesen Fällen werfen wir die Tätigkeit der Vertrags Schnittstelle zu sein (über den Datentyp in der Erklärung zur Verfügung gestellt), eine Ausnahme ausgelöst, wenn die Umwandlung fehlschlägt. Subklassen kann dann den Vertrag Objekt zugreifenüber die getContract () -Methode.

CountriesFragmentAbgeleitet vonContractListFragmentund definiert seinen Vertrag. Daher jede Tätigkeitdass beherbergt einCountriesFragmentist verantwortlich für die Umsetzungdieser Vertrag Schnittstelle, so können wir nennenonCountrySelected ()wannklickt der Benutzer auf eine Zeile in der Liste:

(von

LargeScreen / EU4You / app / src / main / java / com / commonsware /
android / eu4you / CountriesFragment.java)

CountriesFragment hat auch ziemlich viel Code mit geklickten auf Reihen zu tun in einem Zustand

"aktiviert" wird. Dies bietet visuellen Kontext für den Benutzer und wird häufig in dem list-and-Details Muster verwendet. Zum Beispiel in den Tablet-Interpretationen von Google Mail in diesem Kapitel bereits gezeigt, werden Sie feststellen, dass die Liste auf der linken Seite (zB Liste der Labels) mit einem blauen Hintergrund hervorgehoben eine Zeile hat. Dies ist die "aktiviert" Reihe, und es gibt den Rahmen für das Material in dem benachbarten Fragment (zB Liste der Gespräche in der Label). Die Verwaltung dieser Zustand "aktiviert" wird ein wenig über den Rahmen dieses Abschnitts jedoch so werden wir die Diskussion über dieses Thema verzögernein späteres Kapitel in dieses Buch.

DetailsFragment

Die Details angezeigt werden kommen indie Form einer URL zu einer mobilen Wikipedia-Seite für ein Land, entworfen, um in einem WebView angezeigt werden. Die EU4You Beispielanwendung nutzt die gleichen WebViewFragment, die wir früher in diesem Buch gesehen haben, wie in den Tutorials. DetailsFragment selbst muss daher einfach eine Methode zu entlarven ein HostingAktivität zu ermöglichen, es zu sagen, was URL angezeigt werden soll:

(von

LargeScreen / EU4You / app / src / main / java / com / commonsware /
android / eu4you / DetailsFragment.java)

Du wirst bemerkendass dieses Fragment nicht über setRetainInstance gehalten wird (). Das liegt daran, wie Sie sehen werden, werden wir nicht immer dieses Fragment werden angezeigt wird.

Fragmente, die Abstürze, ohne dass es in einigen Konfigurationen (zB Landschaft), aber nicht in anderen Ländern (zB Portrait), bei dem ein Gerät könnte zwischen diesen Konfigurationen zur Laufzeit zu ändern, angezeigt werden beibehalten werden können.

Sie werden auch feststellen,dass dieses Fragment setWebViewClient () verwendet eine URLHandler mit dem WebView zu verknüpfen. Diese URLHandler Klasse zwingt einfach alle URLs zurück in die WebView, im Gegensatz zu einem Browser zu starten. Wikipedia nutzt nun HTTPS für viele Seiten, und es nutzt HTTP Strict Transport Security (HSTS) HTTP-Anfragen an ihre HTTPS Kollegen entsprechend umleiten. Die mobilen Wikipedia-URLs in der App verwendet werden, haben alle das https-Schema, und so in der Theorie sollte es keine serverseitige Umleitungen sein. Aber nur für den Fall gewährleistet die URLHandler, dass solche Umleitungen innerhalb der WebView bleiben.

Die Aktivitäten

Unsere Launcher Aktivität ist auchgenanntEU4You. Es verwendet zwei der Layouts oben gezeigt.

Beide sindmain.xml, Aber man ist inres / Layout-w720dp /:

(von

LargeScreen / EU4You / app / src / main / res /

Layout-w720dp / main.xml)

Die andere ist inres / Layout /:

(von

LargeScreen / EU4You / app / src / main /
res / Layout / main.xml)

Beide habeneinFrameLayoutfürdasCountriesFragment(R.id.countries), aber nurdasres / Layout-w720dp /Ausgabe hat einFrameLayoutfürdasDetailsFragment(R.id.details).

Hier istdie vollständige Umsetzung der EU4You Aktivität:

(von

LargeScreen / EU4You / app / src / main / java / com /
commonsware / android / eu4you / EU4You.java)

Die AufgabeonCreate ()ist einzurichtendie Benutzeroberfläche. Also, wir:

• Sehen Sie, wenn wir bereits eine Instanz haben,CountriesFragment, Indem er
unsereFragmentManagergeben unsdas Fragment in derR.id.countriesSlot - Dies kann
auftreten, wenn wir eine Konfigurationsänderung unterzogen, wieCountriesFragmentwürde neu in dieser Fall

• Wenn wir das tunnicht haben einCountriesFragmentSo erstellen Sie ein und führenein FragmentTransactionladen sie inR.id.countriesvon unserem Layout

• FindendasDetailsFragment(Die seitDetailsFragmentistnicht beibehalten, sollte immer zurückkehrenNull, Sondern, wie sie sagen, "sicher ist sicher")

• Wenn wir das tunnicht haben einDetailsFragment und Das Layout hat
eineR.id.detailsSchlitz, erstelleneinDetailsFragmentund ausführen
dasFragmentTransactionum es in dass Slot ... aber sonst nichts tun

DasErgebnis ist, dass EU4You korrekt jeder Situation umgehen können, wo wir beide Fragmente haben oder nur eine.

Ähnlich,dasonCountrySelected ()Verfahren (erforderlich fürdasVertragSchnittstelle) sehen werden, wenn wir unsereDetailsFragmentodernicht (und ob es sichtbar ist, oder versteckt ist, weil wir es erstellt, aber es ist in der aktuellen Ausrichtung des Bildschirms nicht sichtbar). Wenn wir das tun, rufen wir einfachloadURL ()Sie darauf zu füllendasWebView. Wenn wir nicht haben, um ein sichtbaresDetailsFragment, Müssen wir etwas tun, man angezeigt werden soll. Im Prinzip könnten wir entscheiden, ein

ausführenFragmentTransactionersetzendasCountriesFragmentmitdasDetailsFragment, Aber dies kann kompliziert werden. Hier beginnen wir eine separate upDetailsActivity, Vorbei an der URL für die gewählteLandin einem (nAbsichtextra.

DetailsActivityistähnlich:

(von

LargeScreen / EU4You / app / src / main / java / com / commonsware /
android / eu4you / DetailsActivity.java)

Wir kreierendasDetailsFragmentund laden Sie es indas Layout, erfassen Sie die URL aus derAbsichtExtra und Anruf loadURL ()aufdasDetailsFragment. Da wir jedoch ausgeführt werden aFragmentTransactionDie eigentliche Benutzeroberfläche für dieDetailsFragmentistnicht sofort erstellt, so können wir nicht nennenloadURL ()sofort (sonst,DetailsFragmentwerden versuchen, es zu passierenein nicht existierendesWebViewUnd wir abstürzen). Also, wir Berufung verzögernloadURL ()nachauf Wiederaufnahme(), An welchemPunkt derWebViewsollteexistieren.

Die Ergebnisse

Aufzunächst ist eine größere Bildschirmgerät, Landschaft, haben wir beide Fragmente, obwohl es nichts in die DetailsFragment geladen:

Das Tippen aufein Land bringt die Details auf der rechten Seite:

In jeder anderen Konfiguration, wie beispielsweiseeine kleinere Bildschirmgerät, sehen wir nur die

CountriesFragmentbeimder Anfang:

Das Tippen aufein Land bringt dieDetailsFragmentVollbild-indas

DetailsActivity:

AndereMaster-Detail-Strategien

Die EU4You Probe von oben ist eine Möglichkeit der Annäherung anDieses Master-Detail-Muster.

Es ist nicht der einzige. In diesem Abschnitt werden wir andere Implementierungen von EU4You überprüfen, die Master-Detail-Muster für implementating die andere Techniken verwenden.

Statische CountriesFragment

Imdas OriginalEU4YouAktivität, waren beide Fragmente dynamisch,jeweilsüber eine
hinzugefügtFragmentTransaction.DetailsFragmenthat dynamisch, als obnicht auf Bildschirmgröße und Ausrichtung sichtbar ist abhängig ist. Jedoch gibt es keine besondere Notwendigkeit für unsereCountriesFragmentdynamisch sein, wie Sie sehen in wirddasLargeScreen /

EU4YouStaticCountriesBeispielprojekt.

Hier unsere Einscheibensicherheitsglas Layout verwendeta <Fragment> -Element Draht in die CountriesFragment:

(von

LargeScreen / EU4YouStaticCountries / app / src /
main / res / Layout / main.xml)

In ähnlicher Weise unsere Dual-Fenster-Layout verwendeta <Fragment> -Element für die CountriesFragmentNeben derFrameLayoutfürdie Details:

(von

LargeScreen / EU4YouStaticCountries / app / src / main /
res / Layout-w720dp / main.xml)

UnseronCreate ()fürEU4Youist einfacher, indass wir mit der nicht zu verwirren brauchen CountriesFragmentüberhaupt:

(von

LargeScreen / EU4YouStaticCountries / app / src / main / java / com /
commonsware / android / eu4you3 / EU4You.java)

WederCountriesFragmentoder irgendetwas beteiligtdie Details muss unbedingt geändert werden.

Gehen mit einer Aktivität

Sie fragen sich vielleicht, warum wirmüssen mit DetailsActivity zu stören. Immerhin die DetailsFragment in einer zweiten Scheibe zeigen die EU4You Aktivität durchaus in der Lage ist -
warum haben sie nicht die DetailsFragment im fi anzuzeigen

ScheibeAuch in

Einscheibensicherheitsglas Szenarien? Sicherlich,Dies wird viel einfacher sein, wie wir mit der Aktivität und der Eintragung in das Manifest verzichten kann!

Ja,Das ist möglich. Nein, es ist nicht einfacher.

Der Grund fürdie Komplexität nun alle unsere mögliche Mischung von Fragmenten zu verwalten.

Wir hatten bereits mit den folgenden Möglichkeiten zu befassen:

• Einscheibensicherheitsglas, zeigtdie Länder

• Einscheibensicherheitsglas, zeigtaber die Länder, auf einem großen Bildschirm im Portrait-Modus, nachdem die Aktivität war in der Landschaft ins Leben gerufen worden ist, so dass die DetailsFragment existiert in der FragmentManager, ist aber nicht sichtbar

• Dual-Fenster, die beide Fragmente zeigen

Wenn wir loswerdenDetailsActivityund Dump alledie Verantwortung aufEU4YouHaben wir mehr Szenarien:

• Einscheibensicherheitsglas, zeigtdie Details, die Länder über eine ersetzt haben FragmentTransaction

• Einscheibensicherheitsglas, zeigtdie Länder, nachdem die Details gezeigt haben, und der Benutzer dann BACK drücken

Im Grunde, was müssen wir jetzt tun, istersetzen()dasCountriesFragmentmitdasDetailsFragmentWenn wir in Einscheibensicherheitsglas-Modus befinden, wenn der Benutzer tippt auf ein Land in der Liste. Dies erfordert eine recht umfangreiche Reihe vonÄnderungen, wie Sie in die sehenLargeScreen / EU4YouSingleActivityBeispielprojekt.

Die überarbeiteten Layouts

In unserem Einscheibensicherheitsglas Modus, unsere eine Scheibe wirdentweder halten dieCountriesFragmentoderdasDetailsFragmentJe nachdem, was der Benutzer getan hat. Gerade jetzt, unsereFrameLayoutistgenanntR.id.countries, Das war fi
vor, aber jetzt scheint wie
eine unangemesseneName. So ändern sich die neuen Projekts Layouts dies zuR.id.mainfrag, Ohne etwas zu ändern anderes:

(von

LargeScreen / EU4YouSingleActivity / app / src /
main / res / Layout / main.xml)

Die neue onCountrySelected ()

Die "einfache" Teildie Veränderungen kommt in der überarbeitetenonCountrySelected ()Verfahren in EU4You:

(von

LargeScreen / EU4YouSingleActivity / app / src / main / java / com /
commonsware / android / eu4you2 / EU4You.java)

In unseremüberarbeiteten Szenario werden wir immer habeneinDetailsFragment. Die Frage ist nur, ob es derzeit sichtbar ist. Daher können wir nennenloadURL ()aufDetailsdirekt.

Jedoch gibt es zwei mögliche Szenarien fürden Status unsererDetailsFragmentbeimder Zeitpunkt deronCountrySelected ()gerufen werden:

1. Es besteht in derDetails FrameLayoutunserer Dual-Fenster-Layout Ressource

2. Es existiert, vielleicht aufgrundeine Konfigurationsänderung, ist aber gegenwärtig nicht in einem Behälter

Das könnte dirdenken, dass es ein drittes Szenario wäre, wo es das sichtbare Fragment in der istmainfrag FrameLayout. Tatsächlich manchmalDetailsFragmentwird indass Container ... jetzt gerade nicht. Das einzige Mal, dassonCountrySelected ()aufgerufen wird, wenndie auf ein Element angezapft User in unseremCountriesFragment, was bedeutet, dassCountriesFragmentmuss in mainfrag.

Die IDein Fragment ausgetId ()Ist die ID des Containers, wenn sie mit dynamischen Fragmente verwendet. So prüfen wir, um zu sehen, ob unsereDetailsFragmentist indasDetails FrameLayoutvon ID-Werten zu vergleichen. Obsie unterscheiden sich, wir dannverpflichten()einreplace () FragmentTransactionstellenDetailsFragmentinmainfrag. Beachten Sie jedoch, dass wir verwendenaddToBackStack (), So dass, wenn der Benutzer die BACK-Taste drückt, werden wir auf die diese Transaktion und zurück rollen zurückCountriesFragment.

Die neue onCreate ()

Wenn Sie dachten,das war chaotisch, werden Sie die Änderungen nicht zu onCreate erforderlich () vonEU4Youviel mehr:

(von

LargeScreen / EU4YouSingleActivity / app / src / main / java / com /
commonsware / android / eu4you2 / EU4You.java)

Diese Probe wird abgeleitet ausdie ursprüngliche EU4You Probe und so verwenden wir nochFragmentTransactioneinrichtendasCountriesFragmentimmainfragWenn wir nicht erstellt habenCountriesFragmentvorhin.

Klarkommen mitDetailsFragment aber ist entschieden komplizierter. Die Strömung, die wir wollen, wenn wir in Dual-Fenster-Modus waren und wechseln Sie in Einscheibensicherheitsglas Modus, dass wir die CountriesFragment in diesem einzigen Scheibe zeigen. Wenn wir aus

Einscheibensicherheitsglas Modus Dual-Fenster-Modus umschalten, werden beide Fragmente gezeigt, natürlich werden.

Erstens haben wirder Fall, wo unsereDetailsFragmenttutnoch nicht vorhanden sind. Dies istähnlich wie die ursprüngliche Probe: Wir brauchen das Fragment zu erstellen und in die setzenDetails FrameLayoutWenn derDetails FrameLayoutbesteht.

ObdasDetailsFragmentexistiert, wirmüssen sicherstellen, dass es in der aufwickeltDetails FrameLayout, Falls vorhanden.

Tundass wir fi nden
prüfenseine ID zu sehen, ob es gegenwärtig befindet sich inmainfrag.

Wenn es ist, und wenn wir einenDetails FrameLayoutHaben wir auf Dual-Fenster-Modus und müssen, um Pop Rücken Stapel, in Vorbereitung für das Bewegen der
geschalteteDetailsFragmentnachdasDetails FrameLayout.

ObdasDetailsFragmentjedoch existiert, ist nicht inmainfragwirentfernen()es völlig.

Dann, wenndasDetailsFragmentvorhanden ist, unabhängig davon, wo es vorher war,
wirhinzufügen()esdasDetails FrameLayout.

Das"OH MEIN GOTT! Unsere Fragmente Keine Views! "Changes

In Tests gibt es nun Szenarien, in denenCountriesFragmentheißt mitonSaveInstanceState (), Aber ohne seine Ansichten erstellt wurden (dhonCreateView ()warnicht genannt). Dies würde uns dazu bringen, zum Scheitern verurteilt, wenn sie versuchen zu nutzengetListView (), Wie das Verfahren würde zurückkehrenNull, seit derListenansichttatnicht existieren. Soändern wironSaveInstanceState ()seinein bisschen robuster:

(von

LargeScreen / EU4YouSingleActivity / app / src / main / java / com / commonsware /
android / eu4you2 / CountriesFragment.java)

Wir auchmüssen DetailsFragment ein wenig aufzupeppen. Vorher haben wir uns auf die Tatsache, dass auf einer Konfigurationsänderung, unsere Extras auf unsere Absicht, für DetailsActivity noch zur Verfügung stehen würde. Nun aber gibt es keine DetailsActivity, was bedeutet, dass DetailsFragment seinen Zustand zu halten hat, so dass wir nicht die URL verlieren wir sehen, wenn der Benutzer den Bildschirm dreht oder führt zu einem weiteren Konfigurationsänderung.

Und um das Ganze abzurunden, haben wirdas gleiche Potential Problem wie bei CountriesFragment, wo das Fragment existieren könnte, aber nicht haben onCreateView () aufgerufen (zB waren wir im Dual-Fenster-Modus und schaltet auf Einscheibensicherheitsglas Modus und DetailsFragment noch nicht angezeigt worden ist), so können wir nicht davon ausgehen, dass getWebView () wird immer einen Wert ungleich null zurück.

NachHierzuDetailsFragmentwird kompliziert:

(von

LargeScreen / EU4YouSingleActivity / app / src / main / java / com / commonsware

/ android / eu4you2 / DetailsFragment.java)

DasurlDatenelement vorübergehend haltendie URL der Seite, sollten wir besonders werden sehen, wenn wir nicht habenWebViewarbeiten mit. Also, unsereloadURL ()Verfahren jetzt legtdie URL
inurlwenn wir habenNeinWebViewoder lädt sie
indasWebViewobdasWebViewbesteht.onSaveInstanceState ()wird gesetztdie URL - ob ausurloder vondasWebView- In den ZustandBündeln.onActivityCreated ()versucht zu
füllenurlvondasBündeln(Wenn wir es tunnicht bereits über eine URL), dann verwenden, die zum AuffüllenWebView(Was solltebestehen, wennonActivityCreated ()wird genannt).urlist eingestellt aufNullum anzuzeigendass dieWebViewunsere URL hält, einmaldass abgeschlossen ist.

Die Ergebnisse

Vonein User Experience Sicht haben sich die Dinge nicht wesentlich verändert. Der Benutzer sieht immer noch auf der Liste, noch die Details sieht, wenn auf einen Eintrag in der Liste tippen und bekommt immer noch die Dual-Fenster-Erfahrung auf größeren Bildschirmen.

Aber,der Übergang zwischen der Liste und die Details in Einscheibensicherheitsglas Modus ist ein bisschen schneller, als ein FragmentTransaction weniger Zeit in Anspruch nimmt, als dies eine andere Aktivität starten. Jedoch standardmäßig unsere FragmentTransaction gilt nicht jeder Übergangseffekte und sodas Fragment ändert ohne Fades "einfach passieren", Zooms oder dergleichen. Es ist sicherlich möglich Fragment Übergangseffekte zu spezifizieren, falls gewünscht, auch wenn dies nicht in den Anwendungsbereich dieses Kapitels ist.

DasMashup Möglichkeiten

Es sollte möglich sein, zu kombinieren,die beiden überarbeiteten Versionen von EU4You, eine einzelne Aktivität verwalten alle Fragmente, mit CountriesFragment als statisches Fragment aufgebaut. Der Beweis, daß dies möglich ist, ist dem Leser überlassen.

Die SlidingPaneLayout Variant

Die R13-Updatedas Android-Support-Paket eingeführt SlidingPaneLayout, einen anderen Weg, diese Art von Muster Master-Detail der Handhabung. SlidingPaneLayout reduziert deutlich den Aufwand für den Aufbau von Master-Detail, wie es all die "schmutzige Arbeit" Griffe der verschiedenen Fragmente in verschiedenen Szenarien zeigt (normaler Bildschirm, großer Bildschirm, etc.).

Die Rolle der SlidingPaneLayout

Imder Master-Detail-Muster, zeigen wir sowohl den Master und das Detail-Fragment, Side-by-Side, auf größeren Bildschirmen, während nur ein zu einer Zeit auf kleineren Bildschirmen zeigt.

In den vorhergehenden Beispielen hatten wir alle, dass selbst, in Bezug auf die Entscheidung, wie viele Fragmente zu verwalten zwischen diesen Fragmenten zeigen, die zum Schalten nach Bedarf.

SlidingPaneLayoutVerkapselungendass die Logik.

SlidingPaneLayout wird die Bildschirmgröße zu erkennen. Wenn die Bildschirmgröße groß genug ist, SlidingPaneLayout seine zwei Kinder Seite an Seite angezeigt werden soll. Wenn die Bildschirmgröße nicht groß genug ist, wird SlidingPaneLayout zu einem Zeitpunkt, ein Kind anzuzeigen. Jedoch standardmäßig, wenn der "Master" Kind zu sehen ist, ein dünner Streifen auf der rechten Seite kann der Benutzer auf die "Detail" Kind zurückzukehren. In ähnlicher Weise kann eine streichende Geste aus dem "Detail" wechseln Sie wieder zum "Master" Kind. Diese sind zusätzlich zu irgendwelchen Änderungen in Zusammenhang Sie auf UI-Operationen basierend einführen könnten (zB tippen auf ein Element in einem Master-Listview automatisch zum Detail Kind Schalten).

Konvertierenzu SlidingPaneLayout

DasLargeScreen / EU4YouSlidingPaneBeispielprojekt stehteineÜberarbeitung des EU4You Kernprobe, diesmal mitSlidingPaneLayoutfür Handhabungsdas Meister- Detail Muster.

Schon seitSlidingPaneLayout kapselt die Master-Detail-Logik, wir eine Menge Sachen fallen lassen können, die wir vorher verwendet, aber nicht mehr benötigt werden, einschließlich:

• DetailsActivity(wieSlidingPaneLayoutfunktioniertähnlich unserer Single-Activity-Implementierung)

• die dedizierte Großbild-Layout (wie SlidingPaneLayout "backt in der" Logik für unterschiedliche Bildschirmgrößen Handling)

• dynamische Fragmente (wieSlidingPaneLayoutarbeiten besser mit statischen

Fragmente, sowieso)

• isPersistentSelection () (wie wir wollen immer aktiviert Zeilen zu verwenden, auf API-Ebene 11+, da der Benutzer leichter hin und her wechseln kann zwischen Master- und Detail auf kleineren Bildschirmen, und wir wollen in den Master, um anzuzeigen, was der Kontext das heißt im Detail angezeigt)

Allerdings mussten wir hinzufügenein bisschen Scheibe Management sowie bewegen sich um einige Listen- Verhaltensweisen in unserer CountriesFragment.

Für den Anfang unsererres / Layout / main.xmlfi
jetzt
enthälteinSlidingPaneLayoutZusammen mit unseren beiden Fragmente, stellen jeweils bis als statische<Fragment>Elemente:

(von

LargeScreen / EU4YouSlidingPane / app / src /
main / res / Layout / main.xml)

Durch ein PuttingAndroid: layout_weight auf unserer Details Fragment, wir zeigen, dass wir wollen, dass man alle verbleibenden Zimmer zu nehmen, wenn die beiden Fragmente Seite-an-Seite angezeigt werden. Man könnte denken, dass wir dann die Breite des Details Fragment 0DP setzen sollte; Doch aus irgendeinem Grund, dies nicht funktionieren.

Die Größe vondie Länder (Master) Fragment wird auf größeren Bildschirmen geehrt. Auf kleineren Bildschirmen wird die Größe des Master-Fragment durch die Breite des Bildschirms diktiert werden, minus ein Streifen, damit der Benutzer einen Teil des fragment und Swipe, um zu sehen, dass das Detail-Fragment in toto anzuzeigen.

UnserCountriesFragmentjetzt immer einrichtetdasListenansichtsein Single-Choice-Modus, inonActivityCreated (). Er fordert außerdemonCountrySelected ()auf
unseremCountriesFragment.Contractum sicherzustellen, dass der Master die letzte Auswahl wird hervorgehoben - dies, um sicherzustellen, erforderlich ist, dass alles richtig nach einer Konfigurationsänderung angezeigt wird:

(von

LargeScreen / EU4YouSlidingPane / app / src / main / java / com / commonsware /
android / eu4you4 / CountriesFragment.java)

onListItemClick ()vonCountriesFragmentwirdein bisschen einfacher:

(von

LargeScreen / EU4YouSlidingPane / app / src / main / java / com / commonsware /
android / eu4you4 / CountriesFragment.java)

DasEU4YouAktivität insgesamt wird wesentlich einfacher:

(von

LargeScreen / EU4YouSlidingPane / app / src / main / java / com /
commonsware / android / eu4you4 / EU4You.java)

ImSlidingPaneLayout Terminologie, ist die Scheibe "offen", wenn die Meister wird auf kleineren Bildschirmen gezeigt, unddie Scheibe ist "geschlossen", wenn das Detail auf kleineren Bildschirmen angezeigt wird. Wenn das fühlt sich an, um Ihnen ein wenig kontraintuitiv, sind Sie nicht allein in dieser Hinsicht.

In der StandardeinstellungdasSlidingPaneLayoutist geschlossen. Also, wenn wir (auf kleineren Bildschirmen) starten wollen mitdie Master-Fenster angezeigt, müssen wir nennenopenPane (), Wie wir inonCreate ().Ähnlich:

• Wenn wir wollen, um zu zeigen,die Details, wenn der Benutzer klickt auf ein Land in der CountriesFragmentMüssen wir nennenclosePane ()imonCountrySelected ()

• Wenn wir wollen, um zu zeigen,der Masterbereich, wenn der Benutzer BACK drückt, während die Detailbereich zu sehen, sollten wir onBackPressed () und konsumieren dieses Ereignis (Aufruf openPane ()), durchführen, anstatt den normalen Super Verhalten außer Kraft setzen

Was SlidingPaneLayout aussieht

Aufeinen größeren Bildschirm, dieSlidingPaneLayoutAusgabe derEU4YouAktivität Aussehendie gleichen wie die vorherigen Beispiele.

Jedoch aufein kleiner Bildschirm, sieht die Sache etwas anders. Speziell:

• Unsere Master-Perspektive hatein dünner Streifen auf der rechten Seite, einen Blick des Detail Fragment zeigt

• Der Benutzer kann wechselnDetailfenster entweder durch den Detailbereich klauen öffnen oder auf ein Land klicken

• Der Benutzer kann wechseln Sie wieder zuder Masterbereich entweder durch den

Detailbereich wieder geschlossen ziehen oder die BACK-Taste drücken

ZeigeWeitere Seiten

ViewPager ist ein beliebter Behälter in Android, als horizontale swiping ein zunehmend beliebtes Navigations-Modell ist, zwischen Peer Teile des Inhalts zu bewegen (zB klauen
zwischen den Kontakten, klauen zwischen Buchkapitel). In einigen Fällen, wenndie ViewPager ist auf einem größeren Bildschirm, wir einfach größere Seiten wollen - ein digitales Buch Leser, zum Beispiel, würde einfach eine größere Seite in einer größeren Schrift für bessere Lesbarkeit haben.

Manchmal jedoch können wirnicht in der Lage sein, die Vorteile der vollen Raum, der von dem großen Bildschirm in Anspruch zu nehmen, vor allem, wenn unsere ViewPager den gesamten Bildschirm einnimmt. In Fällen wie diesem könnte es nützlich sein ViewPager zu ermöglichen, in einigen Fällen mehr als eine Seite zu einem Zeitpunkt, zu zeigen. Jede "Seite" wird dann entwickelt, etwa Telefon-Größe zu sein, und wir wählen, ob man zu zeigen, zwei oder vielleicht mehr Seiten zu einem Zeitpunkt, basierend auf den verfügbaren Platz auf dem Bildschirm.

Mechanisch, so dassViewPagerzeigen mehrals eine Seite ist ziemlich einfach, unser ein weiteres Verfahren, das die zwingende inPagerAdapter:getPageWidth (). Um dies zu sehen in Aktion, werfen Sie einen Blick auf dieViewPager / MultiView1Beispielprojekt.

Jede Seite inDiese Probe ist einfach eine Textview-Widget, das in einem Linearlayout zentriert

"großen Auftritt", den Stil der Aktivität unter Verwendung von:

(von

ViewPager / MultiView1 / app / src / main

/ res / Layout / page.xml)

Die Aktivität inonCreate (), Bekommt unsereViewPagervon dasres / Layout /
activity_main.xmlRessource und setzt seinen Adapter zu seineinSampleAdapter:

(von

ViewPager / MultiView1 / app / src / main / java / com /
commonsware / android / mvp1 / MainActivity.java)

Imdieser Fall,SampleAdapteristkeinFragmentPagerAdapterNoch
eineFragmentStatePagerAdapter. Stattdessen ist es eine eigene Implementierung
derPagerAdapterSchnittstelle:

(von

ViewPager / MultiView1 / app / src / main / java / com /
commonsware / android / mvp1 / MainActivity.java)

So erstellen Sie Ihre eigenenPagerAdapter, die großen Methoden, die Sie implementieren müssen, sind:

• instantiateItem (), in dem Sie die Seite selbst erstellen und auf dem mitgelieferten Behälter hinzuzufügen. In diesem Fall haben wir die Seite aufblasen, stellen Sie den Text des Textview auf der mitgelieferten Position basiert, stellen Sie die Hintergrundfarbe der Seite selbst einen anderen Blauton sein basierend auf der Position, ein Klick Zuhörer richten Sie einen Toast zu zeigen, wenn der Textview abgegriffen wird, und verwenden Sie das für unsere Seite. Wir kehren einige Objekt, das diese Seite identifiziert; in diesem Fall

kehren wir die aufgeblasene Ansicht selbst. Ein fragmentbasierte PagerAdapter würde wahrscheinlich das Fragment zurück.

• destroyItem (), wo wir brauchen, eine Seite zu bereinigen, die von dem Pager entfernt wird, wo die Seite vom Objekt identifiziert wird, die wir bisher von instantiateItem zurückgekehrt war (). In unserem Fall nehmen wir nur von der mitgelieferten Behälter.

• isViewFromObject (), Wo wir Konfi
ob einige spezifi Seite im Pager

(dargestellt durch eineAussicht) Ist in der Tat zu einem spezifischen
gebundenenObjektzurückgekehrt voninstantiateItem (). In unserem Fall, da wir wieder dieAussichtvoninstantiateItem (), Wir müssen lediglich Konfi
daß die beiden

Objekte sind in der Tat ein und dasselbe.

• getCount ()Wie bei dem Einbau-PagerAdapterImplementierungen zurück, wie viele

Seiten insgesamt gibt.

In unserem Fall außer Kraft setzen wir auchgetPageWidth (). Dies zeigt an, für eine bestimmte Position, wie viel Raum horizontal im ViewPager sollte zu dieser bestimmten Seite gegeben werden.

Im Prinzip könnte jede Seite ihre eigene einzigartige Größe haben. Der Rückgabewert ist ein Schwimmer, zwischen 0.0f und 1.0f, was darauf hinweist, welcher Anteil der Breite des Pagers auf dieser Seite geht. In unserem Fall kehren wir 0,5f, jede Seite zu haben, die Hälfte der Pager in Anspruch nehmen.

Das Ergebnis istdass wir zwei Seiten auf einmal sichtbar:

Es ist wahrscheinlich aucheine gute Idee setOffscreenPageLimit () auf dem ViewPager zu nennen, wie wir in onCreate () getan hat. In der Standardeinstellung (und mindestens) wird ViewPager drei Seiten-Cache: die eine derzeit sichtbar ist, und eine auf beiden Seiten. wenn Sie mehr als ein zu einer Zeit jedoch angezeigt werden, sollten Sie die Grenze stoßen 3-mal die Anzahl der
gleichzeitigen Seiten zu sein. Für eine Seitenbreite von 0,5f - also zwei Seiten zu einer Zeit - Sie wollen setOffscreenPageLimit anrufen (6), um sicherzustellen, dass Sie sowohl für die aktuellen sichtbaren Inhalt und einen vollen Schlag auf beiden Seiten im Cache gespeichert genug Seiten hatte.

ViewPager sogar Griffe "Teil klaut" - eine sorgfältige Swipe kann die rechte Seite in die linke Position und schieben Sie in einer neuen rechten Seite schieben. Und ViewPager stoppt, wenn Sie aus Seiten ausführen, so dass die letzte Seite immer auf der rechten Seite sein wird, egal, wie viele Seiten auf einmal und wie viele Seiten insgesamt passieren zu lassen.

Der größte Nachteil andieser Ansatz ist, dass es nicht gut von Indikatoren mit der aktuellen Ernte arbeiten. PagerTitleStrip und PagerTabStrip davon aus, dass es eine einzelne ausgewählte Seite.

Wenn die Anzeige richtig einstellen wird, zeigt die visuelle Darstellung, dass die linke Seite die ein (zB die Registerkarte mit dem Highlight), auch wenn zwei oder mehr Seiten sind sichtbar ist, ausgewählt. Sie können sich wahrscheinlich mit einem benutzerdefinierten Indikator (zB markieren Sie die ausgewählte Registerkarte und den einen zu seiner Rechten) überwinden diese.

beachten Sie auch,dass dieser Ansatz kollidiert ein wenig mitsetPageMargin

()aufViewPager.setPageMargin ()zeigt eine Menge von Leerzeichendas sollte in einer Rinne zwischen den Seiten gehen. Im Prinzip funktionieren würde dieses große mit mehreren gleichzeitigen Seiten in einem zeigt,ViewPager. Aber,ViewPagertutnicht berücksichtigen die Rinne in, wenn die InterpretationgetPageWidth ()Wert. Beispiel: Angenommen,getPageWidth ()kehrt zurück0,5fund wirsetPageMargin (20). Auf einem 480 Pixel breitenViewPager240 für die linke Seite, 240 für die rechte Seite, und 20 für den Bund:, werden wir 500 Pixel tatsächlich nutzen. Als Ergebnis 20 Pixel unserer rechten Seite sindüber den Rand des Pagers.

Ideal,ViewPagerwürde subtrahierendie Seitenrand, bevor die Seitenbreite der Anwendung. Eine Abhilfe ist für Sie das Recht ableitengetPageWidth ()Wert basiert aufdasViewPagerGröße und Rinnen selbst, eherWert als feste Codierung. Oder bauen in Ihre Rinne in die Seite Inhalt (zB
mitandroid: layout_marginLeftundandroid: layout_marginRight) UndüberspringensetPageMargin ()vollständig.

Spalten oder Seiten

Ein anderes Muster- Mit Seiten für kleinere Bildschirme und die "Seiten" Seite an Seite mit in Spalten für größere Bildschirme - erkundet werdenspäter imdas Buch.

Das Gittermuster

Ein weiterer Ansatz fürVorteil der größeren Bildschirmgrößen nehmen ist immer ein Master in voller Größe zu zeigen und ein Detail in voller Größe - vielleicht verschiedene Aktivitäten mit - aber ein Raster statt einer Liste für den Master zu verwenden. Dies funktioniert gut, wenn die Daten in dem Netz als "Karten", dargestellt werden kann, gezeigt sind, häufig durch ein Foto oder ein anderes Bild dominiert.

Der grundlegende Ansatz ist weniger Rasterspalten zu verwenden (zB1 oder 2) auf kleineren Bildschirmgrößen und mehr Rasterspalten (zB 3 oder 4) auf größere Bildschirme. Auf diese Weise ist die Anwendung Fluss über Bildschirmgrößen identisch, aber der Bildschirm-Nutzung auf

größeren Bildschirmen ist effektiver. Dies gilt insbesondere, wenn Sie sich auf der "gestaffelt" Raster verwenden Widgets von Dritten zur Verfügung, wieEtsys AndroidStaggeredGridoderMaurycy Wojtowicz des StaggeredGridView:

Fragment FAQs

Hier sind einige andere häufig gestellte Fragen zudie Verwendung von Fragmenten zur Unterstützung von großen Bildschirmgrößen:

Hat alles haben Sie obligatorischein Fragment?

Imein Wort, nein.

UI-Konstruktedass sich nicht ändern basierend auf Bildschirmgröße, Konfigurationen und dergleichen könnte einfach in der Tätigkeit selbst definiert werden. Zum Beispiel kann die Aktivität Elemente an das Aktionsleiste hinzuzufügen, da sein sollte, unabhängig davon, welche Fragmente sind gezeigt.

Was ist, wenn Fragmente nicht richtig fürMich?

Während Fragmente sind nützlich,sie lösen nicht alle Probleme. Nur wenige Spiele werden Fragmente für den Kern des Spiels, zum Beispiel. Anwendungen mit anderen Formen von spezialisierten Benutzeroberflächen - Malerei-Anwendungen, Bildredakteure, usw. - auch besser werden können, durch Verzicht auf Fragmente für die spezifischen Aktivitäten und etwas anderes zu tun war.

Das "etwas anderes" könnte mit benutzerdefinierten Layouts startendie unterschiedlichen Größen und Ausrichtungen. Zur Laufzeit können Sie bestimmen, was Sie benötigen entweder durch Inspektion, was Sie aus dem Layout erhalten, oder durch Konfiguration und DisplayMetrics Objekte, um festzustellen, was die Fähigkeiten der Geräte sind (zB Bildschirmgröße). Die Aktivität müssten dann seinen eigenen Code zu haben Umgang mit was auch immer Sie auf Bildschirmgröße
unterschiedlich basierend machen wollen (zB eine größere Malerei Leinwand bieten und mehr On-Screen-Werkzeugpaletten).

Haben Fragmente Arbeiten an Fernseher?

Viel vonder Fokus auf "größer-Screen-Geräte" hat sich auf Tabletten gewesen, weil, wie der Zeitpunkt des Schreibens dieses, sie sind die beliebtesten "larger-Screen-Geräte" im Einsatz sind.

Allerdings gibt es viele Szenarien Android im Fernsehen beteiligt zu betrachten.Ein Fernseher oder ein anderes externes Display Willen präsentiert sich als -große (720p) oder -xlarge (1080p) auf dem Bildschirm. Fragmente können sicherlich dazu beitragen, eine Benutzeroberfläche für einen Fernseher, aber es gibt auch andere Design-Überlegungen zu berücksichtigen bei der Anzeige, basierend auf der Tatsache, dass der Benutzer von einem TV viel weiter sitzt, als sie von einem Handy oder Tablet zu tun (so genannte "10 -Fuß User Experience "). Dies ist in größerem Detail behandeltspäter imdas Buch.

Bildschirmgröße und Dichte Tactics

Selbst wenn wir nehmendie "Tablette = mehrere Telefone" Design-Ansatz, wird die Größe des

"Telefon" variieren, abhängig von der Größe der Tablette. Darüber hinaus gibt es echte tatsächliche Telefone und diejenigen, die zu variieren in der Größe. Daher unsere Fragmente (oder Aktivitäten, um ihre eigene UI-Hosting direkt) müssen berücksichtigt Mikro fl zu nehmen
im Größe,
sowie die Makro diejenigen.

Screen Dichte ist auch etwas, das uns taktisch auswirkt. Es ist selten, dass eine Anwendung Großhandel UI Änderungen vornehmen wird basierend darauf, ob der Bildschirm 160dpi oder 240dpi oder 320dpi oder etwas anderes. Allerdings können Veränderungen in der Dichte beeinflussen sicherlich die Größe der Dinge, wie Bilder, die an Pixelgrößen untrennbar verbunden sind. Also müssen wir Dichte Rechnung zu tragen, wie wir unsere Fragmente werden Crafting gut von Größen in einem kleinen Bereich zu arbeiten.

Maße und Einheiten

Wieeine Maßeinheit, ist das Pixel (Pixel) eine schlechte Wahl, weil seine Größe durch Dichte variiert. Zwei Telefone könnten sehr ähnliche Bildschirmgrößen aber radikal unterschiedliche Dichten. Alles, was spezifi
im Form von Pixeln wird kleiner sein auf die höhere Dichte Gerät
und in der Regel würden Sie sie etwa die gleiche Größe zu sein. Zum Beispiel kann ein Knopf sollte für einen ~ 4 "Telefon gerade nicht auf magische Weise schrumpfen, weil das Telefon eine viel höhere Rasterdichte als einige andere Telefon zu haben passiert.

Die beste Antwort ist zu vermeidenmit konkreten Größen, soweit möglich. Aus diesem Grund neigen Sie dazu, Container zu sehen, und einige Widgets, verwenden match_parent und wrap_content für ihre Größe - das automatisch auf Geräteeigenschaften auf Basis einzustellen.

In einigen Ländern, aber Sie müssengeben Sie eine konkretere Größe, wie mit padding oder Margen.

Für diese gibt es zwei Hauptgruppen von Maßeinheiten, mit zu arbeiten:

• Diejenigen, basierend auf Pixel, aberAufnahmeeinrichtung Eigenschaften berücksichtigt.

Dazu gehören dichteunabhängige Pixel (dp oder dip), die Größe jedes dp versuchen etwa 1/160 eines Zoll zu sein. Hierzu zählen auch skalierten Pixel (sp), die die Größe auf die Standardschriftgröße auf dem Gerät auf Basis skaliert - sp häufig mit Textview verwendet wird (und Subklassen) für Android: textsize-Attribute.

• Diejenigen, auf rein physikalische Maßeinheiten:mm (Millimeter), in

(Zoll), undpt (Punkte = 1/72 Zoll).

Irgendein vondiejenigen neigt als px besser zu sein. Welche Sie wählen, hängt davon ab, wie Sie und Ihre Grafik-Designer mit mehr Komfort.

Wenn Sie fi
dass es Fälle gibt, in denen die Dimensionen, die Sie stärker variieren als die
automatische Berechnungen von dieser Dichte-aware Maßeinheiten verwenden möchten, können Sie Dimension Ressourcen. Erstellen Sie eine dimens.xml fi
imres / Werte / und der damit
verbundenen Ressourcengruppen und <Dimen> Elemente in dort setzen, die eine Dimension einen Namen und eine Größe geben. Neben vielleicht die Dinge ein bisschen mehr DRY ( "nicht wiederholen sich"), können Sie vielleicht verschiedene Werte dieser Dimensionen für unterschiedliche Bildschirmgrößen, Dichten oder andere Fälle schaffen je nach Bedarf.

Layouts und Stretching

Web-Designermüssen mit der Tatsache zu tun, dass der Benutzer ihre Browser-Fenster Größe ändern könnte. Die Ansätze damit umgehen werden "fl genannt

Designs.

Ebenso Android-Entwicklererstellen müssen "fl

Layouts für Fragmente, Zeilen ein

Listview, und so weiter, mitähnlichen Moll fl beschäftigen
im Größe.

Jeder von "The Big Three" Container-Klassen hat seinen Ansatz für den Umgang mitDies:

• Benutzenandroid: layout_weightmitLinearlayoutzusätzlichen Speicherplatz zuweisen

• Benutzenandroid: stretchColumnsundandroid: shrinkColumnsmitTablelayoutwelche

Spalten zu bestimmen, sollte zusätzlichen Platz absorbieren und die Spalten mit Gewalt

"geschrumpft" werden sollte, zu erhalten Raum für andere Spalten, wenn wir ausrei fehlt
horizontalen Raum

• Verwenden Sie geeignete Regeln fürRelativeLayout Widgets zu verankern, wie für andere Widgets oder die Grenzen des Behälters erforderlich, so dass Extraraum fließt
natürlichüberall dort, wo die Regeln verlangen

Drawables Das Resize

Bilder, insbesonderediejenigen, die als Hintergründe verwendet, muss der Größe verändert werden, um alles zu berücksichtigen:

• Bildschirmgröße und Dichte

• Größe vondas Widget, und dessen Inhalt, für die sie als Hintergrund dient (zum Beispiel Menge an Prosa in einem Textview)

Android unterstützt, was ist bekannt alsdie "Neun-Patch" PNG-Format, in dem Ändern der Größe Informationen im PNG selbst gehalten wird. Dies wird in der Regel für Dinge wie abgerundete Rechtecke verwendet, Android zu sagen, die geraden Abschnitte des Rechtecks zu strecken, aber nicht um die Ecken zu strecken. Nine-Patch PNG fi
wird sein geprüft näher eine spätere

Kapiteldieses Buch.

DasShapeDrawable XML drawable Ressource verwendet eine noch so kleine Teilmenge von SVG

(Scalable Vector Graphics) ein Vektor-Kunst-Definition eines Bildes zu erstellen. Wiederum neigt diese für Rechtecke und abgerundete Rechtecke verwendet werden, insbesondere solche mit einem Gradienten fi

Da Android interpretiertDer Vektor-Definition zur Laufzeit, kann es eine glatte

Steigung, Interpolation alle dazwischen liegenden Farben von Anfang bis fi Dehnen eine PNG-fi erstellen

- Sogar einen Neun-Patch PNG fi

- Neigt dazu, in "Banding-Effekte" auf
den Steigungen zu führen. ShapeDrawable wird auch später in diesem Buch behandelt.

Bibliotheken von Drittanbietern kann auch helfen. Dassvg-androidProjekt liefert eine JAR, die mehr SVG-Funktionen, als dies ShapeDrawable behandelt, obwohl auch sie nicht die gesamte SVG spezifi decken

Ebenfalls,WebView hat eine gewisse Fähigkeit SVG fi auf Android

3.0+ anzuzeigen.

Drawables durch Dichte

Manchmal jedoch istkein Ersatz für Ihr traditionelles Bitmap-Bild. Icons und verwandte Kunstwerk werden nicht unbedingt zur Laufzeit gestreckt werden, aber sie sind immer noch auf Rasterdichte abhängig. Ein 80x80 Pixel großes Bild kann gut aussehen auf ein

Samsung Galaxy Nexus oder andere-xhdpi Gerät, an an einer Seite um ein Viertel-Zoll kommen in.

Wenn sie jedoch auf einem -mdpi Gerät betrachtet, wird das gleiche Symbol ein halb Zoll auf einer Seite, die vollständig zu groß sein kann.

Die beste Antwort ist auf mehrere Interpretationen von erstellendas Symbol in unterschiedlichen Dichten, jedes Symbol in der entsprechenden drawable Ressourcenverzeichnis (zB res / ziehbar-MDPI, res / ziehbar-hdpi) setzen. Dies ist, was Android Asset-Studio hat für uns in den Tutorials, Launcher Icons von einem mitgelieferten Kunstwerk für alle vier Dichten zu schaffen. Noch besser ist es, Symbole für jede Dichte zugeschnitten sind - und nicht nur die Pixelanzahl zu reduzieren, Schritte, um ein Symbol ziehen, die noch Sinn für den Benutzer am unteren Pixelzahl machen, übertreibe wichtigsten Design-Merkmale und fallen andere Sachen aus. Googles Kiril Grouchnikov hateine ausgezeichnete Blog-Post aufDieser Aspekt

Android wird jedoch können Sie betrügen.

Wenn Sie liefern einige Dichten nur, aber Ihre Anwendung läuft aufein Gerät mit einer anderen Dichte, Android wird Ihre Symbole automatisch neu berechnen, um zu versuchen eine mit der richtigen Dichte zu erzeugen, was die gleiche Größe zu halten. Auf der positiven Seite, das spart Arbeit

— vielleicht nur Sie ein Schiff-xhdpi Symbol und lassen Android erledigen den Rest. Und es kann Ihre APK Größe von einem Bit zu reduzieren. Allerdings gibt es Kosten:

• Das istein bisschen langsamer zur Laufzeit und verbraucht mehr Akku ein bisschen

• Android Neuabtastungsalgorithmus kannnicht so anspruchsvoll sein wie die von Ihrer bevorzugten Bildeditor (zB Photoshop)

• Sie können nicht fi
das Symbol, um besser aussehen als ein einfaches

Resampling (zB Drop-off-Design-Elemente, die nicht identifizierbar werden)

Weitere Überlegungen

Da sind andereDinge, die Sie sollten prüfen, wenn Ihre Anwendung entwerfen auf mehreren Bildschirmgrößen zu arbeiten, über das, was oben abgedeckt ist.

Geräten mit kleinem Bildschirm
icht ist einfach der Bildschirmgröße Probleme zu denken, wie "Handys im Vergleich zu Tabletten" zu sein. Aber nicht nur, dass Tabletten in verschiedenen Größen kommen (5 "Samsung Galaxy Note zu einem Bündel von 10.1" Tabletten), aber Handys kommen in verschiedenen Größen. Diejenigen, die weniger als 3 "Diagonale des Bildschirms haben wird als -small Bildschirm kategorisiert werden Geräte, und Sie können für die verschiedenen Layouts haben.

BekommenDinge auf kleinen Bildschirmen zu arbeiten, ist manchmal schwieriger als von normalen zu größeren Bildschirmen zu bewegen, nur weil Sie ausrei fehlt

Zimmer. Sie können nur

Shrink-Widgets so weit, bevor sie unlesbar oder "anzapfbare" werden. Sie müssen möglicherweise aggressiver Scroll benutzen, um Ihre Widgets zu erlauben, mehr Raum zu haben, aber dass der Benutzer durch Ihre gesamte Fragment im Wert von UI zu schwenken. Oder Sie müssen Ihre Anwendung in mehrere Fragmente zu teilen, als sie ursprünglich erwartet, und mehr Aktivitäten oder andere Tricks anwenden, um dem Benutzer erlauben, die Fragmente einzeln auf Geräten mit kleinem Bildschirm navigieren, während Nähen sie zusammen in größere Blöcke für größere Telefone.

Vermeiden Sie VollbildhintergrundAndroid läuft in
vielen verschiedenen Auflösungen.Viele, viele
verschiedene Auflösungen.

Der Versuch, Kunstwerk zu schaffen,jede Auflösung heute im Einsatz wird langwierig und zerbrechlich, letztere, weil neue Vorsätze jeder so oft auftauchen, die Sie möglicherweise nicht bewusst sein kann.

Daher versuchen die App zu entwerfen eine Art von Vollbild-Hintergrund zu vermeiden, in dem Sie erwarten sinddas Kunstwerk perfekt auf den Bildschirm fi. Entweder:

• MachenVerwenden Sie keine Hintergrund, oder

• Benutzeneinen Hintergrund, aber eine, die zu fi abgeschnitten werden soll und wird in seinem beschnittenen Zustand gut aussehen, oder

• Benutzeneinen Hintergrund, aber eine, die natürlich in eine solide fi an den Kanten (zB
ein starfi bluten
dass einfach fehlt Sterne zu den Rändern), so können Sie "fi in"

Raum um den Hintergrund mit dem festen Farbe auf den Bildschirm zu fi nden, oder

• dynamisch ziehender Hintergrund (beispielsweise ein starfi
wo Sie platzierendie

Sterne selbst zur Laufzeit 2D-Grafik-APIs)

Bei den meisten herkömmlichen Anwendungen, nur mitder Hintergrund aus Ihrem Bestand Thema wird in der Regel ausreichend. Dieses Problem ist viel größer für 2D-Spiele, die auf Hintergründe als Spielfläche zu verlassen neigen.

Offensichtliche Elemente für Bildschirmgrößen

Es gibt zweiElemente können Sie diese Auswirkungen auf Ihre Manifest hinzufügen, wie Ihre Anwendung in Bezug auf Bildschirmgrößen verhalten wird.

<Kompatibel-Bildschirme>dient als Werbung für Ihre Fähigkeiten zuDie Google Play Store und ähnliche "Märkte". Sie können eine haben<Kompatibel-Bildschirme>Element mit einem oder mehreren Kind<Screen>Elemente - je<Screen>aufzählteine Kombination von Bildschirmgröße und Rasterdichte, die Sie unterstützen:

Der Google Play Store fi er die App, so wird es zeigen sich nicht auf Geräte, die Bildschirme, die einen Ihrer nicht <screen> Elemente treffen. Allerdings zeigen neue Dichten jedes Jahr oder so, und Geräte, diese Dichten ausgeführt wird nicht von Ihrem <kompatibel-Bildschirme> unterstützt werden Element, wenn Sie das entsprechende <screen> Element für die Dichte hinzuzufügen. Zum Beispiel ist die oben <kompatibel-Bildschirme> Element nicht tvdpi oder xxhdpi Geräte abdecken.

Als Ergebnis abschreckt Google die Verwendung von

<Kompatibel-Bildschirme>.

Es gibt aucha <Träger-Bildschirme> -Element, wie wir gesehen haben, als wir unser erstes Projekt in den Tutorials auf. Hier geben Sie an, welche Bildschirmgrößen Sie Unterstützung, ähnlich

<Kompatibel-Bildschirme>(Abzüglich aller Dichte Erklärungen). Und,die Google Play Store fi er die App, so wird es zeigen sich auf Geräte, die nicht die Bildschirme haben kleiner als das, was Sie zu unterstützen.

So zum Beispiel an, dassdass Sie ein<Träger-Bildschirme>Element wie folgt:

Du wirstzeigen nicht im Google Play Store für alle -small Bildschirm Geräte. Allerdings zeigen Ihnen im Google Play Store für alle -xlarge-Screen-Geräte bis

— Android wird lediglich eine gewisse Laufzeit Logik anwenden, um zu versuchen die App auch auf solchen Bildschirmen laufen zu helfen. Also, während<Kompatibel-Bildschirme> ist eine reine fi er,

<Stützen-Bildschirme> ist ein fi er für kleinere als unterstützten Bildschirme und eine Laufzeit

"geben Sie mir eine Hand!" Flagge für larger-than-unterstützten Bildschirme.

In Anbetracht Neuere Wichten

-tvdpi - um 213dpi - wurde für Android TV hinzugefügt, und die Dichte für 720p Android-TV-Geräte verwendet. Doch Google ebenfalls gewählt zu verwenden-tvdpi für das Nexus 7 Tablet. Doch nicht einmal die Mühe gemacht Google viele -tvdpi spezifische Ressourcen zu schaffen, so dass das Betriebssystem von der -hdpi Ausgabe neu berechnen.

-xxhdpi wurde Ende 2012 und ist für Geräte mit einer Bildschirmdichte um 480dpi hinzugefügt.

Während Android kann ein -xhdpi Bild für -xxhdpi up-Probe, können die Ergebnisse nicht so scharf, wie Sie möchten. Daher können Sie mit dem Erstellen -xxhdpi als "Top-Tier" Dichte betrachten wollen, so dass andere Geräte können bei Bedarf neu berechnen. Zum Zeitpunkt des Schreibens dieses Artikels, etwa 15% der Play Store ausgestatteten Android-Geräte sind -xxhdpi.

-xxxhdpi ist für Geräte mit Bildschirmen um 640dpi. Zum Zeitpunkt des Schreibens dieses Artikels

-xxxhdpiistnicht in signifi
benutzen.

Tutorial # 17- Unterstützung der Große

Screens

Bisher haben wir geschaffeneine Vielzahl von Fragmenten, die man zu einem Zeitpunkt, in einer Hosting-Aktivität verwendet werden: Noten, Hilfe und über. Und auf kleineren Bildschirmgeräte wie Telefone, das ist wahrscheinlich die beste Lösung. Aber auf Geräten wie 10 "Tabletten, könnte es schön sein, um einige dieser Fragmente über einen Teil der Haupttätigkeit der Platz in Anspruch nehmen zu müssen. Zum Beispiel könnte der Benutzer das Kapitel liest und die Online-Hilfe zu lesen.

Daher wird inIn diesem Tutorial werden wir für die Hilfe und über Fragmente arrangieren in EmPubLiteActivity direkt auf Tabletten geladen werden, während unsere bestehenden Funktionen für andere Geräte zu halten.

Das isteine Fortsetzung der Arbeit, die wir haben indie vorherigen Tutorial.

Sie können fi

Die Ergebnisse dervorherigen TutorialundDie ergebnisse vondieses

Tutorialimdie GitHub-Repository Buch:

Schritt 1: Erstellen Unsere Layouts

Der einfachste Weg, um sowohl hinzufügenein Ort für diese anderen Fragmente und zu bestimmen, wann wir diese Fragmente in der Haupttätigkeit verwendet werden sollte, ist neues Layout Ressourcensets für größere Bildschirmgeräte, mit maßgeschneiderten Versionen von main.xml zu erstellen, indem EmPubLiteActivity verwendet werden.

Rechtsklicken Sie aufdie res / Verzeichnis in der App, dann Neu> "Android Resource Directory"

aus dem Kontextmenü wählen. Nach wie vor bringt dies die neue Ressourcenverzeichnis Dialog auf:

Wählen Sie "Layout" ausdie "Ressourcentyp" drop-down. Klicken Sie dann auf "Bildschirmbreite" in der Liste der Qualifikations auf der linken Seite, und klicken Sie auf die Schaltfläche ">>", dass auf der rechten Seite in die Liste hinzuzufügen:

Imdie "Bildschirmbreite" fi
fi in 880:

Klicken Sie auf OK zu erstellendas Verzeichnis. Wiederholen Sie diesen Vorgang ein erstellenres /

Layout-h880dp /
directory, diesmal die Wahl "Bildschirmhöhe" und nicht als "Bildschirmbreite".

Dann mit der rechten Maustaste aufdie res / Layout / main.xml fi und "Kopieren" aus dem Kontextmenü wählen. Danach wird der rechten Maustaste auf das neue res / Layout-w880dp

/ Verzeichnis und wählen Sie "Einfügen" aus dem Kontextmenü. Damit erhöht sich die Kopierdialog auf:

Prüfendie "Open Kopie im Editor" Checkbox und klicken Sie auf OK. Dadurch wird das grafische Layout Editor auf dieser Kopie des Haupt Layout bringen.

Leider, was wir tun wollen istnicht ohne weiteres durch Android Studio Ausgabe des Drag-and-Drop-GUI-Builder unterstützt. So schalten Sie für dieses Layout auf die XML über, und ersetzen Sie es mit:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src /
main / res / Layout-w880dp / main.xml)

Wiederholender gleiche Prozess, Kopierenres / Layout / main.xmlindasres / Layout-h880dp /Verzeichnis und Ersetzender Kopie des Inhalts mit:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src /
main / res / Layout-h880dp / main.xml)

Schritt 2: Laden Unsere Sidebar Widgets

Jetzt dass wir den Teiler Widget und Sidebar Behälter (einige) unserer Layouts hinzugefügt, müssen wir diese Widgets zur Laufzeit zugreifen zu können.

Also, inEmPubLiteActivity, Datenelemente für sie hinzufügen:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Dann inonCreate ()vonEmPubLiteActivity, Jene Datenelemente, irgendwann nach dem Aufruf initialisierensetContentView ():

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Schritt # 3: Eröffnungdie Sidebar

Eine echte Produktionsqualität app würde animierte Effekte verwenden, um unsere Sidebar ein-und ausblenden. Allerdings haben wir noch nicht Animationen in diesem Buch behandelt, so werden wir einfach:

• Ursacheder Teiler sichtbar werden

• Einstellendasandroid: layout_weightunserer Sidebarsein3Anstatt von0Und gibt es ~ 30%
des Bildschirms (mit dem ursprünglichenRelativeLayoutimmer 70%, mit freundlicher Genehmigung von seiner Android: layout_weight = "7")

Mitin diesem Sinne, fügen Sie die folgende Umsetzung einesopenSidebar

()MethodeEmPubLiteActivity:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Hier haben wir:

• Bekommendie bestehendeLinearLayout.LayoutParamsvondie Sidebar

• Wenn es immer noch0 (dh die Seitenleiste nicht geöffnet wurde), weisen sie ein Gewicht von 3, aktualisieren Sie das Layoutüber setLayoutParams (), und schalten Sie die Sichtbarkeit des Teilers

Schritt 4: Laden Inhalt indie Sidebar

Jetzt dass wir unsere Sidebar erscheinen zu bekommen, müssen wir uns damit begnügen, in sie zu laden ... aber nur, wenn wir die Sidebar haben. Wenn EmPubLiteActivity ein Layout lädt, die nicht die Sidebar nicht haben, müssen wir mit unseren bestehenden Logik zu halten, die eine Aktivität gestartet, um den Inhalt anzuzeigen.

Mitin diesem Sinne, Datenelemente zu EmPubLiteActivity hinzufügen auf unsere Hilfe und über Fragmente zu halten:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

fügen Sie auchein Paar statische Datenelemente, die zur Identifizierung dieser Fragmente in unserem FragmentManager als Tags verwendet werden:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

fügen Sie auchein Paar statische Datenelemente, die die Pfade zu unserer Hilfe und über Vermögenswerte halten, da wir von mehr als einem Ort, sie werden unter Bezugnahme, wenn wir fertig sind:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

ImonCreate ()vonEmPubLiteActivityInitialisieren die Fragmente aus dem

FragmentManager:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

DasErgebnis ist, dass, wenn wir von einer Konfigurationsänderung zurückkommen, werden wir unsere Fragmente haben, sonst werden wir an dieser Stelle nicht.

Als Nächstes fügendie folgenden MethodenEmPubLiteActivity:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Beide vonDiese Verfahren nach dem gleichen Grundrezept:

• Überprüfen Sie, obSidebar ist null, um zu sehen, ob wir eine Sidebar haben oder nicht

• Wenn wir habeneine Sidebar, CallopenSidebar ()sicherstellen kann der Benutzer die Seitenleiste sehen, erstellen unsereFragmentwenn wir es tunhaben es nicht schon, und verwenden Sie einFragmentTransactionzu ersetzen, was auch immer war indie

Seitenleiste mit dem neuen

Fragment

• Wenn wir das tunnicht die Sidebar haben, eine Tätigkeit mit einer appropriately-konfiguriert Intent starten

Hinweisein paar Dinge mit unserenFragmentTransactionObjekte:

• Wir gebrauchenaddToBackStack (null), So dass, wenn der Benutzer wieder drückt, Android wird diese Transaktion rückgängig machen

• Wir gebrauchenersetzen()Anstatt vonhinzufügen()kann bereits ein Fragment in der Seitenleiste sein, da es (ersetzen()verhaltendas Gleiche wiehinzufügen()für einleeren Kasten)

Dann indasonOptionsItemSelected ()vonEmPubLiteActivity, ersetze dasetwa, undHilfe FallBlöcke zu verwenden,die neu hinzugekommenen Methoden, ersetzen ihre bestehenden Implementierungen: (von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Schritt # 5: Entfernen von Inhalten ausdie Sidebar

WährendaddToBackStack (null) wird Android ermöglichen, automatisch Fragmente zu entfernen, wenn der Benutzer BACK drückt, die nicht unsere Sidebar auf magische Weise nahe zu verursachen.

Vielmehr müssen wir uns selbst zu tun.

the einfachste Weg, dies zu verfolgen, ist der Zustand des "back-Stack" zu verfolgen. So fügenArbeitsgeräteFragmentManager.OnBackStackChangedListenernachdie Erklärung
vonEmPubLiteActivity, und inonCreate ()vonEmPubLiteActivity, Fügen Sie die folgende Zeile ein, irgendwann, nachdem Sie die initialisiertsidebarundTrennwandDatenelemente:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Diese Anweisung registriert unsere Tätigkeit als Empfangs Ereignisse zu Änderungen im Zusammenhang mit inder Zustand des Stapels zurück.

Um sicherzustellen,diese Kompilierung, müssen wir implementierenonBackStackChanged ()im EmPubLiteActivity:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Hier wird, wenn unser Rücken Stapel leer ist, wir umkehrendie Schritte von openSidebar () und schließen Sie es wieder zurück, den Teiler versteckt und der Seitenleiste des Gewichts auf 0 setzen.

Der kompletteüberarbeitetEmPubLiteActivityaussehen sollte nun so etwas wie:

(von

EmPubLite-Android Studio / T17-LargeScreen / EmPubLite / app / src / main / java / com /
commonsware / empublite /

EmPubLiteActivity.java)

Beimdieser Punkt, wenn Sie das Projekt und führen Sie es auf einem ausreichend großen Gerät oder Emulator zu bauen, und Sie wählen die Hilfe oder Seiten zu betrachten, sehen Sie die Seitenleiste angezeigt, ob im Hoch- oder Querformat.

Hinweisdass ein Tablett-Emulator wird in der Regel nur akzeptierbar schnell laufen, wenn Sie die x86-Emulator Bilder verwenden.

Rückwärtskompatibilität Strategien
und Taktik

Android ist eine sich ständig bewegendes Ziel, im Durchschnitt etwa 2,5 API-Level-Stufen pro Jahr.

Die Website Android Developer hältein Diagramm und Tabelle die letzte zeigtAbbau von OS-VersionenHerstellung von Anfragen vondas Play Store.

Die meisten Geräte sind in der Regel etwa 1-3 kleinere Releases geclustert werden. Aber,diese sind nie die neueste Version, die Zeit zu versickern durch die Gerätehersteller und Netzbetreiber und auf Geräte nimmt, ob diese neue Vertriebs oder Upgrades für bestehende Geräte.

Einige Entwickler Panik, wennsie erkennen dies.

Panic ist verständlich, wenn auch nicht notwendig. Dies ist ein gut verstandene Problem, das häufig in der Software-Entwicklung auftritt - fragen Sie alle Windows-Entwickler, der gleichzeitig alles von Windows 98 auf Windows XP oder Windows XP über Windows 8.1 hatte zu
unterstützen. Darüber hinaus gibt es viele Dinge im Android entwickelt dieses Problem so klein wie möglich zu machen. Was Sie brauchen, sind die Strategien und Taktiken, um sie alle trainieren.

Denken Sie vorwärts, nicht rückwärts

Android selbstsehr hart versucht, die Kompatibilität zu halten rückwärts. Während jede neue Android-Release viele Klassen und Methoden ergänzt werden relativ wenige als veraltet markiert und fast keine sind völlig eliminiert. Und in Android, "veraltet" bedeutet "gibt es wahrscheinlich eine bessere Lösung für das, was Sie versuchen zu erreichen, obwohl wir diese Option für Sie halten so lange, wie wir können".

Trotzdem wollen viele Entwickler reinder kleinste gemeinsame Nenner. Dem Ziel, ältere Versionen unterstützen, ist edel. Das Ignorieren, was da diesen Versionen passiert ist, ist dumm, wenn Sie versuchen, Ihre App an die Öffentlichkeit über den Play Store oder ähnliche Massenverteilungsmittel zu verteilen.

Warum? Sie möchten, dass Ihre App unverwechselbar zu sein,Zersetzen nicht.

Zum Beispiel sah wie wir indas Kapitel über die Aktionsleiste, eine Zeile zu dem Manifest Hinzufügen (android: targetSdkVersion = "11") gibt Ihnen die Aktionsleiste, die holographische Widget-Set (zB Theme.Holo), den neuen Stil der Optionen-Menü, und so weiter . Diejenigen, dead-Set auf 2.1 Dinge neuer als Android Vermeidung dieses Attribut nicht verwenden würde. Als Ergebnis auf Android 3.0+ Geräte, werden ihre Anwendungen sind in der Regel alt aussehen. Einige werden nicht durch andere Techniken, die sie beschäftigen (zB Spiele im Vollbildmodus ausgeführt wird), aber viele werden.

Das könnte dirdenken, dass dies keine Rolle würde. Nach allem, wie viele Menschen im Jahr 2011
wurden mit sogar Android 3.x? 5%?

Aber,diejenigen in Position, um Ihre Anwendung zu Trompete - Android-Enthusiasten Blogger unter ihnen Chef - neigen dazu, neuere Geräte laufen. Ihre Meinung ist uns wichtig, wenn Sie versuchen, ihre Meinung Schwanken andere im Verhältnis zu Ihrer App zu haben. Wenn Sie also auf sie out-of-touch aussehen, können sie weniger geneigt sein, glühende Empfehlungen der App an ihre Leser zur Verfügung zu stellen.

Außerdemnicht alles gegeben, um neuere Versionen von Android reinen "Eye Candy" ist. Es ist durchaus möglich, dass Merkmale in den neueren Android Versionen helfen könnte Ihre App aus dem Wettbewerb abzuheben, sei es eine stärkere Nutzung von NFC zu machen oder eine engere Integration in die Lager Kalenderanwendung anbieten oder was auch immer. eine "alte Funktionen, die nur" Ansatz Indem, lassen Sie diese Bereiche für Verbesserungen aus.

Und um das Ganze abzurunden,Die Welt bewegt sich schneller, als man denkt. Es dauert etwa ein Jahr für eine Freigabe von Version zu Mehrheitsstatus zu gehen (oder sein bereits auf dem Abstieg in Richtung Vergessenheit, ging neuere noch etwas mehr). Sie müssen vorsichtig sein, dass die Entscheidungen, die Sie heute machen müssen Sie nicht morgen Verhängnis. Wenn Sie sich auf das konzentrieren "alte Funktionen, die nur", wie viel Nacharbeit wird es dauern, in sechs Monaten, um aufzuholen, oder ein Jahr?

Daher,Dieses Buch spricht sich für ein Konzept, das von vielen aus, dass genommen unterscheidet: hoch hinaus wollen. Entscheiden Sie, welche Funktionen Sie verwenden möchten, ob diese Funktionen von älteren Versionen sind oder die neuesten und größten Release. Dann schreiben Sie Ihre App diese Funktionen verwenden, und Maßnahmen ergreifen, dass alles noch, um sicherzustellen, einigermaßen gut funktioniert auf älteren Geräten (wenn auch nicht als Voll gekennzeichnet). Auch dies ist ein gut ausgetretenen Pfad, durch Web-Entwickler verwendet, für Kinder ab (zB sexy Sachen in Firefox und Safari unterstützen, während immer noch anmutig für den IE6 zu verschlechtern). Unddie Techniken, die diese Web-Entwickler haben ihre analogen Techniken in der Android Welt verwenden.

Ziel, wohin Sie gehen

EinsSache im Auge zu behalten ist, dass das OS Verteilungsdiagramm und Tabelle oben auf Geräten angezeigt, basierend auf das Play Store zu kontaktieren. Daher ist diese nur direkt relevant, wenn Sie tatsächlich durch den Play Store verteilen.

Wenn Sie verteilen durchdie Amazon App Store oder auf gerätespezifische Steckdosen (zB

Blackberry World), müssen Sie berücksichtigen, welche Arten von Geräten zu ergreifen, um diese Verteilungsmittel verwenden.

Wenn Sie zielen spezifisch bestimmte nicht-Play Store-Geräte, wiedas Feuer anzündet, müssen Sie berücksichtigen, welche Versionen von Android laufen sie zu nehmen.

Wenn Sie eine App zu bauen verteilt durchein Gerätehersteller auf einem bestimmten Gerät, müssen Sie wissen, was Android-Version sein wird (zunächst) auf diesem Gerät und konzentrieren sich darauf.

Wenn Sie verteilen Ihre App an Mitarbeitereine fi

Mitglieder einer Organisation, oder
dergleichen, müssen Sie bestimmen, ob es eine spezifi Teilmenge von Geräten, die sie verwenden, und entsprechend zielen. Zum Beispiel verteilen einige Unternehmen könnten Android-Geräte an ihre Mitarbeiter, wobei in diesem Fall Apps für das Unternehmen auf diesen Geräten laufen soll, nicht unbedingt andere.

A Zielreiche Umgebung

Es gibtein paar Orte in Ihrer Anwendung, wo müssen Sie Android API-Ebenen von Bedeutung, um Ihren Code zu spezifizieren.

Das wichtigste ist,das Android: minSdkVersion Attribut, so früh in diesem Buch diskutiert. Sie müssen dies die älteste Version von Android zu setzen Sie bereit zu unterstützen sind, so dass Sie nicht auf Geräte älter als die installiert werden.

Es gibt auchandroid: targetSdkVersion, erwähnt in diesem Kapitel im Vorbeigehen. In der Zusammenfassung, erzählt dieses Attribut Android "Dies ist die Version von Android ist, ich dachte,
als ich den Code geschrieben". Android können diese Informationen benutzen, sowohl vorwärts und rückwärts Kompatibilität zu helfen. Historisch gesehen, war dies nicht ausreichend genutzt.

Doch mit API-Level 11 und API Ebene 14,Android: targetSdkVersion nahm eine größere Bedeutung.

Festlegen von 11 oder höher haben Sie die Aktionsleiste und den ganzen Rest des Look-and-Feel in der Honeycomb Version eingeführt. Festlegen von 14 oder höher wird Ihnen einige neue Features in Ice Cream Sandwich, wie automatische Leerzeichen zwischen App Widgets und andere Dinge auf dem Home-Bildschirm des Benutzers hinzugefügt. In der Regel eine bestimmte Android verwenden: targetSdkVersion wenn Anweisungen sagen Sie.

Der dritte Platz- Und vielleicht derjenige, der Entwickler verwirrt die meisten - ist das Build-Ziel.

Dies zeigt sich als compileSdkVersion in build.gradle für Android Studio und Gradle Benutzer.

Part der Verwirrung ist die mehrfachen Verwendungen des Begriffs "Ziel". Die Build-Ziel hat nichts mit Android zu tun: targetSdkVersion. Auch ist es nicht streng gebunden an, welche Geräte Sie zielen.

Es ist vielmehreine sehr wörtliche Ausdruck: Es ist das Ziel des Build ist. Es zeigt:

• Welche Version vondie Android-Klassenbibliothek Sie wollen gegen zu
kompilieren, diktierte, welche Klassen und Methoden können Sie direkt zu
beziehen sich auf

• Welche Regeln gelten, wenn die Ressourcen zu interpretieren unddas Manifest,
über Dinge zu beschweren, die nicht erkannt werden

Dasnet ist, dass Sie Ihre Build-Ziel gesetzt die niedrigste API-Ebene zu sein, die direkt alles, was Sie verwenden hat.

Lint: Es ist nicht gerade für Belly Buttons

Imdie alten Zeiten, die einzige Möglichkeit, fi
aus dass Sie eine neuere Klasse oder Methode
als wurden mit, was in Ihrem minSdkVersion war wäre Ihr Build-Ziel gesetzt das gleiche wie Ihr minSdkVersion zu sein. Auf diese Weise jeder Versuch, etwas neuer als Ihre Mindest verwenden würde mit der Kompilierung Fehler begrüßt. Dies funktioniert, aber zu einem hohen Preis: Es macht die Verwendung absichtlich neueren Fähigkeiten sehr schmerzhaft, zwingen Sie Reflektion verwenden sie zuzugreifen.

Heutzutage,ist dies nicht mehr erforderlich, dank Lint.

Lint ist ein Teil vondie Standard-Build-Prozess, neue Fehler und Warnungen für Dinge hinzufügen, die syntaktisch gültig sind, aber wahrscheinlich nicht die richtige Antwort. Insbesondere wird Lint Ihnen sagen, wenn Sie Klassen oder Methoden verwenden, die als Ihre minSdkVersion neuer sind, auch wenn sie für die Build-Ziel gültig sind.

Daher,die Targeting-Strategie ist heute:

• Stellen Sie IhreminSdkVersion, um dieälteste Version, die Sie bereit sind, zu
unterstützen,

• Stellen Sie Ihren Build-Ziel zu seindie Version von Android, die Sie alle Klassen und Methoden hat verwenden wollen, Lint so dass Orte zu zeigen, wo Sie die Aufmerksamkeit auf, welche Art von Gerät zu zahlen, müssen Sie laufen auf (mehr dies später)

• Stellen Sie IhretargetSdkVersion etwas relativ neu zu sein, es sei denn, Sie spezifi Gründe haben einige spezifi-Version zu verwenden

Ein wenig Hilfe von Ihren Freunden

Die einfachste Art und Weise zu verwenden,ein Feature noch Geräte unterstützen, die die Funktion nutzen zu können ist eine Kompatibilitätsbibliothek fehlt, die die Funktion für mehrere Geräte ermöglicht. Das Android-Support-Paket ist eine solche Kompatibilitätsbibliothek, obwohl es auch andere Klassen als auch bietet.

Miteine Kompatibilitätsbibliothek ist die API für die Bibliothek mit nahezu identischen die native Android-Fähigkeit zu verwenden, meist etwas anderen Paketnamen (zB
mittelsandroid.support.v4.app.FragmentAnstatt vonandroid.app.Fragment).

Also, wenn es etwasneu, dass man auf älteren Geräten verwendet werden soll, und das neue Feature ist die Hardware nicht offensichtlich gebunden, ob es eine "Backport" der Funktion zur Verfügung zu Ihnen ist. Beispiele dafür sind updates von:

• Calendar(https://github.com/SimonVT/android-calendarview)

• Schalter (https://github.com/BoD/android-switch-backport)

• Datumsauswahl (https://github.com/SimonVT/android-datepicker)

• Number(https://github.com/SimonVT/android-numberpicker)

• Timepicker (https://github.com/SimonVT/android-timepicker)

Vermeidendas Neue auf dem Alten

Obdas Ziel ist es, neue Möglichkeiten für neue Geräte zu unterstützen, obwohl sie nicht die Unterstützung für ältere Geräte zu verlieren, das bedeutet, wir die Fähigkeit zu bestimmen haben, welche Geräte sind neuere und welche Geräte sind älter. Es gibt einige Techniken, um dies zu tun, an denen Java und Ressourcen.

Java

Wenn Sie möchten, bedingt einige Zeilen Code ausführen basierend auf welche Version von Androiddas Gerät läuft, können Sie den Wert von Build.VERSION überprüfen, auf die android.os.Build Klasse verweisen. Beispielsweise:

Jedes Gerät, eine ältere Version von Android läuft wird überspringendie Anweisungen innerhalb dieser Version Wache und wird daher nicht ausgeführt werden.

Diese Technik ist ausrei
für Android 2.0 und höher Geräte. Wenn Sie noch Unterstützung

Android 1.x-Geräte sind,die Geschichte wird es ein wenig komplizierter, und das wird später in diesem Buch diskutiert werden.

Wenn du entscheidestdass Sie Ihre Build-Ziel möchten Ihre minSdkVersion Ebene zu entsprechen -
wie einige Entwickler zu tun wählen - Ihr Ansatz unterscheiden. Anstatt einige Aussagen Blockierung von auf alten Geräten ausgeführt wird, werden Sie einige Aussagen ermöglichen, sich auf neue Geräte ausgeführt werden, in denen diese Aussagen Java Reflexion verwenden (zB

Class.forName ()) Dinge zu verweisen, die neuer sind als das, was Ihr Build-Ziel unterstützt. Da mithilfe von Reflektion in Java extrem langwierig ist, ist es in der Regel einfacher Ihre Build-Ziel die Klassen und Methoden zu reflektieren haben Sie tatsächlich verwenden.

@TargetAPI

Ein Problem bei derdiese Technik ist, dass Ihre IDE an Sie murren wird, sagen, dass Sie Klassen und Methoden nicht verfügbar auf der API-Ebene für Ihre minSdkVersion gesetzt verwenden. Um beruhigen diese Lint-Nachrichten, können Sie die @TargetAPI Anmerkung verwenden.

Beispielsweise zuvor indas Buch, sahen wir Code wie folgt aus:

Dieses Dienstprogramm Methode führt einAsyncTask mit einem Multi-Threaded-Thread-Pool. Das ist das Standardverhalten von execute () auf API-Ebene 10 und darunter. Bei höheren Versionen von Android, wir ausdrücklich in die Multi-Threaded-Thread-Pool durch den Einsatz
executeOnExecutor () entscheiden können, aber das Verfahren nicht existiert vor der API-Ebene 11.

Daher überprüfen wir unsere API-Ebene zur Laufzeit über Build.VERSION.SDK_INT zu sehen, wenn wir auf Bienenwabe oder höher sind, und verzweigen. Doch für ein Projekt mit einer minSdkVersion von 10 oder darunter, wird Lint noch beschweren - Lint ist einfach nicht ausgereift genug, um zu erkennen, dass wir richtig neuere API-Ebenen umgehen. Das

@TargetApi (Build.VERSION_CODES.HONEYCOMB)Anmerkung sagt Lintdass wir in der Tat Konfi
dass we sind "das Richtige zu tun", zumindest über die API-Ebene 11.

Jedoch unter Verwendung von@TargetApi (Build.VERSION_CODES.HONEYCOMB), sagen wir implizit, dass wir nicht überprüft, um zu sehen, ob wir die Dinge richtig für höhere Versionen von Android tun. Solange alle Klassen, Methoden, und so, dass wir in diesem executeAsyncTask () -

Methode sind in API-Ebene verfügbar Referenz 11, wir sind fi

Ob wir verändern uns die

Umsetzung zu verweisen, etwas von, sagen wir, API Ebene 14, jetzt Lint wird wieder von vorn anfangen zu beschweren. Das ist, was wir wollen, so sind wir auf das Problem aufmerksam gemacht und es fi nden können. Daher setzen nur die @TargetApi () Anmerkung zur API-Ebene, die Sie

explizit Handhabung. setzen Sie es nicht nur bis zu einem gewissen willkürlich hohen Niveau (oder, schlimmer noch, verwenden @SuppressWarning versuchen Lint zu bekommen ganz zu schweigen).

Ressourcen

Die oben genannten Version Wachen arbeiten nur für Java-Code. Manchmal werden Sie verschiedene Ressourcen für die verschiedenen Versionen von Android zu haben. Zum Beispiel möchten Sie vielleicht macheneinen benutzerdefinierten Stil, die von Theme.Holo für Android 3.0 und höher erbt.

Da Theme.Holo existiert nicht auf früheren Versionen von Android, versucht, einen Stil zu verwenden, die von ihr erbt wird kläglich scheitern auf, sagen wir, ein Android 2.2-Gerät.

So behandelnDieses Szenario, verwenden Sie die -vNN ausrei zwei Ressourcengruppen zu haben. Eine (zB res / Werte-v11 /) würde auf bestimmte Android Versionen beschränkt sein und höher (beispielsweise API-Ebene 11 und höher). Die Standard-Ressource festgelegt (zB res / Werte /) würde für jedes Gerät gültig. Da jedoch Android wählt mehr spezifi Spiele fi
ein Ice Cream

Sandwich Telefon gehen würde mitdie Ressourcen, um die -v11 ausrei enthält

Damit, imdie -
v11 Ressourcen-Verzeichnisse, setzen Sie die Ressourcen, die Sie auf API-Ebene verwendet werden sollen 11 und höher, und legte die rückwärtskompatibel diejenigen in dem Satz ohne das Suffix.

Dies funktioniert für Android 2.0 und höher. Sie können auch verwenden-v3 für Ressourcen, die nur auf Android verwendet werden 1.5 (und nicht mehr) oder -v4 für Ressourcen, die nur auf Android 1.6 verwendet werden.

Komponenten

Eine Variantedie oben Trick ermöglicht es Ihnen, bedingt Komponenten aktivieren oder deaktivieren, API-Ebene basiert.

Jeden<Aktivität>.<Empfänger>, oder<Service>imdas Manifest kann eine Unterstützungandroid: aktiviertAttribut.Eine behinderte Komponente (Android: enabled = "false") Kann von niemandem gestartet werden, auch Sie.

Wir haben bereits gesehen String-Ressourcen in verwendet werdendas Manifest, für Dinge wie android: label-Attribute. Boolesche Werte können auch als Ressourcen erstellt werden. Vereinbarungsgemäß werden sie in einem bools.xml fi gespeichert
im res / Werte / oder damit verbundene

Ressourcengruppen. So wie <string> Elemente der Definition eines String-Ressource zur Verfügung stellen, <bool> Elemente liefern die Definition einer boolean Ressource. Geben Sie dem boolean Ressource einen Namen und einen Wert:

Das obige Beispiel hateine boolean Ressource, mit dem Namenon_honeycombMit einem Wert vonfalsch. Das würde typischerweise residieren inres / Werte / bools.xml. Allerdings könnte man auch eine habenres / Werte-v11 / bools.xmlfi
in dem Sie festlegenon_honeycombnachwahr.

Jetzt können Sie verwenden@ Bool / on_honeycombimandroid: aktiviertbedingtermöglichen, eine Komponente für die API-Stufe 11 oder höher, so dass es fürältere Geräte deaktiviert.

Das kann seinein nützlicher Trick in Fällen, in denen Sie mehrere getrennte Implementierungen einer Komponente benötigen, API-Ebene basiert. Zum Beispiel, die später in dem Buch werden wir App Widgets untersuchen - diese interaktiven Elemente Benutzern, ihre Home-Bildschirme hinzufügen.

App widgets sind Benutzerschnittstellen beschränkt, sondern API Stufe 11 hinzugefügt einige neue Funktionen, die zuvor nicht verfügbar waren, wie die Fähigkeit, Listview zu verwenden. Jedoch kann der Code für eine Listview-Backed-App-Widget wesentlich anders sein als für einen Ersatz App-Widget, das auf älteren Geräten funktioniert. Und wenn Sie das Listview-App-Widget im Manifest aktiviert zu lassen, kann der Benutzer versuchen, es wählen und abstürzt. So würde man nur die Listview-App zu aktivieren Widget auf API-Ebene 11 oder höher, mit den Booleschen Ressource Trick.

Testen
auf älteren Geräten funktioniert sowie neuere Natürlich, werden Sie sicher, dass Ihre App wirklich zu machen.

Bei BuildZeit, ein Trick in regelmäßigen Abständen zu verwenden, ist Ihr Build-Ziel zu ändern, um Ihre minSdkVersion übereinstimmen, dann sehen, wo der Compiler beschwert. Wenn alles bekannt ist (zum Beispiel, die Ressourcenattribute auf älteren Versionen werden ignoriert) oder geschützt (zB

Java-Anweisungen in einer Version Guard if-Anweisung), dann sind Sie auf OK. Wenn Sie jedoch Beschwerden über etwas sehen, vergessen haben, war nur in neueren Android Versionen, können Sie Schritte unternehmen, um die Dinge zu fi nden.

Sie wollen auch aufdenke über den Android-Versionen, wenn es um Tests geht, ein Thema, das später in diesem Buch abgedeckt wird.

Die Verfolgung der Änderungen

Jedes Android SDK Release wird von API Release Notes begleitet, wie zum Beispieldieser Satz für Android 4.4 / API Stufe 19.

Ähnlich, Jedes Release Android SDK ist durch seine "API Unterschiede Report", eine Liste von jedem hinzugefügt, entfernt oder geändert Klasse oder Methode begleitet. Beispielsweise kann dieseAPI Unterschiede Bericht weist darauf hin,die Änderungen zwischen API-Ebene 18 und API Stufe 19.

Weitere Änderungen sind aufgerufen, indie JavaDocs für Build.VERSION_CODESMit besonderem Schwerpunkt auf das, was passiert, wenn man einen spezifi API-Ebene als Ihr Android gesetzt: targetSdkVersion. Beachten Sie, dass diese Dienstplan nicht vollständig ist, aber einige Dinge nicht in den anderen Orten erwähnt erwähnen kann.

Jede Klasse, Methode und fi
im die JavaDocs hat eine Notation, was API-Ebene, die
bestimmte Element hinzugefügt wurde. Klasse API-Ebenen erscheinen in Richtung der oben auf der Seite; Verfahren und fi

API-Ebenen erscheinen aufdie rechte Seite von der grauen Leiste die

Methodensignatur oder fi enthält,

Erklärung. Auch indie JavaDocs "Android-APIs" Spalte auf
der linken Seite gibt es ein Drop-down, die Sie er den Inhalt, basierend auf API-Ebene zu fi nden können.

Systemdienste

Einer vondie Probleme, die wir in Android-App-Entwicklung haben, ist die Überlastung von Begriffen. Wir haben bereits gesehen, wie "Layouts" manchmal Layout Ressourcen beziehen und manchmal Containerklassen wie Linearlayout beziehen.

another Beispiel kommt in dem Namen "Service". Dies wurde bereits in einigen Orten in Java verwendet wird (zB ExecutorService). Android verwendet es dann füreiner unserer vier App Komponenten. Android nutzt auch "Service" als Teil des Begriffs "Systemdienst" ... wo Systemdienste wenig mit Java-Dienste oder Android-Diensten zu tun.

Was istein System Service?

Systemdienste sind "Manager" -Typ Klassendass Sie durch den Aufruf getSystemService () auf einem bestimmten Kontext, wie eine Tätigkeit oder die Dienstleistung zu bekommen.

Normalerweise Systemdienste auf niedrigerer Ebene Gerätefunktionalität gebunden, wie Telefonie.

Allerdings sind nicht alle Low-Level-Gerätefunktionalität wird durch Systemdienste ausgesetzt; einige haben getrennte APIs, die von anderen Arten von "Manager" Klassen implementiert.

Es gibt zwei Arten vongetSystemService (). Die eine, die Sie wahrscheinlich zu verwenden sind, ist das eine, die einen String-Parameter annimmt, dass der Name des Systems, Service, den Sie möchten. Sie erhalten ein generisches Objekt zurück, die Sie dann auf den spezifi Art von Systemdienst niedergeschlagenen, die Sie verwenden möchten:

API Stufe 23 fi
y hinzugefügt, um eine typsichere Version von getSystemService (). Sie
passieren in der Java-Klasse-Objekt für den Systemdienst und eine Instanz dieser Klasse zurück: Doch bis IhrminSdkVersionsteigt auf 23 oder höher, werden Sienicht verwenden können, um diese VersiongetSystemService ()aufKontextaufälteren Geräten.

Ach,es gibtkeine RückportierungvongetSystemService ()aufContextCompatvondie Android-Support-Bibliothek.

Was Systemdienste gibt es?

Es gibt viele Systemdienste mitneue jede Android-Version Release oder zwei kommen. Hier sind die wichtigsten sind, wie von Android 6.0, mit Links zu den Kapiteln, die auf sie konzentrieren (wo verfügbar):

• AccessibilityManager, für wobei der Schlüsselsystemereignisse (zB das Starten von Aktionen) informiert, dieüber eine haptische Rückmeldung, Audio-Hinweise oder andere nicht-visuelle Hinweise an Benutzer weitergeleitet werden könnten

• Accountmanager, für mit Android-System von Benutzerkonten arbeiten und

Synchronisation

• Activitymanager, um weitere Informationen zu bekommen, was Prozesse und

Komponenten derzeit auf dem Gerät ausgeführt werden

• Alarmmanager, für geplante Aufgaben (auch bekannt als "cron-Jobs"),
überdachteanderswo in dieses Buch

• AppOpsManager, für "Tracking-Anwendung Operationen auf dem Gerät"

• AppWidgetManager, Für die Erstellung oder HostingApp-Widgets

• Audio-Manager, für die Verwaltung von Audio-Stream-Volumes, Audio-Ducking
und andere systemweite affordances Audio

• BatteryManager, Für fi
aus etwa der Zustand der Batterie

• BluetoothManager, Zum Belichten oder Anschlussverbindungen zu Bluetooth

• ClipboardManager, für mit dem Gerät Zwischenablage arbeiten, abgedecktanderswo in diesem Buch

• ConnectivityManager, für eine High-Level-Look wie auf welche Art von Netzwerk
das Gerät für Daten verbunden ist (zB WiFi, 3G)

• ConsumerIrManager, für "IR-Blaster" oder andere IR-Sende-Anwendungen erstellen, auf Hardware, die hat einen IR-Sender

• DevicePolicyManager, für den Zugriff aufGeräteverwaltungFunktionen wie

Abwischendas Gerät

• Displaymanager, zur Kommunikation mit externen Displays arbeiten,
abgedecktanderswo in dieses Buch

• Downloadmanager, für das Herunterladen großer fi
auf im Auftrag von der

Benutzer, bedeckt inanderswo indas Buch

• DropBoxManager, für Ihre eigenen Ringpuffer von

Protokollinformationenähnlich LogCat Aufrechterhaltung

• FingerprintManager, Denn mit fi Arbeits
erprint Leser auf Android 6.0+ Geräte

• InputMethodManager, Für mit Eingabemethoden-Editoren arbeiten

• Inputmanager, zur Identifizierung von externen Eingabequellen, wie Tastaturen und Trackpads

• Jobscheduler, für die Planung der regelmäßigen Hintergrundarbeit, abgedecktanderswo im Buch

• KeyguardManagerZum Verriegeln und Entriegeln der Tastensperre, soweit möglich

• LauncherApps, für auf dem Gerät startbar Anwendungen zu identifizieren (zB für Trägerraketen Home-Bildschirm), wobei in die Politik Rechnung Gerät

• LayoutInflater, für fi Layout XML Aufpumpen
in Ansichten, wie Sie gesehen
haben früher in das Buch

• Locationmanager, für die Bestimmung die Position des Geräts (zB GPS), bedeckt indas Kapitel über die Standortverfolgung

• MediaProjectionManagerfürErfassung von Screenshots und Screencasts

• Mediarouter, fürArbeiten mit externen Lautsprechern und Displays

• MediaSessionManagerFür etwa Medien Android Lehre, die Sie wiedergeben

• MidiManager, Für MIDI-Audio-Wiedergabe

• NetworkStatsManager"Für die Netznutzungsstatistiken abfragen"

• NfcManager, fürLesen NFCTags oder Schieben NFC Inhalt

• NotificationManager, für Symbole in der Statusleiste und ansonsten Warnung der Nutzer, um die Dinge setzen, die noch asynchron aufgetreten ist, bedeckt indas Kapitel Benachrichtigung

• NsdManager, für Netzwerk-Service-Discovery-Operationen

• PowermanagerZur GewinnungWakeLockObjekte und solche, bedecktanderswo in
diesem Buch

• PrintmanagerfürDruck von Android

• RestrictionsManagerZur Identifizierung und Arbeiten mit eingeschränktem

Betrieb

• Search, Denn mit dem globalen Suchsystem interagieren

• Sensormanager für Datenüber Sensoren, wie beispielsweise dem Beschleunigungsmesser Zugriff abgedecktanderswo indieses Buch

• Storagemanager, für mit erweiterten Nutzlasten arbeiten (OBBs) geliefert als Teil Ihrer App-Installation aus dem Play Store

• SubscriptionManager, Für mit Daten-Roaming und andere Telefonie Abonnement-

Regeln zu tun

• TelecomManager, Für mit ein- und ausgehende Anrufe zu tun

• TelephonyManager, für fi
aus etwa der Zustand des Telefons und die
zugehörigen Daten (zB SIM-Karte Details)

• TextServicesManager, Denn mit Rechtschreibprüfung und andere "Textdienste"

working

• TvInputManager, für Android-Fernsehern, zu fi
aus über TV-Eingänge

• UiModeManager, für den Umgang mit verschiedenen "UI-Modi", wie in einem Auto oder Schreibtisch Dock angedockt

• UsageStatsManager"Für die Gerätenutzungsstatistiken abfragen"

• UsbManager, für die Arbeit direkt mit Zubehör und Rechnerüber USB

• Usermanager, für die Arbeit mit mehreren Benutzerkonten auf einem kompatiblen

Gerät (Android 4.2+ Tabletten, Android 5.0+ Telefone)

• Vibrator, zum Schütteln des Telefons (zB haptisches Feedback)

• WallpaperService, Für mit dem Gerät arbeiten Tapete

• WifiManager, um weitere Informationenüber die aktiven oder WiFi-Netzwerken
bekommen

• WifiP2pManager, für den Aufbau und die Kommunikationüber WiFi Peer-to-Peer (P2P) Netzwerke

• Windowmanager, vor allem für Detailsüber die Standardanzeige für das Gerät Zugriff auf Google Play-Dienste

Ein Begriff, der Sie ein gutes Stück als Android-Entwickler begegnen, ist "Google Play-Dienste"

oder "Play Services" für kurz. Dies ist Ihr Tor in eine Reihe von proprietären Funktionen, die Google auf der Android lagert hat. Viele dieser Funktionen werden auf den Google-Servern und Dienstleistungen gebunden, wie Anzeigen und Google Drive.

Aber,diese Fähigkeiten, während in der Regel frei von monetären Kosten in den Entwickler, sind von Problemen oder nicht unumstritten.

Was ist Google Play-Dienste?

Google Play Servicesein "kitchen sink" Begriff, gleichermaßen eine breite Palette von Dingen aus der Sicht der Entwickler und Anwender umfasst.

... Aus der Sicht der Entwickler?

Die Play Services SDK ermöglicht es Ihnen, Ihre Android-App zu integriereneine Reihe von Google proprietäre Dienste, von Leaderboard-Management für Spiele mit Chrome Geräten zu interagieren.

Viele, aber nicht alle dieser Dienste werden auf Google-Server gebunden. Viele, aber nicht alle dieser Dienste wird eine Art von API-Schlüssel als Ergebnis benötigen.

Das SDK kommt indie Form eines Android-Bibliothek-Projekt, das Sie in Ihrer Anwendung verknüpfen, so dass Sie auf Klassen und Methoden zugreifen, die Sie Karten lassen hinzufügen oder Zahlungsoptionen oder Push-Nachricht Empfang in Ihrem Android-Apps.

Nichte, dass, während der Name "Play-Dienste" enthält das Wort "services", Play-Dienste ist nur eine API, eine, die nicht direkt etwas hat mit dem zu tunDienstleistungenoder

Systemdienstleistungen.

... Aus der Sicht der Nutzer von Google Play-Geräte?

In den westlichen Ländern,die gemeinsame Wahrnehmung ist, dass alle Android-Geräte ein Teil der Google Play Welt sind. Diese Geräte haben die Play-Services Framework vom Gerätehersteller vorinstalliert und leise über die Luft von Google aktualisiert. Apps, die die Play-Services SDK in der Theorie können alle auf allen Geräten mit der Play-Services Framework ausgestattet verfügbaren APIs SDK verwenden.

In der Praxis, ältere Geräte (vor allem Android 2.x) haben einigeReihe von Einschränkungen zu Play-Dienste im Zusammenhang, nicht zuletzt von denen der Mangel an automatischen Over-the-Air-Updates sein. Wie viele Entwickler setzen nun ihre minSdkVersion etwas höher (zB 15), ist diese besondere Klasse von Problemen auf der Strecke fallen wird dazu neigen, zu sein.

... Aus der Sicht des Android-Ökosystem?

Googles weiteren Ausbaudie Play-Services SDK, manchmal auf Kosten von Android selbst, hat sich als nicht bewiesen allgemein beliebt:

• Entwickler, die davon abhängen,die Play-Services SDK wird nicht auf Geräte in der Lage zu laufen, dass die Play Services Framework fehlen. Und während viele Leute denken, dass die einzigen Geräte, die die Play Services Framework Rolle, zeigen einige Schätzungen, dass mehr als die Hälfte der Android-Geräte im Einsatz heute von den Herstellern, die nicht Teil des Google-Ökosystem zu spielen sind.

• Die Play Services SDK ist Closed-Source, und als solche macht das Debuggen
bestimmte Klassen von Problemen erschwert.

• Die Bedingungen für die Verwendung von verschiedenen Aspekten derdie Play-Services SDK für einige Entwickler können Probleme verursachen, angefangen mit ihrem geplanten Geschäftsmodell stören ihre geplante Software-Lizenz zu stören (zB GPL).

Was ist indie Play-Services SDK?

Wie bereits erwähnt,die Play-Services SDK ist riesig. Die folgenden Unterabschnitte einige der wichtigsten Stücke des Play Services SDK umreißen, was Gradle Abhängigkeit sie zieht, und welche unabhängige Alternativen vorhanden sind (falls vorhanden).

Android Pay/ Google Geldbörse

Google hatein paar Mal versucht, in die Mobile-Payment-Markt zu bekommen, mit Google Wallet starten, die jetzt in Android Pay verwandelt hat. Wenn Sie Benutzern erlauben möchten, Waren und Dienstleistungen durch Ihre App zu kaufen, und Sie möchten die Benutzer zu erlauben, über Android Pay bezahlen, können Sie diesen Teil des Play Services SDK verwenden.

Android Wear

Für die Kommunikation vonein Gerät, eine Open-Source-Betriebssystem (Android, auf einem Smartphone oder Tablet) zu einem Gerät mit einer Open-Source-Betriebssystem (Android, auf einem Android Wear Gerät) ausgeführt wird, müssen Sie eine proprietäre, Closed-Source-Bibliothek verwenden.

Es ist möglich, zu zeigen,Eine Benachrichtigung über eine Wear-Gerät direkt aus dem Android SDK.

Es ist auch möglich, eine Wear App zu erstellen, die aus dem Android SDK Standalone gerade vorhanden ist. Aber wenn Sie zum Senden von Daten an die Wear-Gerät aus dem Handy oder Tablet, oder umgekehrt wollen, dass erfordert die Verschleißteil des Play Services SDK.

Diese Bibliothek stelltein paar diskrete APIs für die Kommunikation:

• Eine gemeinsam genutzte Daten-API, wo beide Seiten können von einem Schlüssel-

Wert-Speicher lesen und zu schreiben, die sich zwischen den beiden Umgebungen
synchronisiert ist

• Eine Meldung API, für einen klassischen Punkt-zu-Punkt-Kommunikation Muster

• Ein Asset-Transfer-API, die für größere Datenmengen (zB große Bilder)

Google+

Die Dokumentation und Geschäftsvorschlag fürdie Google+ API ist ein bisschen zu diesem Zeitpunkt begrenzt. Es scheint jedoch, dass man:

• hinzufügena + 1-Schaltfläche, um Ihre Anwendung, wenn das klingt interessant

• haben reichere Möglichkeiten für den Austausch von Inhalten zuGoogle+ Konto des Benutzers, über einfache ACTION_SEND

• untersuchendie Google+ des Benutzers profi
und einigeDie Freunde des Benutzers
auf Google+

Google-Konto einloggen/ Anmeldung mit Google

Lieberals Ihr eigenes Konto System beizubehalten, könnte Ihre App, die Nutzer in ihrem Google-Konto als Teil Ihrer Anwendung der Verwendung unterzeichnen fragen.

Google Analytics

"Analytics" bezieht sich auf die Verwendung zu verfolgen. Web Analytics verwendeteine Mischung aus Web-Server-Logs, Tracking-Cookies und dergleichen beliebten Web-Seiten, Navigation Ströme, die Zeit in bestimmten Bereichen einer Website und so weiter ausgegeben, um zu bestimmen. Mobile Analytics überwacht die Benutzung innerhalb einer App: bestimmte Tätigkeiten, bestimmte Operationen usw.

Google Analytics ist sehr beliebt für Web-Sites und Google erweitertdies zu einem mobilen API für Tracking-App-Nutzung ausgelegt.

Es gibt unzählige Analysedienste mit Android-APIs (zBFlurry) über Google. Zwar gibt es offenbar nur wenige selbst gehosteten oder Open-Source-Lösungen zu sein, ist Analytik Datensammlung nicht besonders schwierig, auf eigene Faust zu implementieren, wenn Sie diese Informationen mehr privat halten würde es vorziehen. Die Datenanalyse ist, wo die Herausforderungen im Zusammenhang mit home-grown-Lösungen entstehen. Oder Sie könnten einfach nicht diese Art von Informationen zu sammeln.

Google App-Indexierung

Google App-Indexierung, unter anderem ermöglicht "Deep-Links" in eine Android App, tauchte von Google-Suchergebnissen. Dass auf eigene, tutkeine besonderen proprietäre APIs erfordern.

Allerdings erlauben Google diese "Deep-Links" zu entdecken, scheint es, dass Sie eine benutzerdefinierte App-Indizierung API verwenden.

Google App Ankündigungen

Googles App lädt ein Service ermöglicht es den Benutzern zu ärgernihre Kontakte, nervt sie die App zu installieren.

Eine einfachere, wenn auch weniger glatt, Lösung ist dem Benutzer zu ermöglichen, um Ihre Anwendung von seinem Vertriebskanal zum Senden von Nachrichten aus Ihrer App mit einem Link zurück (zB Play Store), wie zum Beispiel über eine ACTION_SEND Intent.

Google Cast

Google Cast kann gedacht werden alsein Steuerprotokoll für Google Cast-fähigen Empfänger. Durch eine von Google bereitgestellte SDK (oder andere Mittel), Google Cast Client-Anwendungen (

"Absender") können eine Google Cast-fähigen Empfänger direkt zu spielen, Pause, Zurückspulen, Schnellvorlauf usw. einen Stream. Android-TV-Geräte und Chromecast-Geräte sind die primären Cast-fähigen Empfänger.

Google Cast übernimmtdass in der Regel der Media-Receiver verfügt über eine eigene Betriebssystem und ist in der Lage Streaming-Medien ohne laufende Unterstützung der Google Cast-Client zu spielen. Daher wird der Kunde nicht "gesperrt in" Feeding Inhalt an den Google Cast Client halten zu müssen, so dass der Benutzer zu gehen und andere Dinge tun, mit dem Kunden während der Wiedergabe los ist.

Chrome bietet Remote-Wiedergabe Medien Routen und arbeitet mitRemotePlaybackClientWird, wie diskutiert indas Kapitelüber Mediarouter. Die Beispielanwendung fürRemotePlaybackClientwurde getestet aufein Chrome.

Wenn Sie eine größere Kontrolleals über RemotePlaybackClient angeboten wird, können Sie jedoch verwendendas Cast SDK. Jedoch unter Verwendung vondas Cast SDK finden Sie auf Google Cast binden - und einige seiner Beschränkungen, sowohl technische als auch rechtliche - aber werden Sie größere Entwickler Kontrolle über das Verhalten sowohl der Google Cast-Gerät und Ihre Anwendung geben.

Wie oben beschrieben,RemotePlaybackClient, zusammen mitdas PräsentationAPI, Angebotein signifi

Teilmenge dessen, wasdas Cast SDK bietet.

Google CloudMessaging

Google Cloud Messaging- GCM für kurze - asynchron liefert Meldungen aus dem Internet (

"Cloud"), um Android-Geräte. Anstatt das Gerät und Polling in regelmäßigen Abständen auf Geheiß der App wachen, können Sie Ihre App für Benachrichtigungen anmelden und dann warten, bis sie ankommen. GCM ist mit Effizienz im Verstand ausgeführt:

• Apps tunnicht ständig in Betrieb sein müssen, ihre eigene Socket-Verbindungen zu einem gewissen XMPP oder MQTT Server beibehalten (allein mehrere solcher

Anwendungen können)

• Apps können teileneine einzelne verwaltete Verbindung zu einem Server von Google, eine, die auch sorgfältig abgestimmt ist die Leistungsaufnahme zu minimieren, während die Verbindung am Leben zu halten

• Apps können häufige Wakeup-Ereignisse für die Abfrage zu vermeiden, einige Server tun lassendie "schweres Heben" und tippen Sie einfach die App auf dem virtuellen Schulter es einige interessante Daten zu informieren

Die richtige Verwendung von GCM bedeutet bessere Akkulaufzeit für die Benutzer. Es kann auch reduzierendie Menge an Zeit, um Ihr Code ausgeführt wird, die Sie bleiben aus Sicht der Nutzer hilft suchen auf Hintergrundaufgaben zu stürzen und sie mit Aufgabe Killer auszurotten.

GCM hat durch vier Revisionen seiner API gegangen, einschließlichdie 2016 Rebranding als Firebase Cloud Messaging (FCM). Achten Sie darauf, up-to-date Referenzen und Beispiele zu verwenden, wenn GCM / FCM auf Anwendungen hinzufügen.

You kann auch Verweise auf "C2DM", GCM der Vorläufer begegnen. C2DM im Jahr 2010 debütierte und wurde schnell populär, für alles von der Auslösung in der Nähe von Echtzeit-Daten-

Synchronisation (zB Remember the Milk To-do-Liste-Updates), um leichte Koordination zwischen mehreren Spielern in einem Spiel. Allerdings war C2DM ein Google Labs Produkt und in ständiger Beta-Form. Bei Google Labs heruntergefahren wurde, war C2DM in der Schwebe: nicht abgebrochen, aber nicht in einem tatsächlichen Produkt umgewandelt. Im Jahr 2012 ersetzt GCM
formal C2DM, und im Jahr 2015, C2DM wurde komplett heruntergefahren. Während also High-Level-Konzepte über Push-Messaging aus der C2DM Ära noch relevant sein könnte, zu Ihnen, jede tatsächliche C2DM bezogenen Code wird nutzlos sein.

Andere Geräte von außerhalbdie Play-Ökosystem Google können ihre eigenen Kollegen zu GCM
bieten. Unabhängige Push-Implementierungen von XMPP und MQTT zu einfachen WebSockets reichen, obwohl diese Grenzen haben, wenn sie GCM verglichen.

Google Drive

Google Drive ist von Google gehostet fi -Speicher-Service. Über Drive-APIs in der Play-Dienste SDK können Sie arbeiten indirekt mit dem Google Drive-gehosteten Inhalten des Benutzers, einschließlich Erstellen und Löschen von fi

Sowie die Suche durch fi
für Einsen dass
bestimmte Suchkriterien erfüllen.

Hinweisdass ein Teil dieser Funktionalität wird über die verfügbarenSpeicherzugangsrahmenin ab Android 4.4, mitden Vorteil, dass es über mehrere Inhaltsquellen funktioniert, nicht nur Google Drive.

Andere Dienste (zB Dropbox) habenals auch ihre eigenen APIs.

Google Fit

Google Fit ist Googles tragbare Sensor Initiative für "smartbands" und verwandte Geräte.

Durchdie Fit-APIs können Sie Fit Geräte erkennen mit dem Gerät eines Benutzers verbunden sind, lesen Daten aus diesen Geräten "Sensoren (zB Herzfrequenz), und so weiter.

Andere Hersteller indieser Raum (zB Fitbit) haben ihre eigenen SDKs auch.

Google Location Services

This Teil des Play Services SDK bietet die "verschmolzenen Standortanbieter". Dies kombiniert GPS und Netzwerkquellen und Standortdaten sowie Sensorinformationen, um zu versuchen, eine bessere Standortinformationen mit weniger Stromverbrauch bieten. wenn die Sensoren vorschlagen, zum Beispiel, dass das Gerät nicht bewegt wird, kann der fusionierten Standortanbieter zurückfahren, wie aggressiv er die Standortquellen verwendet, da die Lage wahrscheinlich nicht verändert.

Diese Bibliothek bietet auchein "Geofencing" Implementierung, wo Sie die Play-Services SDK
fragen Spur von bestimmten Orten zu halten und lassen Sie wissen, ob das Gerät in einem gewissen Abstand von diesen Stellen wird.

Dieses Buch hatein Kapitel überder kondensierte Standortanbieter.

GoogleKarten

Android hat integrierte Google Maps für Entwickler angeboten seitder Anfang. Mit der Einführung von Karten V2 im Jahr 2012 wurde diese Fähigkeit in die Play-Services SDK gefaltet. Durch Karten V2 können Sie eine Karte bereitgestellt von Google Maps in Ihre Anwendung, komplett mit Markern und Pop-ups, Linien und schraffierten Flächen, und so weiter einbetten.

Dieses Buch hatein Kapitel überKartenV2.

Wegendie Popularität von Embedded-Karten anderer Hersteller (zB Amazon, Blackberry) haben ihre eigene Karte Motoren angeboten, die oft mit APIs, die von Karten V2 (oder vielleicht sein Vorgänger, jetzt bekannt als Karten V1) zu imitieren versuchen. Darüber hinaus gibt esdas OpenStreetMap-Projekt,, Für die Android-Bibliotheken zur Verfügung.

GoogleMobile Ads / AdMob

Google ist eine Werbe-Unternehmen. Sie bieten andasGoogle Mobile Ads-SDK (aka, AdMob für Android) im Rahmendas Play Services SDK für Sie Banner, Interstitial, und andere Formen der Werbung, um Ihre Anwendung zu können hinzuzufügen.

Es gibt auch andere konkurrierende mobile Ad-Netzwerkedass Sie sollten sich überlegen, ob Sie besser konzentrieren gedient sein kann mit einem besseren Geschäftsmodell kommen.

GoogleMobile Vision

Google hateine Vielzahl von APIs, unter dem "Mobile Vision" Banner gruppiert, zum Nachweis spezifi Arten von Objekten oder andere Informationen in noch Fotos und Videos ausgelegt. Diese beinhalten:

• Detektion von Gesichtern, undder Zustand dieser Flächen (zB Ausdrücke)

• Detektions- und Decodieren von Barcodes

Android nativen Kamera-API hat eine gewisse Menge an Gesichtserkennung, obwohlnicht auf das Niveau des Gesichts API in der Mobile Vision SDK.

Es gibteine Vielzahl von Barcode-Scanning-Anwendungen (zB das legendäre ZXing Barcode-Scanner) und Bibliotheken (zB ZBar), dass man unabhängig von der Play-Services SDK
verwenden können.

Google Nähe

Google Nähe Angeboteein Paar von APIs für die Kommunikation zwischen Geräten in der Nähe.

Die Nachrichten-API-Angeboteein Publish-and-Subscribe-Messaging-Framework, die für kleine Datenblöcke zwischen dem Internet verbundenen Android und iOS-Geräte zu senden. Dies ist weitgehend reibungsfrei für den Benutzer (über die Netzwerkverbindung), da das Nachrichten-API

eine Mischung von Funkgeräten (Bluetooth, Bluetooth LE, WiFi) und Ultraschall-Signalisierung verwendet die Paarung und Interaktion zu handhaben.

Die Nähe Connections API bietet verbindungsbasierte Messaging-Gruppe zwischen den Geräten aufdas gleiche WiFi-Netzwerk. Während Sie mehr Daten auf diese Weise passieren kann, da jeder auf WiFi sein muss, es reduziert die Anzahl der möglichen Kommunikationspartner.

Während einige Aspekte von Google in der Region (zB Ultraschall) ungewöhnlich sind, gab es serverlose Gruppenkommunikation bietet viele Projekte gewesen, von ZeroMQ zu AllJoyn.

Sicherheitsnetz

Die SafetyNet APIs lässt Ihre App wissen ", obdas Gerät, auf dem es läuft entspricht dem Profi

Ofa-Gerät, das Android-Kompatibilitätstests "bestanden hat. Vermutlich wird diese Ihnen erkennen benutzerdefinierte ROMs oder Kopien Ihrer App von Piraten-Sites auf inkompatible Hardware installiert zu helfen.

Hinzufügen von Play Serviceszum Projekt

Aufdie zuvor erwähnte Kompilierung statement (s) hinzufügen, dann beginnen, einige Methoden aus den gelieferten Play Services SDK-Bibliotheken aufrufen: Die Oberfläche, Play-Dienste verwenden sollte einfach sein.

Leider ist esnicht so einfach. Es gibt eine Reihe anderer Dinge, die Sie mit, damit beschäftigen müssen Play-Dienste in Ihre Anwendung zu integrieren.

DasMetadaten

Sie werden viele Beispiele sehendie zeigen, eine mit<Meta-data>Element, in Ihrem<Application>Element, mit einemandroid:

namevoncom.google.android.gms.versionundein Wert in einem Integer-Ressource ziehen (@

Integer / google_play_services_version) Aus dem Play Services SDK:

(von

Lage / FusedNew / app / src / main /

AndroidManifest.xml)

Das istwenn Sie nicht mehr benötigt, werden mit der Version 8.1.0 oder höher von der Play-Services SDK. Dieses Element wird zu Ihrem Manifest hinzugefügt werden, automatisch überdas Manifest Merger-Prozess.

Die Lizenz

Die Bedingungen für die Verwendung vondie Play-Services SDK Zustand, dass Sie einige Lizenzbedingungen von Play-Dienste in Ihrer Anwendung zeigen müssen. Genau dort, wo und wie Sie dies tun, ist weitgehend an Ihnen, wenn auch bedenken, dass Google könnte Ihre Anwendung überprüfen

Compliance, und so sollten Sienicht versuchen, die Lizenzen zu betrügen und nicht zeigen. Wenn Sie eine eigene Lizenz haben (zB in einem Info-Bildschirm), können Sie die Play-Dienste Lizenzen zeigen zusammen mit Ihrem eigenen.

ImFalle dieser Beispielanwendungen Buch, das die Play-Services SDK verwenden, gibt es eine spezielle Aktivität (LegalNoticesActivity), die für die Anzeige der Lizenzen zuständig ist: (von

Lage / FusedNew / app / src / main / java / com / commonsware / android /
weather2 / LegalNoticesActivity.java)

BekommenDer

Lizenztext,

CallgetOpenSourceSoftwareLicenseInfo

()auf
einer

Instanz
vonGoogleApiAvailability. Sie können dann diese irgendwo angezeigt werden (zB in einemTextview).

Hinweisdass diese Methode einSchnur, keinCharSequenceUnd so wird nicht der Text formatiert werden.

Dann ist es lediglicheine Frage, die Benutzer ermöglicht, diese Aktivität zu sehen, wie ein mit MenüRessource für sie:

(von

Lage / FusedNew / app / src / main / res / menu /
abstract_google_api_client_activity.xml)

... Und mitdiese Ressource in eine andere Tätigkeit

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Der Umgang mit Runtime Berechtigungen

Android 6.0, die Laufzeit- Berechtigungssystem wirkt sich auf einige vondie Play Services APIs.

Zum Beispiel, wenn Sie versuchen, die Lage über das zu bekommenverschmolzenen

Standortanbieter, Du wirstmüssen ACCESS_COARSE_LOCATION oder

ACCESS_FINE_LOCATION. Beide von denen sind gefährliche Berechtigungen, so apps mit einem targetSdkVersion von 23 oder höher benötigen diese Berechtigungen zur Laufzeit zu verlangen.

DasLage / FusedNewBeispielanwendung enthält einAbstractGoogleApiClientActivitydass unter anderem, hilft uns, mit Laufzeitberechtigungen in unserem Play Services SDK-Apps verwenden beschäftigen.

Erkennen, ob wir die Erlaubnis haben

Die Idee hinterAbstractGoogleApiClientActivityistdass apps die Play Services SDK werden die Aktivitäten, die erben vonAbstractGoogleApiClientActivity, Ein paar Methodenüberschreiben zu

konfigurieren, wieAbstractGoogleApiClientActivityGriffeDinge wie Laufzeitberechtigungen.

Beispielsweise,AbstractGoogleApiClientActivityhat
einabstraktMethodegenanntgetDesiredPermissions ()dass Unterklassen müssen außer Kraft setzen, eine Bereitstellung vonSchnurFeld von Berechtigungen, die die Aktivität
benötigt.AbstractGoogleApiClientActivitydann verwendethasAllPermissions ()undhasPermission ()private Methoden, ob alle zu bestimmen,die angeforderten Berechtigungen werden zur Zeit gehalten: (von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

ImonCreate ()vonAbstractGoogleApiClientActivityUnter anderem, nennen wirhasAllPermissions ()zu sehen, wenn wir alle unsere erforderlichen Berechtigungen- Wenn ja, können wir voran gehen und rufen eininitPlayServices ()Verfahren zu startender Prozess unser Zugriff auf die Play-Services SDK der Initialisierung:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Anfordern von Berechtigungen

Wenn wir das tunnicht alle Berechtigungen haben,onCreate ()werde anrufenrequestPermissions ()aufActivityCompatFragender Benutzer für sie. Aber auch sie nutztnetPermissions ()zu fi er die Berechtigungen aus, dass der Benutzer zuvor gewährt, so
wir nur die Müheder Benutzer mit Berechtigungen, die der Benutzer entweder noch nicht gesehen hat oder vorher verweigert hat:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Hinweisdass dieser Code den Benutzer auf vorherige Genehmigung Dementis Verwendung von shouldShowRequestPermissionRationale () machen zu erkennen und vielleicht einige UI zeigen zu erziehen, was die Auswirkungen sind von dieser Ablehnung nicht.

Handhabungdas Ergebnis

Der AufrufrequestPermissions ()schließlich auslösenein RückrufonRequestPermissionsResult ().

Hier wird, wenn wir jetzt alle Berechtigungen haben, nennen wirinitPlayServices ()(Mehrdies in einem Bit) und dannverbinden()nachdie Play-Services SDK (auch auf diese mehr in Kürze): (von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Wenn wir jedoch tunnicht alle angeforderten Berechtigungen verfügen, eine andere abstrakte Verfahren aufDiese Klasse isthandlePermissionDenied (), Wo die Unterklasse tun, was

es will. Das könnte von reichen zu erklären,der Benutzer, was kann und nicht einfach getan werden kann, um Aufruf finish () und gehen weg.

Der Umgang mit Konfigurationsänderungen

Es gibtdie Möglichkeit, dass der Benutzer den Bildschirm drehen oder auf andere Weise eine Konfigurationsänderung ausgelöst werden, während wir in der Anfrage-Erlaubnis-Prozess sind.

Auch wenn unsere Tätigkeit nicht im Vordergrund von einem Eingangs Standpunkt aus ist, ist es sichtbar, und so wird es die Konfigurationsänderung durchlaufen, während der Anfrage-Erlaubnis Dialog noch im Vordergrund steht. Wir wollen nicht wieder um den Dialog zu Pop-up (und verwirren den Benutzer). Also, die isInPermission fi
ist Tracking, ob die Anfrage-Erlaubnis

Dialog ist hervorragend, so dass wir nicht versuchen, in onCreate den Dialog wieder zu zeigen ().

Schon seitdie Aktivität könnte als Teil der Konfigurationsänderung zerstört und neu erstellt werden, hängen wir auf den isInPermission Wert im Instanz Zustand Bundle gespeichert:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

(dasSTATE_IN_RESOLUTIONBit wird in Kürze erklärt)

Und inonCreate ()Wir neu zu initialisierenisInPermissionwenn wir bekamendie gespeicherte Instanz ZustandBündelneingeleitet.

Überprüfungfür Play-Dienste

Während Sie in der Regeldenken von Android-Geräten wie Play-Dienste mit, dass nicht immer der Fall ist. Manchmal tun sie nicht, noch eingereicht ohnehin eine Kopie Ihrer App mit, vielleicht durch weniger als rechtliche Maßnahmen. Oder hat das Gerät Play-Dienste, aber es ist nicht die neueste Version - vielleicht der Benutzer einen letzten Play-Services-Update verpasst aufgrund der internationalen Reisen, vorübergehenden Aufenthalt in einem Faradayschen Käfig oder andere technische Probleme aufzunehmen.

Daher, eine weitereSache, dass AbstractGoogleApiClientActivity tut, ist Konfi
dassdas

Gerät hat Play-Dienste und das Play-Services-Prozess für was auch immer bestimmte API verbinden können (n) wir nutzen wollen.

Initialisierendie GoogleApiClient

Für viele, obwohlnicht alle, Play-Dienste APIs verwenden Sie einen GoogleApiClient als Einstiegspunkt für Dienstleistungen zu Spielen zu reden. Einige APIs, wieKartenV2, Verwenden GoogleApiClient nicht aus irgendeinem Grund. Aber mehr als oft nicht, werden Sie fi sichbenötigen GoogleApiClient.

ErschaffeneinGoogleApiClientBeispiel Verwendung einGoogleApiClient.Builder. Da die Klasse Name schon sagt,GoogleApiClientwird verwendet alseine Client-Verbindung zu viele (aber nicht alle) Google Play-Service-APIs undGoogleApiClient.Builderistein Bauherr für den Aufbau einer solchen Verbindung. Bestimmtes:

• Wir geben unser Aktivitätals unsereKontext

• Wir nennenaddConnectionCallbacks (), um anzuzeigen, was benachrichtigt werden
soll, wenn unsere Verbindung zum Play Services Prozess bereit ist

• Wir nennenaddOnConnectionFailedListener ()um anzuzeigen, was sein
sollte,benachrichtigt, wenn wir ein Problem beim Verbinden mit dem Play Services Prozess

• Wir nennenbauen()aufdasBaumeistertatsächlich bauendasGoogleApiClient

Dies wird gehandhabt durchinitPlayServices ()aufAbstractGoogleApiClientActivity, Die nennen wir, wenn wir unsere Berechtigungen eingerichtet haben:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Dazu gehören zu rufendie Unterklasse "Implementierung von configureApiClientBuilder (), wo die Unterklasse Methoden wie addApi () verwenden können, um speziell, welche Teile der Play Services Familie von APIs die Aktivität verwenden möchte zeigen.

Gegebendass wir einGoogleApiClient, wir müssenverbinden()zu dieser aufgefordert Standortdaten in der Lage sein zu beginnen, danntrennen()aus es, wenn wirmüssen nicht mehr, dass die Standortdaten.

Trennen der Verbindung isteinfach: wir tun, dass in OnStop () von

AbstractGoogleApiClientActivity:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Es gibt zwei Orte, an denen wir möglicherweise nennenverbinden(). Eine davon ist, wenn wir für die Berechtigungen zu fragen brauchte, und der Benutzer gewährt ihnen. ImonRequestPermissionsResult ()Nach Konfi
dass wir sie in der Tat alle notwendigen Berechtigungen verfügen wir
nenneninitPlayServices ()unddann sofort aufrufenverbinden()aufdasGoogleApiClient: (von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Wenn wir nichtmüssen die Berechtigungen zu beantragen, nennen wirverbinden()imonStart (), Spiegelung derOnStop ()wo wir trennen:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

DasisResolvingPlayServicesError booleanWert wird diskutiert etwas später in diesem Kapitel.

Verbinden und Trennen von

Der Aufrufverbinden()wiederum wird, auslösen Anrufe zu unseremonConnected

()undonDisconnected ()MethodendasGoogleApiClient.ConnectionCallbacksSchnittstelle, die alle unter der Annahme, gut geht.AbstractGoogleApiClientActivitytutnicht diese Implementierungen; sie sind Teil der in Betracht gezogenabstraktAPI und deshalbmüssen von Unterklassen implementiert werden.

Jedoch offensichtlich ist es möglich,dieser Verbindungsversuch fehl. Genau wie und warum es vielleicht ist, scheitern nicht gut dokumentiert. Wenn es fehlschlägt, dieonConnectionFailed ()Verfahren aus unseremGoogleApiClient.OnConnectionFailedListenerImplementierung aufgerufen.onConnectionFailed ()ist bestandeneinConnectionangibt, was speziell falsch gelaufen ist.

EsDies erweist sich, dassConnectionkann enthalteneinPendingIntentdass kann verwendet werden, um zu versuchen, dem Benutzer zu helfen, wieder aus, was auch immer das Problem war. Das Rezept, daswir haben gegeben wordenum zu versuchen, zu verwenden,dies ist zu nennenhasResolution ()(zu sehen, wenndasPendingIntentvorhanden ist) und zu verwenden,startResolutionForResult ()(Aufzurufendie Aktivität, auf die durch diePendingIntent). Na sicher,hasResolution ()kann zurückkehrenfalschUnd anscheinend dasPendingIntentkönnte gebrochen werden, so müssen wir behandelndiese Szenarien auch:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

Wenn wir habeneine Auflösung und erfolgreich die Auflösung Aktivität, unsere Tätigkeit wird gestoppt starten und später begann, an welchem Punkt wir () wieder natürlich zu verbinden eingereicht werden versuchen.

Wenn da istkein PendingIntent, um zu versuchen, das Problem zu beheben, können wir immer noch einen Dialog mit Informationen über angezeigt werden versuchen, was schief läuft. Das Play Services SDK bietet diesen Dialog, obwohl wir sie verantwortlich sind, in einem DialogFragment uns für die Verpackung. Das kommt in Form von ErrorDialogFragment:

(von

Lage / FusedNew / app / src / main / java / com / commonsware / android / weather2

/ AbstractGoogleApiClientActivity.java)

onCreateDialog ()AnwendungendasGoogleApiAvailabilitySingleton zu zeigen,der Fehlerdialog, den Fehlercode gegeben, die von unseren früheren Versuch kam zu verbinden. Wir passieren, dass Fehlercodeüber dieErrorDialogFragmentüberdie ArgumenteBündeln, So daß es eine

Konfigurationsänderungüberstehen.

Allerdings müssen wir auch berücksichtigen,dass das Gerät möglicherweise eine

Konfigurationsänderung, während entweder die Auflösung Aktivität gestartet von
startActivityForResult () oder die ErrorFragmentDialog im Vordergrund unterziehen. Was wir wollen, ist nicht sofort tun versuchen Verbindungsdienste zu Spielen wieder in onStart (), während wir in den Prozess der versucht zu fi sind, was Problem uns vorher eine Verbindung zu verhindert.

Also müssen wir verfolgen einbooleanBundesland,isResolvingPlayServicesErrorAls fi imunserer T ä tigkeit. Das wird anf ä nglich auf falsch, aber wirFlipeswahrwenn wir zeigen,die

Auflösung oder die AktivitätErrorFragmentDialog. Wir fl
eszurück zufalschwannentweder die

Aktivität gestartet kehrt die Steuerung zu uns inonActivityResult ()oder
wanndasErrorDialogFragmentwird zurückgewiesen. Währenddass fl
istwahrSie
versuchen,überspringen wir Dienstleistungen zu verbinden zu spielenonStart (). Und das fl Ist

Teil vonunserer Instanz Zustand gespeichert, so können wir die Konfigurationsänderungen behandeln.

Hilfe bekommen

Offensichtlich,dieses Buch nicht alles abdecken. Und während Ihre # 1 Ressource (außer dem Buch) wird das Android-SDK-Dokumentation zu sein, sind Sie wahrscheinlich Informationen über zu müssen, was in einem dieser Orte bedeckt ist.

Online-Suche für "Android" undein Klassenname ist ein guter Weg, Tutorials auftauchen, die eine bestimmte Android-Klasse verweisen. Allerdings sollten Sie das Alter des Blog-Post zu überprüfen, oder was auch immer, dass Sie gerade lesen. Je älter es ist, desto wahrscheinlicher ist, dass es nicht mehr aktuell ist, basierend auf Änderungen in Android oder einfach bessere Lösungen, die im Laufe der Zeit entwickelt haben.

Jenseits der Jagd um zufällig für Tutorien, obwohl,In diesem Kapitel werden einige andere Ressourcen im Auge zu behalten.

Fragen. Manchmal mit Antworten.

Die "offi

Plätze zu bekommen Unterstützung bei Android sinddie Android Google Groups.

Bezüglich des SDK gibt es drei folgenden berücksichtigen:

1. Stack-Überlauf desandroideEtikett

2. Android-Entwickler, Für SDK Fragen und Antworten

3. adt-dev, Fragen und Antworten zudie offi

Android-Entwicklungstools

Der AutorDieses Buch unterhält auchdie AndGlobe Website.eine Liste der Android-Entwickler-Support-Sites, mit einem Schwerpunkt auf diejenigen, die in anderen Sprachen als Englisch arbeiten.

Es ist wichtig, vor allem für die Stack-Überlauf unddie Google Groups, gut schriftliche Fragen zu schreiben:

1. Fügen Sie relevante Teileder Quellcode (zum Beispiel das Verfahren, bei dem man eine Ausnahme erhalten) und die Stack-Trace von LogCat, wenn das Problem eine nicht behandelte Ausnahme ist.

2. Auf Stack-Überlauf, stellen Sie sicher, dass Ihr Quellcode und Stack-Trace werden als Quellcode formatiert ist; auf Google Groups, sollten auf lange Auflistungen
veröffentlichengist.github.comodereine ähnliche Art von Code-Paste-Website.

3. Erklären Sie gründlich, was Sie sindversuchen zu tun, wie Sie es zu tun versuchen, und warum Sie es auf diese Weise zu tun (wenn Sie Ihr Ziel oder Ansatz denken vielleicht ein wenig unkonventionell sein).

4. Auf Stack-Überlauf, reagieren auf Antworten und Kommentare mit Ihren eigenen

Kommentaren, Adressierungdie Person, die die @ Syntax (zB @CommonsWare), um die

Chancen zu maximieren Sie eine Antwort erhalten. Verwenden Sie jedoch nur, dass für Menschen, die bereits in Ihrer Frage beteiligt sind.

5. Aufdie Google Groups, nicht "ping" oder zu Ihrer eigenen Mitteilung antworten, um zu versuchen, eine Antwort zu entlocken, bis eine angemessene Höhe der Zeit durch (zB

24 Stunden) gegangen.

Überschriftzur Quelle

Der Quellcode für Android ist ab sofort verfügbar. MeistDies ist für die Menschen zu verbessern suchen, zu verbessern oder auf andere Weise mit den Innenseiten des Android-Betriebssystem Aufhebens. Aber es ist möglich, dass Sie fi
die Antworten suchen Sie in diesem Code,
vor allem, wenn Sie sehen möchten, wie einige eingebauten Android-Komponente "macht seine Sache".

Der Quellcode und die damit verbundenen Ressourcen finden Sie unterhttp://source.android.com.

Hier kannst du:

1. Herunterladender Quellcode

2. DateiFehlerberichtegegendas Betriebssystem selbst

3. Reichen Sie Patchesund lernender Prozess, wie solche Patches erhalten
ausgewertet und genehmigt

4. Beitretenein separater Satz vonGoogle Groupsfür Android-Plattform-Entwicklung Wie Sie Ihre Nachrichten Fix

Ed Burnette,ein netter Kerl, der gerade sein eigenes Android Buch zu schreiben, ist auch der ManagerPlanet Android.ein Feed-Aggregator für eine Reihe von Android-bezogenen Blogs. Abonnieren Sie den Feed des Planeten lässt Sie ziemlich viel von Android-bezogenen Blog-Posts zu überwachen, aber nicht ausschließlich auf die Programmierung im Zusammenhang.

Trail: Code Organisation und Gradle

Arbeiten mit Bibliotheksprojekte

Android Bibliotheksprojekte sindnur Java-Quellcode, wie Android Ressourcen die primäre Einheit von Android Quelle Wiederverwendung, insbesondere dann, wenn die Quelle mehr als einbezieht.

ImIn diesem Kapitel werden wir die Grundlagen für die Einrichtung und Verwendung eines Android-Bibliothek-Projekt zu erkunden.

Voraussetzungen

VerstehenDieses Kapitel setzt voraus, dass Sie die Kern Kapitel dieses Buches gelesen haben.

Erstellen a Library Project

Ein Android-Bibliothek-Projekt, in vielerlei Hinsicht, sieht aus wieeine regelmäßige Android-Projekt. Es hat Quellcode und Ressourcen. Es hat ein Manifest.

Was es machtwenn auch nicht tun, ist eine APK fi bauen

Stattdessen, es repräsentiert ein

Korb des Programmvermögens, die die Werkzeuge Android bauen wissen, wie mit regelmäßigen Android-Projekten zu mischen.

Herstellungein Projekt, ein Android-Bibliothek-Projekt ist einfach eine Frage der richtigen Android Plugin für Gradle wählen.

Lieberist als:

benutzen:

Das ist es- dascom.android.libraryPlugin jetzt weißdass es eine Bibliothek schafft, nicht eine App.

Die eigentliche Frage ist, wo sind Sie machendiese Bibliothek? In vielen Fällen werden Sie tun, um ein Modul in einem Projekt, in dem es ein weiteres Modul, das eine App ist. Dies bezieht sich sowohl auf:

• Eine Bibliothek, die entworfen werden, standalone, aber mit einer Beispielanwendung demonstriert seine Verwendung

• Eine Bibliothek entwickelt, um die von der App verwendet werden, und vielleicht auch andere App-Module in diesem Projekt

Hinzufügenneue Module zu einem Projekt Android Studio wird am einfachsten über das neue Modul-Assistenten behandelt, die Sie über Datei> Neu> Neues Modul ... aus dem Hauptmenü bringen kann. Dies bringt die fi Seite des neuen Modul-Assistenten auf:

Hinzufügenein Bibliotheksprojekt als Modul in ein vorhandenes Projekt, wählen Sie "Android Library" in der Liste der Modultypen, klicken Sie auf Weiter auf die zweite Seite des Assistenten, um fortzufahren:

Dieser sammelt einige Bits von Informationen, einschließlich:

• die "application name", die Verwendung in diesem Fall dessen ist unklar

• die "Modulname", die das Verzeichnis, in diesem Projekt sein wird, in die diese Bibliothek erstellt werden soll

• die "Paketname", die in dem Manifest der erzeugten Bibliothek gehen

• Ihres Moduls minSdkVersion

Beimdieser Punkt, auf Weiter klicken werden Sie auf die gleichen neuen Aktivitätsfluss nehmen, die Sie gesehen haben, als ein neues Projekt anlegen. Wenn Sie eine Aktivität erzeugt werden für Sie in dieser Bibliothek wollen, gehen Sie durch die Aktivitätsvorlage auswählen und die Aktivitätsvorlage Konfigurationsdaten. Wenn Sie nicht eine Aktivität wollen, wählen Sie "Add keine Aktivität" im Raster von Vorlagen, klicken Sie auf "Fertig stellen", um das Modul zu erstellen.

ImAm Ende wird das neue Modul-Assistent das neue Modul für Sie, in Ihrem benannten Unterverzeichnis des Projekts, einschließlich der Modifikation settings.gradle einrichten aufzulisten Dieses Unterverzeichnis als ein Modul innerhalb des Projekts zu sein. An dieser Stelle können Sie sich mit Hilfe der Bibliothek im Rahmen des Projekts zu beginnen.

Mitein Bibliotheksprojekt, Teil II

Sobald du hastein Bibliotheksprojekt, können Sie es zu einem normalen Android-Projekt anschließen, damit der reguläre Android-Projekt hat in der Bibliothek Zugang zu allem. Wir deckten einfache Szenarien für diesefrüherdas Buch. Mit Android Studio, haben Sie zwei andere major Möglichkeiten, neben dem, was war vorher abgedeckt.

Obdie Bibliothek vorhanden ist zur Unterstützung von ein paar eigene Anwendungen, können Sie all das in einem einzigen Projekt mit mehreren Modulen (zB app / und app2 / für die Apps, mit myCoolLibrary / für die Bibliothek) organisieren könnte. So richten Sie wird diese Struktur in abgedeckt werdendas Kapitel über Gradle Abhängigkeiten.

Obdie Bibliothek vorhanden ist zur Unterstützung von Anwendungen, die Sie nicht, wie man sie für eine andere Entwicklungsteam in Ihrer Organisation oder ein für den öffentlichen Vertrieb schreiben

— Sie werden wahrscheinlich ein AAR fi eingereicht Veröffentlichung
zusammengestellt von
die Bibliothek. Auch dies ist bedeckt indas Kapitel über Gradle Abhängigkeiten.

Bibliothek Projekte und das Manifest

Bibliotheksprojekte können veröffentlichenihre eigenen AndroidManifest.xml fi
welche trägt
bei zu die Gesamt Manifest von Anwendungen verwendet, die die Bibliothek integrieren. Daher kann eine Bibliothek:

• Anforderung von Berechtigungendass vielleicht nicht in der eigenen Manifest der App sind

• veröffentlichen Aktivitäten oder anderen Komponenten, ohnedie App-Entwickler-

Einträge der App-eigene Manifest hinzufügen zu müssen

• festlegenein Minimum SDK-Version von der Bibliothek Code erforderlich, die von der App erforderlich höher als die minimale SDK-Version sein könnte selbst

Allerdings VerschmelzungDiese Manifeste ist ein sehr komplexes Thema, und als solche werden abgedecktviel später indas Buch.

Einschränkungen der Bibliotheksprojekte

Während Bibliotheksprojekte für die Code-Organisation und Wiederverwendung nützlich sind,sie haben ihre Grenzen.

Wie oben erwähnt, wenn mehrdie gleiche Ressource als ein Projekt definiert (Haupt und Bibliotheken), bekommt der mit höherer Priorität Projekts Kopie verwendet. Im Allgemeinen, das ist eine gute Sache, denn es bedeutet, dass die Hauptprojektressourcen durch eine Bibliothek definiert ersetzen können (zB Symbole ändern). Aber es bedeutet, dass zwei Bibliotheken kollidieren könnten. Es ist wichtig, Ihre Ressourcennamen zu halten verschiedene, die Chancen dieses Ereignisses zu minimieren.

Gradle und Legacy-Projekte

Projekte lassen sich in zwei Hauptkategorien:diejenigen, die neue Gradle spezifische Verzeichnisstruktur, und diejenigen, die die Legacy-Struktur verwenden, die jeder von 2008 bis 2013 verwendet (und bis zu einem gewissen Umfang, darüber hinaus) - meist, erstellt Projekte mit Eclipse.

Allerdings ist Gradle Lage von Bauvorhaben inentweder Verzeichnisstruktur. In diesem Kapitel wird überprüfen, wie Gradle Unterstützung zu einem Legacy-Eclipse-Stil Android Projekt hinzuzufügen, ohne die Verzeichnisstruktur zu ändern.

Voraussetzungen und Warnungen

VerstehenDieses Kapitel setzt voraus, dass Sie das Kapitel gelesen haben, dasseinführt Gradle.

"Erbe"?

Hier "Legacy-Verzeichnisstruktur" bedeutetein Projektbaum, die ein bisschen wie folgt aussieht:

Es wird dominiert von ein traditionelles Java src / Baum, plus die Android-spezifi Produkte wie res /.AndroidManifest.xml, und so weiter.

Diese Verzeichnisstruktur wird perfekt funktionieren mit Gradle fi, und Sie könnenmüssen diese Struktur für eine Weile zu halten, um die Kompatibilität mit anderen Tools zu erhalten, wie Eclipse.

Erstellen Sie Ihre Gradle Build-Datei

Siebrauchen eine build.gradle fi
der Lage sein, Ihr Projekt mit Gradle zu bauen.

Wie bereits inDer einleitende Kapitel über Gradle, Gradle istdas native Build-System für Android Studio. Wenn Sie also, dass die IDE verwenden, sollten Sie automatisch eine build.gradle fi bekommen. Auch, wenn Sie von Eclipse Android Studio bewegen, verwenden Sie die Android Studio Import-Assistenten, wie es ist besser als Ihre Alternativen und wird auch helfen, Ihren Code in das sourceSet-basierte Projektstruktur reorganisieren, die Android Studio (und Gradle für Android) verwenden nativ.

Wenn du bistwenn auch nicht Android Studio verwenden, gibt es zwei Hauptwege, eine build.gradle fi bekommen

Heute: exportieren man von einem Eclipse-Projekt, oder erstellen Sie eine von

Hand. In der Theorie von Eclipse-Export wäredie beste Wette. Aber mit Eclipse nicht unterstützt wird, können Sie mit Wind bis es von Hand voll zu schaffen. Nach allem, wie Sie sehen werden, ist veraltet, was Sie von der Eclipse-Export-Prozess zu bekommen.

Exportierenvon eclipse-

Wenn Sie einebestehende Eclipse-Projekt, ist der einfachste Weg, um einen build.gradle fi bekommen
fürdieses Projekt ist es, die ADT-Plugin Export für Sie zu lassen.

Darstellendeder Export

Exportierenbuild.gradle, wählen Sie entweder Datei> Exportieren aus dem Eclipse-Hauptmenü oder wählen "Exportieren ..." aus dem Kontextmenü im Paket-Explorer. Entweder derer sollte einen Assistenten-Stil-Dialog, aus dem Sie auswählen können, was Sie exportieren möchten: Wählen Sie hier "Gene Gradle fi bauen

. Wenn das nicht möglich ist, können Sie auf eine
ältere Version des ADT-Plugin und würde aktualisieren müssen.

Im nächsten Schritt werdenbringen dann eine Liste aller installierten Projekte, bei denen Sie benötigen, um das Projekt zu überprüfen, die Sie exportieren möchten:

Hinweis dass Ihr Projekt nicht bereits überprüft werden kann, aufgrund eines Fehlers im Assistenten.

Sobald Sie überprüftDas Projekt sollte die Schaltfläche Weiter aktiviert werden. Ein Klick, der eine Konfi bringen

Zauberer Seite:

Es sollte zeigen,das Projekt, das Sie im Assistenten überprüft. Es gibt eine "Kraft überwiegendes bestehender fi

Checkbox- Verwenden Sie, dass, wenn Sie zuvor die Gradle fi ausführte
und ersetzen wollensie mit einem frisch exportierte Kopie.

Ein Klickdie Schaltfläche Fertig wird der Export zu tun und einen Bericht Seite bringen: Nach sorgfältiger Überprüfungdie Noten hier (oder möglicherweise ignorieren sie einfach), klicken Sie auf Fertig, um den Assistenten zu schließen.

Was wird generiert

Was Sie für Ihre Mühen erhalten ist:

• EINbuild.gradlefi

• Ein Gradle Wrapper, in Form einesgradlewund / odergradlew.batfi
und
eingradle /Unterverzeichnis, wie es diskutiertimdie vorherigen Kapitel. Wenn du
möchtestnicht den Wrapper verwenden, können Sie diese fi löschen

Mit

Ausnahme dergradle-wrapper.propertiesfi

• Ein .gradle / hidden Unterverzeichnis, im Cache gespeicherten Daten enthält, die durch die Gradle verwendete Verfahren, wie zum Beispiel eine analysierte Kopie Ihres
build.gradle fi bauen
fürwenn Sie eine schnellere Ausführung Gradle ausführen, ohne
mit modifiziertenbuild.gradle seit Ihrem letzten Gradle laufen.

Was muss repariert werden

Habendie resultierende Projektarbeit gut mit Android Studio, ändern:

• die Version des Android-Plugin für Gradle zu1.0.0oder höher(Classpath

'com.android.tools.build:gradle:0.12.+'nachClasspath

'com.android.tools.build:gradle:1.0.0')

• dasAnwendung Plugin:'Android'ErklärunganwendenPlugin:

'com.android.application'

• dasdistributionUrlimdasgradle / Wrapper / gradle-wrapper.properties
fi
nachhttps: \ // services.gradle.org/distributions/
gradle-2.2.1-all.zip
untersuchendie Gradle Datei

Der Beispielcode Buch enthälteinGradle / HalloBeispielprojekt. Dies ist nurein Lager "Hallo, Welt"

app, wie sie in der Eclipse-new-Projekt-Assistenten erstellt.

Es ist jedoch auch enthältein build.gradle, Eclipse exportiert:

(vonGradle / Hallo / build.gradle)

die meistender Inhalt dieser fi
ist bedeckt mit Der einleitende Kapitel über Gradle. Die

Ein-Bitdas ist nicht - der sourcesets Verschluss - bedeckt inein kommender Kapitel.

Gradle und Aufgaben

Ein build.gradle fi
lehrtGradle, wie Aufgaben ausführen, wie zum Beispiel, wie ein Android-

Projekt zu kompilieren. Außerhalbein Gradle-fähige IDE wie Android Studio, verwenden Sie Gradle selbst diese Aufgaben auszuführen. Wenn Sie Ihre eigene Kopie von Gradle installiert haben, würden Sie den gradle Befehl verwenden; wenn Sie auf eine vertrauenswürdige Kopie des Gradle Wrapper angewiesen sind, würden Sie das ./gradlew Skript in Ihrem Projektstamm verwenden.

Fürdie Zwecke dieses Buches wird der gradle Befehl gezeigt werden - nur Ersatz

./gradlewwo man sehengradlewenn Sie mitdie Gradle Wrapper-Skript.

Key Build-bezogenen Aufgaben

Um fi
aus Was Aufgaben stehen Ihnen zur Verfügung, Sie gradle Aufgaben aus dem

Projektverzeichnis ausführen können. Das wird in der Ausgabe führen verwandt:

Diese Liste wird dynamisch generiert basierend aufder Inhaltbuild.gradle, Insbesondere unter Einbeziehung der Aufgaben durch die definiertecom.android.applicationPlugin.

Grundsätzlich sollen Siegeben Sie den gesamten Aufgabennamen, wenn diese Aufgabe ausgeführt wird. Sie können jedoch eine Abkürzung verwenden, solange sie eindeutig die Aufgabe identifiziert.

Wahrscheinlichdie häufigste Aufgabe, ein Entwickler, zumindest auf kurze Sicht zu verwenden, ist installDebug (oder iD für kurz). Dies wird eine Debug-Version der App zu bauen und sie auf einem

verfügbaren Gerät oder Emulator installieren. Dies entspricht in etwa Debug für diejenigen, die mit Legacy installieren, um ant Ant-basierte Befehlszeilen aufbaut.

So wie es ist,installDebug kann es auch installRelease sein. Die Debug und Release-Teile der Aufgabe nicht hartcodiert, sondern stammen aus dem "bauen Typen" in der build.gradle fi definiert

Das Konzept, Rolle, und die Verwendung von Build Typen werden in abgedeckt
werdendas nächste Kapitel. Aber,installRelease ist nicht standardmäßig verfügbar, da eine App Installation erfordert, dass die APK unterzeichnet werden, und Gradle für Android nicht weiß, wie es zu unterzeichnen. Wir adressieren diese indas nächste Kapitelals auch.

Wenn Sie wollen einfach nur bauendie App, ohne sie zu installieren,assembleDebug(Anzeige) oderassembleRelease(aR) Wird dieses Ziel erreichen. Wenn Sie die App von einem Gerät oder Emulator zu deinstallieren,uninstallDebug(uD) unduninstallRelease(uR) sollte arbeiten.

Diskussion andererAufgaben, wie zum Beispiel die "check" Aufgaben, werden in späteren Kapiteln behandelt werden.

Ergebnisse

Alle Build-Ausgabe geht inein Build / Verzeichnis. Konkret geht Ihre APKs in build / Ausgänge /
apk, mit verschiedenen Editionen APK basierend darauf, ob Sie eine Debug-tat oder Build freigeben.

Hinweisdass Gradle hat eine saubere Aufgabe, die die Build / Verzeichnis löscht.

Gradle unddas neue Projektstruktur

EINvorheriges Kapitelzeigte, wie man Gradle verwenden können, unddas Android-Plugin für Gradle, baut von Projekten Befehlszeile zu tun, die auch mit Eclipse, IntelliJ IDEA, Ant arbeiten können, usw.

Während jedochDas Legacy Projekt Verzeichnisstruktur funktioniert, ist es nicht lassen Sie die volle Leistung des Android-Plugin für Gradle nutzen. Um die Vorteile des Build-fl von
die neue Build-System, müssen Sie Ihre Quelle, Ressourcen, Vermögenswerte und damit verbundener fi zu organisieren
somewhat anders.

Dieses Kapitel umreißtdiese "neue Projektstruktur" und zeigen Ihnen, wie das Android-Plugin für Gradles die Konzepte von Build-Typen und Produkt Aromen wird es leichter für Sie mehrere verschiedene Formen der Ausgabe von einem einzigen, wenn auch neu organisiert, Projektbaum zu haben. Diese Projektstruktur stammt aus Android Studio, so sind Android Studio-Projekte bereits eingerichtet, um diese Art von erweiterten Funktionen zu unterstützen.

Voraussetzungen und Warnungen

VerstehenDieses Kapitel setzt voraus, dass Sie die Kapitel gelesen haben, dassvorstellen Gradleund umfassen grundlegende Gradle / Android-Integration, inder KontextAbdeckungdas Verwendung von Gradle mit dem Legacy-Projektstruktur.

Ziele derdas neue Projektstruktur

Imder Anfang, Android Apps eher ziemlich einfach zu sein, da wir nur eine Handvoll Geräte hatte, ein paar Brocken der Nutzer, eine primäre Vertriebsweg (die dann- Android Market) und einige wichtige Investoren im Android-Ökosystem.

Die Zeiten haben sich geändert.

Jetzt, Android-Apps für den öffentlichen Konsum kann schrecklich komplex sein, allein Apps für die interne Unternehmenseinsatz lassen (die komplex zu sein scheinen, alseine Nebenwirkung) von einem Unternehmen entwickelt. Wir haben mehrere Vertriebskanäle, wie der Amazon Appstore für Android und Yandex.Store. Wir haben eine Milliarde Geräte und fast eine Milliarde Nutzer. Marken groß und klein sind fl
auf Android, bringt mitsie ihre eigenen Herausforderungen.

Dasneue Build-System ist so konzipiert, komplexe Android-Anwendungen zu vereinfachen, zu schaffen, während im Idealfall nicht einfach Android-Anwendungen viel härter zu machen. Es ist für Szenarien konzipiert, wie:

• Unterstützung mehrerer Vertriebskanäle, die mehrere In- App-Kauf erfordernMotoren

• Unterstützung einer Appdas ist für die einzelnen Kunden maßgeschneiderte, wie für die Verwendung von verschiedenen Unternehmen

• Unterstützung einer Appdass wirklich braucht unterschiedliche APKs für verschiedene Arten von Geräten zu haben, trotz aller Bemühungen um alle Geräte von einem einzigen APK zu unterstützen

• Unterstützung einer Appdas ist ein Teil eines viel größeren integrierten System und benötigen als Teil gebaut werden und Paket des größeren Systems

• Unterstützungein fl
von Apps das hängt von gemeinsamen Code, Ressourcen von

Drittanbietern Bibliotheken und dergleichen

• Und so weiter

Dasneue Struktur Projekt, verbunden mit dem Android-Plugin für Gradle und Gradle selbst, macht dies möglich, alle ... wenn auch mit ein bisschen eine Lernkurve.

Terminologie

Um zu verstehen, wasdie neuen Projektstruktur zur Folge hat, müssen wir ein paar Begriffe zu definieren, von Gradle und dem Android-Plugin für Gradle.

Sourcesets

Zitierendie Gradle Dokumentation: "A sourceSet einfacheine Gruppe von Quelle fi, die zusammen

"Hier" Quelle "bedeutet, dass alle Eingänge kompiliert und ausgeführt werden., die Sie für die App erstellen, wie Java-Quellcode, Android Ressourcen und manifestieren fi

Und dergleichen.

Dies steht im Gegensatz zu Abhängigkeiten, die sind Eingänge, die Sie (in der Regel) von anderen Entwicklern zu erhalten, wie zum Beispiel wiederverwendbare Bibliotheken.

Sourcesets, aufihre eigenen, haben keine besondere semantische Bedeutung. Sie können wählen Sie Ihr Projekt ein einzelnes sourceSet verwenden zu haben oder mehrere sourcesets, für Ihren Code zu organisieren. Sie könnten für verschiedene sourcesets haben:

• Seriencode im Vergleich zu Test-Code, ersetzendas separate Testprojekt, die wir historisch in Android-Entwicklung verwendet

• Interface-Code im Vergleich zu Implementierungscode

• Verschiedene wichtigsten Funktionsbereiche innerhalbdie App, vor allem, wenn sie von getrennten Teams oder Entwickler Paare gehalten werden

• Und so weiter

Wie wir sehen werden,die neue Projektstruktur setzt die Existenz von mindestens einem sourceSet, in der Regel dem Namen main, aber auch andere Merkmale des neuen Build-System zusätzliche sourcesets einzubeziehen.

Bauen Sie Typen

Ein Build-Typ ist eine Achse möglicher alternativer Ergebnisse aus den Build-Prozess.

In der Standardeinstellungdas Android-Plugin für Gradle geht davon aus, dass Sie zwei BuildTypen wollen: Release und debuggen. Diese gehen können durch etwas andere Build-Schritte, wie ProGuard zum Release-Build anzuwenden, sondern es für die Debug-Build zu überspringen.

Das Android-Plugin für Gradle erlaubt obwohl bauenTypen leicht unterschiedlichen Konfigurationen zu haben, wie ein .debug ausrei dem Paketnamen APK hinzufügen, so dass Sie einen Release-Build und Debug-Build Ihrer Anwendung auf dem gleichen Gerät zur gleichen Zeit haben. Sie können auch neue Build-Typen für den Umgang mit verschiedenen Szenarien erstellen. Der neue Build-System Dokumentation, zum Beispiel schlägt eine separate "jnidebug" Buildtyp, in dem Sie, dass die fi .so Linux hinweisen
für sollte ein Projekt im Debug-Modus kompiliert werden.

Wie wir sehen werden, die Schaffungeine neue Build-Typ beinhaltet Änderungen an der build.gradle fi
und Zugabeein passender sourceSet.

Artikel Flavors

Ein Build-Typ ist eine Achse für die Ausgabe variiert. Ein Produkt Geschmack ist eine weitere, unabhängige Achse für die Ausgabe variiert.

Produkt Aromen werden für Szenarien entwickelt, in denen Sie für verschiedene Fälle unterschiedliche Freigabe ausgegeben werden soll. Zum Beispiel können Sie eine Version Ihrer App gebaut haben

Google In-App-Kauf-APIs (für die Verteilung zu verwenden, um durchdas Play Store) und eine weitere Version der App gebaut Amazon in-App-Kauf-APIs verwenden (für die Verteilung durch die

Amazon Appstore für Android). In diesem Fall werden beide Versionen der App in der Version Form verfügbar sein, und Sie können separate Debug baut auch haben möchten. Und die meisten der Code für die beiden Versionen der App werden die gleichen sein. Allerdings werden Sie anderen Code für die verschiedenen Vertriebskanäle haben - nicht nur, dass der richtige Code haben für den rechten Kanal zu laufen, aber es gibt keinen besonderen Wert den Code für einen Kanal durch den anderen Kanal zu verteilen.

Ein weiteres Beispiel wäre eine Anwendung sein,dass sich der Marke und für verschiedene Unternehmenskunden konfiguriert. Sie sehen diese viel mit Web-Anwendungen - der Verkäufer verkauft eine Marke-und konfigurierte Version der Web-App auf den Kunden, ob diese App auf dem vom Hersteller bereitgestellte Hardware oder vom Kunden gelieferten Hardware läuft. In ähnlicher Weise könnte wollen, dass die Hersteller von Android-App für das Sammeln Mitarbeiter Stundenzettel an seine Kunden für ihre Version der Zeiterfassungs App bieten dem Logo des Kunden für den Sport, binden in die spezifi Accounting-Server des Kunden, aktivieren oder Funktionen deaktivieren, abhängig davon, wie der Kunde Anwendungen Stundenzettel, und so weiter. Allerdings ist der größte Teil der Code zwischen allen Kunden gemeinsam genutzt, und so, wenn die App aktualisiert Funktionen oder fi Bugs hinzufügen, neu sind für alle Kunden erforderlich Builds. In diesem Fall kann jeder Kunde als eigenständiges Produkt Geschmack eingerichtet werden, ein großer Teil der Code-Sharing, aber mit leicht unterschiedlichen Code, Ressourcen (zB Logo) und die Konfiguration auf der Grundlage, dass Kundenbedürfnisse.

Produkt Aromen sind optional. Wenn Sie tunbeschreiben keine Produkt Aromen in Ihrem build.gradle fi
es wird angenommen dass Sie ein einzelnes Produkt Geschmack haben, als

Standard intern bezeichnet. Viele Anwendungen werden nicht Produkt Aromen benötigen; dies ist eine Funktion, die Sie in wird entscheiden, wie gebraucht.

Wie wir sehen werden, die Schaffungein neues Produkt Geschmack beinhaltet Änderungen an der build.gradlefi
undHinzufügen ein passender sourceSet.

Build-Varianten

Der Begriff "Build-Variante" wird verwendet fürdas Kreuzprodukt der Build-Typen und den Produkt Aromen. Also, ein Projekt mit Debug-und Release-Typen bauen und Google und Amazon Produkt Aromen in insgesamt vier Build-Varianten standardmäßig führen wird: 1. debuggen+Google

2. debuggen+Amazonas

3. Freisetzung+Google

4. Freisetzung+Amazonas

Flavor Abmessungen

Manchmal, auchdies ist nicht ausreichend Flexibilität, wie die Google und Amazon Szenario weiter oben in diesem Abschnitt beschrieben. Oder Sie trennen kostenlos benötigen im Vergleich zu bezahlten Ausgaben, wenn Sie eine up-front Gebühr haben wollen für eine Premium-Version der App zugreifen.

By sind standardmäßig Produkt Aromen als Teil eines einzigen "Geschmack Dimension" zu sein.

Allerdings können Sie Ihre Aromen in Ihren eigenen separaten Geschmack Dimensionen (zB ein kostenlos gegen Entgelt, eine für Vertriebsweg) zu organisieren.

Diesefügen Sie dann ein weiterer Faktor in die Cross-Produkt, das Ihre Build-Varianten bestimmt.

Angenommen, wir eine dist Geschmack Dimension haben, die aus kostenlosen und kostenpflichtigen Produkt Aromen, und wir haben einen Kanal Geschmack Dimension, die aus Google und Amazon Aromen. Nun haben wir insgesamt 8 möglichen Build-Varianten, wenn wir in den Build-Typen Faktor:

1. debuggen+Google+frei

2. debuggen+Amazonas+frei

3. Freisetzung+Google+frei

4. Freisetzung+Amazonas+frei

5. debuggen+Google+bezahlt

6. debuggen+Amazonas+bezahlt

7. Freisetzung+Google+bezahlt

8. Freisetzung+Amazonas+bezahlt

Erstellenein Projekt in der neuen Struktur

Abdie Zeit des Schreibens dieses Artikels, gibt es zwei große Möglichkeiten, ein Projekt in die neue Projektstruktur bekommen: Android Studio verwenden, oder es von Hand machen.

Wie bereits inDie frühesten Kapiteln des Buches, Android Studio native Build-System ist mit dem Android-Plugin für Gradle Gradle. Wenn Sie ein neues Projekt durch diese IDE erstellen, wird es automatisch mit der neuen Projektstruktur eingerichtet werden.

Wenn du bistnicht Android Studio verwenden und ein Projekt in der neuen Struktur wollen, müssen Sie den Verzeichnisbaum, Handwerk und fi build.gradle
sich. Das könnte seineine

Frage der sie von Grund auf neu erstellen, oder es könnte eine Frage der das Kopieren einer Projektstruktur aus einer bestehenden Quelle sein. Martin Liersch (auch bekannt als "Goddchen") hat
veröffentlichtein GitHub-Repository mit einer Vielzahl von Beispielprojektendass Sie als Quelle der Inspiration nutzen, zusammen mit den Proben über den Rest dieses Kapitels vorgestellt.

Wasdas neue Projektstruktur aussieht

Mit allendass als Hintergrund, lassen Sie uns auf der einen BlickGradle / HelloNewBeispielprojekt.

Dieses Projekt begann als Eclipse-Projekt,dann hatte eine build.gradle fi, um es über die Eclipse-Export-Assistenten hinzugefügt. Später jedoch wurde sie reorganisiert die neue Projektstruktur zu fi nden.

Der Verzeichnisbaum

Die Pre-Reorganisation Verzeichnisbaum fürdas Projekt ist ziemlich konventionell, nur mit einigen zusätzlichen Gradle spezifische fi

Hallo

| - AndroidManifest.xml

| - Vermögenswerte/

| - build.gradle

| - libs /

|

| - android-support-v4.jar

| - local.properties

| - proguard-project.txt

| - project.properties

| - res /

|

| - ziehbar-hdpi /

|

|

| - ic_launcher.png

|

| - ziehbar-LDPI /

|

| - ziehbar-MDPI /

|

|

| - ic_launcher.png

|

| - ziehbar-xhdpi /

|

|

| - ic_launcher.png

|

| - Layout/

|

|

| - activity_main.xml

|

| - Menü/

|

|

| - main.xml

|

| - Werte/

|

|

| - dimens.xml

|

|

| - strings.xml

|

|

| - styles.xml

|

| - Werte-sw600dp /

|

|

| - dimens.xml

|

| - Werte-sw720dp-Land /

|

|

| - dimens.xml

|

| - Werte-v11 /

|

|

| - styles.xml

|

| - Werte-v14 /

|

| - styles.xml

| - src /

| - com /

| - commonsware /

| - android /

| - gradle /

| - Hallo/

| - MainActivity.java

(Anmerkung: obige Aufzählung nur fi enthält
von Relevanz für die aktuelle

Diskussion) Die neue Projektstruktur ist jedoch, ein wenig anders:

HelloNew

| - build.gradle

| - libs /

|

| - android-support-v4.jar

| - local.properties

| - proguard-project.txt

| - project.properties

| - src /

| - Main/

| - AndroidManifest.xml

| - Vermögenswerte/

| - Java/

|

| - com /

|

| - commonsware /

|

| - android /

|

| - gradle /

|

| - Hallo/

|

| - MainActivity.java

| - res /

| - ziehbar-hdpi /

|

| - ic_launcher.png

| - ziehbar-LDPI /

| - ziehbar-MDPI /

|

| - ic_launcher.png

| - ziehbar-xhdpi /

|

| - ic_launcher.png

| - Layout/

|

| - activity_main.xml

| - Menü/

|

| - main.xml

| - Werte/

|

| - dimens.xml

|

| - strings.xml

|

| - styles.xml

| - Werte-sw600dp /

|

| - dimens.xml

| - Werte-sw720dp-Land /

|

| - dimens.xml

| - Werte-v11 /

|

| - styles.xml

| - Werte-v14 /

| - styles.xml

Währenddie libs / Verzeichnis ist auf ihrem Platz, zusammen mit build.gradle und zugehörige Build fi

Hat der Rest verschoben.

Mitdie neue Projektstruktur, src / ist die Wurzel der Quelle-Sets, nicht nur, wo der Quellcode geht. Es gibt einen sourceSet, genannt Haupt, im src / main / Verzeichnis. Dort, wo die Vermögenswerte / und res / Verzeichnisse gehen, zusammen mit dem AndroidManifest.xml fi

Und, es gibt ein java / Verzeichnis, das die Java-Quellbaum enthält (was im
ursprünglichen src / Verzeichnis gewesen war).

Die build.gradle Datei

Dasbuild.gradle fi
ist viel wie das, was wir profi
zurück inder einleitende

Kapitel über Gradle:

(vonGradle / HelloNew / build.gradle)

Wir habendie buildscript Schließung zu beschreiben, was wir für unsere Build-Tools benötigen, die com.android.application Plugin und die Details für welche Version von Android wir kompilieren gegen und welche Version des Build-Tools, die wir verwenden.

Und wieein Ergebnis, wir habendie StandardaufgabenEinschließlich installDebug.

Konfigurierendie Aktien Build-Typen

DasDebug und Release-Build-Typen sind bereit "out of the box" für Ihren Einsatz, mit einem vernünftigen Satz von Standardeinstellungen. Allerdings können Sie diese Standardeinstellungen ändern und andere Anpassungen vorzunehmen, wie diese Build-Typen arbeiten, zusätzlich zuDefinieren Sie Ihre eigenen Build Arten. Hier werden wir uns auf die Optionen suchen, um das Verhalten von Buildtyp ändern, auf dem Aktien Debug-Fokussierung und Entriegelungstypen bauen.

Insbesondere werden wir untersuchendasGradle / HelloConfigBeispielprojekt, das baut aufdie vorherige Probe, um das Verhalten von sowohl modifizierendedebuggenundFreisetzung.

sourceSet

Jeder BuildTyp kann seine eigene zugeordnete sourceSet haben. Wenn Sie das Verzeichnis für die es zu überspringen, das bedeutet, dass die Build-Typ ist nicht Änderungen an der Haupt sourceSet beitragen.

Also, indasGradle / HelloConfigBeispielprojekt, haben wireine Ersatz-Version des strings.xmlRessource, ineindebuggensourceSet:

HelloConfig

| - build.gradle

| - HelloConfig.keystore

| - libs /

|

| - android-support-v4.jar

| - local.properties

| - proguard-project.txt

| - project.properties

| - src /

| - debuggen/

|

| - res /

|

| - Werte/

|

| - strings.xml

| - Main/

| - AndroidManifest.xml

| - Vermögenswerte/

| - Java/

|

| - com /

|

| - commonsware /

|

| - android /

|

| - gradle /

|

| - Hallo/

|

| - MainActivity.java

| - res /

| - ziehbar-hdpi /

|

| - ic_launcher.png

| - ziehbar-LDPI /

| - ziehbar-MDPI /

|

| - ic_launcher.png

| - ziehbar-xhdpi /

|

| - ic_launcher.png

| - Layout/

|

| - activity_main.xml

| - Menü/

|

| - main.xml

| - Werte/

|

| - dimens.xml

|

| - strings.xml

|

| - styles.xml

| - Werte-sw600dp /

|

| - dimens.xml

| - Werte-sw720dp-Land /

|

| - dimens.xml

| - Werte-v11 /

|

| - styles.xml

| - Werte-v14 /

| - styles.xml

Dassstrings.xml enthält eineüberarbeitete Version des app_name, zu helfen, es deutlicher zu machen, dass wir die Debug-Version der App ausgeführt werden:

(von

Gradle / HelloConfig / src / debug / res

/ Werte / strings.xml)

Wie wir sehen werden, Ressourcen in BuildTypen "sourcesets ersetzen ihre Kollegen in der Main. Oder könnte ein Buildtyp eine neue Ressource hinzufügen, die von der Haupt fehlt, falls gewünscht.

build.gradle Einstellungen

Wir können auch verwendendie buildTypes Schließung in build.gradle das Verhalten des Debug-und

/ oder Release-Build-Typen zu konfigurieren. In diesem Beispielprojekt, ändern wir beide, sowie einige andere Änderungen vornehmen:

(von Gradle / HelloConfig / build.gradle)

Wie wurde festgestellt, zurück indie Einführung in die Android-Plugin für Gradle.die DefaultConfig Verschluss ermöglicht es uns, Aspekte zu ändern, was in der AndroidManifest.xml fi gefunden

Ersetzung etwas gefunden in die tatsächliche fi
von die Haupt sourceSet.

DasbuildTypes Schließung ist, wo wir das Verhalten der Build-Typen konfigurieren. Jeder Buildtyp konfiguriert werden, erhält eine eigene Schließung innerhalb von buildTypes, und dort können wir verschiedene Eigenschaften außer Kraft setzen.

Bemerkenswerte Eigenschaftendass wir für einen Build Typ angeben können, umfassen:

• debug(überschreibenandroid: debugvondas<Application>Element im Manifest, um anzuzeigen, dass die App debug in Betracht gezogen werden sollte)

• applicationIdSuffix(Anhängen zuder Paketname spezifi
durch das Manifest
oder diedefaultConfig applicationIdEigentum)

• versionNameSuffix(Anhängen zuder Versionsname spezifi
durch das

Manifest oder diedefaultConfig versionEigentum)

(HINWEIS:applicationIdSuffixwar früher bekannt alspackageNameSuffixvordie das Android-Plugin für Gradle 0.11 Release)

UnserDebug-Build-Typ fügt Suffixe an den Versionsnamen und der Anwendungs-ID Rolle für den Paketnamen. Beachten Sie, dass die Anwendungs-ID zuändern nur den Paketnamen beeinflusst wie von Android gesehen, wenn die App installiert ist, und wenn die Anwendung ausgeführt wird. Es wirkt sich nicht auf das Verzeichnis, in dem die R-Klasse gebaut wird, die den Paketnamen von der AndroidManifest.xml fi verwendet

Es tut aucheine der Java-Pakete nicht beeinflussen für
unsere eigenen Klassen, die sind, was wir, wenn wir sie geschrieben haben. Daher wird viel von unserem Code zu dem Paketnamen ändern blind sein. Wenn Sie jedoch die reale Paketnamen, wie zum Beispiel auf der Suche nach Dinge in Packagemanager oder für die Verwendung mit der Konstruktion eines Component verweisen möchten, verwenden Sie getPackageName () auf jedem Kontext (wie eine Aktivität), anstatt einige hartcodierte Zeichenfolge, wie getPackageName () gibt, was die Laufzeitumgebung denkt das Paket, die alle Suffixe umfassen wird während des Erstellungsprozesses hinzugefügt. Oder verwenden Sie BuildConfig.APPLICATION_ID, in Fällen, in denen Sie getPackageName keinen Kontext praktisch, auf dem haben () aufzurufen.

Wir können auch habeneine signingConfig Eigenschaft, für Konfi
wie unsere APK fi
sind digital signiert. Dies wird abgedecktimein späteres Kapitel.

Rangfolge

Eigenschaften definiertein Build-Typ, und die für die definierten

EigenschaftendefaultConfigaußer Kraft setzenihre Entsprechungen in derAndroidManifest.xmlfi jedochein sourceSet Build-Typ kann auch seine eigene habenAndroidManifest.xmlfi Die Gesamtrangordnung ist:

• Was ist inbuild.gradlehat Vorrang vor ...

• …was ist inein Buildtyp desAndroidManifest.xmlfi
welche hat Vorrang vor ...

• …was ist indasHaupt AndroidManifest.xmlfi

Allerdings manifestiert sich in der Regel Verschmelzung istein komplexes Thema, mitein eigenes Kapitel später im dieses Buch.

Ressourcen aussourceSet Build sind aus dem Haupt sourceSet in die Ressourcen zusammengeführt, und wenn es Kollisionen sind, der Ressource Buildtyp hat Vorrang. Dasselbe gilt für Vermögenswerte.

Aber,das Verhalten von Java Quelle ist etwas anders. Die Quelle-Set Buildtyp ist immer noch mit dem Haupt sourceSet verschmolzen, aber wenn es eine Kollision ist, ist das Ergebnis ein Buildfehler.

Entweder ist die Build-Typ oder der Haupt sourceSet kann jede beliebige Quelle fi definieren nichtbeide. Also, währendDebug noch eine Version Ihres / package / name / Foo.java und Freigabe
haben könnte, eine andere Version Ihres / package / name / Foo.java, Haupt haben könnte konnte nicht ebenfalls habenIhr / package / name / Foo.java. Wenn Sie also eine Klasse in einem Buildtyp definieren, müssen Sie diese Klasse zu definieren, in alle Typen bauen, sodass Verweise von Haupt zu dieser Klasse sind satisfi
für alle bauen Arten.

Einem Fall, in demdies nicht für wäre Debug-only-Aktivitäten erforderlich wäre. Nehmen wir an, dass Sie eine Aktivität in Ihrer Anwendung zu liefern Diagnoseinformationen an die Entwickler dieser App in Bezug auf den Zustand der Cache-Speicher und andere In-Memory-Konstrukte wollten.

Während Sie an dem Zeug über einen Debugger bekommen könnte, ist, dass manchmal ärgerlich, und nur auf einem Launcher-Symbol tippen kann einfacher sein. Aber Sie nicht wollen, geschweige denn Notwendigkeit, diese Diagnose-Aktivität in Ihrem Release-Builds. Um diese Arbeit zu machen, würden Sie die Tätigkeit der Java-Klasse setzen nur im Debug-sourceSet, zusammen mit seinen Ressourcen und manifestieren Eintrag (komplett mit MAIN / LAUNCHER <Intent-Filter>).

Schon seitdie wichtigsten sourceSet auf Ihre Diagnose-Aktivität bezieht sich nicht, gibt es keine Voraussetzung für die Release-Build-Typ eine Implementierung dieser Java-Klasse zu haben.

Hinzufügen von Build-Typen

Viele Entwickler werden nur fi Tarif
mit die Debug-und Release-Build-Typen, vielleicht mit
einigen Anpassungen, wie oben gezeigt. Einige Entwickler werden aber haben andere Szenarien, die neue Build-Typen rechtfertigen. Glücklicherweise ist eine neue Build-Typ Hinzufügen ziemlich einfach, wie es in der gesehenGradle / HelloBuildTypeBeispielprojekt, das baut aufdie vorherige Probe, das Hinzufügen eines neuen Build-Typ.

Wie beiDie Einbau-Build-Typen, Ihre neue Build-Typen können ihre eigenen sourcesets haben, indem Sie die entsprechend benannten Verzeichnisse unter src / hinzufügen. Und wie bei den eingebauten Typen bauen, können Sie die neue Build-Typen in der buildTypes Schließung in build.gradle konfigurieren:

(von Gradle / HelloBuildType / build.gradle)

ImDieses Projekt wollen wir eine dritte Buildtyp namens Mezzanine, ein "Mittelweg" zwischen einem normalen Debug-Build und Release-Build darstellt.

Um sagen Android überdie neue Build-Typ, brauchen wir ein zu initialisieren. Dies wird durch die mezzanine.initWith (buildTypes.release) Anweisung behandelt, die die neue Mezzanine-Build-Typ-Konfiguration auf den bereits definierten Release-Build-Typ basierend initialisiert. Von dort aus
kann die nachfolgende Mezzanine-Schließung die Eigenschaften dieser Buildtyp ändern. In diesem Fall haben wir:

• Stellenein .mezz ausrei auf den Paketnamen

• Flaggedas Projekt als debug

• Anmeldung mitdie Freigabe Signaturschlüssel

Schon seitdie Mezzanine-Build-Typ mit der Release-Build-Konfiguration gestartet wird, ist der Nettoeffekt ist, dass wir einen Build haben, die mit dem Release-Build entspricht, nur mit dem debug fl

Set (und ein einzigartiges Paket Name).

Jetzt gewinnen wir GradleAufgabenMezzaninimder Name, wieinstallMezzanine, Zu gehen zusammen mit ihrenDebuggenundFreisetzungPendants.

Hinzufügen Produkt Flavors und Erste Varianten bauen

Viele Anwendungen werdennicht Produkt Aromen, aber einige werden müssen. Hinzufügen eines Produktgeschmack ähnelt in vielerlei Hinsicht, um das Hinzufügen eines Build-Typ, wie wir in die sehenGradle / HelloProductFlavorsBeispielprojekt, das baut aufdie vorherige Probe, ein Paar Produkt Aromen hinzu: Vanille und Schokolade.

(Anmerkung: Die Produkt Aromen tunwerden müssen, nicht nach dem tatsächlichen Aromen genannt) Jedes Produkt Geschmack, wie mitjeder Buildtyp, kann seine eigene sourceSet haben. In diesem Beispiel haben wir src / Vanille / und src / Schokolade / Verzeichnisse ein Quellsatz für jedes Produkt Geschmack darstellt:

HelloProductFlavors

| - build.gradle

| - HelloConfig.keystore

| - libs /

|

| - android-support-v4.jar

| - local.properties

| - proguard-project.txt

| - project.properties

| - src /

| - Schokolade/

|

| - Java/

|

| - com /

|

| - commonsware /

|

| - android /

|

| - gradle /

|

| - Hallo/

|

| - MainActivityOptionsStrategy.java

| - debuggen/

|

| - res /

|

| - Werte/

|

| - strings.xml

| - Main/

|

| - AndroidManifest.xml

|

| - Vermögenswerte/

|

| - Java/

|

|

| - com /

|

|

| - commonsware /

|

|

| - android /

|

|

| - gradle /

|

|

| - Hallo/

|

|

| - MainActivity.java

|

| - res /

|

| - ziehbar-hdpi /

|

|

| - ic_launcher.png

|

| - ziehbar-LDPI /

|

| - ziehbar-MDPI /

|

|

| - ic_launcher.png

|

| - ziehbar-xhdpi /

|

|

| - ic_launcher.png

|

| - Layout/

|

|

| - activity_main.xml

|

| - Menü/

|

|

| - main.xml

|

| - Werte/

|

|

| - dimens.xml

|

|

| - strings.xml

|

|

| - styles.xml

|

| - Werte-sw600dp /

|

|

| - dimens.xml

|

| - Werte-sw720dp-Land /

|

|

| - dimens.xml

|

| - Werte-v11 /

|

|

| - styles.xml

|

| - Werte-v14 /

|

| - styles.xml

| - Vanille/

| - Java/

| - com /

| - commonsware /

| - android /

| - gradle /

| - Hallo/

| - MainActivityOptionsStrategy.java

Imdie sourcesets, haben wir einMainActivityOptionsStrategyKlasse, eine Implementierung pro Produkt Geschmack. Diese Klasse wird verwiesen durcheine neue Implementierung
derHauptaktivitätKlasse indasMainsourceSet, zu delegierender Umgang
mitonOptionsItemSelected ():

(von

Gradle / HelloProductFlavors / src / main / java / com / commonsware /
android / gradle / hallo / MainActivity.java)

Da wir tunnicht viel haben nichts in der Menü-Option zu tun, protokolliert jede Implementierung des Produkts Geschmack von MainActivityOptionsStrategy einfach eine geschmacksspezifischen Nachricht an LogCat, wie die hier für Vanille gezeigt:

(von

Gradle / HelloProductFlavors / src / Vanille / java / com / commonsware / android /
gradle / hallo / MainActivityOptionsStrategy.java)

Erzählendas Android-Plugin für Gradle über unser Produkt Aromen und ihr Verhalten zu konfigurieren, haben wir einen neuen productFlavors Verschluss in der build.gradle fi

(von Gradle / HelloProductFlavors /
build.gradle)

DasdefaultConfigimplementiert wird unter Verwendungdie gleichen Objekttyp wie für das Produkt Aromen verwendet wird. Daher können wir die gleichen Dinge auf einem Produkt Geschmack konfigurieren, das wir können auf diedefaultConfig, sowieapplicationIdWird, wie in dies getanbuild.gradlefi

In Bezug auf die Rangordnung:

• Produkt AromenÜberschreibungdasMainsourceSet unddasdefaultConfig

• BauenTypen der Produkt Aromen außer Kraft setzen

Damit,ein Debug-Build des Aroma Vanille Produkt wird in einem Paketnamen Ergebnis com.commonsware.android.gradle.hello.vanilla.d.

UnserAufgabennamen erhalten zahlreicher und komplizierter, das Kreuzprodukt der Produkt Aromen zu reflektieren und Arten bauen. Nun, anstattinstallDebug.installMezzanine, undinstallRelease, wir haben:

• installChocolateDebug

• installChocolateMezzanine

• installChocolateRelease

• installVanillaDebug

• installVanillaMezzanine

• installVanillaRelease

Tundie Splits

Das Android-Plugin für Gradle bietetfür zwei unterschiedliche Szenarien spaltet als leicht für Produkt Aromen in Dosen Ersatz:

• Mit verschiedenen APK fi
mit anders NDK Binärdateien für ARM vs. x86

(gegen irgendetwas anderes)

• Mit verschiedenen APK fi
mit Ressourcen für eine spezifi Rasterdichte, wichtig
für die Anwendungen, die so viele Grafiken, die sie Vertriebsweg Grenzen werden Stoßen gegen (zB 100 MB im Play Store, im Vergleich zu einer früheren 50MB Grenze)

Alles, was Sie alsein Entwickler tun, ist verlangen, dass eine bestimmte Spalte, mit begrenzter Konfiguration aktiviert werden. Bemerkenswert ist, haben Sie keine separaten Gradle Konfiguration (zB applicationId) noch sourcesets für Splits. Das ermöglicht Splits schneller zum Zeitpunkt der Erstellung verarbeitet werden, da die Build-Tools können einige vereinfachende Annahmen machen und eine Menge neu zu kompilieren vermeiden.

Scoping Ihre Splits

Ein Split, standardmäßig wird eine APK pro mögliche Art der Ausgabe zu erzeugen. Zum Beispiel Spaltung auf Dichte wird Ihnen ein APK für LDPI, MDPI, tvdpi, hdpi, xhdpi, xxhdpi und xxxhdpi.

Außerdem im Fall der Dichte, erhalten Sie auch eine "universelle" APK enthält Unterstützung für alle Dichten standardmäßig.

Das ist schön ... aber was ist, wenn Sie tun,benötigen keine gesonderten APKs für alle diese Dichten? Zum Beispiel, wenn Sie nicht tvdpi Ressourcen versenden, gibt es wenig Grund, eine APK zu treffen, damit sie getrennt von, sagen wir, der hdpi APK.

Es gibt zwei Grundmuster zu steuernder Umfang dessen, was gebaut wird:

1. Verwenden Sie einAusschlussanweisung mit den Standardeinstellungen gestartet
werden und einige Optionen entfernen

2. Benutzeneinreset ()Verfahren auszulöschendie Standardeinstellungen, dann verwenden Sie eineinschließen

Anweisung zur Liste, was Sie wollen

Mit anderen Worten,ausschließen implementiert eine schwarze Liste, und die Reset () / include Kombination eine weiße Liste implementiert. Unter sonst gleichen Bedingungen, eine weiße Liste ist wahrscheinlich eine bessere Wahl, so können Sie es explizit Linie mit dem, was Sie in Ihrer Anwendung geschrieben haben.

Anfordern von NDK Splits

In deinemandroid-Verschluss, können Sie einen Spagat Verschluss, enthaltend ein abi Verschluss, der wiederum richtet die APK-Splits von CPU-Architektur hinzu:

Hier haben wir:

• Aktivierendie Spaltung (aktivierenwahr)

• Entfernen die Standard ABIs enthalten (reset ()) werden

• Listeder Abis, die wir aufgenommen werden sollen (gehören "armeabi-V7A ','X86')

• Anforderndass ein "universelles APK" auch erstellt werden, enthält alle ABIs (universalApk true)

Letzteres wäre nützlich für die Vertriebskanäledass es nicht möglich, mehrere APK fi hochladen
fürverschiedene CPU-Architekturen. Auf diese Weise können Sie zumindest
verteilen Sie Ihre App gibt, auch wenn es mehr Speicherplatz in Anspruch nimmtals Sie mögen. In der Standardeinstellung für die CPU-Architekturen, erhalten Sie nicht eine "universelle APK".

Anfordern Dichte Splits

Das gleiche Grundmuster kann für Dichten realisiert werden:

Wiederum wirermöglichen die Spaltung, die Standardeinstellungen zurückzusetzen, dann entscheiden sich in den Dichten, die wir wollen.

Beachten Sie jedoch,dass ein "universelles APK" wird immer für Dichten erzeugt. Wir brauchen nicht universalApk wahr zu haben, und es scheint, dass universalApk falsch in der heutigen Zeit ist keine Option.

Neubetrachtungdas Vermächtnis Gradle Datei

In Anbetracht all dieser, lassen Sie uns wieder besuchendie build.gradle fi
von Eclipse-Export:

(vonGradle / Hallo / build.gradle)

Der Großteildasandroide-spezifische Konfiguration indie exportiertebuild.gradlefi kommt indassourceSetsVerschluss InnendasandroideSchließung. Hier haben wirangeben, welche zusammengestellt werden soll.

Gradle ermöglicht getrennten Standorten für alle Einzelteile derzeit deponiert insrc /: Java-Quellcode, AIDL Schnittstellendefinitionen, render Quelle fi

Und Java-Stil Ressourcen (nicht zu
verwechseln mit Android Ressourcen werden). Seit diesem Build fi
ist für jede dieser Arten
von Eingabe fi eine klassische Verzeichnisstruktur, obwohl,
werden noch sein in src /,
so dass die Haupt sourceSet Punkte Android src / für jeden von ihnen gefunden. Darüber hinaus zeigt, Haupt den Namen des Manifests fi
und die Lage der res / und Vermögen / Bäume.

DasHaupt Verschluss in der sourceSets Schließungüberschreibt die Standardpositionen von fi, die die sourceSet umfassen. Zum Beispiel in der neuen Projektstruktur geht das Java-Quellcode in Java / innerhalb von sourceSet, aber in der alten Projektstruktur, geht es in einem src / Verzeichnis im Projektstamm.

DasSetRoot () fordert die Lager Debug- und Release-Build-Typen zeigen, dass ihre sourcesets, wenn sie vorhanden sind, in einem separaten Build-Typen / Verzeichnis vorhanden sein sollten, als die normale src / Lage ist für Java-Quellcode verwendet wird.

Arbeiten mitdas neue Projektstruktur im Android Studio

Es überrascht nicht, Android Studio hatein paar Features, die Ihnen helfen, mit den verschiedenen sourcesets arbeiten, die Sie erstellen wählen und zu verwenden.

Die Build-Varianten anzeigen

Wenn wir unser Projekt ausführen, tut Android Studioveranlassen uns, nicht für einen Build-Typ oder ein Produkt Geschmack. Es läuft nur das Projekt. Es stellt sich die Frage, wie Android Studio ist zu bestimmen, welche bauen Variante die man laufen soll.

Dies wird gehandhabt durchdie Build-Varianten Ansicht, in der Regel auf der linken Seite des Fensters Android Studio IDE dockt:

Jede App-Module gezeigt, zusammen mitdie aktuelle Build-Variante, wenn Sie das Modul ausgeführt wird verwendet. Das Tippen auf der Build-Variante ermöglicht es Ihnen, eine alternative Build-Variante zu wählen:

Das Android-Projekt-Ansicht

Zuvordas Buch, wenn Android Studio Einführung haben wir gesehen,das Android-Projekt Aussicht.

In anderen Ländern, wir sahen, wiedas Android-Projektansicht können Sie Ressourcen über mehrere Ressourcengruppen helfen zu verwalten.

Genauso wiedas Android-Projektansicht "kollabiert" Ressource-Set, es auch kollabiert sourcesets: Hier haben wir zweiAusgaben des com.commonsware.myapplication Paket. Man ist nur der Name des Pakets, während der andere hat "(androidTest)" angefügt. Das ist, wie Sie sich vorstellen können, spiegelt die Haupt- und androidTest sourceSet jeweils:

Das könnte seinein wenig sinnvoll, zwischen Haupt- und androidTest. Es ist wahrscheinlich, viel nützlicher, wenn Sie Produkt Aromen verwenden, da die Klassen für die Aromen zu werden Seite an Seite ... zumindest für den aktuell ausgewählten Geschmack erscheinen in der Build-View-Varianten.Beimdas GeschenkZeit, Android Studio behandelt nur die aktive Variante des sourcesets (plus Haupt- und androidTest) als "Quelle", mit anderen Build-Variante sourcesets einfach nur fi betrachtet werden

.

Flavors, Build-Typen, unddie Projektstruktur Dialog

Sie sind herzlich eingeladen zu verwendenDie Build-Typen und Produkt Flavors

RegisterkartenProjekt Struktur-Dialog aufrecht erhaltendiese Teile Ihrer build.gradle fi beim dest für einfachere Szenarien.

Gradle und Abhängigkeiten

John Donne schrieb: "Kein Mensch ist eine Insel". Heute, nur wenige Anwendungen sind Inseln, auch nicht. Es ist die seltene Anwendung, die vermeiden kann alle Drittanbieter-Code Basen. Die meisten Anwendungen werden ein Backport oder andere Klasse benötigen (zB ViewPager) aus dem Paket Android-Support, oder wird auf das Play-Services SDK verlassen, oder wird eine beliebige Anzahl von Dritten JAR-Dateien und Android-Bibliotheksprojekte verwenden.

Das guteNachricht ist, dass Gradle zur Referenzierung dieser Code von Drittanbietern Basen viel Kraft hinzufügt, wenn Sie Ihre Anwendung bauen. Während es die Komplexität ein Bit für

"Wiederverwendung im kleinen" (beispielsweise ein einfaches JAR) erhöht, kann es erheblich vereinfachen "Wiederverwendung in den großen" (zB mehrere Android Bibliotheksprojekte).

In diesem Kapitel wird darlegen, welche Arten von "Abhängigkeiten" Ihre Anwendung haben können und wie Sie Gradle konfigurieren zu unterstützenSie.

Voraussetzungen und Warnungen

VerstehenDieses Kapitel setzt voraus, dass Sie die Kapitel gelesen haben, dassvorstellen Gradleund umfassen grundlegende Gradle / Android-Integration, einschließlichdas Vermächtnis Projektstrukturunddie neue Projektstruktur.

"Abhängigkeiten"?

Im Fallder Begriff ist neu für Sie, in diesem Kapitel und in der Gradle Dokumentation

"Abhängigkeiten" bedeutet "Code außerhalb Ihres Projekts, dass Ihr Projekt hängt".

Imder Fall von Gradle gebauten Android Apps, dazu gehören:

• lokale JARs

• NDK gebauten lokalen Linux .so fi

• lokale Android-Bibliotheksprojekte

• andereArten von "Teilprojekte"

• "ArtefakteRepositorys ", wie Maven Zentrale Jede dieser" erteilen

"wird in diesem Kapitel wiederum abgedeckt werden.

Eine Geschichte von zwei Abhängigkeiten Closures

EINbuild.gradlefi

- Oder das Paarbuild.gradlefi
im ein Projekt klassischen Android

Studio - werden zwei habenAbhängigkeitenVerschlüsse.

Man wird innen seindie buildscript Schließung, und dieser Satz von Abhängigkeiten Abhängigkeiten für den Build-Prozess selbst. Hier werden wir Abhängigkeiten wie die Android Build-Tools Liste, die diejenigen, die die Android-Optionen definieren wir konfigurieren können.

DasAbhängigkeitenSchließungdas ist ein Peer vonbuildscriptundandroideListendie

Abhängigkeiten für das Projekt, das durch diese besondere gebaut wirdbuild.gradlefi Mit anderen Worten,dasbuildscript AbhängigkeitenAbhängigkeiten werden Werkzeuge, währenddie regelmäßigeAbhängigkeitensind Kompilierung-Quellen von Code von Drittanbietern.

Abhängig voneine JAR

Imdie frühen Tage der Android-Entwicklung, Ant und Eclipse teilten eine gemeinsame Regel für Drittanbieter-JAR-Dateien: setzen Sie sie in Ihrem Projekt libs / und beide Umgebungen bauen es von dort nehmen würde. Genauer gesagt, sie würden:

• Hinzufügendiese JAR-Dateien zur Kompilierung-Classpath, so dass Ihr Code, dass diejenigen, JAR-Dateien "öffentliche APIs verweist würde kompilieren, und

• Hinzufügendie Inhalte dieser JAR-Dateien auf Ihre APK, so zur Laufzeit, Ihre Verweise auf diese Klassen "JAR-Dateien aufgelöst werden können

Und es funktionierte.

Dasneue Gradle-basierten Build-System verwenden, nicht automatisch den Inhalt Ihres libs /

Verzeichnis in der gleichen Weise. Deshalb ist unsere build.gradle fi, die einfache lokale JAR-Dateien verwenden, wird mit einem Abhängigkeiten Schließung eingereicht, die wie folgt aussieht: (vonGradle / Hallo / build.gradle)

Dasfiletree () den Verzeichnisbaum im Verzeichnis Eigentum verwurzelt gehen (hier Libs) und suchen fi

Abstimmungdas sind Wildcard-Muster (hier * .jar). Dadurch werden alle JAR fi
zurückkehren
imlibs /, die dann zu dem Kompilieren hinzugefügt.

Und während wir tunnicht explizit enthalten sagen, jene JAR-Dateien in der resultierenden APK
fi, die für uns als Teil der Android-Verarbeitung tatsächlich behandelt wird.

Hinweisdass dies konfigurierbar. Also, wenn aus irgendeinem Grund, würden Sie Ihren JAR-Dateien lieber sein zu haben, in einem anderen Verzeichnis alslibs /, sowieGläser /oderlocalDependencies

/oderwheeMakingLongDirectoryNamesIsFun /Sie sind herzlich eingeladen, dies zu tun.

... Und warum manche nicht mag dieses

Doch mit einfachen JARsAuf diese Weise ist verpönt, zumindest in Ermangelung besserer Optionen.

Ein Grund dafür istdass eine JAR-fi
tut enthalten nicht notwendigerweise alle Informationen
über die Version der JAR-fi

JAR-Dateien häufig aktualisiert werden, und es sei denn der

Autor des JAR ist "Mangeln in" die Versionsinformationen in die fi

Sie können nicht sagen,
indem maneine JAR ob sie alt oder neu ist.

Beispielsweise,die klassische Android JAR des Support-Paket ist android-support-v4.jar. Einige Entwickler sehen den -v4 Teil und gehen davon aus, dass dies bedeutet, dass dieser spezifi JAR ist die Version 4 der Bibliothek. In Wirklichkeit bedeutet -v4, dass es in erster Linie die Klassen aus android.support.v4 enthält und ist für den Einsatz mit Anwendungen konzipiert, die auf API-Ebene 4.

jedoch zur Unterstützung zurück, wird diese JAR alle paar Monate mit neuen Klassen aktualisiert und Bug-fi es. Daher zwei fi
genannt android-support-v4.jar kann radikal unterschiedliche

Inhalte haben, wenn man aus dem Jahr 2011 und ist ab 2013, zum Beispiel.

Dies ist, was verursachtdie Ant / Eclipse-Build-Prozess Schluckauf, wenn mehrere Kopien derselben JAR fi Begegnungen

(z.B, ein in Ihrem Projekt und eine mit den gleichen Namen in einem

Android-Bibliothek-Projekt). Name allein kann nicht unterscheiden, ob sie gleich sind. Die Build-Tools in Liquidation mit MD5-Hashes, um zu versuchen, um zu bestimmen, ob der Inhalt tatsächlich identisch waren, die funktioniert, aber ist keine ideale Lösung.

Ein weiterer Grund, warum die Menschen auf bloßen JARs Stirnrunzeln istdass es nichts gibt, die Abhängigkeiten der JAR selbst zu verwalten. Viele Male eine JAR auf andere JAR-Dateien abhängig ist, sondern
die JAR hat keine Möglichkeit, dass auszudrücken. Stattdessen werden die Entwickler angeblich auf eigene Faust zu kümmern, dass, vielleicht über die Dokumentation zu lesen und diese Anweisungen befolgen. Und da die Entwickler nicht immer Dokumentation zu lesen oder diese Anweisungen befolgen, manuelle Abhängigkeitsmanagement ist voller Gefahren.

In der klassischen Java-Entwicklung, "Artefakte" und "Repositorys" eingeführt wurden einige Wrapper zu helfen, bieten Metadaten umeine JAR-Entwickler fi helfen
die richtige Version
und bestimmen, wann Updates benötigt werden. Mit Artefakte und Repositories mit Gradle empfohlen und Gradle macht es vergleichsweise einfach, diese Strukturen zu verwenden, wie wir sehen werdenspäter imdieses Kapitel.

Je nach NDK Binaries

Es ist möglich, zu verwenden,das NDK mit Gradle für Android. Dies wird jedoch kompliziert genug, dass es degradiert wirddas Kapitel über die erweiterte Gradle für Android Techniken.

Je nach einem Android-Library Project

Android-Bibliotheksprojektebeliebte Möglichkeiten des Teilens Code haben zwischen den Projekten werden, wiesie umfassen Ressourcen zusätzlich zu den Java-Code. Einige Entwickler werden Android-Bibliotheksprojekte verwenden rein intern, für wiederverwendbare Code zwischen Projekten.

Einige Entwickler hängen von Drittanbieter-Bibliothek Projekte, wie Widget-Bibliotheken oder Googleappcompat-v7 Rückeinbindung des Aktionsleiste Muster. Einige Entwickler haben ihre eigenen Bibliotheken für fremde Nutzung veröffentlichen.

Erstellen a Library Project

Wie bereits indas Kapitel über die Android-Bibliothek-Projekt.Der primäre Unterschied zwischen einem normalen Android-Projekt und ein Android-Bibliothek-Projekt, in Bezug auf die Gradle Konfiguration ist, welches Plugin Sie verwenden. Regelmäßige Anwendung Projekte werden die com.android.application Plugin verwenden, während Android-Bibliotheksprojekte der com.android.library Plugin verwenden:

(von

Gradle / HelloMultiProject / Bibliotheken /

HelloLibrary / build.gradle)

Quelle Sätze verhaltendie gleichen, wie sie tun für regelmäßige Anwendungen, und sonst wird Ihr Code ist nicht anders, als es für eine regelmäßige Anwendung wäre. Aber wie immer, ist ein Android-Bibliothek-Projekt nicht entwickelt, um eine APK fi erstellen
aber vielmehr dienen
als eine Bibliothek.

Allerdings haben die Projekte Android-Bibliothek kann zugehörigen Testcode, der in abgedeckt istdas Kapitel überUnit-Tests.

Abhängig vondie Library Project

Sie haben zwei wichtige Entscheidungen für je nachein Bibliotheksprojekt:

1. Obdas Bibliotheksprojekt ist dein, und vor allem, wenn es nur wirklich dienen einer App ist, könnten Sie das Bibliotheksprojekt als Modul oder Teilprojekt des Projekts enthält, die App einrichten, wie wir sehen in werdender nächste Abschnitt.

2. Sie könnenveröffentlichendas Bibliotheksprojekt zu einem gewissen Repository als AAR Artefakt, sowieein lokales Repository.dannReferenzdass AAR als Abhängigkeit.

Coverage von Artefakten und Repositories angezeigtspäter imdieses Kapitel.

Diese sindnicht gegenseitig aus. Die CWAC Bibliotheken, die vom Autor dieses Buches veröffentlicht, zum Beispiel verwenden beide Techniken. Diese Projekte werden als Android-Bibliothek-Projekt veröffentlicht und eine (oder mehrere) Demo-Anwendung (en), um die Nutzung der Bibliothek zu demonstrieren. Im Debug-Builds hängen die Demo-Anwendung (en) auf die Bibliothek als Teilprojekt. In Version baut allerdings hängt die Demo-Anwendung (en) auf einem veröffentlichten AAR der Bibliothek, um besseres Modell, was andere Entwickler sehen würde.

Wir werden sehen, wie Abhängigkeiten von Buildtyp variieren zu habenspäter imdieses Kapitel.

Je nach Teilprojekte

Gradle und Android Studio Unterstützungeine Struktur eines Top-Level-Verzeichnis eine Reihe von Teilprojekten oder Module enthält. Android Studio verwendet den Begriff "Modul"; Gradle wird der Begriff "Teilprojekt" verwenden

Beispielsweise,dasGradle / HelloMultiProjectVerzeichnis enthält:

• einHelloLibraryConsumerProjekt

• einBibliotheken /Unterverzeichnis enthält,einHelloLibraryProjekt

Imdieser Fall,HelloLibraryist ein Android-Bibliothek-Projekt,derjenige, von dem wir sahen diebuild.gradlefi früher indieses Kapitel.HelloLibraryConsumeristeine regelmäßige Anwendung, die Code verwendet in der gefundenHelloLibraryAndroid-Bibliothek-Projekt.

Wenn Ihre Bibliothek-Projekt mit einer App ausschließlich für den Einsatz ist, können Siewählen Sie den Code mit diesem Ansatz zu strukturieren.

Die Top-Level-Verzeichnis mussein settings.gradle fi die Gradle Projekte im Verzeichnis Verzeichnis (und alle seine Unterverzeichnisse):

(von Gradle / HelloMultiProject /
settings.gradle)

Die Führung:bezieht sich aufdie gesamte Stammverzeichnis, so: HelloLibraryConsumeristein Hinweis auf dieHelloLibraryConsumer /Verzeichnis unterder Ursprung. Andere:Werte repräsentieren Ebenendie Hierarchie, so: Bibliotheken: HelloLibrarybezieht sich aufdasBibliotheken / HelloLibrary

/subdirectory.:ichs anstelle von/eins/ichS durch Gradle für andere Zwecke verwendet.

Daher,die Anweisung include sagt Gradle, dass dieses Aggregat Projekt aus den beiden Teilprojekten besteht.

Um anzuzeigendassHelloLibraryConsumerzu konsumieren möchte Code ausdasHelloLibraryBibliothek, ein andererLeitung ist mit den zusätzlichenAbhängigkeitenSchließung, Referenzierungdas Teilprojekt: (von

Gradle / HelloMultiProject /

HelloLibraryConsumer / build.gradle)

Wohingegenfiletree ()ist fi
die JAR-Dateien in derlibs /Verzeichnis,Projekt ( ':

Bibliotheken: HelloLibrary')ist die Identifizierungdas Teilprojekt, und wir sagen, dass Gradle Teilprojekt in unser Projekt zu kompilieren.

Vondie gesamte Stammverzeichnis (das mit dersettings.gradlefi

Du kannst
rennengradleAufgaben für die gesamte App. Dies funktioniert auch von den wichtigsten App-Verzeichnis (in diesem Fall,HelloLibraryConsumer /).

WährendDieser Ansatz ist fi für einige Anwendungen, wird diese Struktur nicht gut funktionieren, wenn die Bibliothek mehrere mögliche raubend Apps hat, vor allem, wenn diese Anwendungen von anderen Autoren sein könnten. In diesem Fall müssen die Bibliothek als ein Artefakt in einem Repository veröffentlicht wird, die im nächsten Abschnitt behandelt.

Je nach Artifacts

Während JAR-Dateien und Teilprojekte durchaus möglich sind mit Gradle für Android,die vorherrschende Ansatz Abhängigkeiten für die Angabe ist von gehosteten Artefakte in Repositories verweisen.

Was ist ein Artefakt?

Im, Eine Liste von dem Artefakt eigenen Abhängigkeiten und die damit verbundenen Informationen der Kontext von Java-basierten Programmierung, ein Artefakt der Regel bezieht sich auf eine JAR-Datei (oder andere kompilierte Ausgabe, wie ein Java EE WAR), durch Metadaten zu ergänzen, die Versionsinformationen zur Verfügung stellt.

Was istein Repository?

Ein Repository ist eine Sammlung von Artefakten, in einer Stelle gespeichert, die um fi bezeichnet werden kann,
und lösen die Anforderung von Abhängigkeiten.

Such-Repositories sind in der Regel unterteilt in "lokale" und "remote" zu sein. Ein lokales Repository ist eine, die auf die eigene Entwicklung Maschine befindet; ein Remote-Repository ist eine, die auf einem Server befindet. Dieser Server könnte relativ lokal sein (zB ein Repository in Unterstützung vonein Unternehmensentwicklung Team) oder es könnte irgendwo anders sein.

Vielleicht ist die bekannteste "woanders" ist Maven Central, ein Repository, das von vielen OpenSource-Projekten für ihre Artefakte zu verteilen.

Arten der Artefakte und Repositorys

Es gibt zweiArten von Repositories, und die damit verbundenen Artefakt Strukturen, unterstützt von Gradle: Maven und Ivy. Jede hat ihr eigenes Format für die Metadaten und ihre eigene Struktur, wie das Fi
sind gelagert.

Maven

Apache Mavenistein vollwertiges Build-System. Ein Teil dieses Build-System ist ein System von Artefakten und Repositories. Während Gradle Maven nicht System Build verwenden - und nicht ersetzt es weitgehend it - Gradle veröffentlicht Artefakte in einem Maven- strukturierten Repository verbrauchen kann. Maven Central, wie man erwarten könnte, ist ein solches Repository, aber es ist eminent möglich, eigene zu gründen, und einige Organisationen haben das getan.

Wie Maven scheint zu sein,desto beliebter der beiden, wird dieses Buch konzentrieren sich auf Maven- strukturierten Repositories und Maven-Stil Artefakte.

Efeu

Apache Ivyist ein Ableger vondie Apache Ant-Projekt, das uns die Ant-Build-System gab. Ivy ist einfach eine Möglichkeit, Abhängigkeiten zwischen den Komponenten zu erklären, darunter

"transitiven Abhängigkeiten" Handling (dh App A hängt von Bibliothek B, die wiederum hängt von Bibliotheken C und D).

Allgemeine Artifact Dependency-Setup

Um hängen von Artefakten, Siemüssen Gradle zwei Dinge zu lehren:

1. Wo kann Artefakte gefunden werden?

2. Was Artefakt (n) tun Siebrauchen?

Erstere kommt ausein Repositorys Verschluss in Ihrem build.gradle fi
nachgeben Sie die

Repositories, die Sie für Artefakte suchen möchten.

Das letztere kommt von anderen Variationendie Kompilierung-Anweisung in der Abhängigkeiten Schließung. Anstatt mit so etwas wie ein filetree kompilieren () verwenden, werden Sie die Artefakte an, die Sie verwenden möchten.

Artefakte werden durch drei Stücke von Daten identifiziert:

1. Eine Gruppe

2. Ein Artefakt ID

3. Eine Versionsnummer

Diese werden durch Doppelpunkte voneinander getrennt, sokompilieren 'com.commonsware.cwac: Colormixer: 0.5.0'würde anzeigen,dass Sie suchen, das Artefakt, dass:

• …ist indascom.commonsware.cwacGruppe…

• …hatdasColormixerArtefakt ID und ...

• ... Ist die Version0.5.0

Abhängig vonMaven Central oder JCenter Artifacts

Der häufigste Ort, um Artefakte zu bekommen istMaven Zentral. Dies ist in etwa analog zudie RubyGems Repository für Ruby-Entwickler oder CPAN für Perl-Entwickler. Maven Central ist ein

Lager von vielen, vielen Artefakte, nur eine Teilmenge davon wird für Android relevant sein, wie Maven Zentrale hat für viele andere Java-Umgebungen verwendet wurden (zB Java-Web-Container).

Bintray- Eine fi
im das Artefakt-Repository Geschäft - hat JCenter. JCenter ist ein Spiegel
von Maven Central, und Entwickler als auch Artefakte direkt zu JCenter veröffentlichen.

Wenn Sie möchten, um Artefakte zu verwenden, um von einem derdiese Repositories, Ihrebuild.gradlefi
werden braucheRepositorysVerschluss, beiDie oberste Ebene (dh getrennt
von der eine in derbuildscriptSchließung),dass Anfragen entwedermavenCentral ()oderjcenter (): Dann können Siekompilieren Anweisungen in Ihrer Abhängigkeiten Schließung, die Artefakte auflisten, die auf Maven Central oder JCenter gefunden werden kann. Ein Weg, um fi aus
was Sie können, ist enthalten zu besuchen das"Gradle, bitte" Website, wo Du kannstTyp in der Name einer populären Bibliothek (zBPicasso) Und erhalten die entsprechendenAbhängigkeiten Schließung:

Wenn Sie mehrere Abhängigkeiten, Listesie in der einen Abhängigkeiten Schließung, eine nach der anderen. So zum Beispiel, abhängig sowohl von Picasso und lokalen JARs, würden Sie haben: Vielleicht erinnern Sie sichdass ein Top-Level-build.gradle fi Android Studio-Projekt enthält so
etwas wie:

Dasallprojects Schließung stellt Konfiguration, die für alle Module (Teilprojekte) im Projekt angewendet werden soll. Daher sind die hier definierten Repositorys für alle Module definiert werden, darüber hinaus alle Repositorys Schließung im eigenen build.gradle fi des Moduls Je nach Googly Artifacts

Aber,nicht alle Artefakte sind bei Maven Central oder JCenter gespeichert.

Ein wichtiger Satz von Artefakten an anderer Stelle gespeichert sind Google. Lieberals Sie auf Maven Central sind abhängig sind, bieten sie ihre eigenen Repositories, diejenigen, die Sie auf Ihrer Entwicklungsmaschine über den SDK-Manager herunterladen können. Sie sind die "Android-Support Repository" und das "Google-Repository" genannt, wo der ehemalige das Haus für Dinge wie die Android-Support-Paket ist, und letztere ist die Heimat für Dinge wie das Play-Services SDK.

Diese Repositories, wenn sie gefunden werden, um Ihre Gradle Umgebung automatisch hinzugefügt. Also, im Gegensatz mit Maven Central, was Sie tunnicht brauchen, um sie zu einem Repositories Schließung manuell hinzufügen.

Wenn Sie lesen durchdie Kern Kapitel dieses Buches haben Sie gelernt, über die Unterstützung-v4 und Support-v13-Artefakte und bietet Klassen wie ViewPager und NotificationCompat. Es gibt Dutzende von anderen kombiniert zwischen dem Android-Repository und Google

Repository, von denen viele werden an anderer Stelle in diesem Buch behandelt.

durch Referenzierungdiese Artefakte, müssen Sie nicht mehr herum zu verwirren mit JAR-Dateien oder Anbringen Android Bibliothek Projekte zu Ihrer eigenen Projekte kopieren.

Je nach Andere Artifact Repositorys

Gradle unterstützt Repositories benutzerdefinierte Artefakt, in Maven oder Ivy Stil, für den Abruf von Artefakten. Zum Beispiel könnte Ihr Entwicklungsteam habenein gemeinsames Artefakt-Repository für Ihre Projekte, unter den Entwicklern geteilt und eine kontinuierliche Integration Server. Oder Sie können wählen Sie Ihre wieder verwendbare Komponenten in Ihrem eigenen Repository zu veröffentlichen, meidet Maven Central.

DasGradle Dokumentation Abdeckungendie verschiedenen Möglichkeiten, wie zum Beispiel, wie Authentifizierungsinformationen für gesicherte Repositories enthalten. Normalerweise aber werden Sie eine einfache URL:

DiesRepositorys Schließung fügt eine Maven-Stil-Repository, befindet sich auf
http://repo.commonsware.com.

Dies ist einäquivalentesRepositorysSchließung, sondern gibt anhttpswiedie Regelung für die sichere Downloads der Artefakte. Da dies insbesondere Repository bei Amazon S3 gehostet werden passiert, erfordert das SSL-Zertifikat, dass wir die volle Amazon S3 Domain-Namen

(repo.commonsware.com.s3.amazonaws.com) Anstelle derCNAMEStenografie

(repo.commonsware.com).

Von dort aus können Siedann fordern Sie gegen zu kompilieren, was auch immer Artefakte der Herausgeber dieses Repository zur Verfügung stellt.

Ihre ganz eigene Repository

Sie können Ihr eigenes lokales Repository zu haben, nur auf die eigene Entwicklung Maschine.

Beispielsweise, wenn Sie ein Android-Bibliothek-Projekt schreiben, und mit Teilprojekten verweisen es unangemessen ist (zB wird die Bibliothek von mehreren unterschiedlichen Anwendungen verwendet wird), können Sie Ihre AAR Artefakt zu Ihrem lokalen Repository veröffentlichen, dann haben Sie Ihre anderen Anwendungen abhängig wie in diesem Repository auf dieses Artefakt gefunden.

Verbrauchen Artefakte aus dem lokalen Repository ist nureine Angelegenheit von a mavenLocal ()Eintrag in IhremRepositorysSchließung:

Die genaue Lage derDieses Repository wird plattformabhängig. Unter Linux, zum Beispiel, ist es in ~ / .m2 /. Allerdings wird es auf dem lokalen Computer sein.

HINWEIS: Bei einigen Versionen von Gradle,mavenLocal ()tutnicht arbeiten. Die Abhilfe ist:

Sie können Ihre eigenen gehosteten Repository haben, wenn Sie es wünschen. Beispielsweise,Der Autor dieses Buches ist als JAR verfügbar sein, seine Projekte CWAC über und AAR Artefakte aus dem repo.commonsware.com Repository oben erwähnt langsam umwandelt. Von Gradle (und Maven) Sicht gibt es keinen wirklichen Unterschied zwischen einem Repository auf einem nahe gelegenen fi gehostet

Server oder einige Remote-Web-Server. Eine Diskussion darüber, wie Ihre Artefakte zu einem solchen Repository zu bekommen, ist nicht in den Anwendungsbereich dieses Buches.

Publishing Bibliotheken als Artefakte

Natürlich, miteine lokale (oder remote) Repository ist nur so gut wie Ihre Fähigkeit ist, die Dinge in das Repository zu setzen. Und gerade jetzt, das ist ein Ort, an dem die aktuelle Gradle für Android-Plugin herunter fällt. Die Dokumentation erwähnt das AAR-Format bietet aber keine Anweisungen zu deren Veröffentlichung im Zusammenhang mit, und Änderungen im Plugin haben viele gepflasterte-together-Lösungen von 2013 gebrochen.

Die aktuelle einfachste Lösung kommt indie Form des Maven-Plugin, das, wie der Name schon sagt, ein Plugin für Gradle ist, die Unterstützung für die Veröffentlichung von Maven Artefakte aus Gradle baut hinzufügt.

Wiedies ist ein Standard Gradle Plugin, alles, was Sie tun müssen, ist
habenanwendenPlugin: "Maven"in deinembuild.gradlefi
um es zu benutzen.

Dann können Sie festlegen, wo und wiedas Maven Plugin sollte Ihr AAR über einen uploadArchives Verschluss, als Top-Level-Verschluss (dh einem Peer von Ihrem Android-Schließung) veröffentlichen:

DasgroupId und artifactId bilden die Grundlage für den Namen Ihres Artefakt (in diesem Fall ein fi
com.commonsware.cwac: Alles-ist-awesome-Bibliothek). Die Version, ist
natürlich die Version des Artefakts. Der URL-Parameter auf dem Repository-Aufruf zeigt an, wo das Artefakt sollte hochgeladen werden, und dies zu einemöffentlichen Repository verweisen kann (zB Maven Central), ein privates Unternehmen Repository gehostet wird, ein lokales Repository (wie es hier der Fall) usw.

Beimdieser Punkt wird die gradle uploadArchives Befehl Ihre AAR bauen und es zu Ihrem benannten Maven-Repository bereitstellen.

Veröffentlichen Vermächtnis-Strukturierte Bibliotheken als Artefakte

Hinweis dass es keine besondere Anforderung, dass Ihre AARs von Android Projekte, die die neue Build-System bevorzugte Verzeichnisstruktur verwenden erstellt werden. Ihre AARs kann aus einem Projekt kommen, die die Legacy-Verzeichnisstruktur erhalten bleibt. Dies ist der Schlüssel für die nächsten Jahre, während AAR Unterstützung langsam dominant wird, so dass Sie Ihr Android-Bibliothek-Projekt verwendet wird, in der traditionellen Quelle Form als auch unterstützen kann.

Wir werden sehen, Beispiele für die VerwendungLegacy-Strukturen für AAR-Erstellung Bibliotheksprojektespäter imdieses Kapitel.

Über Artifact Updates

Die Version vondas Artefakt, das Sie erhalten durch die Version qualifiziert in Ihrer angegebenen Abhängigkeit bestimmt. Es scheint nicht alles in Gradle zu sein, sich selbst Sie über Fälle zu sagen, wo es Artefakte mit aktualisierten Versionen zur Verfügung. Ben Manes veröffentlichtein Gradle Pluginfügt hinzu, dass eine dependencyUpdates Aufgabe, einen Bericht von dem, was erzeugt der Status aller Ihrer Abhängigkeiten.

Erstellen von Android JARsvon Gradle

Gradle hateine lange Geschichte der in der Java-Entwicklung verwendet wird, und die Standard-Java Plugin für Gradle weiß, wie JAR fi erstellen

.

Aber wir sindmit dem Java-Plugin nicht. Stattdessen verwenden wir das Android oder Android-Bibliothek Plugin. Im letzteren Fall könnte man argumentieren, dass es sollte JAR-Erstellung Aufgaben, für Bibliotheken unterstützen, die eigentlich keine Ressourcen verwenden und so weiter.

Leider ist es tutzumindest ab dem Zeitpunkt des Schreibens dieses Artikels nicht. Daher gibt es keine JAR-Erstellungsaufgabe verfügbar von Android oder Android-Bibliotheksprojekte.

Wie allgemein indiese Fälle, Jake Wharton hat zur Rettung kommen.

Jake geschriebeneine Antwort aufeinen Stapelüberlauf FrageBereitstellen eine schnelle und unsaubere bisschen Gradle Code JAR-Erstellung Aufgaben zu einem Android-Bibliothek-Projekt hinzuzufügen:

Der Gradle DSL inGroovy geht es vor allem Datenstrukturen aufzubauen. Daher wickeln alle unsere Build-Varianten in einer Sammlung von Objekten zur Verfügung zu android.libraryVariants auf.

Jakes Snippet iteriert über diejenigen, wirft aus diejenigen, die für Debugbuilds und dynamisch defi
eine neue Aufgabe. Dassneue Aufgabe wird genannt Glas werden ..., wo der ... der Name des Build-Typ ist. Sein Snippet konfiguriert dann diese Aufgabe eine JAR-fi zu erstellen
nach der Java-Code kompiliert wurde, für Java-Kompilierung das Ergebnis in das

Zielverzeichnis setzen.

DasErgebnis ist, dass am Ende dieses Schnipsel einschließlich Ihrerbuild.gradlefi fügtAufgaben wiejarReleasedas wird eine JAR erstellen inbuild / libs /Ihres Projekts. Hinweisdass diejarReleaseAufgabe erscheint nicht, wenn Sie laufengradle Aufgaben, Obwohl es wird angezeigt, wenn Sie laufengradle Aufgaben--allebekommendie komplette Liste.

Dies giltkein vollständiges Artefakt um die JAR erstellen, so dass, wenn Ihr Plan dieses JAR zu einem Artefakt-Repository vorzulegen war, würden Sie zusätzliche Arbeit zu tun haben. Doch für den einfachen Fall einer JAR für die manuelle Verteilung zu schaffen (zB durch den

"Veröffentlichungen" Bereich eines GitHub-Repository), sollte es fi arbeiten Eine Eigenschaft von Transitive (Abhängigkeiten)

Einswas zu achten ist, wenn Abhängigkeiten spezifiziert ist, wo Ihre Abhängigkeiten

'Abhängigkeiten kommen. Kurz der Prüfung Konfiguration fi
für diese Abhängigkeiten

(zB ihre Maven POM fi
du hastkeine gute Möglichkeit, zu wissen, was Ihre

Abhängigkeiten "Abhängigkeiten werden, geschweige denn, aus denen sie kommen sollte.

Trotzdass,nach Gradleware:

Nurdie Repository-Erklärungen für das Projekt, dessen Konfiguration derzeit aufgelöst werden berücksichtigt, auch wenn transitiven Abhängigkeiten beteiligt sind.

So zum Beispiel an, dass AppA hängt von Bibliothek B, die wiederum hängt von Bibliothek C-Bibliothek B in Ihrem Team die eigenen Maven Repository, während Bibliothek C von Maven Zentrale kommt. App A müssen sowohl Ihre eigenen Maven-Repository und Maven Central in den Repositories Schließung definiert zu haben, um für Gradle der Lage sein, beide Bibliotheken zu erhalten.

Abhängigkeiten von Build-Typ

Ein Build-Typ kann seine eigenen Abhängigkeiten.

Daskompilieren Anweisung in einem Abhängigkeiten Schließung definiert Abhängigkeiten für alle Arten bauen. Jedoch kann jeder Buildtyp hat seine eigene Version der Kompilierung Anweisung, wie debugCompile, die eine Abhängigkeit ausschließlich für den Gebrauch von diesem Buildtyp hinzufügen.

Wenn Sie Ihre eigene benutzerdefinierte Typen bauen erstellen, beachtendass Sie benötigen, um Ihre Abhängigkeiten Verschluss zu haben, nachdem Sie die Build-Typ in der build.gradle fi

definieren

Nur nach Gradle hat Build definiert Typ wird Ihre individuelle Kompilierung

Anweisung zur Verfügung.

Es gibt auchandroidTestCompile, die Abhängigkeiten ausschließlich für den Einsatz mit der Prüfung definiert. Dies ist in größerem Detail behandeltimdas Kapitel über die Unit-Tests.

Abhängigkeiten von Flavor

Und falls Sie Produkt Aromen definieren, können Sie Abhängigkeitendass nur auf einen bestimmten Geschmack gebunden.

Beispiel: Angenommen, Sie eine App für verschiedene Wearables wurden zu schreiben und Ihnen bei der Einrichtung drei Produktgeschmacksrichtungen:

EINAbhängigkeitenVerschluss nach dasandroideVerschluss
enthält,obenstehendesproductFlavorsKonfiguration könnteeine Mischung aus pro-Flavour Abhängigkeiten und geschmacksspezifische Abhängigkeiten, wie zB:

Hier,die letzte Abhängigkeit sonyCompile verwendet, anstatt kompilieren, was darauf hinweist, dass es eine Abhängigkeit ist nur für den Sony Produktaroma eingesetzt werden.

Hinweisdass das Artefakt aufgelistet für die sonyCompile Richtlinie nicht tatsächlich existiert, zumindest ab dem Zeitpunkt des Schreibens dieses Artikels. Es ist möglich, von SONY

Codebeispiele in lokale Artefakte zu konvertieren, als Referenz über mavenLocal (), bis zu dem Zeitpunkt SONY beginnt sie auf Maven Central oder ihr eigenes Artefakt-Repository-Hosting.

Untersuchen Einige CWAC Baut

Der Autordieses Buch veröffentlicht mehrere Open-Source-Bibliotheken, als CommonsWare Android Components (CWAC) bekannt. In diesem Abschnitt werden wir einige dieser Projekte untersuchen, um zu sehen, wie die Gradle Unterstützung durchgeführt wurde, mit einem besonderen Auge auf Abhängigkeiten.

Ein einfaches CWAC Projekt: CWAC-Layouts
die meistendie CWAC Projekte sind ziemlich einfach. Darüber hinaus relativ wenige Klassen, am meisten CWAC Projekte haben keine Abhängigkeiten über Android selbst. Diese sind recht einfach mit Gradle zu unterstützen, sowohl für den Aufbau der Bibliothek selbst und für einen Gradle-kompatiblen Artefakt zu veröffentlichen.

Beispielsweise,die CWAC-Layouts Projektdiskutiert indas Kapitel über die benutzerdefinierte Aussichts, Da es ein paar solche Ansichten bietet, vor allem die Spiegelung Klassen.

Das CWAC-Layouts Repository hat zwei Projekte:Layouts und Demo. Die Layouts Projekt ist das eine für die Bibliothek selbst, während Demo die Benutzung der Bibliothek zeigt.

Fürdie Gradle bauen,DemoundLayoutsModule sind mit freundlicher Genehmigung
vonsettings.gradleimdas Projekt Stammverzeichnis:

DasDemo-Modul hängt von dem Layout-Modul. Es wird jedoch so in eine von zwei Arten:

• obdies ist ein Debug-Build, es auf dem Layout-Modul ab, so dass die Demo-

Anwendung, die Unterentwicklung Version dieses Moduls verwenden können

• obdies ist ein Release-Build, es auf dem AAR Artefakt im CommonsWare
arifact Repository hängt

In jeder anderen Hinsichtdie build.gradle fi des Demo-Projekt
ist eine herkömmliche

Implementierung "finden Sie in der Legacy-Projektstruktur verwenden".

Die Bibliothekbuild.gradlefi
ist ein bisschen mehr beteiligt:

Es benutztdas Maven Plugin die uploadArchives Aufgabe zu ermöglichen, wie bereits erwähntfrüher dieses Kapitel. Das wird kompilierendas Bibliotheksprojekt in ein AAR und veröffentlichen sie auf den lokalen CWAC Maven Repository Entwicklungsmaschine. Unabhängig davon hat der Autor ein Skript, das die notwendige fi drücken wird
nachdie Amazon

S3-hosted CommonsWare Maven-Repository.

Die Konstanten bezeichnet indasrepositories.mavenDeployerSchließung kommen ausein gradle.propertiesfi
welche wird abgedeckt in einem der nächsten Kapitel.

Die Bibliothekbuild.gradlefi
ebenfalls enthält die benutzerdefinierte Gradle-Code, der eine
hinzufügtjarReleaseAufgabe wie beschriebenfrüherdieses Kapitel. DiesAufgabe verwendet auch

Werte wiePUBLISH_VERSIONundPUBLISH_ARTIFACT_IDvondasgradle.propertiesfi Daher wird, wennDer Autor möchte eine neue Version der Bibliothek zu schieben, die Schritte sind: 1. ändern Sie diePUBLISH_VERSIONimdasgradle.propertiesfi

2. LaufgradleuploadArchivesgenerierender AAR und veröffentlichen sie lokal

3. Verwenden Sie einen externen Mechanismus zu veröffentlichendie AAR zum

CommonsWare Repo

4. LaufgradlejarReleasegenerierendie JAR-Version des Projekts

5. Veröffentlichendass JAR über die GitHub "freigibt" Teil des GitHub-Repository CWAC-Upon-CWAC: CWAC-Präsentation

Ein CWAC ProjektDas hat eine Abhängigkeit istdie CWAC-Presentation-Projekt. Dies wird diskutiert indas Kapitel über Präsentationund externe Display-Unterstützung, Angebotdie PresentationHelper und verwandte Klassen die Erstellung von Anwendungen zu erleichtern, die externe Displays unterstützen.

Einigediese im Zusammenhang mit Klassen verwenden, um die CWAC-Layouts Spiegelung Klassen. Zum Beispiel wird MirrorPresentationFragment entworfen, um auf einem externen Display einen Spiegel eines Teils der primären Anzeige angezeigt werden, wie die Spiegelung nur die Folien, mit der primären Anzeige auch Steuerungen für die Folienpräsentation mit. Daher hängt CWAC-Präsentation auf CWAC-Layouts, und dass berücksichtigt werden muss, in das Projekt erstellen fi

.

Wie bei CWAC-Layouts,die CWAC-Presentation-Repository hat die Bibliothek (Präsentation) und ein Demo-Projekt (Demo). Es hat auch einen separaten demoService Projekt, das eingerichtet ist, einen anderen Teil der Bibliothek zu demonstrieren. Und, anders als die Abhängigkeit Einschalten Präsentation zu sein, anstatt Layouts, die build.gradle fi
von die Demo und demoService

Projekte sind die gleichen wie die für die CWAC-Layouts:

Die Bibliothekbuild.gradle fi
ist die gleiche wie die für die CWAC-Layouts Bibliothek, mit
zwei Ausnahmen:

1. Es beinhaltetein Repositorys Schließung, die URL zum CommonsWare Maven Repository liefert

2. sie fügt hinzu, eine Abhängigkeit von der CWAC-Layouts Bibliothek in ihrer

Abhängigkeiten

Schließung

Die resultierende AAR haben wird, in seiner Maven POM Metadaten fieine Abhängigkeit von CWAC-Layouts. Wenn wir also die Demo-Projekt zu erstellen, wird laden Sie es sowohl die Präsentation AAR und die Layouts AAR, alle seine Abhängigkeiten zu fulfi.

Abhängigkeiten unddie Projektstruktur Dialog

Sie sind herzlich eingeladen zu verwendenAuf der Registerkarte Abhängigkeiten indie Projektstruktur DialogIhre Abhängigkeiten, zumindest für einfachere Szenarien zu halten.

Table of Contents

- Key Android Konzepte
- Die Wahl Ihrer Entwicklungs-Werkzeugen
- Tutorial # 1- Installieren der Werkzeuge
- Android und Projekte
- Tutorial # 2 - Erstellen eines Stub-Projekt
- Unterwegs in Android Studio
- Inhalt von Android-Projekte
- Einführung in Gradle unddas Manifest
- Tutorial # 3- Offensichtliche Änderungen
- Ein paar Worte über Ressourcen
- Tutorial # 4- Einstellen Unsere Ressourcen
- DasDie Theorie von Widgets
- Die Android-Benutzeroberfläche
- Grund Widgets
- Debugging-App
- Die Classic-Container-Klassen
- Andere gebräuchliche Widgets und Container
- Tutorial # 5- Fortschritte machen
- GUI-Gebäude, Fortsetzung
- AdapterViews und Adapter
- Die WebView Widget
- definierenund Verwendung von Stilen
- JAR-Dateien und Bibliotheksprojekte
- Tutorial # 6Hinzufügen einer Bibliothek -
- Einführung in ConstraintLayout
- Die Aktionsleiste
- Vector Drawables

- Tutorial # 7- Einstellung der Aktionsleiste oben

- Android-Prozessmodell
- -Aktivitäten und deren Lifecycles
- Tutorial # 8- Einstellung eine Tätigkeit Up
- Die Taktik des Fragments
- Tutorial # 9- Start Unsere Fragmente
- Swiping mit ViewPager
- Tutorial # 10- Aufriggen ein ViewPager
- Ressourcen Sets und Konfigurationen
- Material Design Basics
- Der Umgang mit Themen
- Anfordern von Berechtigungen
- Tutorial: Runtime Permission Unterstützung
- Assets, Dateien und Daten-Parsing
- Tutorial # 11Hinzufügen einfacher Inhalt -
- Tutorial # 12- Anzeige der Buch
- Mit Voreinstellungen
- Tutorial # 13- Mit einigen Einstellungen
- SQLite-Datenbanken
- Tutorial # 14- Speichern Hinweise
- Internet Zugang
- Intents, Intent-Filter
- Broadcasts und Broadcast-Receiver