code it

Martins Tech Blog

SourceTree und 'ssh-agent' ist fehlgeschlagen mit Code -1: System.NullReferenceException

Seit ich Git als SCM benutze, verwende ich auch SourceTree, um mir das Ganze etwas grafischer darstellen zu lassen. Bisher war ich auch ziemlich zufrieden und glücklich damit.

Aber dann kam das Update auf Version 1.8 und es änderte sich einiges. Neben der Änderung der Nutzungsbedingungen, die zwar im Blog deutlich hervorgehoben, aber irgendwie im Installationsprozess für mich nicht ersichtlich war, trat seitdem bei jedem Start von SourceTree folgender Fehler auf:

'ssh-agent' ist fehlgeschlagen mit Code -1: System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
()
Ich brauche wohl nicht zu erwähnen, dass es mit der Vorversion problemlos ging.

Mein Lösungsweg:
a) das System-Git mal wieder auf einen aktuellen Stand bringen
und
b) im SourceTree unter Tools ⇨ Optionen ⇨ Git auf den Button "Benutze System Git" klicken

Schon werde ich wieder nach meinem Kennwort für den SSH-Key gefragt und alles läuft wie vorher.

Code Coverage Reports für UnitTests in Android Studio

Android Studio unterstützt automatisiertes Testen bereits out-of-the-box. Dabei wird grundsätzlich zwischen verschiedenen Arten von Tests unterschieden. Eine detaillierte Beschreibung findet man im Testing-Abschnitt der Doku.

Nach dem Durchführen der Tests erhält man einen Testreport und (sofern aktiviert) auch einen mit JaCoCo erzeugten Coverage-Report. Allerdings war das Android-Studio-Team hier nicht ganz so konsequent, denn die Coverage-Reports werden für UnitTests nicht erzeugt. Hier spiegeln sich lediglich die Android-Tests wider.

Wie kann man nun erreichen, dass meine ganz normalen Unit-Tests mit JUnit auch einen solchen Coverage-Report erzeugen. In meinem Projekt habe ich nämlich lediglich JUnit-Tests und ich mocke den ganzen Android-Kram mit Hilfe von Robolectric und Mockito - was zugegebenermaßen dafür sorgt, dass ich keine Integrationstests habe, aber dafür eben die Funktionen sauber getestet sind ohne dass ich ich auf einen Emulator verlassen muss.

Nach stundenlangem Suchen in ähnlich gelagerten Problemen auf Stackoverflow bin ich dann in den Kommentaren auf ein Plugin gestoßen, das mein Build-Script genau mit den erforderlichen Funktionalitäten erweitert wird - und seit der Version 0.2.1, welche derzeit bereits als Snapshot vorliegt werden auch Intermediates ignoriert, die "$$" im Dateinamen haben.

Playlist erstellen für PlayPoster von OOSM

Nachdem ich in meinem letzten Post geschrieben habe, wie man PlayPoster in Betrieb nimmt, soll es heute darum gehen, meine Anwendungsfälle mal abzubilden. Dazu erstelle ich im Admin-Portal eine Playlist und befülle diese mit Inhalten.

Das Admin Portal kommt sehr übersichtlich daher und alle wichtigen Menüpunkte sind per Direktlink verfügbar. Nun ein paar Worte zur Struktur: Ein PlayPoster Stick (= Unit) gehört zu einer Gruppe (= Location). Einer Location und damit allen darin enthaltenen Devices können Playlists zugeordnet werden, die entweder ganztägig, morgens, mittags oder abends aktiv sein können. Eine Playlist selbst ist eine Reihenfolge von Bausteinen, die im Editor erstellt oder bearbeitet werden können. In einigen Bausteinen werden Bilder benötigt (oder sind zumindest sinnvoll). Diese liegen unter Files.
Logo Baustein erzeugen
Ein recht simpler Baustein ist der Bildbaustein in dem einfach eine bestimmte Zeit lang ein Bild angezeigt wird. Dieser Baustein ist auch bereits in der Standard-Playlist mit der das Gerät ausgeliefert wird enthalten. Wie erzeugt man nun selbst einen solchen Baustein? Ganz einfach: Dazu legt man einfach in der Menüleiste ein Bild per Drag&Drop ab und definiert im anschließend erscheinenden Dialog noch die Anzeigedauer (diese ist immer im Format mm:ss).

Externe Webseite einbinden
In meinem vorigen Post habe ich ja als Use-Case angegeben, dass ich den Ticketstatus (bei uns aus dem Redmine) und den Status des Build- und Testsystems (bei uns Jenkins) anzeigen will. Dafür gibt es natürlich keine vorgefertigten Bausteine. Aber wozu bin ich Entwickler? Ich kann ja auf einem unserer Rechner noch einen Webserver laufen lassen, der die Daten nach meinen Wünschen aggregiert und anzeigt. Diese Webseite kann ich dann anzeigen lassen. Dazu erstelle ich unter Editor einfach einen neuen Baustein, weise das Template "External Page" zu und gebe die Url an, die angezeigt werden soll und auch wieder die Anzeigedauer. Die Url muss aus Sicht des Sticks angegeben werden - ich kann also auch lokale Urls verwenden. Die Vorschau im Browser funktioniert technisch bedingt nicht, wenn ich mich beim editieren nicht im gleichen Netz wie der Stick befinde und die Webseite für mich dann nicht erreichbar ist oder wenn meine Url eine http-Url ist (da das Portal https ist und der Browser unsichere Elemente in blockiert). Auf dem Device funktioniert es dann aber.

Tweets anzeigen
Ähnlich einfach ist die Anzeige von Tweets. Dazu verwendet man den Baustein "Twitter" und gibt den Hashtag oder die Person an der man folgen will. Innerhalb der definierten Anzeigedauer wird dann alle paar Sekunden durch die so gefilterten Tweets gewechselt. Da sowohl Schriftfarbe als auch Standard-Hintergrund weiß sind, ist es bei diesem Baustein wichtig, dass man im Editor das Hintergrundbild definiert. Dazu lädt man einfach im Vorab über Files ein Bild in der Hintergrundfarbe seiner Wahl hoch und setzt es im Baustein als Hintergrund.

Statische Texte
Zur Anzeige statischer Texte gibt es verschiedene Templates. Ich verwende dazu in der Regel eines der "Pricelist" Templates, da ich oft eine tabellarische Ansicht brauche (z.B. für die Ankündigung von Community Events). 

Playlist erstellen
Nun da ich alle Bausteine erstelle habe, muss ich nur noch eine Playlist aus diesen erstellen. Dazu wechsle ich unter Playlists und ziehe mir per Drag&Drop die Bausteine in der gewünschten Reihenfolge in meine Timeline und speichere die Playlist ab. 
Wenn ich mir noch aussuche wann und wo die Playlist gespielt werden soll, wird sie auch gleich auf die anhand der Location gewählten Devices gepusht und dort direkt angezeigt.

Ein komplettes Tutorial gibt es auf der OOSM Support Seite

Digital Signage mit PlayPoster von OOSM

Wer hat sie noch nicht gesehen - die Werbemonitore in den Geschäften, die Info-Screens bei Veranstaltungen. Digitale Schilder oder auch Digital Signage sind beim Marketing nicht mehr wegzudenken. 

Auch bei uns im Büro sollte so ein Screen her. Weihnachten war es dann so weit - im Büro stand ein nagelneuer Fernseher, der auch schnell recht professionell an der Wand hing. Doch wie geht's dann weiter? Ok, für ein paar statische Inhalte funktioniert das recht gut - USB-Stick angeschlossen und schon kann eine Slideshow von Bildern angezeigt werden. Aber das war's dann auch schon.

Unser Screen soll nicht nur Marketingfunktionen erfüllen, sondern ich möchte dort auch nützliche Informationen für die Mitarbeiter anzeigen und diese sind nur dann wirklich nützlich, wenn sie dynamisch erzeugt werden. Wir sind ein Unternehmen, das Software herstellt. Also was sind denn nützliche Informationen? Ich denke hier an:
  • den aktuellen Projektstatus (also das Sprint- oder Projekt-Burndown)
  • den Status des Buildsystems (welche Builds laufen gerade; gibt es irgendwo Builderrors oder fehlgeschlagene Tests)
  • Informationen zum Unternehmen oder zur Abteilung
  • Informationen zu Community-Events
  • Informationen aus sozialen Medien (z.B. einen Twitter-Feed)
Das alles lässt sich mit der statischen Dia-Show die der Fernseher mitbringt nicht lösen. Da muss etwas anderes her.

Im Frühsommer letzten Jahres war ich in Amsterdam zu einem Startup-Event und habe dort die Köpfe eines Unternehmens kennengelernt, die genau so eine Digital Signage Lösung herstellen: OOSM (sprich: awsome) mit Ihrem Produkt PlayPoster. In den Gesprächen mit dem CEO Peter Bruner stellte sich heraus, dass der Stick von OOSM vermutlich genau die einfache Lösung ist, die wir brauchen.

Also habe ich einen Stick bestellt. Nach wenigen Tagen war der dann auch in meinem Briefkasten. Die Installation ist denkbar einfach und in 3 Schritten erledigt: 
  • Stick auspacken und an Stromversorgung und HDMI-Port des Bildschirms anschließen
  • WLAN-Credentials eingeben (dafür braucht man mal kurzzeitig eine USB-Maus)
  • Stick kurz vom Stromnetz nehmen, damit er rebootet
Das war's auch schon. Ab jetzt öffnet sich bei jedem Boot automatisch die vorinstallierte App und zeigt die definierten Inhalte an.

Da kommen wir auch schon zum nächsten Punkt: Definieren der Inhalte. Denn ich wollte ja statische und dynamische Inhalte darstellen.

Bei der Bestellung erhält man Credentials zum Admin-Portal von OOSM. Dort definiert man sogenannte Playlists, die man einer Gruppe von Devices zuordnen kann - also ein Device ist in einer Gruppe; eine Gruppe hat eine oder mehrere aktive Playlists (ganztägig oder für einen bestimmten Zeitraum); eine Playlist besteht aus Bausteinen, für die eine Reihenfolge definiert wird. Wie das genau geht, erkläre ich in einem späteren Post.

Digital Signage Lösungen gibt es viele am Markt, deswegen hier neben dem persönlichen Kontakt zum Entwicklerteam noch ein paar Hard-Facts für die Entscheidung für PlayPoster. 

Einfache Installation mit vorhandener Hardware (+)
Es muss ja nicht immer der neue TV sein - wir alle haben igendwelche alten Monitore herumstehen, die wir nicht mehr brauchen und die super für Digital Signage geeignet sind. Einfach den Stick anschließen, WLAN einrichten, fertig. Und der Stick ist mit Abmessungen von 85 x 30 x 10 Millimeter wirklich nicht groß.

Cloudbasierte Definition (+)
Ich kann von zu Hause oder von unterwegs steuern, was auf meinen Screens im Office wann angezeigt wird.

Niedrige Kosten (+)
Die Anschaffungskosten sind vergleichsweise sehr gering - andere Digital Signage Produkte kosten über 100 Euro pro Device, die aktuellen Kosten (Stand Januar 2016) des PlayPoster Sticks sind 59 Euro einmalig ohne weitere nutzungsbasierte Zahlungen.

Betaphase (+/-)
Das System ist noch in der Betaphase. Man stolpert also noch manchmal im Admin-Portal über Punkte die von der User Experience noch nicht optimal sind, aber das Entwicklerteam freut sich über Feedback und behebt Bugs (wenn man welche findet) super schnell.

Viele vordefinierte Templates (+)
Für die Bausteine gibt es vordefinierte Templates, die schon viele Anwendungsgebiete abdecken:
  • statisches Bild (also quasi wie Diashow)
  • externe Webseite (z.B. für unsere Systemstatus-Anzeigen)
  • Tweets (anhand Hashtag oder Person)
  • RSS-Feed
  • Gimmicks wie Uhr, Horoskop, Wetter
  • verschieden gelayoutete Bild-/Text-Screens (Preisliste, Bild mit Text)

Nur FullHD (-)
Der Stick in seiner aktuellen Konfiguration unterstützt lediglich FullHD und noch kein 4K. Für uns reicht das im Moment. Nach der Aussage von OOSM soll die nächste Generation aber definitiv 4K-fähig sein.

Damit genug zum Thema Installation. In meinem nächsten Post zeige ich, wie ich meine Playlist für PlayPoster zusammenbaue.

OutOfMemoryError beim Kompilieren von Xamarin Projekten

Heute hab ich versucht in ein Xamarin Android Projekt das Google Ads Framework hinzuzufügen. Nichts leichter als das: Nuget und dort Xamarin.GooglePlayServices.Ads ausgewählt. 

Die Ernüchterung kam recht schnell: Ab diesem Zeitpunkt ließ sich mein Projekt nicht mehr kompilieren. Der Build dauerte viel länger als gewohnt und brach dann mit dem Fehler
java.lang.OutOfMemoryError. Consider increasing the value of $(JavaMaximumHeapSize). Java ran out of memory while executing 'java.exe'
ab. 

Nun befinde ich mich ja in Visual Studio und hab dort nicht wirklich eine Einstellung gefunden, die mir weiter geholfen hätte. Nach einiger Internetrecherche hier nun die Lösung: In der csproj-Datei muss folgender Code hinzugefügt werden: 
<PropertyGroup>
    <JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
</PropertyGroup>
und schon läuft der Build wieder durch.

GreenDao ... und wo sind meine Daten?

In meinen Android-Projekten verwende ich gern GreenDao als OR-Mapper, denn es ist einfach zu verwenden und nach Aussagen des Herstellers auch performant und ich habe bisher keinen Grund gehabt daran zu zweifeln.

Heute bin ich über ein mir zunächst nicht erklärbares Phänomen gestolpert, das sich im Nachhinein mit Performance-Optimierungen im GreenDao-Core erklären lässt.

Aber ich beginne von vorn. Meine App hat einen klassischen Aufbau - eine Liste und per Klick auf einen Eintrag sieht man die Details und kann diese editieren. Jeder dieser Einträge hat nun noch datumsabhängige Sub-Daten. 

Um es zu verdeutlichen: Wald - Baum - Stammumfang pro Tag.

Da ich sowieso den Baum identifizieren und dessen Daten anzeigen musste, habe ich wie folgt auf die Daten zugegriffen:
Tree tree = _daoSession.getTreeDao().load(id);
List<MeasuringValue> mvls = tree.getMeasuringValueList(); 

Das Speichern der eigentlichen Daten erfolgt dann auch ganz nach Doku.
MeasuringValue mv = new MeasuringValue();
mv.setTreeId(id);
mv.setDate(date);
mv.setCircumference(circumference);

_daoSession.getMeasuringValueDao().insert(mv);

Das Phänomen ist nun gewesen, dass beim erneuten Aufrufen die neu gespeicherten Datensätze zunächst nicht vorhanden waren. Das Problem war mit debugging auch nicht nachvollziehbar - alles funktionierte korrekt und war auch auslesbar. Noch seltsamer: auch ohne angehängten Debugger waren die Daten die zunächst nicht angefügt schienen nach einigen Minuten doch enthalten.

Wie schon geschildert verwendet GreenDao einen Cache und der scheint hier das Problem zu sein, da ich die Daten auf einem anderen Weg auslese als ich sie einfüge. Beim Auslesen gehe ich über den Fremdschlüssel von Tree, beim Einfügen gehe ich direkt über die Messwert-Tabelle.

Das Problem lässt sich umgehen, indem man den Cache von GreenDao leert. 
_daoSession.clear();
Nachteil: man tauscht aktuelle Daten gegen den Performancevorteil ein - und so wäre die richtigere Lösung die Daten über den gleichen Weg auszulesen wie man sie anfügt.

Proguard und Realm.IO

In einem Projekt habe ich mal Realm ausprobiert. Dabei handelt es sich um eine alternative Datenbank, die verspricht die Wiederverwendung von Code aufgrund gleicher Model-Klassen sowohl in IOs als auch in Android hoch zu halten.

Detaillierte Erfahrungsberichte dazu kommen sicher in einem späteren Post.

Zunächst gab es eine kleiner Überraschung nach der Aktivierung von Proguard. Der Hersteller gibt folgende Konfiguration an:
-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-dontwarn javax.**
-dontwarn io.realm.**
Allerdings erreichte mich dann bei der Ausführung folgende Exception:
java.lang.IllegalArgumentException: class io.realm.internal.d declares multiple JSON fields named c
    at a.a.a.b.a.q.a(Unknown Source)
    at a.a.a.b.a.q.a(Unknown Source)
    at a.a.a.j.a(Unknown Source)
     .....
Heißt, die korrekte Proguard-Konfiguration sollte dieses Package wohl besser auch von der Obfuskierung ausschließen:
##---------------Begin: proguard configuration for Realm  ---------- 
-keep class io.realm.annotations.RealmModule -keep @io.realm.annotations.RealmModule class * -keep class io.realm.internal.** { *; } -dontwarn javax.** -dontwarn io.realm.** ##---------------End: proguard configuration for Realm ----------

SSLPeerUnverifiedException in Verbindung mit Android und IIS8

Das Backend für meine App sollt nur über eine https-Verbindung erreichbar sein. Alles kein Problem dachte ich mir, schnell ein SSL-Zertifikat besorgt und dieses der https-Bindung der Webanwendung zugewiesen. Alles kein Problem und auch der Browser zeigt das kleine grüne Schloss an und der Zertifizierungspfad war ok.

Um so überraschter war ich, dass meine Android App nun jeden Request mit einer Exception quittierte: 
javax.net.ssl.SSLPeerUnverifiedException (SSL peer not authenticated)

Laut Dokumentation passiert das, wenn man ein selbst signiertes Zertifikat verwendet und die Tipps im Web sind sehr breit gestreut - unter anderem "stelle den HttpClient doch so ein, dass er allen Zertifikaten vertraut". Das hilft bei selbst signierten Zertifikaten für eine Demo sicher, für eine echte App mit Kundendaten verwende ich diesen Tipp lieber nicht.

Was war nun aber Ursache für das Problem? Ich hatte im IIS in der https-Bindung den Haken bei "Require Server Name Indication (SNI)" gesetzt. Diese Einstellung sorgt eigentlich dafür, dass sich mehrere verschlüsselt abrufbare Websites unterschiedlicher Domains einen Server mit nur einer IP Adresse teilen können. Allerdings können ältere Browser damit Probleme haben. Offenbar zählt der HttpClient in Android / Java dazu, denn kaum hatte ich den Haken entfernt, ließ sich problemlos auf meine REST-API über HTTPS zugreifen.

Update 14.08.2015
Nach einiger Recherche habe ich nun herausgefunden, dass die neueren HttpClients durchaus in der Lage sind, mit SNI umzugehen. In der App in der das Problem auftrat hatte ich Spring for Android in der Version 1 verwendet. Der HttpClient dort hat das Problem mit SNI. Die neuere Version 2 von Spring for Android verwendet einen HttpClient, der problemlos damit umgehen kann.

Ein Wochenende beim Developer Open Space

An diesem Wochenende war ich beim Developer Open Space in Leipzig, der nun schon einige Male dort stattgefunden hat. Leider konnte ich auch dieses Jahr aus Zeitgründen nicht an den wirklich interessanten Workshops am Freitag teilnehmen, aber Samstag und Sonntag war ich vor Ort. 

Das Konzept ist recht einfach: Versammle eine Menge Entwickler und gib ihnen den Freiraum, selbst Themen zu bestimmen über die sie reden wollen. Was initial mal als .NET Open Space gestartet ist, hat sich in den letzten Jahren von der Technologie entfernt. Und so kommt es, dass inzwischen auch Entwickler mit dabei sind, die in anderen Technologien zu Hause sind, wie Java, Ruby, JavaScript und so weiter.

Welche Themen waren für mich interessant? Nun ja, dadurch, dass ich mich auch beruflich mit IoT beschäftige, fand ich die Wearables und Smarthome-Sessions sehr spannend. Als Freelancer/Geschäftsführer auch sehr interessant war die anschließende Session bei der es darum ging, gescheiterte Projekte zu analysieren und die Meinungen anderer zu hören, wie sie und auch ihre Auftraggeber damit umgehen. Leider war die Event Storming Session parallel, so dass ich bei dieser nicht dabei sein konnte. Weil auch wir oftmals vor Technologieentscheidungen stehen, besuchte ich anschließend die Session zum Thema NoSql vs. RDBMS in der diskutiert wurde, wann man welche Technologie sinnvollerweise einsetzt. Die für mich letzte Session des Tages hielt ich mit einigen Usergroup-Leads gemeinsam, in der wir zeigten, wie wir die Seite der .NET Usergroup Dresden aufgebaut haben (Jekyll auf Github). Es folgten noch zwei weitere Slots, aber die Zeit habe ich eher für entspannte Gespräche auf dem Hof genutzt. Der Abend endete dann in entspannter Atmosphäre und durchaus auch lustigen Gesprächen im Pub.

Der Sonntag lief recht ähnlich ab: interessante Sessions, spannende Gespräche in den Pausen oder nebenher. 


Es war für mich wieder ein Erlebnis, mit den ganzen Leuten quer aus dem DACH-Raum fachsimpeln und Gedanken austauschen zu können. Und auch wenn ich eher Technologie oder Management-Sessions besucht habe, so gab es auch dieses Jahr wieder Sessions zu Softskill und Psychologie - es ist also für jeden etwas dabei. Und mit 200 Anmeldungen zählt dieser Event nun schon zu den größeren Konferenzen.

Facebook zeigt falschen Vorschau-Content an

In der letzten Woche war mir aufgefallen, dass bei einer meiner Seiten der falsche Inhalt in der Vorschau angezeigt wurde. Das Problem hatte mehrere Ursachen.

1. IPv6
Das erste Problem ließ sich recht einfach lösen: Ich hatte in der Domain-Konfiguration noch einen AAAA-Record auf die IPv6  des Hosters gesetzt. Offenbar versucht Facebook einen Zugriff über IPv6 durchzuführen. Damit kam der Inhalt der Vorgabeseite des Hosters und damit auch ein hübsches rotes Verkehrszeichen als Bild, was mit meiner Webseite nun so überhaupt nichts zu tun hat.

2. Cache
Nun wurde es aber spannend. Die IP-Zuordnung war korrekt und trotzdem wurde noch der alte Inhalt angezeigt. Problem 2 ist, dass Facebook die Inhalte cacht. Das ist natürlich nur dann ein Problem, wenn man die Inhalte ändert. Glücklicherweise gibt es von Facebook ein Tool (das eigentlich einen anderen Zweck hat), aber hier sehr hilfreich ist - der Open Graph Object Debugger. Hier kann man die Url eingeben und sich ansehen, was Facebook daraus ausliest zum Erzeugen der Vorschau. Und man kann hier auch erzwingen, dass die Daten neu abgerufen werden.

3. Bilder
Letztes Problem bei mir waren Bilder. Auf vielen Webseiten ist es gerade üblich, im Header einen Slider mit Bildern zu haben. Diese Bilder findet auch der Crawler und möchte in der Vorschau eine Galerie anzeigen. Das ist aber nicht immer gewünscht. Nun kann man mit Meta-Informationen ein bestimmtes Bild erzwingen. Der entsprechende Metatag ist:

<meta property="og:image" content="http://komplette.url/zum/bild.jpg" />

Wichtig zu beachten: Das Bild muss mindestens 200 x 200 Pixel groß sein. Und: Größe und Seitenverhältnis definieren, ob das Vorschaubild links neben den anderen Metainformationen angezeigt wird (quadratisches Bild) oder ob sich das Bild über die komplette Breite des Posts zieht.