Posts mit dem Label Android werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Android werden angezeigt. Alle Posts anzeigen

18. Juni 2014

In eigener Sache: Android-Library "AndroidSeekBarPreference"

Gemäß den Design-Richtlinien des mobilen Betriebssystems "Android" werden die Einstellungen einer App als sogenannte "Preferenes" angeboten. Die Android-API, die für die Entwicklung von Apps zur Verfügung steht, bietet eine Reihe solcher Preferences, wie beispielsweise solche zur benutzerdefinierten Eingabe mittels Textfelder oder zur Auswahl eines Wertes aus einer vorgegebenen Liste, an. Eine Preference zur Auswahl eines Zahlenwertes aus einem kontinuierlichen Zahlenbereich mittels eines Schiebereglers, einer sogenannten SeekBar fehlt der API jedoch. Die Android-Library "AndroidSeekBarPreference" schließt diese Lücke, indem sie die Implementierung einer solchen Funktionalität, einschließlich vielseitiger Konfigurationsmöglichkeiten anbietet. Eine Preference, die mit Hilfe der Library umgesetzt wurde, erlaubt es, wie es durch den unten stehenden Screenshot verdeutlicht wird, einen Auswahldialog zu öffnen mit dessen Hilfe es möglich ist, einen Fließkommawert oder einen ganzzahligen Wert aus einem vorgegebenen Wertebereich zu wählen. Der ausgewählte Wert wird dabei erst übernommen, wenn der Benutzer die Auswahl bestätigt. Daneben besteht auch die Möglichkeit, den Dialog zu beenden, ohne die getätigte Änderung zu übernehmen.

Das Erscheinungsbild einer Preference der Library "AndroidSeekBarPreference" (Klicken zum Vergrößern)

Die Library unterstützt dabei die folgenden Funktionen:
  • Erlaubt es, einen Fließkommawert oder einen ganzzahligen Wert aus einem kontinuierlichen Wertebereich mittels einer SeekBar zu wählen.
  • Die Anzahl der Dezimalstellen der Fließkommawerte, die durch die Preference ausgewählt werden können sollen, kann vorgegeben werden. Wenn die Anzahl der Dezimalstellen auf 0 gesetzt wird, können stattdessen nur ganzzahlige Werte ausgewählt werden.
  • Der Wertebereich, bzw. der minimale und maximale Wert, kann frei gewählt werden. 
  • Der Dialog, der dem Benutzer zur Auswahl des Wertes angezeigt wird, kann eine frei wählbare Nachricht beinhalten.
  • Der ausgewählte Wert wird erst übernommen, wenn der Benutzer die Auswahl bestätigt. Daneben besteht auch die Möglichkeit, den Dialog zu beenden, ohne die getätigte Änderung zu übernehmen.
  • Es ist möglich, eine Schrittweite zu definieren. Wenn die SeekBar von dem Benutzer bewegt wird, wird der aktuelle Wert um diese Schrittweise erhöht, bzw. erniedrigt.
  • Die Anzeige des aktuell gewählten Wertes kann dahingehend konfiguriert werden, dass eine Einheit definiert werden kann, die zur Ausgabe an den eigentlichen Wert angehängt wird und dass das Symbol, das zur Trennung von Fließkommazahlen genutzt wird, frei gewählt werden kann.
  • Die Unterschrift der Preference kann abhängig von dem aktuell ausgewählten Wert gewählt werden. Alternativ kann auch der gewählte Wert selbst angezeigt werden.
  • Das Erscheinungsbild der Preference entspricht dem der, von der Android-API bereits angebotenen, Preferences.
Die Library kann über diese Projektseite auf Sourceforge bezogen werden. Der Quellcode wird unter der GLPL 3-Lizenz veröffentlicht und steht über ein Mercurial-Repository bereit. Unter diesem Link finden sich die JUnit-Tests der Library und unter diesem Link wird eine Beispielanwendung angeboten, die zu Präsentationszwecken Gebrauch von der Library macht.

Weiterführende Links:


4. März 2014

In eigener Sache: Bachelor-Thesis veröffentlicht

In diesem kurzen Post soll darauf hingewiesen werden, dass ab sofort für alle Interessierten die Abschlussarbeit meines Informatik-Bachelor-Studiums in der Rubrik "Publikationen" auf dieser Webseite zur öffentlichen Verfügung steht. Alternativ kann die Arbeit als PDF-Dokument unter diesem Direktlink heruntergeladen werden.

Das Titelblatt der Bachelorarbeit "Eine mobile Anwendung zur videogestützten Benutzerführung mittels Augmented Reality" (Klicken zum Vergrößern)

Im Rahmen dieser Bachelor-Thesis mit dem Titel "Eine mobile Anwendung zur videogestützten Benutzerführung mittels Augmented Reality", die 2014 an der Fakultät für Informatik und Wirtschaftsinformatik der Hochschule Karlsruhe - in Zusammenarbeit mit dem Forschungszentrum Informatik (FZI) in Karlsruhe - entstand, wird eine Möglichkeit evaluiert, eine zusätzliche Kommunikationsmöglichkeit zur Erweiterung von Video-Kommunikationen zu realisieren, die es den Teilnehmern ermöglicht, benutzerdefinierte Grafiken auf Basis des Videobildes auszutauschen. Außerdem wurde eine Android-Anwendung umgesetzt, die das entsprechende Verfahren implementiert.

Weiterführende Links:

10. September 2013

Arch Linux: Zugriff auf Android-Gerät via MTP über Nautilus

Dieser Artikel soll nur ein kurzer Hinweis darauf sein, wie man unter Arch Linux auf das Dateisystem neuerer Android-Geräte über den GNOME-Dateimanager "Nautilus" zugreifen kann. Ab der Android-Version 3.0 wird hierfür das MTP-Protokoll verwendet, welches Anfangs nur sehr schlecht von den verschiedenen Linux-Distributionen unterstützt wurde. Als ich heute jedoch die MTP-Unterstützung unter Arch Linux installierte, war ich positiv überrascht darüber, wie einfach die Installation funktioniert und wie reibungslos ich auf mein Nexus 10-Tablet, das ich zu Testzwecken verwendete, zugreifen konnte.

Der Inhalt des internen Speichers eines Nexus 10-Tablets im Dateimanager Nautilus (Klicken zum Vergrößern)

Installation der MTP-Unterstützung


Um MTP im Dateimanager Nautilus nutzen zu können ist lediglich die Installation von zwei Paketen notwendig. Zu diesen Paketen gehört libmtp und gvfs-mtp, welche beide über die offiziellen Repositories zur Verfügung stehen. Über die folgenden Konsolenbefehle können sie installiert werden:
 $ sudo pacman -S libmtp  
 $ sudo pacman -S gvfs-mtp  
Anschließend muss das System neu gestartet werden. Nachdem dann das Android-Gerät per USB mit dem PC verbunden wurde, sollte dieses automatisch erkannt werden und in der Seitenleiste von Nautilus sollte unter der Kategorie "Geräte" ein neuer Eintrag für das entsprechende Gerät erscheinen, wie es auf dem oben abgebildeten Screenshot zu erkennen ist.

Falls das Gerät nicht erkannt wird, sollte man überprüfen, ob das Android-Gerät überhaupt so eingestellt ist, dass es das MTP-Protokoll verwendet. Hierfür zieht man die Benachrichtigungsleiste nach unten, wodurch eine Benachrichtigung mit dem Titel "Als Mediengerät angeschlossen" sichtbar werden sollte. Wenn man auf diese Benachrichtigung klickt, öffnen sich die Verbindungseinstellungen. Hier muss sichergestellt sein, das die Option "Verbinden als Mediengerät (MTP)" aktiviert ist.

Weiterführende Links:

Nexus 4: CyanogenMod flashen

In diesem Artikel wurde bereits beschrieben, wie ein Nexus 4-Smartphone gerootet werden kann. In diesem Artikel sollen darüber hinaus die weiteren Schritte beschrieben werden, die nötig sind um auf einem solchen gerooteten Gerät das CustomROM "CyanogenMod" zu installieren, das unter Anderem erweiterte Einstellungsmöglichkeiten gegenüber dem Stock-Android bietet. Voraussetzung für die in diesem Artikel beschriebenen Schritte ist das vorherige Rooten des Geräts nach der bereits erwähnten Anleitung und dass das Kommandozeilentool adb auf dem PC installiert ist, von dem das Flashen des CustomROMs durchgeführt werden soll. In diesem Artikel wird davon ausgegangen, das es sich hierbei um ein Linux-System handelt, das Vorgehen unter Windows oder MacOS müsste jedoch analog erfolgen.

Die folgenden Schritte sind nötig um CyanogenMod auf ein bereits gerooteten Nexus 4 zu flashen:
  1. Zunächst muss das Gerät in den Recovery-Modus versetzt werden. Hierfür müssen die beiden Lautstärke-, sowie die Power-Taste gedrückt werden, bis das Gerät in den Bootloader-Modus neustartet. Über die Lautstärke-Tasten navigiert man Anschließend zu dem Menüpunkt "Recovery mode" und wählt diesen über die Power-Taste aus.
  2. Im Recovery-Modus wählt man auf die selbe Weise den Menüpunkt "install zip from sideload". Das Gerät muss Dabei per USB mit dem PC verbunden sein, von dem das Flashen von CyanogenMod durchgeführt werden soll. Die Konnektivität der Verbindung lässt sich anschließend über den folgenden Befehl überprüfen, wobei als Ausgabe eine Seriennummer und der Begriff "sideload" ausgegeben werden sollte.
     $ adb devices  
    
  3. Anschließend muss eine passende CyanogenMod-Version heruntergeladen und installiert werden. Unter dieser Downloadseite werden alle Releases von CyanogenMod für das Nexus 4 zum Download angeboten. Die Releases auf dieser Seite werden nach verschiedenen Release-Zyklen kategorisiert. Die wichtigsten sind die Nightly-Builds, die täglich aktualisiert werden und den aktuellen Entwicklungsstand repräsentieren, wobei die Stabilität nicht gewährleistet werden kann, sowie die Stable-Releases, die in größeren Zeitabständen veröffentlicht werden und jeweils einen stabilen Entwicklungsstand repräsentieren. Nachdem eine CyanogenMod-Version heruntergeladen wurde, kann anschließend über den folgenden Konsolenbefehl installiert werden, insofern das Gerät per USB mit dem PC verbunden ist und sich im Sideload-Modus befindet. Der übergebene Dateiname muss hierbei je nach Version angepasst werden. Außerdem sollte beachtet werden, dass bei diesem Vorgang alle Nutzerdaten auf dem Gerät verloren gehen!
     $ adb sideload cm-10.2-20130909-NIGHTLY-mako.zip  
    
  4. Anschließend müssen außerdem, falls erwünscht, die Google-Apps separat installiert werden, da diese aus rechtlichen Gründen nicht in CyanogenMod enthalten sind. Diese sogenannten Gapps lassen sich unter dieser Downloadseite herunterladen, wobei die jeweilige Version auf die Version des installierten CustomROMs angepasst sein muss. Nach Abschluss des Downloads lassen sich die Google-Apps über den Sideload-Modus analog zu dem CustomROM selbst über folgenden Befehl installieren, wobei der übergebene Dateiname wiederum an die Version angepasst werden muss.
     $ adb sideload gapps-jb-20130813-signed.zip  
    
Nach Abschluss der oben genannten Schritte sollte die installierte CyanogenMod-Version nach einem Neustart des Nexus 4 gestartet werden. Falls der Bootvorgang jedoch in dem, auf dem unten dargestellten, Bootscreen hängen bleibt, sollte dies durch einen Factory-Reset, bzw. durch Leeren des Dalvik-Caches zu beheben sein. Ein Factory-Reset kann durch die Option "wipe data/factory reset" im Menü von ClockwordMod Recovery durchgeführt werden, die Option zum Leeren des Dalvik-Caches ist unter dem Menüpunkt "advanced" → "wipe dalvik cache" zu finden.

Der Bootscreen von CyanogenMod (Bildquelle: zdnet.com, Klicken zum Vergrößern)

Weiterführende Links:

9. September 2013

Nexus 4: Rooten unter Linux

Da mein stets treuer Begleiter, mein Galaxy Nexus, demletzt leider von uns gegangen ist, habe ich mir als Ersatz dessen Nachfolger, das Nexus 4, zugelegt. Um auch auf diesem Smartphone erweiterte Rechte für die Ausführung bestimmter Apps, wie z.B. eines In-App-Werbeblockers, zu haben, gilt es, das Gerät vor der Inbetriebnahme zunächst einmal zu Rooten. Da in diesem Blog auch bereits für das Galaxy Nexus eine Anleitung zu finden ist, wie es gerootet werden kann, soll ein dementsprechender Artikel über das analoge Vorgehen beim Nexus 4 natürlich nicht fehlen. Im Folgenden sollen daher die Schritte erklärt werden, die notwendig sind, um das Android-Smartphone zu rooten. In der Anleitung wird davon ausgegangen, dass das Rooten über einen PC erfolgt, der unter Linux läuft. Außerdem müssen auf dem System die Kommandozeilentools fastboot und adb installiert sein.

Das Nexus 4 (Bildquelle: n-droid.de, Klicken zum Vergrößern)

Bootloader entsperren


Zunächst einmal muss der  Bootloader des Geräts entsperrt werden. Hierfür, so wie auch für die folgenden Schritte, kann ein sogenanntes Root-Kit genutzt werden, das alle Tools enthält, die für das Rooten des Geräts notwendig sind. Ein solches Root-Kit für das Nexus 4 ist unter diesem Link verfügbar. Nachdem die zip-Datei heruntergeladen wurde, müssen die folgenden Punkte befolgt werden, um den Bootloader zu entsperren.
  1. Als erstes sollte das Archiv, das das Root-Kit enthält, in einen neuen Unterordner kopiert und entpackt werden. Hierfür können die folgenden Befehl in einem Terminal aus dem Download-Ordner heraus durchgeführt werden:
      $ mkdir Nexus4Root   
      $ mv Nexus4Root.zip Nexus4Root   
      $ cd Nexus4Root   
      $ unzip Nexus4Root.zip
    
  2. Um das Skript, das es erlaubt den Bootloader zu entsperren, ausführen zu können müssen Anschließend die Ausführrechte der entpackten Dateien über den folgenden Befehl angepasst werden:
      $ sudo chmod 755 *   
    
  3. Nun muss das Smartphone über ein USB-Kabel mit dem PC verbunden werden und über Halten der beiden Lautstärke- und der Power-Taste in den sogenannten Bootloader-Modus gestartet werden. Um zu überprüfen, ob eine funktionierende Verbindung zwischen dem Gerät und dem PC besteht, kann der folgende Konsolenbefehl genutzt werden. Falls eine Verbindung besteht, sollte als Ergebnis des Befehls eine Ausgabe erscheinen, die eine Seriennummer und den Begriff "fastboot" beinhaltet.
     $ sudo fastboot devices  
    
  4. Anschließend muss folgende Befehl ausgeführt werden um das Entsperren des Bootloaders anzustoßen:
     $ sudo ./fastboot-linux oem unlock  
    
    Daraufhin sollte auf dem Smartphone eine Abfrage erscheinen, ob das Entsperren tatsächlich durchgeführt werden soll, was mit "Yes" bestätigt werden muss. Hierfür kann über die Lautstärke-Tasten zu der entsprechenden Option navigiert werden und die Auswahl mit der Power-Taste bestätigt werden. Dabei sollte man jedoch beachten, dass dieser Schritt zur Löschung aller Nutzerdaten auf dem Gerät führt!
Wenn der Bootloader erfolgreich entsperrt werden konnte, ist die über die Zeile "LOCK STATE - unlocked" sichtbar, die zusammen mit anderen Informationen über den Status des Geräts im Bootloader angezeigt wird.

Alternativen Recovery-Modus flashen


In diesem nächsten Schritt muss ein alternativer Recovery-Modus auf das Gerät geflasht werden, der es erlaubt Skripte auszuführen und CustomROMs zu installieren. Im bereits genutzten Root-Kit ist als solcher bereits der Recovery-Modus "ClockworkMod Recovery" zu finden. Um diesen auf das Gerät zu flashen und zu starten sind die folgenden beiden Schritte nötig:
  1. Um das img-Datei, die den Recovery-Modus enthält, zu flashen muss der folgende Befehl in einem Terminal ausgeführt werden. Dabei muss weiterhin eine USB-Verbindung bestehen und das Smartphone im Bootloader-Modus gestartet sein.
     $ sudo fastboot flash recovery recovery-clockwork-touch-6.0.2.3-mako.img  
    
  2. Anschließend kann der Recovery-Modus gestartet werden, indem im Bootloader-Modus über die Lautstärke-Tasten zu dem Menüpunkt  "Recovery mode" navigiert wird und die Auswahl über die Power-Taste bestätigt wird.

App zur Root-Verwaltung installieren


In diesem letzten Schritt muss außerdem noch die App "SuperSU" installiert werden, die es erlaubt die Root-Rechte zu verwalten und einzelnen Apps zeitweise oder dauerhaft einzuräumen. Auch diese App ist im bereits heruntergeladenen Root-Kit enthalten. Über die folgenden Schritte kann sie installiert werden.
  1. Das Gerät sollte sich momentan im Recovery-Modus befinden und dessen Menü angezeigt werden. Um die SuperSU-App von dem PC auf das Smartphone zu transferieren und zu installieren ist über die Lautstärke- und die Power-Tasten der Menüpunkt "install zip from sideload" auszuwählen.
  2. Anschließend wird vom PC aus das Kommandozeilentool adb genutzt um die zip-Datei, die die App enhält auf das Smartphone zu übermitteln. Analog zu dem Tool fastboot  kann die Konnektivität über den folgenden Konsolenbefehl überprüft werden:
     $ adb devices  
    
    Wenn eine Verbindung besteht, kann die App über den folgenden Befehl installiert werden:
     $ adb sideload CWM-SuperSU-v0.99.zip  
    

Neustart des Geräts und Überprüfung der Root-Rechte


Zuletzt kann das Gerät, das sich immer noch im Recovery-Modus befinden sollte, über die Option "reboot system now" neugestartet werden. Um zu Überprüfen, ob das Rooten erfolgreich war, gibt es spezielle Apps im Google Play Store, wie beispielsweise die App RootChecker.

Weiterführende Links:

8. September 2013

Nexus 10: Stock-Android wiederherstellen unter Linux

In diesem Artikel soll die Vorgehensweise erklärt werden, wie ein Nexus 10-Tablet, auf dem ein Custom-ROM aufgespielt wurde, wieder in den Auslieferungszustand zurückgesetzt werden kann, indem ein Stock-Android geflasht wird. Voraussetzung hierfür ist, dass auf dem Linux-Rechner der für das Flashen des Stock-ROMs genutzt wird die Kommandozeilen-Tools adb und fastboot installiert sind. Diese Anleitung sollte analog auch für alle anderen Nexus-Geräte funktionieren, insofern die dafür passende Version des Stock-ROMS heruntergeladen und geflasht wird.

Das hier beschriebene Vorgehen löste bei mir außerdem ein Problem, bei dem das Tablet nach dem Aufspielen einer CyanogenMod-Version nicht mehr startete, weil es im Bootscreen (in dem das Google-Logo angezeigt wird) hängen blieb. Nachdem ich das Stock-Android zurück gespielt hatte, bootete das Nexus 10 wieder ich konnte anschließend wieder CyanogenMod flashen.

1 Entsperren des Bootloaders


Zunächst muss der Bootloader entsperrt werden, insofern dies nicht bereits im Zuge der Installation eines CustomROMs geschehen ist.
  1. Um zu überprüfen, ob der Bootloader bereits entsperrt ist, muss das Gerät in den Bootloader-Modus gebootet werden. Hierfür müssen die beiden Lautstärke-, sowie die Power-Taste gehalten werden. Alternativ kann das Tablet bei bestehender USB-Verbindung in den Bootloader-Modus versetzt werden, indem der folgende Befehl in einem Linux-Terminal ausgeführt wird:
     $ adb reboot bootloader  
    
    In dem daraufhin erscheinenden Bootloader sind eine Reihe von Informationen über das Gerät aufgeführt. Unter dem Eintrag "LOCK STATE" ist ersichtlich, ob der Bootloader bereits entsperrt ist, oder nicht.
  2. Falls der Bootloader nicht bereits entsperrt ist, muss hierfür der unten stehende Konsolenbefehl bei bestehender USB-Verbindung ausgeführt werden.
     $ sudo fastboot oem unlock  
    
    Daraufhin sollte auf dem Tablet eine Abfrage erscheinen, die durch die Option "Yes" bestätigt werden muss. Hierfür muss mit den Lautstärke-Tasten zu dem entsprechenden Menüpunkt navigiert werden um die Auswahl anschließend mit der Power-Taste zu bestätigen. Es sollte jedoch beachtet werden, dass durch diesen Schritt alle auf dem Tablet gespeicherten Nutzerdaten gelöscht werden! 
    Der Bootloader des Nexus 10 (Bildquelle: gizmophiliacs.com, Klicken zum Vergrößern)

    2 Flashen eines "Factory Images"


    Wenn der Bootloader erfolgreich entsperrt wurde, kann anschließend ein sogenanntes "Factory Image", dass ein Stock-Android beinhaltet, auf das Gerät geflasht werden. Solche Factory Images für die Nexus-Geräte stehen unter https://developers.google.com/android/nexus/images zum Download zur Verfügung. Über diesen Direktlink kann das Android 4.3-Image für das Nexus 10 heruntergeladen werden. Nachdem die Datei heruntergeladen wurde, müssen die folgenden Schritte durchgeführt werden um das Stock-ROM zu flashen:
    1. Die zuvor heruntergeladene tgz-Datei muss zunächst entpackt werden. Hierfür kann unter Linux der folgende Konsolenbefehl genutzt werden, wobei der übergebene Dateiname eventuell angepasst werden muss:
       $ tar -zxvf mantaray-jwr66y-factory-3d8252dd.tgz  
      
    2. Anschließend muss in das, durch das Entpacken entstandene, Verzeichnis gewechselt werden und über folgenden Befehl das Skript zur Installation des Factory Images ausgeführt werden. Auch hierbei werden alle Nutzerdaten auf dem Gerät gelöscht! Dabei muss eine USB-Verbindung zu dem Gerät bestehen und sich dieses im Bootloader-Modus befinden.
       $ sudo ./flash-all.sh  
      
    Nachdem die oben aufgeführten Schritt durchgeführt wurden, sollte das Stock-Android des Nexus 10 wiederhergestellt sein.

    Falls der Bootvorgang des Stock-Androids bei dem Nexus-Logo nicht weiter geht, muss das Gerät erneut in dem Bootloader-Modus versetzt werden, indem die beiden Lautstärke-Tasten und die Power-Taste gehalten werden. Anschließend muss die Option "Recovery mode" über die Lautstärke-Tasten ausgewählt werden und der Recovery-Modus über Drücken der Power-Taste gestartet werden. Der Recovery-Modus des Stock-Androids zeigt einen auf dem Rücken liegenden Androiden. Über mehrmaliges Drücken der beiden Lautstärke- und der Power-Taste sollten die Optionen des Recovery-Modus sichtbar werden. Aus diesen Optionen ist die Auswahl "wipe data/factory reset" zu wählen und zu bestätigen. Nach einem anschließenden Neustart des Geräts, sollte das Stock-Android erfolgreich gebootet werden.

      Weiterführende Links:

      23. Juni 2013

      Android: WLAN-Konnektivität prüfen

      Innerhalb einer Android-App kann es sinnvoll sein, zu überprüfen, ob das Gerät im Moment über eine aktive WLAN-Verbindung verfügt. Dies ist beispielsweise sinnvoll wenn Netzwerkzugriffe mit erhöhtem Datendurchsatz nicht über die mobile Datenverbindung ausgeführt werden sollen. Im Folgenden soll daher gezeigt werden, wie aus einer Activity heraus überprüft werden kann, ob eine WLAN-Verbindung verfügbar ist.

      Den notwendigen Zugriff auf den WLAN-Adapter erlangt man über die Verwendung des sogenannten ConnectivityManager. Eine Referenz auf diesen erhält man durch den Aufruf der getSystemService-Methode der Klasse Context, indem man als Parameter die Konstante Context.CONNECTIVITY_SERVICE übergibt und den Rückgabewert entsprechend castet. Über einen anschließenden Aufruf der getNetworkInfo-Methode des eben referenzierten Services, wobei hierbei der Parameter ConnectivityManager.TYPE_WIFI übergeben werden muss, erhält man dann ein Objekt der Klasse NetworkInfo, über das Informationen über den WLAN-Adapter bezogen werden können. Dessen Konnektivität kann über die isConnected-Methode abgefragt werden.
       ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);  
       NetworkInfo wifiNetworkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);  
       boolean wlanConnectionAvailable = wifiNetworkInfo.isConnected();  
      
      Um den Zugriff auf den WLAN-Adapter zu erhalten muss außerdem, wie folgendermaßen dargestellt, eine entsprechende Permission in der AndroidManifest.xml definiert werden.
       <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
      

      21. Juni 2013

      Android: Drawable skalieren

      Der folgende Code zeigt, auf welche Weise eine Grafik, die als Drawable-Objekt vorliegt, in einer Android-App auf eine bestimmte Größe skaliert werden kann. Dazu muss das Drawable-Objekt über die Methode getBitmap():Bitmap zunächst in ein Bitmap-Objekt konvertiert werden. Dieses kann anschließend über die statische createScaledBitmap-Methode der Klasse Bitmap skaliert werden, indem die Objektreferenz, sowie die erwünschte Breite und Höhe des skalierten Bildes in Pixeln übergeben wird. Die Methode gibt als Rückgabewert ein skaliertes Duplikat des übergebenen Bitmap-Objektes zurück. Als letzter Schritt muss dann dieses Bitmap-Objekt zurück in ein Drawable-Objekt konvertiert werden, was über den Konstruktur der Klasse BitmapDrawable möglich ist.
       Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();  
       Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, false);  
       Drawable scaledDrawable = new BitmapDrawable(resources, resizedBitmap);  
      
      Bei dem Objekt drawable im obigen Beispielcode handelt es sich um das zu konvertierende Drawable-Objekt, welches auf 50 x 50 Pixel skaliert werden soll. Das Objekt scaledDrawable enthält am Ende das skalierte Bild.

      16. Juni 2013

      In eigener Sache: <netz.kinder/> ist nun bei Google Currents verfügbar

      Dieser Blog ist von nun an auch über Googles News-Dienst "Currents" verfügbar. Google Currents ist als App für Android-Smartphones und -Tablets, sowie für die iOS-Plattform, also für Apples iPhone und iPad, verfügbar. Der Dienst erlaubt dabei verschiedene News-Kanäle, die über Currents angeboten werden zu abonnieren um geräteübergreifend auf die jeweils neuesten Artikel zugreifen zu können. Weitere Informationen sind unter diesem Link verfügbar.

      Die Artikelübersicht dieses Blogs in der Google Currents-App unter Android (Klicken zum Vergrößern)

      Galaxy Nexus: CyanogenMod flashen

      In diesem Artikel soll erläutert werden, wie es möglich ist, das Android-CustomROM "CyanogenMod" auf dem Smartphone "Samsung Galaxy Nexus" zu installieren. Hierfür ist ein Gerät notwendig, dessen Bootloader entsperrt wurde und auf dem der alternative Recovery-Modus "ClockworkMod Recovery" installiert wurde. Außerdem muss auf dem PC von dem aus die Installation durchgeführt werden soll, das Tool adb installiert sein. Die hierfür notwendigen Schritte wurden in diesem Blog bereits im Rahmen dieses Artikels beschrieben.

      Zunächst muss die zu installierende Version des CustomROMs von der offiziellen Download-Seite heruntergeladen werden. Die CyanogenMod-Versionen, die für die Installation auf einem Galaxy Nexus vorgesehen sind, tragen dabei den Namen "maguro". Man hat hierbei die Wahl zwischen sogenannten Nightly-Builds, die ihrem Namen entsprechend täglich aktualisiert werden und stets dem aktuellen Entwicklungsstand entsprechen, oder den sogenannten Release Candidates, die in größeren Zeitabständen veröffentlicht werden und dementsprechend einen stabileren Entwicklungsstand garantieren. Die Nightly-Builds sind unter dieser Adresse verfügbar, während die Release Candidates unter dieser Adresse heruntergeladen werden können.

      Die Download-Seite für die RC-Versionen von CyanogenMod "magura" (Klicken zum Vergrößern)

      Außerdem sollten auch die Google-Apps heruntergeladen werden, die üblicherweise auf einem Android-Smartphone vorinstalliert sind. Aus lizenzrechtlichen Gründen sind diese nicht in dem Cyanogenmod-Download enthalten und müssen separat von der Seite http://goo.im/gapps bezogen werden. Zum Zeitpunkt der Verfassung dieses Artikels (16. Juni 2013) war die aktuelle Version der Apps unter diesem Direktlink verfügbar.

      Nach dem Herunterladen der Dateien sind folgende Schritte notwendig um die jeweilige CyanogenMod-Version inklusive der Google-Apps auf dem Smartphone zu installieren. Dabei ist jedoch zu beachten, dass alle Daten, die auf dem Gerät gespeichert sind, verloren gehen!
      1. Zunächst muss das Galaxy Nexus durch gleichzeitiges Halten der beiden Lautstärke- und der Power-Taste in den sogenannten Bootloader-Modus neugestartet werden.
      2. Über die Lautstärke-Tasten navigiert man nun zu der Option "Recovery mode", welche über Drücken der Power-Taste ausgewählt werden kann.
      3. Es sollte das Hauptmenü von ClockworkMod Recovery sichtbar werden, das wie bereits ewähnt auf dem Gerät installiert sein muss. Über die Lautstärke-Tasten navigiert man zu dem Eintrag "wipe data/factory reset" und bestätigt die Auswahl über die Power-Taste. Die erscheinende Sicherheitsabfrage bestätigt man ebenfalls auf diese Weise mit "Yes". Dadurch werden alle Daten auf dem Gerät gelöscht.
      4. Das Gerät muss nun über ein MicroUSB-Kabel mit dem PC verbunden werden. Über den folgenden Befehl kann überprüft werden, ob das die Verbindung korrekt hergestellt werden konnte. In diesem Fall sollte die Seriennummer des angeschlossenen Smartphones ausgegeben werden.
         adb devices  
        
      5. Nun müssen die zuvor heruntergeladenen Dateien auf das Smartphone kopiert werden. Dies geschieht am einfachsten über die folgenden beiden Konsolenbefehle aus dem jeweiligen Verzeichnis heraus. Die beiden Dateinamen müssen hierfür natürlich möglicherweise angepasst werden.
         adb push cm-10.1.0-RC5-maguro.zip /data/media  
         adb push gapps-jb-20130301-signed.zip /data/media  
        
      6. Damit die kopierten Dateien für die Auswahl im Recovery-Modus sichtbar werden, muss dieser neu gestartet werden. Dies ist über folgenden Befehl möglich.
         adb reboot recovery  
        
      7. Auf dem Smartphone, bzw. in dem Menü von ClockworkMod Recovery muss nun die Option "install zip from sdcard" und anschließend "choose zip from sdcard" gewählt werden. Das zip-Archiv, das die zu installierende CyanogenMod-Version enthält sollte auf diese Weise aus dem Verzeichnisbaum ausgewählt werden können. Es sollte sich dabei im Wurzelverzeichnis befinden. Nachdem die Auswahl mit "Yes" bestätigt wurde, wird das CustomROM auf das Gerät geflasht. Dabei kann es in manchen Fällen zu einem Fehler kommen, der "assert failed" lautet. In einem solchen Fall muss der am Ende dieses Artikels beschriebene Workaround angewendet werden um anschließend die Installation erneut durchzuführen.
      8. Analog zum vorherigen Schritt muss nun auch das zip-Archiv, das die Google-Apps enthält zur Installation ausgewählt werden.
      9. Abschließend kann im Hauptmenü von ClockworkMod Recovery die Option zum Neustart des Geräts gewählt werden, woraufhin die frisch installierte Android-Version gebootet wird.

      Workaround bei Fehlermeldung "assert failed"


      Bei der Installation der Cyanogenmod-Version kann es zu einem Fehler kommen, der etwa wie folgt lautet und zu einem Abbruch der Installation führt.

      assert failed: getprop("ro.product.device") == "manduro" || getprop("ro.build.product")=="manduro" 

      In einem solchen Fall muss eine Datei innerhalb des zip-Archivs, das zur Installation genutzt wird, modifiziert werden. Die folgenden Schritte zeigen wie hierfür vorgegangen werden muss:
      1. Zunächst muss das betroffene Archiv mit einer dafür geeigneten Anwendung, wie z.B. WinRAR unter Windows oder FileRoller oder ARK unter Linux, geöffnet werden ohne die den Inhalt zu entpacken.
      2. Die Datei /META-INF/com/google/android/updater-script muss nun mit einem Texteditor geöffnet werden.
      3. Die erste Zeile der Datei, bzw. der Text bis zu dem ersten Semikolon muss gelöscht werden. Es ist wichtig, dass hierbei auch das Semikolon entfernt wird. Anschließend muss die Datei gespeichert und das Archiv dadurch aktualisiert werden.
      Das auf diese Weise modifizierte zip-Archiv muss anschließend wie bereits oben beschrieben auf das Smartphone kopiert werden, wo es über ClockworkMod Recovery installiert werden kann.

      Galaxy Nexus: Rooten unter Linux

      In der folgenden Anleitung sollen die Schritt erläutert werden um das Smartphone "Samsung Galaxy Nexus" unter einem Linux-System zu rooten um erweiterte Rechte zu erhalten. Voraussetzung hierfür ist, dass die Tools adb und fastboot zuvor installiert wurden. Die Schritte dieser Anleitung führen zur Löschung aller internen Daten auf dem Gerät. Da das Galaxy Nexus keine SD-Karte besitzt gehen dadurch alle gespeicherten Daten verloren!

      Das Samsung Galaxy Nexus (Bildquelle: androidmag.com; Klicken zum Vergrößern)

      Entsperren des Bootloaders


      Der erste Schritt zum Rooten des Geräts ist das Entsperren des Bootloaders. Dies ist notwendig um anschließend einen alternativen Recovery-Modus installieren zu können.
      1. Das Gerät muss hierfür zunächst durch Halten beider Lautstärke-Tasten, sowie der Power-Taste in den Bootloader-Modus gestartet werden.
      2. Das Smartphone muss nun über ein MicroUSB-Kabel mit dem PC verbunden werden.
      3. Anschließend kann über eine Konsole auf dem Linux-System die korrekte Verbindung über folgenden Befehl überprüft werden. Falls eine korrekte Verbindung besteht, sollte die Seriennummer des Smartphones ausgegeben werden.
         sudo fastboot devices  
        
      4. Ist diese Bedingung erfüllt, so kann in diesem nächsten Schritt der folgende Befehl eingegeben werden um den Bootloader zu entsperren. Um die Entsperrung zu bestätigen muss dabei die erscheinende Abfrage mit "Yes" beantwortet werden, indem über die Lautstärke-Tasten zu dem entsprechenden Menüpunkt navigiert wird und die Auswahl anschließend mit der Power-Taste bestätigt wird.
         sudo fastboot oem unlock  
        
      5. In dem nun erscheinenden Menü muss nun auf die selbe Weise über die Lautstärke-, bzw. der Power-Tasten, der Recovery-Modus ausgewählt werden. Es sollte nun das Android-Maskottchen auf dem Rücken liegend mit einem roten Warndreieck dargestellt werden. Über zufälliges Drücken der Lautstärke- und Power-Tasten sollte ein Menü sichtbar werden, über dieses dann die Option "wipe data/factory reset" gewählt und anschließend bestätigt werden muss (Hierdurch werden die Daten auf dem Gerät gelöscht).

      ClockworkMod Recovery installieren


      Wie bereits erwähnt muss im folgenden Schritt ein alternativer Recovery-Modus installiert werden, der erweiterte Modifikationen und das Installieren von Custom-ROMs erlaubt. In diesem Fall handelt es sich dabei um "ClockworkMod Recovery", dessen Installation in den folgenden Schritten erläutert wird:
      1. Zuerst muss das Gerät einmal mehr über das Halten der beiden Lautstärke- und der Power-Taste in den Bootloader-Modus gestartet werden.
      2. Anschließend nun der alternative Recovery-Modus "ClockworkMod Recovery" heruntergeladen und auf das Gerät gespielt werden. Die hierfür notwendige Datei ist unter diesem Link verfügbar.  Nach dem Download der Datei wechselt man per Konsole in das entsprechende Verzeichnis, in dem diese gespeichert wurde und führt folgenden Befehl aus um den Recovery-Modus auf dem Galaxy Nexus zu installieren.
         sudo fastboot flash recovery recovery-clockwork-5.5.0.4-toro.img  
        
      3. Nachdem angezeigt wird, dass das Flashen von ClockworkMod Recovery erfolgreich abgeschlossen wurde, kann das Gerät über den unten stehenden Befehl neu gestartet und das Android-Betriebssystem gebootet werden.
         sudo fastboot reboot  
        
      4. Um zu testen, ob Recovery-Modus korrekt installiert werden konnte, sollte das Gerät nun erneut, wie bereits beschrieben, in den Bootloader-Modus gestartet werden. In dem entsprechenden Menü wählt man dann die Option zum Starten des Recovery-Modus. Falls ClockworkMod Recovery erfolgreich installiert wurde, ist die über eine Ausgabe der installierten Version ersichtlich. Falls stattdessen der Stock-Recovery-Modus, bei dem der bereits beschriebene, auf dem Rücken liegende, Androide angezeigt wird geladen wird, wurde der installierte Recovery-Modus beim Starten des Betriebssystems überschrieben. In diesem Fall  muss der im Folgenden beschriebene Workaround angewendet werden um anschließend die vorherigen Schritte zur Installation von ClockworkMod Recovery erneut auszuführen.
      Das Hauptmenü von ClockworkMod Recovery (Bildquelle: theunlockr.com; Klicken zum Vergrößern)

      Überschreiben von ClockworkMod Recovery verhindern


      Die folgenden Schritt sind nur notwendig wenn, wie zuvor beschrieben, die Installation des alternativen Recovery-Modus gescheitert ist, indem dieser durch das anschließende Booten des Android-Betriebssystems überschrieben wurde.

      Falls ClockworkMod Recovery beim Starten von Android überschrieben wird, liegt das an der Datei /system/etc/install-recovery.sh, die beim Bootvorgang ausgeführt wird und dafür sorgt, dass der Stock-Recovery-Modus wiederhergestellt wird. Die folgenden Schritte stellen einen Workaround dar, durch den dieses Verhalten verhindert werden kann.
      1. Das Galaxy Nexus muss über das MicroUSB-Kabel mit dem PC verbunden werden. Dabei muss das Android-Betriebssystem regulär gestartet worden sein und in den Entwickleroptionen das USB-Debbuging aktiviert werden. Über folgenden Konsolenbefehl kann die korrekte Funktion der Verbindung überprüft werden. Der Befehl sollte als Ausgabe die Seriennummer des angeschlossenen Geräts anzeigen.
         adb devices  
        
      2. Anschließend muss folgender Befehl in der Linux-Konsole ausgeführt werden. Dadurch wird eine Shell gestartet über die sich auf das Gerät zugreifen lässt.
         adb shell  
        
      3. In dieser adb-Shell müssen nun nacheinander folgende Befehle ausgeführt werden, um die bereits erwähnte Datei install-recovery.sh in install-recovery.bak umzubenennen. Dadurch kann sie vom System nicht mehr gefunden und ausgeführt werden um den Stock-Recovery-Modus wiederherzustellen.
         su  
         mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system  
         chmod 755 /system/app  
         cd system/etc  
         mv install-recovery.sh install-recovery.bak  
         exit 
      Die Installation von ClockworkMod Recovery kann nun nach den, im vorherigen Abschnitt "ClockworkMod Recovery installieren" bereits aufgeführten, Schritten erneut durchgeführt werden. Anschließend sollte die Installation auch nach erneutem Booten des Android-Betriebssystems erhalten bleiben.

      Root-Rechte erlangen


      Nachdem nun eine funktionierende Version von ClockworkMod Recovery auf dem Gerät vorhanden sein sollte, muss dieser alternative Recovery-Modus nun dazu genutzt werden, die Root-Rechte zu erlangen. Dieses Vorgehen wird durch die folgenden Schritte beschrieben.
      1. Zunächst muss das Tool "SuperSU" unter dieser Adresse heruntergeladen werden. Bei bestehender USB-Verbindung zu dem Galaxy Nexus, welches ein weiteres mal erst in den Recovery-Modus versetzt werden muss, kann anschließend folgender Befehl ausgeführt werden, um das zip-Archiv aus dem Download-Verzeichnis heraus auf das Gerät zu kopieren.
         adb push UPDATE-SuperSU-v1.04.zip /data/media  
        
      2. Über folgenden Befehl wird das Smartphone nun erneut in den Recovery-Modus neugestartet.
         adb reboot recovery  
        
      3. Dort muss nun der Menüpunkt "install zip from sdcard" und anschließend "choose zip from sdcard" gewählt werden. Das zip-Archiv sollte im Root-Verzeichnis der SD-Karte zu finden sein. Nach dessen Auswahl und Installation kann das Gerät neu gestartet werden und sollte von nun an gerootet sein.
      Mittels bestimmter Apps aus dem Google Play Store lässt sich überprüfen, ob das Gerät tatsächlich korrekt gerootet wurde. Hierfür eignet sich beispielsweise die App Root Checker.

      3. Juni 2013

      Nexus 10: CyanogenMod auf verschlüsseltem Gerät updaten

      Das CustomROM "CyanogenMod" bietet seit Version 10 die Möglichkeit, vorhandene Updates automatisch herunterzuladen, so dass diese anschließend installiert werden können. Unter dem Nexus 10 oder ähnlichen Geräten, die über keine externe SD-Karte verfügen, kann das Einspielen der Updates  jedoch zu Problemen führen, falls das Gerät mittels der entsprechenden Android-Funktion verschlüsselt wurde. Im Folgenden soll diese Problematik erläutert und eine Möglichkeit zur Abhilfe gezeigt werden.

      Die Update-Überprüfung von CyanogenMod 10 in den Android-Systemeinstellungen (Klicken zum Vergrößern)

      Wenn ein Update zur Verfügung steht, wird das entsprechende zip-Archiv, dass die dafür notwendigen Dateien enthält, durch den Update-Mechanismus heruntergeladen und unter dem Verzeichnis /sdcard/cmupdater/ gespeichert. Wenn das Gerät über keine externe SD-Karte verfügt, handelt es sich bei diesem Verzeichnis lediglich um eine virtuelle Partition. Wenn das Update durch den Benutzer zur Installation ausgewählt wurde, wird das Gerät neu gestartet und in den Recovery-Modus (in diesem Post wird davon ausgegangen, das es sich hierbei um "ClockworkMod Recovery" handelt) gebootet um die Dateien des entsprechenden Archivs zu entpacken und zu installieren. Falls das Dateisystem des Geräts jedoch verschlüsselt wurde, steht die virtuelle SD-Karte, die das Archiv enthält, nicht zur Verfügung, da das zugehörige Verzeichnis auf dem verschlüsselten Dateisystem liegt und zu diesem Zeitpunkt keine Möglichkeit zu dessen Entschlüsselung besteht. Das Updaten des Geräts scheitert demzufolge, da die notwendige Datei nicht gefunden werden kann.

      Die elegante Möglichkeit, die CyanogenMod-Installation von dem jeweiligen Gerät aus herunterzuladen und zu installieren, ist damit ausgeschlossen, falls das Gerät verschlüsselt werden soll. Das Einspielen von Updates muss dann über eine USB-Verbindung manuell gesteuert werden, wozu folgende Schritt nötig sind:
      1. Zunächst muss die zu installierende CyanogenMod-Version auf dem Rechner heruntergeladen werden.
      2. Anschließend muss das Android-Gerät durch Halten der Power-, sowie der beiden Lautstärke-Tasten in den Bootloader-Modus neu gestartet werden.
      3. Über die Lautstärke-Tasten navigiert man anschließend zum Menüpunkt "RECOVERY MODE", den man durch Drücken der Power-Taste auswählt.
      4. Der Recovery-Modus wird anschließend gestartet. In dessen Hauptmenü wählt man dann die Option "install zip from sideload".
      5. Das Gerät muss nun per Micro-USB mit dem Rechner verbunden werden.
      6. Über die Kommandozeile kann anschließend aus dem Verzeichnis, das das heruntergeladene zip-Archiv enthält an das Android-Gerät übertragen werden. Hierzu genügt folgender Befehl, wobei der Name der zip-Datei natürlich angepasst werden muss:
         adb sideload cm-10.1-20130603-NIGHTLY-manta.zip  
      Das Update sollte darauf hin eingespielt werden und das Gerät kann anschließend neu gestartet werden.

      2. Juni 2013

      Nexus 10: CyanogenMod flashen

      In diesem Post sollen die Schritte erläutert werden, die nötig sind um das Android-CustomROM "CyanogenMod" auf ein "Nexus 10"-Tablet zu flashen, wie die Installation eines solchen alternativen Betriebssystem genannt wird. Voraussetzung hierfür ist ein bereits gerootetes Gerät mit installiertem, alternativen Recovery-Modus. Das Rooten eines Nexus 10 unter Ubuntu wurde in diesem Blog bereits hier behandelt. Für die folgenden Schritte wird angenommen, dass auf dem Gerät der Recovery-Modus "ClockworkMod Recovery" gemäß dieser Anleitung installiert wurde.

      Das Tablet "Nexus 10" (Bildquelle: google.de; Klicken zum Vergrößern)

      Zunächst müssen die notwendigen Dateien zum Flashen des CustomROMs heruntergeladen werden. Die CyanogenMod-Versionen für das Nexus 10 tragen den Namen "manta". Es können entweder die Nightly-Builds gewählt werden, die stets den aktuellen Entwicklungsstand enthalten und unter der Adresse http://get.cm/?device=manta&type=nightly erhältlich sind, oder eine sogenannte Release Candidate-Version, die unter der Adresse http://download.cyanogenmod.com/?device=maguro&type=RC heruntergeladen werden kann und eine stabilere Version des alternativen ROMs darstellt. Auch weitere Releases, die nach ähnlichen Release-Zyklen veröffentlicht werden sind auf dieser Seite verfügbar. Auf diese soll an dieser Stelle jedoch nicht näher eingegangen werden.

      Außerdem werden nach Bedarf die Google-Apps benötigt, die üblicherweise auf dem Nexus 10 installiert sind, aus urheberrechtlichen Gründen jedoch nicht in CyanogenMod enthalten sind. Diese sind unter http://goo.im/gapps/ erhältlich. Zum Zeitpunkt der Verfassung dieses Posts  (02. Juni 2013) war die aktuelle Version der Apps unter diesem Direktlink verfügbar.

      Die heruntergeladenen Dateien müssen anschließend auf die virtuelle SD-Karte des Nexus-Geräts kopiert werden (z.B. in den Downloads-Ordner). Die folgenden Schritte führen ermöglichen dann das eigentliche Flashen (Achtung: Dabei gehen alle Daten bis auf diejenigen, die auf der SD-Card, bzw. der virtuellen Systempartition gespeichert sind, verloren!):
      1. Die Power-, sowie beide Lautstärke-Tasten des Geräts gedrückt halten bis in den Bootloader-Modus gestartet wird.
      2. In dem Menü der Bootloader-Modus mit den Lautstärke-Tasten den Menüpunkt "RECOVERY MODE" wählen und durch Drücken der Power-Taste bestätigen.
      3. In dem erscheinenden Menü des Recovery-Modus muss nun der Menüpunkt zum "wipe data/factory reset" gewählt werden.
      4. Anschließend muss im Hauptmenü des Recovery-Modus der Menüpunkt "install zip from sdcard" gewählt werden um das ZIP-Archiv, das die CyanogenMod-Dateien enthält, aus dem Verzeichnisbaum auszuwählen.
      5. Nach der Installation muss analog dazu die Datei, die die Google-Apps enthält, ausgewählt werden.
      6. Zuletzt muss im Hauptmenü die Option zum Reboot des Systems gewählt werden. Die installierte CyanogenMod-Version wird dann anschließend gestartet. Dabei wird der Installations-Assistent zur Einrichtung der Sprache, der Netzwerkverbindung und des Google-Kontos aufgerufen.

      21. April 2013

      Android: Automatische Drehung einer Activity verhindern

      Um in einer Android-App den Orientierungswechsel einer Activity zu unterbinden, wenn das Gerät gedreht wird, gibt es die Möglichkeit, eine bestimmte Orientierung fest vorzuschreiben. Dies kann entweder über ein entsprechendes Attribute in der AndroidManifest.xml oder im Code der Activity geschehen.

      Um die Orientierung in der AndroidManifest.xml fest vorzuschreiben, genügt es, die Definition der jeweiligen Activity folgendermaßen zu erweitern:
       <activity  
         android:name=".Activity"  
         android:label="@string/app_name"  
         android:screenOrientation="portrait" >  
         <intent-filter>  
           <action android:name="android.intent.action.MAIN" />  
           <category android:name="android.intent.category.LAUNCHER" />  
         </intent-filter>  
       </activity>  

      Durch setzen des Attributs android:screenOrientation auf den Wert "portrait" wird die Orientierung der Activity auf den Portraitmodus, also das Hochkantformat, festgelegt. Soll stattdessen der Landscape-Modus verwendet werden, muss der Wert auf "landscape" gesetzt werden.

      Um die Orientierung stattdessen im Code zu setzen muss in der jeweiligen Activity folgender Befehl aufgerufen werden:
       setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT);  

      Auch bei dieser Variante muss der Wert ORIENTATION_PORTRAIT auf ORIENTATION_LANDSCAPE geändert werden, falls der Landscape-Modus gesetzt werden soll. Um die Festlegung der Orientierung später wieder aufzuheben, kann der Wert auf ORIENTATION_UNDEFINED gesetzt werden.

      Statt die Orientierung bereits im Vorraus fest zu setzen, ist es manchmal gewollt, die Activity der aktuellen Ausrichtung des Geräts nach zu starten, anschließend aber keinen Orientierungswechsel mehr zu erlauben. Ein solches Verhalten ist über folgenden Code realisierbar:
       @Override  
       public final void onCreate(final Bundle savedInstanceState) {  
         super.onCreate(savedInstanceState);  
         setContentView(R.layout.activity_layout);  
         if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {  
           setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT);  
         } else {  
           setRequestedOrientation(Configuration.ORIENTATION_LANDSCAPE);  
         }  
       }  

      Hierbei wird nach dem Starten der Activity die aktuelle Orientierung über den Befehl getResources().getConfiguration().orientation ausgelesen und abhängig von ihrem Wert anschließend über den bereits oben erwähnten Befehl festgelegt.

      Android: ActionBar verbergen

      Um in einer Android-App die ActionBar einer bestimmten Activity zu verbergen, bzw. die Activity als Fullscreen darzustellen, genügt das Hinzufügen eines entsprechenden Attributs in der AndroidManifest.xml. Die Definition der jeweiligen Activity muss dabei, wie in folgendem Beispiel verdeutlicht, um das Attribut android:theme erweitert werden:
       <activity  
         android:name=".Activity"  
         android:label="@string/app_name"  
         android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" >  
         <intent-filter>  
           <action android:name="android.intent.action.MAIN" />  
           <category android:name="android.intent.category.LAUNCHER" />  
         </intent-filter>  
       </activity>  
      In diesem Beispiel wird die Activity mit einem hellen Hintergrund dargestellt, so wie es bei dem Theme "Holo Light" üblich ist. Wenn die App stattdessen ein dunkles Theme verwendet, muss statt Theme.Light.NoTitleBar.Fullscreen der Wert Theme.Black.NoTitleBar.Fullscreen verwendet werden um einen dunklen Hintergrund darzustellen.

      Bei dieser Vorgehensweise ist zu beachten, dass die Activity-Methode getActionBar() eine Null-Referenz zurück liefert, da keine ActionBar erzeugt wird.

      19. April 2013

      Android: Erkennen wenn App zum ersten Mal gestartet wird

      Manchmal kann es bei der Entwicklung einer Android-App hilfreich sein, erkennen zu können wenn diese nach ihrer Installation zum ersten Mal gestartet wird. Diese Erkennung kann man dann beispielsweise nutzen um die Datenbank mit standardmäßigen Einträgen zu füllen oder dem User hilfreiche Tipps einzublenden. Im Folgenden soll kurz aufgezeigt werden, wie so etwas erreicht werden kann.

      Die Erkennung sollte in der Activity stattfinden, die beim Starten der App als Erste angezeigt wird. Für die Umsetzung genügt folgender Code:
       public class StartActivity extends Activity {  
         
         SharedPreferences sharedPreferences;  
         
         @Override  
         public void onCreate(Bundle savedInstanceState) {  
           super.onCreate(savedInstanceState);  
           sharedPreferences = getSharedPreferences("preferenceName", MODE_PRIVATE);  
         }  
         
         @Override  
         public void onResume() {  
           super.onResume();  
         
           if (sharedPreferences.getBoolean("firstrun", true)) {  
             sharedPreferences.edit().putBoolean("firstrun", false).commit();  
             // Hier Code einfügen der beim ersten Start einmalig ausgeführt werden soll  
           }  
         }  
         
       }  
      Der Code basiert auf der Verwendung von SharedPreferences, die es erlauben, primitive Datentypen zu speichern und zu erhalten, selbst wenn die App beendet wird. In der onCreate-Methode wird zunächst eine solche SharedPreferences-Instanz über einen Namen instanziiert. In der onResume-Methode, die dem Activity-Lifecycle nach erst nach der onCreate-Methode aufgerufen wird, wird versucht einen boolschen Wert mit dem Key "firstrun" aus den SharedPreferences zu laden. Für den Fall, dass dies nicht gelingt, also genau dann, wenn die App zum ersten Mal gestartet wird, wird der Default-Wert "true" angegeben. In diesem Fall wird der Code innerhalb der if-Bedingung ausgeführt, wo nun der Boolean-Wert mit dem Key "firstrun" auf "false" gesetzt werden muss, so dass bei den folgenden Durchläufen die if-Bedingung nie wieder erfüllt wird. Außerdem kann an dieser Stelle derjenige Code eingefügt werden, der beim ersten Start der App ausgeführt werden soll.

      7. April 2013

      Android: Komplexe Objekte in Bundle speichern

      In Android ist es nötig, gewisse Zustände einer Activity oder eines Fragments zu speichern und wiederherzustellen, insofern die Werte nicht verloren gehen sollen, wenn die Activity bzw. das Fragment zerstört und neu gestartet wird, wie es z.B. bei einem Orientierungswechsel des Geräts geschieht. Die prinzipielle Vorgehensweise zum Sichern solcher Werte wurde bereits in dem Post "Die Activity-Methoden onSaveInstanceState und onRestoreInstanceState" für Activities und in dem Post "Die Fragment-Methoden onSaveInstanceState und onActivityCreated" für Fragments erklärt.

      Meistens handelt es sich bei den Werten, die dabei in dem Bundle-Objekt gespeichert werden um primitive Datentypen. Hierfür bietet die Bundle-Klasse jeweils Methoden um Werte hinzuzufügen, bzw. später wieder auszulesen. Es besteht jedoch darüber hinaus auch die Möglichkeit, komplexe Objekte zu sichern, indem die Methode putSerializable(String key, Serializable value):void zum Ablegen eines Objekts in dem entsprechenden Bundle, bzw. die Methode getSerializable(String key):Serializable zum referenzieren eines zuvor gespeicherten Objekts aus dem Bundle, genutzt wird. Das zu sichernde Objekt muss demnach die das Interface java.io.Serializable implementieren.

      Sollen allerdings Objektinstanzen von Klassen gespeichert werden, die dieses Interface nicht implementieren und die nicht angepasst werden können, weil sie beispielsweise Klassen der Java-API oder eines Frameworks sind, steht man vor dem Problem, dass solche Klassen nicht ohne Weiteres an ein Bundle übergeben werden können. Eine Möglichkeit, wie dieses Problem umgangen werden kann, soll nun im Folgenden aufgezeigt werden.

      Die Lösung besteht darin, eine Wrapper-Klasse zu schreiben, die das Serializable-Interface implementiert und eine Instanz des zu sichernden Objekttyps aufnimmt. Dabei sind grundsätzlich zwei Ansätze denkbar: Entweder man entscheidet sich für einen sehr einfachen Wrapper, der lediglich eine Getter- und eine Setter-Methode auf das gekapselte Objekt anbietet, oder man setzt auf eine komplexere, aber eleganter zu verwendende Implementierung, die zudem als Proxy fungiert, indem sie neben dem Serializable-Interface auch die Schnittstelle des zu sichernden Objekttyps implementiert und alle Methodenaufrufe an das gekapselte Objekt weiterleitet. Die hat den Vorteil, dass sich Instanzen dieser Klasse exakt wie das Original handhaben lassen. Eventuell bereits vorhandener Code muss auf diese Weise kaum angepasst werden. Auf eine mögliche Implementierung dieser Variante soll nun näher eingegangen werden. Als Code-Beispiel ist im Folgenden ein Wrapper für das Interface java.util.List, das als Schnittstelle für alle Listenimplementierungen der Java-Standardbibliothek dient, zu sehen. Als Szenario für die Sicherung einer solchen Datenstruktur wäre beispielsweise ein Listenadapter denkbar, der Suchergebnisse in einer ListView darstellt. Wenn bei einem Orientierungswechsel der entsprechenden Activity der zeitaufwendige Netzwerkzugriff der Suchanfrage nicht erneut durchgeführt werden soll, muss die zugrunde liegende Datenstruktur zwischengespeichert werden.
       public class SerializableList<Type> implements List<Type>, Serializable {  
         
           private static final long serialVersionUID = 1L;  
         
           private List<Type> list;  
         
           public SerializableList(final List<Type> list) {  
               this.list = list;  
           }  
         
           public final boolean add(final Type object) {  
               return list.add(object);  
           }  
         
           public final void add(final int location, final Type object) {  
               list.add(location, object);  
           }  
         
           public final boolean addAll(final Collection<? extends Type> collection) {  
               return list.addAll(collection);  
           }  
         
           public final boolean addAll(final int index,  
                   final Collection<? extends Type> collection) {  
               return list.addAll(index, collection);  
           }  
         
           public final void clear() {  
               list.clear();  
           }  
         
           public final boolean contains(final Object object) {  
               return list.contains(object);  
           }  
         
           public final boolean containsAll(final Collection<?> collection) {  
               return list.containsAll(collection);  
           }  
         
           public final Type get(final int location) {  
               return list.get(location);  
           }  
         
           public final int indexOf(final Object object) {  
               return list.indexOf(object);  
           }  
         
           public final boolean isEmpty() {  
               return list.isEmpty();  
           }  
         
           public final Iterator<Type> iterator() {  
               return list.iterator();  
           }  
         
           public final int lastIndexOf(final Object object) {  
               return list.lastIndexOf(object);  
           }  
         
           public final ListIterator<Type> listIterator() {  
               return list.listIterator();  
           }  
         
           public final ListIterator<Type> listIterator(final int location) {  
               return list.listIterator(location);  
           }  
         
           public final Type remove(final int location) {  
               return list.remove(location);  
           }  
         
           public final boolean remove(final Object object) {  
               return list.remove(object);  
           }  
         
           public final boolean removeAll(final Collection<?> collection) {  
               return list.removeAll(collection);  
           }  
         
           public final boolean retainAll(final Collection<?> collection) {  
               return list.retainAll(collection);  
           }  
         
           public final Type set(final int location, final Type object) {  
               return list.set(location, object);  
           }  
         
           public final int size() {  
               return list.size();  
           }  
         
           public final List<Type> subList(final int start, final int end) {  
               return list.subList(start, end);  
           }  
         
           public final Object[] toArray() {  
               return list.toArray();  
           }  
         
           public final <T> T[] toArray(final T[] array) {  
               return list.toArray(array);  
           }  
         
           @Override  
           public final int hashCode() {  
               final int prime = 31;  
               int result = 1;  
               result = prime * result + ((list == null) ? 0 : list.hashCode());  
               return result;  
           }  
         
           @Override  
           public final boolean equals(final Object obj) {  
               if (this == obj)  
                   return true;  
               if (obj == null)  
                   return false;  
               if (getClass() != obj.getClass())  
                   return false;  
               SerializableList<?> other = (SerializableList<?>) obj;  
               if (list == null) {  
                   if (other.list != null)  
                       return false;  
               } else if (!list.equals(other.list))  
                   return false;  
               return true;  
           }  
         
       }  
      Die Klasse implementiert sowohl das Interface java.io.Serializable, als auch das Interface java.util.List. Außerdem handelt es sich um eine generische Klasse, die mit dem Typ der Objekte, die die gekapselte Liste aufnehmen soll, typisiert wird. Über den Konstruktor wird diese Liste übergeben und in dem entsprechenden Attribut gespeichert. Dieses wird dazu verwendet, um alle Aufrufe der Methoden, die in dem List-Interface definiert sind, unverändert an die gekapselte Liste weiter zu leiten. Darüber hinaus wurde auch jeweils eine Implementierung der hashCode- bzw. equals-Methode hinzugefügt, damit sich Klasseninstanzen tatsächlich so verhalten, wie man es von einer Liste erwarten würde.

      Das Abspeichern der oben gezeigten Listenimplementierung in einem Bundle könnte beispielsweise wie folgt aussehen:
       public final void onSaveInstanceState(final Bundle outState) {  
         SerializableList<String> serializableList = new SerializableList<String>(new ArrayList<String>());  
         serializableList.add("elem1");  
         serializableList.add("elem2");  
         outState.putSerializable("list", serializableList);  
       }  
      Um die, auf diese Weise im Bundle gespeicherte, Liste anschließend wiederherzustellen, sind dann folgende Zeilen nötig:
       public final void onRestoreInstanceState(final Bundle savedInstanceState) {  
         SerializableList<String> serializableList = (SerializableList<String>) savedInstanceState.getSerializable("list");  
       }  
      Dabei ist ein Cast vom Interface Serializable auf die Serializable-List implementierung nötig.