19.11.2012

Eclipse und Android - was man alles falsch machen kann

Heute mal was für Programmierer und solche, die es werden wollen ...
Wahrscheinlich amüsieren sich die Profis über meine ersten Stolperschritte mit einer neuen Eclipse-Installation. Ich hab's ja nicht so mit GUIs, ich bin ein reiner Kommandozeilenmensch ;)

Es war einmal ... ein Eclipse Indigo mit Android SDK auf einem WXP-System zur Entwicklung einer kleinen App für Android 2.2.
Android 2.2 als Target, weil sich exakt mit dieser Version das API für den Zugriff auf eine SD-Karte eingeführt wurde (getExternalFilesDir()).
Dann war lange Zeit Pause, weil die App einfach so fröhlich vor sich hin funktionierte.
Nach einem Jahr und etwas mehr war ich genervt von den neuen Android-Versionen, die an mir vorübergingen, weil Samsung keine Updates für die Galaxy-S-Geräte auf die Reihe bekam. Also Anschaffung Nexus7 und Galaxy Nexus ;), Verkauf Archos 101 (Android 2.2.1), Galaxy i9000 (2.3.3). Am Rand: Nexus7 seit 2 Tagen auf 4.2, GNexus noch auf 4.1.2.

Interessanterweise funktioniert die bisherige App für den Wetterauer Tiernotdienstkalender (aus dem Play Store) auch auf diesen Nexus-Geräten, die ja prinzipiell keine SD-Karten unterstützen (außer mit Tricks auf gerooteten Geräten und einem USB-OTG-Adapter ...).

Irgendwann kam ein neuer PC mit Linux (RHEL 6.3) und Eclipse Juno und die Lust, ein bißchen weiter an den bisherigen Apps zu basteln und auch mal am lang geplanten und siechenden Romanverwaltungsprogramm (für PR und die anderen Serien, die ich sammle) weiterzuschrauben.

Also:
  1. Eclipse Juno installiert
  2. Android SDK installiert
  3. Android plugin für Eclipse installiert
  4. Android SDK Manager zum Download diverser Google Images und APIs gestartet
  5. An diversen Permissions geschraubt, bis Eclipse, AVD und ADT als User (nicht root) funktionieren
  6.  Sourcen der Apps in den Eclipse-Workspace kopiert
  7. Freundliche Fehlermeldungen über R.java
  8. Clean Project
  9. R.java wird in gen/ nicht neu erzeugt ;(
  10. Fehlersuche bei stackoverflow.com und diversen anderen
  11. Alle Tipps der Reihe nach ausprobieren ...
  12. z.b. "manage imports" erzeugt immer wieder "import android.R;" (Erklärung dafür: das Android SDK stößt auf einen Fehler und bricht ab. R.java wird nicht erzeugt, deshalb bastelt Eclipse sich irgendwas zurecht ;( )
  13. z.b. "clean"
  14. z.b. "properties->android tools->fix project properties"
  15. z.b. "Build Path->Order"
  16. z.b. "per-project java build environment"
  17. Aus lauter Verzweiflung dann statt dem IBM JRE 1.6.0.11 noch Sun JDK 1.7.09 installiert und eclipse -vm /opt/jdk_1.7.0_09/jre/bin aufgerufen.
  18. z.b. Prüfen aller XML auf Korrektheit
  19. Im grafischen Editor für das UI fiel mir auf, dass nix angezeigt wurde, und zum ersten Mal wenigstens mit einem Hinweis: keine Version angegeben für Emulator!
  20. Also Preferences->Android aufgerufen
  21. Dort wurde nur Version 4.0.3 und 4.1.2 angezeigt, obwohl ich in der Zwischenzeit auch die benötigte 2.2 mit dem SDK Manager geladen hatte.
  22. Meine App hat aber minSdkVersion="8", also brauche ich Google API 8 zum Bauen.
  23. Android SDK Pfad neu gesetzt und Eclipse neu gestartet.
  24. Jetzt werden alle im SDK Manager geladenen Android-Versionen korrekt angezeigt. Bingo!
  25. Normalerweise kenne ich den "Neustarten"-Trick ja nur von Windows ;)
  26. Und die Moral von der Geschicht': man soll nicht Sachen parallel machen, hier Nachladen von Android-APIs mit dem SDK Manager und schon mit dem Entwickeln in Eclipse anfangen.
Des weiteren habe ich meinen Code etwas umgestellt, um sowohl mit Geräten ohne als auch solchen mit SD-Karte umzugehen.

Alt:
        public static void setDataDir(Context c) {
                if (okStorage()) {
                        DataDir = c.getExternalFilesDir(null).toString();
                        logger("setdatadir.ext", DataDir);
                } else {
                        logger("setdatadir.error", "no external storage");
                }
        }

        public static boolean okStorage() {
                StorageState = Environment.getExternalStorageState();
                if (Environment.MEDIA_MOUNTED.equals(StorageState)) {
                        StorageAvailable = StorageWriteable = true;
                } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(StorageState)) {
                        StorageAvailable = true;
                        StorageWriteable = false;
                } else {
                        StorageAvailable = StorageWriteable = false;
                }
                return StorageWriteable;
        }


Neu:
        public static void setDataDir(Context c) {
                if (okExtStorage()) {
                        DataDir = c.getExternalFilesDir(null).toString();
                        logger("setdatadir.ext", DataDir);
                } else {
                        DataDir = c.getFilesDir().toString();
                        StorageAvailable = StorageWriteable = true;
                        logger("setdatadir.int", DataDir);
                }
        }

        public static boolean okStorage() {
                return (DataDir != null);
        }

        public static boolean okExtStorage() {
                StorageState = Environment.getExternalStorageState();
                if (Environment.MEDIA_MOUNTED.equals(StorageState)) {
                        StorageAvailable = StorageWriteable = true;
                } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(StorageState)) {
                        StorageAvailable = true;
                        StorageWriteable = false;
                } else {
                        StorageAvailable = StorageWriteable = false;
                }
                return StorageWriteable;
        }