Is it just み?

[Larp] Krieg der Runen

by on Sep.10, 2012, under Larp

Ich war wieder auf Larp, diesmal als Con-Fotograf. Da meine Galerie-Software noch immer nicht fertig ist und mein kleiner Server eh nicht so viel aushält, habe ich die Bilder mal auf Google gestellt: Hier geht es zum Krieg der Runen Album – Sollte jemand Interesse an den Bildern in voller Auflösung haben, schreibt mir kurz.

Die Aufnahmen wurden mit einer Canon EOS 60D und größtenteils dem EF 70-300mm 1:4,0-5,6 IS USM Objektiv und dem Sigma 17-50mm 1:2.8 EX DC OS HSM-Objektiv aufgenommen, bei Nacht habe ich den Canon 430 EX II Blitz zusammen mit dem passenden Mini-Diffusor benutzt – die Bilder sind entweder original Kamera-Jpeg oder wurden leicht (Weißabgleich, Kontrast, Farben) mit Hilfe von RawTherapee nachbearbeitet.

Comments Off on [Larp] Krieg der Runen :, , , , , more...

Desktop-Fernbedienung für Dune HD Mediaplayer

by on Aug.12, 2012, under Programmierung, Technik

Ich besitze einen Dune BD Prime 3.0 Mediaplayer mit dem ich sehr zufrieden bin. Er befüttert den Fernseher zwischen den Arbeitsplätzen von meiner Freundin und mir – und jeder will die Fernbedienung haben. Glücklicherweise haben alle neueren Dune-HD-Geräte eine “IP-Steuerung“, also einen eingebauten Webserver mit einem per cgi zugänglichen Programm, dass Parameter auswertet wie Eingaben der normalen Infrarot-Fernbedienung.

Also musste eine Möglichkeit her den Player vom Rechner aus zu bedienen. Hier ist meine Implementierung in C++ mit Qt, sie erstellt drei System-Tray-Icons (nur eins unter Gnome/Unity, wer da Hilfe weiß, bitte Bescheid sagen), Play/Pause, Previous und Next und blendet auf Wunsch eine vollständige Fernbedienung ein. Konfigurieren kann man derzeitig nur die IP (bzw. den Hostname) des Players, mehr wird nicht benötigt. Zum Download gibt es derzeitig neben dem Quellcode eine 64Bit Linux-Version und eine 32Bit Windows Version. Sollte die Nachfrage da sein reiche ich weitere Versionen gerne nach.

http://dev.himmelrath.net/projects/miduneremote/

Für die Zukunft sind noch ein paar Features geplant, wie weitere Fernbedienungsmodelle, Tastaturbedienung und Playerstatusanzeige, aber als einfacher Fernbedienungsersatz läuft es schon mal.

Über Tester und Rückmeldungen würde ich mich sehr freuen.

Comments Off on Desktop-Fernbedienung für Dune HD Mediaplayer :, , , , , , more...

Kleiner Küchenhelfer – Umrechnungstabelle imperial <-> metrisch

by on Aug.12, 2012, under Asides

Genervt davon ständig nachgucken zu müssen wie viel denn nun z.B. 4 cup im amerikanischen Rezept wirklich sind habe ich eine kleine Umrechnungstabelle für die Küche erstellt. Der erste Wert ist grob gerundet, der zweite die auf zwei Dezimalstellen exakte Angabe.

Das ganze habe ich als Google-Document erstellt falls es jemand brauchen kann: Kitchen unit conversion

Falls man es drucken will sollte man “show gridlines” im Druckdialog ausschalten.

 

 

Comments Off on Kleiner Küchenhelfer – Umrechnungstabelle imperial <-> metrisch :, , , , , , , more...

[Larp] Testamentum III

by on Jul.17, 2012, under Larp

Ich war seit langem endlich mal wieder auf Larp und habe diesmal einige Fotos gemacht. Da meine Galerie-Software noch immer nicht fertig ist und mein kleiner Server eh nicht so viel aushält, habe ich die Bilder mal auf Google gestellt:

Hier geht es zum Testamentum III Album

Sollte jemand Interesse an den Bildern in voller Auflösung haben, schreibt mir kurz.

Die Aufnahmen wurden mit einer Canon EOS 60D und größtenteils dem EF 70-300mm 1:4,0-5,6 IS USM Objektiv aufgenommen – die Bilder sind entweder original Kamera-Jpeg oder wurden leicht (Weißabgleich, Kontrast, Farben) mit Hilfe von RawTherapee nachbearbeitet.

Comments Off on [Larp] Testamentum III :, , more...

NAS – Fertig kaufen oder selber bauen?

by on Mar.15, 2012, under Computer, Technik

Ich wollte schon seit längerem ein NAS haben, bisher tat es ein preiswertes Festplattengehäuse (5-fach) an unserem Multimedia-Rechner, aber besonders Stromsparend war das nicht, daher sollte nun ein NAS her. Ich stand also vor der Wahl entweder ein fertiges NAS-gerät zu kaufen oder mir selbst ein NAS zu bauen – hier beschreibe ich jetzt meine Entscheidung und das Gerät, dass ich jetzt besitze.

Entscheidungskriterien

Ein Freund hatte mir sein kleines Synology-NAS gezeigt und die Weboberfläche hat mich wirklich beeindruckt – nur kam für mich kein Gerät mit gerade einmal 2 Festplatten in Frage, schließlich sollte es ja mein vorhandenes 5-Platten Raid ersetzen oder (noch besser) erweitern.

Die Alternative zu Synology sind die Geräte von Qnap – alle anderen Hersteller scheinen mir keine gute Bandbreite an Produkten zu liefern, WD liefert nur Mini-NAS, Buffalo und Netgear haben IMHO keine sinnvolle Mittelklasse. Abgesehen vom fertigen NAS kann man natürlich auch selbst eins zusammenbauen, hier meine Entscheidungsfindung:

Synology Mid Synology High Qnap Mid Qnap High Selbstgebaut
Preis 0 – – – + – – – 0
Erwerterbarkeit – – 0 – – + + + + +
Stromverbrauch + + – –
Größe + + + +
Bedienung + + + + + + + + + + 0
Software + + + + + + + + +
Aufwand + + + + + + + + + + – –

Die Synology-Geräte der Mittelklasse sind handlich und hübsch, die Qnap-Geräte sehen auf ähnlichem Preisniveau eher aus wie ich mir ein NAS vorstelle (mit Festplatten-Slots außen sichtbar), die Höheren Klassen (allerdings unter 2000€) sind bei beiden Herstellern recht robust, bieten allerdings bei Synology weniger Erweiterungsmöglichkeiten. Der Eigenbau kann natürlich theoretisch alles was ein normaler Rechner kann und darüber hinaus noch Port-Multiplier-Unterstützung auf allen (E)SATA-Ports – was den Betrieb meines alten RAID5 sicherstellen würde.

Nach bloßem zusammenrechnen gewinnt das Mittelklasse-Gerät von Synology auf Grund der wirklich guten Grafischen Oberfläche knapp vor dem Qnap-Gerät. Allerdings haben beide den Nachteil der schlechten (nicht vorhandenen) Erweiterbarkeit, die ich persönlich höher bewerte als die Bedienung – da ich davon ausgehe die grafische Oberfläche bei einem NAS-System im Optimalfall möglicht wenig benutzen zu müssen. Weiterhin ist mir der Aufwand der Einrichtung auch ziemlich egal, schließlich ist es mein Hobby und ich lerne etwas dabei.

Wenn ich also nun diese drei Faktoren als Gewichtung mit einbringe, gewinnt der Eigenbau deutlich gegenüber den Fertiglösungen.

Der Eigenbau

Nachdem ich mich nun also für den Eigenbau entschieden hatte, musste ich die Komponenten zusammensuchen:

Das Herz ist ein Asus E35M1-I DELUXE Mainboard, das ist komplett passiv gekühlt und bietet dennoch genügend Power um so ziemlich jede Software auf dem NAS laufen zu lassen. Wichtig sind mir natürlich die vielen SATA-Ports mit Port-Multiplier, schließlich will ich ja externe Festplattengehäuse mit mehreren Platten anschließen. Das Board hat zwar nur einen ESATA-Port, aber die anderen internen Ports führe ich (nicht ganz Standardkonform aber problemlos) über solche Kabel ganz einfach nach außen. Da das Board “nur” 6 SATA-ports hat, habe ich mir dazu noch die günstige Asus U3S6 Erweiterungskarte bestellt, die zwar kein Performancewunder ist, aber für meine zwecke günstig zwei vollwertige SATA-Ports hinzufügt und dazu noch zwei USB3-Ports hat (die brauche ich zwar nicht, aber schaden können die auch nicht). Dazu noch günstige 8GB Speicher, damit ich wirklich nie in Speichernöte gerate (Ich gebe zu, da hätten wohl 2GB auch gereicht, aber Speicher ist günstig und schadet nie). Das ganze packe ich in das kompakte Eolize SVD-NC11-4 mini ITX Gehäuse mit integriertem Netzteil und ich bin quasi fertig.

Nutzung

Zusätzlich zu den 4 Festplatteneinschüben (von denen ich im Moment nur einen nutze) konnte ich meine komplette alte externe SATA-Hardware weiter nutzen. An dem NAS hängen nun 5 Festplatten im Software-RAID5 in einem Lian Li EX-50 und dazu noch einmal 4 Festplatten in einem Fantec QB-35US2. Wenn man auf die 5. Festplatte verzichten kann würde ich das Fantec eher empfehlen, da es deutlich kompakter ist und generell für mich subjektiv stabiler wirkt – außerdem schaltet es sich automatisch ein und aus, wenn man es zusätzlich zum SATA per USB verbindet. Das Lian Li Gehäuse hatte dafür eine ESATA-Karte im Lieferumfang – als ich mir das Gehäuse gekauft habe unterstütze mein Onboard-Controller noch keinen Multiplier, daher hätte ich die Karte in jedem Fall benötigt. Die letzten beiden freien ESATA-Ports habe ich dann mit meinem Alten Sharkoon Quickport Duo2 verbunden – davon gibt es mittlerweile eine neue Version mit Port-Multiplier für 2 Platten und eine mit 4 Festplattenslots die nur einen ESATA-Port brauchen.

Als Betriebssystem benutze ich derzeitig ein Ubuntu Server 10.04 LTS das ich dann demnächst wohl auf die nächste LTS-Version aktualisieren werde. Das Betriebssystem startet derzeitig über einen USB-Stick, dafür wollte ich keine Festplatte “verschwenden”, da besteht aber noch Optimierungspotential.

Da ich jetzt eine kleine stromsparende Powerbox vor mir stehen habe, dachte ich mir, kann ich auch gleich mal meiner paranoia nachgehen und alle meine Festplatten und Raids verschlüsseln. Dafür benutze ich LUKS mit Schlüsseldateien statt Passwörtern, die dann wieder in einem (diesmal per Passwort) verschlüsseltem Image liegen. So muss ich nur ein Passwort eingeben und die Festplatten sind dennoch jeweils mit einem anderen Schlüssel versehen. Ich habe um das ganze zu automatisieren einen kleinen Server in C++ geschrieben, so dass man die ganzen Platten im LAN über eine Weboberfläche automatisch entschlüsseln und Mounten kann. Dazu aber in einem eigenen Artikel mehr (Der Artikel kommt noch).

Zusätzlich kann ich jetzt natürlich jede unter Ubuntu verfügbare Software auf meinem NAS einsetzen – sogar HD-Videos könnte das Ding ohne Probleme abspielen, das brauche ich zwar nicht, aber es ist gut zu Wissen, dass da noch Luft nach oben ist. Derzeitig laufen auf dem Gerät ein FTP-Server, ein Torrent-Client, ein NFS-Server, ein Samba-Server und ein Webserver – demnächst werde ich noch versuchen die eingebaute WiFi-Karte zu benutzen um einen weiteren Access-Point zu haben – ich werde berichten ob und wie das klappt. Für die Zukunft ist auch noch ein Backup-Server geplant, der sich aktiv per SSH auf den Client-Rechnern einloggt und vorher definierte Daten sichert – das wird mein nächstes Projekt.

Fazit

Ich bin rundum glücklich mit meiner Entscheidung selbst gebaut zu haben, nur um die schöne grafische Oberfläche beneide ich die Synology-Nutzer ein wenig – dem Nerd in mir ist das aber egal, schließlich hab ich einen root-Zugang per ssh auf mein NAS.

Was ich noch suche ist eine Möglichkeit meine langsame Betriebssystem-“Festplatte” zu beschleunigen, das System wird zwar dank des vielen Speichers schon jetzt automatisch sehr gut gepuffert, aber ich habe das Gefühl da geht noch was. Kennt vielleicht jemand eine Dateisystem-Lösung, die alles in den Hauptspeicher lädt und Änderungen im Hintergrund nach und nach auf die Festplatte schreibt? Sicherheit bzw. Fehleranfälligkeit (z.B. bei Stromausfall) wäre mir ziemlich egal, da kann ich jederzeit ein Backup des Systems einspielen.

 

 

 

 


  1. Glücklicherweise ein Software-RAID, ansonsten hätte ich mir die Idee das an ein NAS übernehmen zu können direkt abschminken können.
  2. Das Ding scheint es nicht mehr im Handel zu geben, da moderne SATA-Chips aber Multiplier unterstützen sehe ich keinen Nachteil im Nachfolgemodell. Der Multiplier macht es langsamer bei Parallelzugriff, aber wenn man den letzten Rest Geschwindigkeit rauskitzeln will nutzt man wahrscheinlich eh kein ESATA.

PS: Die Links zu Amazon sind Partner-Links, die habe ich mal testweise eingefügt – bei einem Kauf über diesen Link würde ich also eine Provision bekommen.

Comments Off on NAS – Fertig kaufen oder selber bauen? :, , , , , more...

[Linux] Verzeichnis mit Hard-Links kopieren

by on Nov.16, 2011, under Linux

Wieder einer dieser Einträge um es selbst nicht wieder zu vergessen…

Wenn man versucht ein Verzeichnis mit Hard-Links einfach so zu kopieren, erstellt man für jede Datei eine neue im Zielverzeichnis, auch wenn im Original zwei Dateien auf die gleichen Daten auf der Festplatte zeigen (hard link).

In meinem Fall hatte ich ein inkrementelles Backup gemacht, bei dem alle unveränderten Dateien nur “hart” mit der Datei aus dem letzten Backup verlinkt wurden, so habe ich jeweils einen Snapshot des so gesicherten Verzeichnisses ohne sehr viel Platz einzunehmen. Beim Versuch meine Backup-Platte auf eine Größere umzuziehen sagte er mir dann, dass mir ein paar TB an Platz fehlen.

Die Lösung ist einfach: Hard-Links mit kopieren. Das mache ich mit dem gleichen Tool mit dem ich das Backup auch erstellt habe, rsync:

rsync -a -H -v /altePlatte/backup /neuePlatte/backup

Die Optionen machen folgendes:

-a Ist eine zusammenfassung (fast) aller Optionen die man benötigt um ein Backup mit rsync zu machen
-H Der springende Punkt – sucht nach Hard-Links und stellt diese im Zielverzeichnis wieder her
-v Zeigt welche Datei gerade kopiert wird. Gibt mir ein besseres Gefühl, wenn ich nicht Stundenlang auf einen leeren Bildschirm gucke und einfach nur hoffe, dass im Hintergrund alles läuft.

Vorsicht: die “-H”-Option benötigt ziemlich viel Speicher, weil rsync sich für jede Datei merken muss, wo ihre Daten liegen.

Comments Off on [Linux] Verzeichnis mit Hard-Links kopieren :, , more...

[Android] Service automatisch mit dem Gerät starten

by on Sep.30, 2011, under Sonstiges

Nachdem ich beschrieben habe, wie man auch einfache Weise zwischen einem Service und einer Activity kommunizieren kann, möchte ich natürlich den Service auch als solchen nutzen, nämlich als stillen Wächter im Hintergrund der (fast) immer aktiv ist.

Dazu muss ich den Service irgendwie automatisch starten. Wie man das macht findet man relativ schnell – nun will ich es hier einmal am oben genannten Beispiel zeigen.

Um einen Service zu starten, wenn etwas bestimmtes passiert, müssen wir drei Dinge tun:

  1. Unseren Service auf die gewünschten Ereignisse “lauschen” lassen.
  2. Uns die Erlaubnis holen diese Ereignisse zu bedienen.
  3. Den Service starten sobald das Ereignis eintrifft.

Um das zu bewerkstelligen muss man sogenannte Intents nutzen. Dafür gibt es Intents selber, Intent Categories, Broadcastreceiver usw. und das ist IMHO nicht sonderlich intuitiv – daher habe ich darüber einen eigenen Artikel geschrieben.

“Lauschen” kann man mit Hilfe eines so genannten BroadcastReceivers, das ist einfach eine Klasse die die Klasse BroadcastReceiver erweitert und deren Methode onReceive() automatisch aufgerufen wird sobald ein registriertes Broadcast-Event eintritt.

In meinem Fall füge ich die folgende Klasse “ServiceBroadcastReceiver” einfach neue Klasse meinem Service hinzu:

    public class ServiceBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action != null) {
                if (
                    action.equals(Intent.ACTION_BOOT_COMPLETED)
                    || action.equals(Intent.ACTION_USER_PRESENT)
                ) {
                    Intent startServiceIntent = new Intent(context, MyService.class);
                    context.startService(startServiceIntent);
                }
            }
        }
    }

Wichtig: Man kann den Receiver augenscheinlich nicht als Nested Class innerhalb einer anderen Klasse wie z.B. dem Service deklarieren, wenn man ihn über das Manifest registrieren möchte.

Das obige Codebeispiel sorgt dafür, dass im Falle der Ereignisse “Gerät wurde gestartet” (Intent.ACTION_BOOT_COMPLETED) und “Bildschirm wurde entsperrt” (Intent.ACTION_USER_PRESENT) der Service “MyService” gestartet wird. Falls der Service schon läuft passiert nichts.

Damit lauscht der Receiver allerdings noch nicht, er muss noch in der AndroidManifest.xml als Receiver eingetragen werden, damit das System weiß, dass dort überhaupt ein Receiver ist.

Ein kleiner Hinweis zum Namen: Wenn ich einen Klassennamen in das Manifest eintrage, kann ich das auf mehrere Arten tun:

  1. Vollständiger Name. Sowas wie “com.hell.the.what.android.MyClass”
  2. Name im festgelegten “default” package. Sowas wie “.MyClass” – bedeutet, dass “MyClass” in dem package gesucht wird, dass im Manifest als attribut “package” festgelegt wurde.
  3. Nur der Name. Sowas wie “MyClass” – sollte im Zweifelsfall genauso funktionieren wie 2, ist aber AFAIK nicht spezifiziert.

(Spezialfall: Der Vollständige Name einer “Nested Class” wird als Name der umgebenden Klasse, dahinter ein “$” und dahinter der Name der verschachtelten Klasse geschrieben: “.MyClass$NestedClass”  – Aber wie oben bereits gesagt, funktioniert das augenscheinlich nicht bei Receivern.)

In diesem Fall fügt man folgendes in das AndroidManifest ein:

    <receiver android:name=".ServiceBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            <action android:name="android.intent.action.USER_PRESENT"></action>
            <category android:name="android.intent.category.DEFAULT"></category>
        </intent-filter>
    </receiver>

Damit sagt man nichts anderes als “Im Falle von BOOT_COMPLETED oder USER_PRESENT, rufe meinen Receiver auf”. Die Default Category muss hinzugefügt werden, damit der Matcher auf die beiden Ereignisse anspricht – ansonsten passiert einfach nichts.

Comments Off on [Android] Service automatisch mit dem Gerät starten :, more...

[Android] Das Problem mit Intents

by on Sep.30, 2011, under Programmierung

Bei Android dreht sich alles um Intents. Wenn man eine einfache Applikation in Eclipse entwickelt muss man sich damit nicht unbedingt auseinandersetzen, weil die korrekten Daten für einen eingetragen werden, aber spätestens wenn man einen Service implementiert oder auf externe Ereignisse reagieren will muss man sich mit Intents beschäftigen.

Da ich Probleme damit hatte das System zu verstehen, will ich hier einmal das was ich gelernt habe zusammenfassen, schon alleine weil ein Aufschreiben immer dabei hilft das eigene Wissen in geordnete Bahnen zu lenken und Lücken zu finden.

Was sind Intents

Intents sind erst einmal nur eines: Nachrichten.

Google hat in seinem Android-Betriebssystem quasi eine Architektur gebaut, in der alle möglichen Komponenten getrennt voneinander erstellt werden können und über diese Nachrichten miteinander kommunizieren, sich aufrufen und aufeinander reagieren können. Intents sind quasi IPC, Hooks, Systemintegration und Prozess-Aufrufe in einem.

Intents können für folgende Aufgaben genutzt werden:

  1. Eine Aktivity oder einen Service starten
  2. Das Programm im System verankern
  3. Auf ein Ereignis reagieren

Dafür gibt es zwei Arten von Intents (die im Quelltext beide ein “Intent” sind), die sich durch die enthaltene Information unterscheiden:

  • explizite Intents
  • implizite Intents

Explizite Intents enthalten einen absoluten Komponentennamen, z.B. den genauen Namen des Service der gestartet werden soll. Android kümmert sich darum, dass diese Intents genau bei dieser Komponente ankommen.

Implizite Intents enthalten quasi “nur” Informationen darüber was passiert – wer/was darauf reagiert hängt davon ab welche Applikationen sich im System mit einem passenden Intent-Filter registriert haben. Passt der Implizite Intent auf den registrierten Filter einer Applikation wird die Komponente zu der der Filter definiert wurde aufgerufen.

Eine Aktivity oder einen Service starten

Der einfachste und offensichtlichste Fall. Genau dafür gibt es folgende Methoden der Klasse Context: startActivity und startService – denen übergibt man einen Intent der den genauen Namen der Activity bzw. des Service (also ein expliziter Intent) enthält (man kann darüber hinaus nahezu beliebige zusätzliche Informationen in den Intent packen und diese dann beim Starten des Service oder der Activity abfragen). Das macht man im Code einer Activity dann z.B. so:

    startService(new Intent(this, MyService.class));

Hier wird ein neuer Intent erstellt, mit der aufrufenden Activity als Context und dem zu startenden Service als Komponentenname  direkt an die Methode startService der Activity übergeben wird. Es handelt sich hier um einen expliziten Intent, da die zu startende Komponente eindeutig spezifiziert ist (nämlich durch den Wert von MyService.class).

Das Programm im System verankern

Dieser Fall ist deutlich weniger intuitiv als der vorherige. Ich will das ganze mal an einem in wohl 95% aller Applikationen vorhandenem Beispiel veranschaulichen:

Um meine Applikation in der Liste der vorhandenen Applikationen aufzulisten muss ich diese im System registrieren – soweit alles wie üblich. Allerdings muss ich bei Android nicht die Applikation, sondern z.B. eine meiner Activities registrieren, und zwar für den Intent der für die Applikationsliste “gesendet” wird. Genauer: Im Manifest meiner Applikation muss stehen, dass meine Activity auf den Intent mit der Action “android.intent.action.MAIN” in der (Intent-)Category “android.intent.category.LAUNCHER” registriert ist.

Im Manifest sieht das dann z.B. so aus:

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"></action>
                <category android:name="android.intent.category.LAUNCHER"></category>
            </intent-filter>
        </activity>
    </application>

Eclipse erstellt diesen Intent-Filter sogar automatisch.

Auf ein Ereignis reagieren

Wenn ich es richtig verstehe ist dies eigentlich nur eine andere Form des vorherigen.

Wenn ich z.B. möchte, dass mein Service automatisch gestartet wird, sobald das Telefon startet, dann muss ich ihn für die Action “android.intent.action.BOOT_COMPLETED” registrieren und dann natürlich noch eine Möglichkeit zur Verfügung stellen darauf zu reagieren. Die Action wird vom System erzeugt, dann guckt das System nach was sich dafür registriert hat (genauer, welche Intent-Filter passen) und schickt dann diesen Intent an genau diese registrierten Applikationen – das nennt Android dann “Broadcast”.

Um einen Broadcast empfangen (“to receive”) zu können benötigt man einen – Überraschung! – BroadcastReceiver, darauf gehe ich in diesem Posting näher ein. Ein ganz einfacher Receiver sieht ungefähr so aus:

    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Do something based on the Intent received
        }
    }

Da wo jetzt der Kommentar steht würden wir natürlich überprüfen welche Action gesendet wurde und im Falle von “android.intent.action.BOOT_COMPLETED” eben den Service starten.

Jetzt muss ich diesen Receiver genau wie meine Activity im vorherigen Beispiel noch im Manifest eintragen und dort in Form eines Intent-Filters mitteilen wann das System denn nun den Receiver aufrufen soll. Das sieht dann in unserem Beispiel so aus:

    <receiver android:name="com.example.MyBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            <category android:name="android.intent.category.HOME"></category>
        </intent-filter>
    </receiver>

Dieser Abschnitt muss (genau wie das activity-Element oben) innerhalb des application-elements geschachtelt sein.

Hinweis

Hier endet mein “Wissen” über Intents, ich will schwer hoffen, dass sich das in nächster Zeit noch vertiefen wird, aber das kommt dann mit der weiteren Entwicklung.

Über Hinweise, Korrekturen und Kritik würde ich mich sehr freuen – ich hab schließlich noch einen langen Weg vor mir bis zum Android-Experten. 😉

Comments Off on [Android] Das Problem mit Intents :, more...

[Android] Zugriff auf UI durch einen Service

by on Sep.29, 2011, under Programmierung

Da ich mich gerade wieder mit Android beschäftige, möchte ich hier einmal einen einfachen Weg darstellen, wie man die UI (Activity) von einem Hintergrund-Dienst (Service) aus verändern kann.

Wenn man im Netz nach einer Lösung für dieses Problem sucht, wird man schnell in Richtung Handler geschickt – diese Lösung finde ich für Minimalaufgaben zu groß und zu aufwändig. Ich wollte einfach nur Nachrichten an die UI schicken, sofern diese überhaupt da ist – dafür benötigt man keinen extra Handler.

Das Problem ist folgendes: Der Service läuft im Hintergrund und losgelöst von der UI – er arbeitet also in einem eigenen Thread. Die UI kann nur aus ihrem eigenen Thread verändert werden. Sobald ich also versuche aus dem Service direkt eine Methode in der UI-Activity aufzurufen um eben diese zu verändern, hagelt es Exceptions. Um das zu umgehen muss ich also irgendwie dem UI-Thread sagen “mach das für mich” – hier ist die einfachste Methode, die ich gefunden habe:

Man gibt dem UI-Thread Runnable-Objekte in seine Queue von abzuarbeitenden Aufgaben mit Hilfe der post()-Methode der View.

Und nun die Details:

Erst einmal muss ich den Service starten, so dass er unabhängig von der UI im Hintergrund läuft – das ist ein anderes Thema, dazu gibt es aber genügend Tutorials im Netz.

Wenn der Service einmal läuft muss er natürlich wissen ob eine Activity vorhanden ist und falls ja, wie er sie erreichen kann. Und hier kommt die schnelle Lösung ins Spiel, die mir zwar theoretisch ein wenig Kopfschmerzen macht, aber praktisch wunderbar funktioniert (sollte dies ein erfahrener Android-Entwickler lesen: Ich freue mich sehr über Verbesserungsvorschläge): Da der Service nur einmal im Hintergrund läuft, geben wir ihm einfach eine statische Singleton-Methode, die von der Activity abgefragt werden kann.

Jetzt müssen wir dem Service nur noch mitteilen, dass die Activity vorhanden ist (quasi wie einen Listener hinzufügen) und schon kann der Service jederzeit mit der Activity kommunizieren. Dafür erstellen wir eine Activity-Variable im Service und eine setActivity()-Methode. (Und falls wir mehrere Activities benachrichtigen wollen machen wir daraus eben eine List<Activity> und eine addActivity()-Methode.)

Jetzt kann der Service jederzeit Methoden auf der Activity aufrufen (so lange diese vorhanden ist).

Wir gehen also folgendermaßen vor:

  1. Activity wird gestartet.
  2. Activity erstellt einen Intent zum Starten des Service (da der Service nur einmal gestartet wird, wird dieser also ignoriert wenn der Service schon läuft).
  3. Die Activity erstellt einen Thread, der nichts anderes macht als die Singleton-Methode des Services aufzurufen – und zwar so lange bis ein valides Service-objekt zurückgegeben wird (das sollte im Normalfall sehr schnell gehen) und diesem nun die Activity mitteilt.
  4. Der Service überprüft wenn er etwas mitteilen soll ob die Activity vorhanden ist – und falls ja, teilt der Activity mit welche Methode ausgeführt werden soll.

Punkt vier ist der interessant Punkt, denn hier passiert die Übergabe von einem Thread in den anderen. In meinem Beispiel will ich der Activity einfach nur einen Text hinzufügen, dafür benutze ich folgenden Code in dem ich das Layout der Activity direkt manipuliere:

    public void showMessage(String message) {
        TextView tv = new TextView(this);
        tv.setText(message);
        layout.addView(tv);        
    }

Vorher habe ich das Layout (hier ein LinearLayout) und die View (hier Scrollview) in der onCreate()-Methode der Activity mit folgendem Code in den Membervariablen layout und view abgespeichert, so dass ich nun darauf zugreifen kann:

        view = new ScrollView(this);
        layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        view.addView(layout);        

        setContentView(view);

Die Methode showMessage() funktioniert so aber nur, wenn sie im UI-Thread aufgerufen wird. Um das ganze aus dem Thread des Service ausführen zu können, verändere ich den Code folgendermaßen: (“MainActivity” muss durch den Namen der Activity-Klasse ersetzt werden.)

    public void showMessage(final String message) {
        view.post(new Runnable() {
            @Override
            public void run() {
                TextView tv = new TextView(MainActivity.this);
                tv.setText(message);
                layout.addView(tv);        
            }
        });
    }

Man beachte das “final” vor dem Parameter – dies ist notwendig um den Wert der Variablen im anderen Thread nutzen zu können. Nun muss ich showMessage() nur noch mit meiner Nachricht als Parameter aufrufen und es wird automatisch im UI-Thread ausgeführt.

 

Damit alles läuft und der Service auch startet: Nicht vergessen den Service in die AndroidManifest.xml einzutragen.


(continue reading…)

Comments Off on [Android] Zugriff auf UI durch einen Service :, more...

Bye bye Social Networks

by on Sep.29, 2011, under Asides

Naja, nicht so ganz – ich bleibe noch bei Google+ und Twitter, zumindest so lange bis ich mich dort auch nicht mehr wohl fühle. (Und bei Twitter werde ich immer inaktiver und das wo ich eh nie wirklich aktiv war.)

Zumindest mein Facebook-Account ist seit heute nicht mehr existent, und der studivz-Account musste gleich mit dran glauben. Bei Facebook ist es ganz klar die Datenschutzpolitik mit der ich nicht einverstanden bin, bei studivz ist es schlicht und ergreifend die Tatsache, dass ich es seit mindestens einem Jahr nicht mehr genutzt habe.

Mal sehen ob meine sozialen Kontakte nun tatsächlich weniger werden, oder – wie meine SWMBO behauptet – die wirklichen Kontakte sogar stärker.

Comments Off on Bye bye Social Networks more...