© DrHitch/Shutterstock.com
Android-Entwicklung für Einsteiger

3 Auf hoher See


Hinweis: Unser U-Boot hat inzwischen die eine oder andere Seemeile unter und auch über Wasser hinter sich gebracht. Wir haben tatsächlich Seeungeheuer zu Gesicht bekommen, und unser U-Boot ist nicht mehr so schön und glänzend, wie es zu Beginn unserer Reise war. Zeit für Ausbesserungsarbeiten. Wir wollen die eine oder andere unschöne Delle ausbeulen.

3.1 Etwas für die Optik – oder doch mehr?

Bisher haben wir uns fast nur in dem Quellcode unserer Datei SkeletonActivity.java umgesehen und haben uns auch in der Projektstruktur auf den Ordner src beschränkt. Es gibt aber noch mehr in unserem Projekt: XML-Dateien für statische Texte oder das Layout, Bildordner und Assistenten für die Icon-Erstellung warten darauf, entdeckt zu werden.

Neue Namensschilder an den Kabinentüren – aus „Clear“ wird „Ändern“

Die Beschriftung unseres Buttons und die Bezeichnung im Menü ist mit „Clear“ nicht mehr so ganz passend, das wollen wir noch ändern. Bei einer Durchsicht des Quellcodes in unserer SkeletonActivity.java sieht man zwar das Wort clear in verschiedenen Variationen, aber nirgends als String, den wir direkt ändern können. Und wer versucht, den Quellcode an einigen Stellen auf Verdacht hin zu ändern, erreicht unter Umständen nur, dass Eclipse den Rotstift ansetzt und unsere App gar nicht mehr kompilieren will. Wer sich so durch den Quellcode gearbeitet hat, dem ist vielleicht aufgefallen, dass auch der ursprüngliche, formatierte Text aus dem Editorfeld, „Hello there, you Activity!“, nirgends zu sehen ist. Eigentlich muss ja auch noch irgendwo festgelegt sein, wo und wie alle Elemente positioniert werden. Und was ist mit unserer Bordkatze? Woher kommt die eigentlich?

Es muss also irgendwo in unserer Projektstruktur noch etwas geben, wodurch all diese Texte, Elemente und Anordnungen definiert sind. Machen wir uns einfach auf die Suche danach in unserem Projekt. Als Erstes suchen wir die Bezeichnung oder Definition für „Clear“, um diese zu ändern.

Es ist keine Detektivarbeit notwendig, um in unserem Quelltext erste Spuren zu finden: In der Methode onCreateOptionsMenu finden wir einen verdächtigen Hinweis in der Form R.string.clear, der offenbar für die Bezeichnung unseres Menüpunkts verantwortlich ist. Wo sich aber die Beschriftung unseres Buttons befindet, bleibt immer noch rätselhaft.

menu.add(0,BACK_ID,0,R.string.back).setShortcut('0', 'b');
menu.add(0,CLEAR_ID,0,R.string.clear).setShortcut('1', 'c');

Das mysteriöse „R“ taucht tatsächlich recht häufig in unserem Quellcode auf. So wird unserem Editorfeld in der Methode onCreate offenbar ein Text über ein R.string.main_label zugewiesen, den wir dann als „Hello there, you Activity!“ zu sehen bekommen:

@public void onCreate(Bundle savedInstanceState) {
...
mEditor.setText(getText(R.string.main_label));
}

Listing 3.1: Und schon wieder das mysteriöse „R“

Es muss also in unserem Projekt eine Klasse R.java geben, in der Informationen wie unsere Strings verwaltet werden. Nutzen wir die Gelegenheit, um einen Blick in unsere Projektstruktur zu werfen.

Hinweis: Sicherlich könnten wir die Elemente teilweise direkt durch Strings ersetzen, das wäre aber noch immer keine Lösung für unsere fehlende Katze, die Buttons und die Frage der Anordnung aller Elemente. Und wer weiß, vielleicht gibt es ja sogar einen plausiblen Grund für diese Arbeitsweise?

Ein Rundgang durch das Schiff – die Projektstruktur

Hinweis: Was vielleicht so spannend klingt wie Deck schrubben mit Salzwasser, kann durchaus interessant sein, wenn man zu sehen bekommt, woher die bisher vermissten Elemente unserer App kommen. Außerdem werden wir ein paar Abkürzungen nehmen, versprochen.

Wir lassen in unserem Paket-Explorer den Ordner SkeletonApp ausklappen, soweit dies nicht bereits geschehen ist. Falls das Dargestellte einmal zu viel geworden ist, kann die Ordnerstruktur jederzeit wieder vollständig eingeklappt werden. Dazu bitte einfach auf das kleine Symbol mit dem Minuszeichen im Kopf unseres Fensters klicken oder alternativ die Tastenkombination STRG + SHIFT + NUMERISCHER TASTENBLOCK DIVISIONSZEICHEN verwenden. Ja, Eclipse ist berühmt für seine schon fast künstlerischen Tastenkombinationen.

Hinweis: Wer unvorsichtigerweise einmal etwas gelöscht haben sollte und so verursacht, dass die App daraufhin den Dienst verweigert, kann sich mit Projekt | Bereinigen ... das gesamte Projekt von Grund auf neu generieren lassen. Aus Performancegründen werden bei einem einfachen Start nicht alle notwendigen Elemente und Class-Dateien vollständig neu generiert. Gelöschten Quellcode oder andere Ressourcen im Original, wie beispielsweise Bilder, kann Eclipse so natürlich nicht neu generieren.

Abb_3_1.png

Abbildung 3.1: Unsere Projektstruktur im Paket-Explorer, schon mit einem gewagten Blick zwar nicht in Zukunft, aber auf die „R.java“

Die Ordner assets, tests und Android Dependencies wollen wir als versprochene Abkürzung außer Acht lassen, da dort tatsächlich nichts (oder kaum) Interessantes zu finden ist. Der Ordner Android 2.1 stellt unser verwendetes API mit allen Klassen dar. Ohne an dieser Stelle tiefer darauf eingehen zu wollen, sei zumindest soviel verraten: Wir finden hier alle Pakete mit ihren Klassen und können uns deren Methoden anzeigen lassen. Es kann durchaus hilfreich sein, auf diesem einfachen Weg einmal zu sehen, welche Methoden uns eine Klasse noch (oder überhaupt) zur Verfügung stellt.

Wir gehen aber weiter und sehen uns dafür lieber die Ordner bin und gen an.

„bin“ und „gen“ – ein paar Blicke nach links und rechts durch das Bullauge

Bei beiden Ordnern handelt es sich um Projektordner, deren Inhalte automatisch generiert werden. Ein Blick ist interessant und bei unserer Suche auch hilfreich, von Änderungen können und sollten wir hier aber Abstand nehmen: Im besten Fall werden unsere Änderungen überschrieben und sind damit nur nutzlos. Im schlimmsten Fall macht unsere App Probleme.

Der Ordner bin enthält eine Datei SkeletonApp.apk, die später noch wichtig für uns sein wird. Dabei handelt es sich um die Datei, die unsere App samt Programmcode und aller anderen Elemente wie Bilder oder Icons ausmacht und auf einem Smartphone (oder einer virtuellen Maschine) installiert werden kann.

Hinweis: In dieser Ansicht leider nicht erkennbar, enthält der Ordner bin auch alle kompilierten Java-Klassen unserer App. Wenn Ihnen abends langweilig ist, können Sie sich das über die Sicht „Navigator“ anzeigen lassen. Über Fenster | Sicht anzeigen | Navigator können Sie diese Sicht aktivieren, die sich mehr an der tatsächlichen Ordnerstruktur orientiert. Tatsächlich würden Sie dort auch eine verdächtige Klasse R.class finden. Natürlich kompiliert als Bytecode und damit nicht wirklich lesbar, aber es ist eine erste, gute Spur. Denn wo eine .class-Datei ist, ist oft eine lesbare .java-Datei nicht weit.

Im Stamm von bin ist dafür aber eine andere, sehr wichtige Datei sichtbar: Die AndroidManifest.xml. In dieser zentralen Datei sind viele Informationen unserer App zusammengefasst: das Package, Bezeichnungen und vor allem auch die Berechtigungen, die eine App für ihren Betrieb benötigt und die von dem User vor einem ersten Start bestätigt werden müssen. Benötigt eine App beispielsweise den Zugriff auf das Internet, um Inhalte abzurufen, dann genügt es bei Android nicht, das nur im Quelltext so zu programmieren. Aus Sicherheitsgründen muss transparent mitgeteilt werden, was die App benötigt, und das muss dann bei der Installation auch vom User bestätigt werden.

Hinweis: Versucht eine App trotzdem, auf eine Funktion zuzugreifen, die nicht in der AndroidManifest.xml angegeben ist, funktioniert der Zugriff schlicht und ergreifend nicht. Eine vergessene Berechtigung ist übrigens eine recht beliebte Fehlerquelle, die besonders Anfänger gerne ärgert.

Damit verlassen wir den Ordner bin. Änderungen sind hier wie gesagt nicht sinnvoll, da alle Dateien jederzeit neu generiert werden können. Auch die AndroidManifest.xml ist in Wirklichkeit nur eine Kopie der originalen (und bearbeitbaren) Datei im Stamm unseres Projekts.

Die erste (direkt sichtbare) heiße Spur finden wir in dem Ordner gen [Generated Java Files]. Auch in diesem Ordner gen werden übrigens alle Elemente automatisch generiert, Änderungen sind also hier auch nicht sinnvoll: Schauen ist aber trotzdem erlaubt.

Unter unserem Paket com.example.android.skeletonapp finden wir tatsächlich eine Datei R.java, die für unsere Inhalte verantwortlich sein muss. Der erste Blick in diese Datei mag aber etwas enttäuschen: Der Inhalt wirkt kryptisch und bringt uns der Lösung unseres Rätsels scheinbar nicht näher.

Wir lösen das Geheimnis von „R“

„R“ ist keine mysteriöse Geheimorganisation, die versucht, die Weltherrschaft an sich zu reißen: R.java ist eine (die) zentrale Datei, über die alle Zugriffe auf die Ressourcen des Projekts geregelt werden. Sie ist das Bindeglied zwischen Ressourcen und dem Quellcode. Alle Elemente in unserem Projekt, das Bild unserer kleinen Katze und auch unsere vermissten Texte werden dort automatisch für eine Verwendung in unserem Programmcode referenziert. Die Erzeugung von „R“ übernimmt Eclipse ganz automatisch für uns.

Hinweis: R.java wird automatisch generiert, deshalb finden wir diese Datei auch im Ordner gen [Generated Java Files]. Manuelle Änderungen werden im Normalfall von Eclipse sofort durch eine neu erzeugte R.java überschrieben. Selbst das Löschen ist zwar möglich, Eclipse erzeugt aber auch in diesem Fall sofort eine neue Datei.

Sehen wir uns die Menübeschriftung in der R.java und die Verwendung in unserem Quellcode doch einmal an: Der Text in unserer App, im Quellcode taucht er als R.string.clear auf, leitet sich aus der Klasse R aus string ab und hält als Variable clear (daher eben R.string.clear) die Referenz zu unserem Text. Der zur Referenz passende Text ist übrigens im Ordner res in der Datei strings.xml abgelegt (das sei schon einmal verraten). Um die korrekte Referenzierung brauchen wir uns selbst nicht zu kümmern, das geschieht intern durch Eclipse. Der Fall ist also gelöst.

public static final class string {
public static final int back=0x7f050001;
public static final int clear=0x7f050002;
...

Listing 3.2: Unsere Menübeschriftung: Wir brauchen uns zum Glück keine Gedanken zu machen, was genau „0x7f050002“ bedeutet, es ist ein Verweis auf einen tatsächlich vorhandenen Text

public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, BACK_ID, 0, R.string.back).setShortcut('0',
'b');
menu.add(0, CLEAR_ID, 0, R.string.clear).setShortcut('1',
'c');

Listing 3.3: Und hier die Verwendung in unserem Quellcode, in unserer „SkeletonActivity.java“

Das einzige, was jetzt tatsächlich noch fehlt, ist ein Blick auf den Ordner res, in dem sich die entsprechenden Elemente befinden. Und wir wollen auch nicht vergessen, dass die Beschriftung unseres Buttons damit zwar identifiziert, aber ja immer noch nicht geändert ist.

„res“ – mehr ...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang