[:en]Appside Down: Should my App Work Upside Down?[:]

[:en]When creating an iPhone app, many app developers lean towards disallowing their app being used upside down. Reasons given are usually:

  • The big companies (Apple, Google) have most of their apps only in portrait mode, not in upside down portrait mode
  • When allowing upside down and a phone call comes in, the user is confused, which would not have happened, if the user had to use the phone in portrait mode only

While I do see the reasons behind this, there are situations, where this portrait mode only is just not convenient:

  • When the app is used on a bike, in a rain-shelter but a cable needs to go outside (either phone or charging / lightning). If you are lucky, your bike app shelter knows where the cable is. Else you wish, you could use your navigation app upside down.
  • When the app is used in a car and you want to place the iPhone holder on the windshield in a phone holder as low as possible – then you either are 2-3 cm (or 1 inch) over the windshield due to the charging / lightning cable going out below, or you can turn your iPhone upside down and put the cable in on top, allowing you to lower the phone a little more.
  • When you are charging your phone in a car where there is no phone holder (e.g. rental car), then the cup holders are helpful (sometimes). Being able to put a phone into the cup holder upside down and still being able to see the content of your app helps you save the money for the car phone holder.

So when designing an app that is used over a longer time, e.g. could be used with the lightning cable being plugged in, then the option of using the app upside down suddenly may make sense for your customers.

What do you think?[:]

[:en]ToDo before publishing an Android App[:]

[:en]Assume your app is ready. What do you need to do to get it into the Google play store?

  1. Generate a signed Apk
    1. Check that the version has a unique version code
    2. Check the applicationId to be unique and starts with your company name, e.g. „com.smallapps.“
  2. Create a new entry in your Google Play Store
    1. Decide which language is the default language
    2. Give it a title up to 30 char long
    3. Give it a short description up to 80 char long
    4. Give it a long description up to 4000 char long
    5. Upload at least 2 screen shots, maximum 8 Screen shots per Type of each: Telephone, Tablet, Android TV and Android Wear – of course only if it is applicable
    6. Upload a „high resolution“ symbol, e.g. the icon if your app in 512×512 pixels. But could also be a nicer version. Will be shown in the google play store entry.
    7. Upload a „Funktionsgrafik“ (sorry, need to check the english name): Another image of size 1024×500 pixels. Will also be shown in the play store entry.
    8. Optional: Upload an ad picture 180×120 pixels, a TV banner or a video
    9. Select the App-type: App or Game
    10. Select the Category: Learning, Work, Comics, …
    11. Choose a content rating (age rating)
    12. Answer some questions to result in an age rating
    13. Enter an email Address, where you can be contacted
    14. Enter a link to your privacy policy (or click „will be supplied later“)
    15. Enter price or „for free“. This decision is forever!
    16. Decide in which countries to distribute the app
    17. Answer if the app contains ads
    18. Answer if you and your app agree to the android content policy
    19. Answer if you know about export control
    20. Upload the Apk into Alpha or Beta test or upload it to the final store
    21. Decide if it is a open or closed test phase
  3. Then wait until the App is published
    1. If it is a alpha or beta test, you may share the link to find the Apk in the  App store

That’s it already, have fun![:]

[:en]boolForKey:[:]

[:en]When storing objects in the NSUserDefaults or in some other key-value store, convenience methods are often used to store and retrieve keys.

boolForKey: is such a method, but since the BOOL data types have only two values, the the information, if the key was in the store or not, is lost in this method. Because it returns NO if the value NO was stored and it also returns NO if no information was stored at all.
This is the reason, why I prefer to store „default-off“ values in the user defaults. I rather check for disclaimerWasRead than for shouldShowDisclaimer. I rather check for values which can be off or non-existing by default and will be YES for exactly one decision than having distinguish all three states.

[Edit:] A similar situation arises if you use integerForKey:. The value 0 does not inform you, if the key existed at all, or if it existed as 0. If you use objectForKey: first and then transform the result to a integer value, than you still can distinguish if you received nil from the first call.[End Edit][:]

[:en][object compare: weHaveAProblem][:]

[:en]When using Objective-C Methods like compare: and similar methods like caseInsensitiveCompare: you should be aware of one possible problem:

  • Compare returns NSOrderedSame when two objects are considered equal
  • NSOrderedSame is also returned, if you call compare: on a nil-pointer!
  • Why is that?

    Because any method being called on a nil pointer returns nil.
    Which is the same as 0 (zero).
    Which is the same as NSOrderedSame.
    Ouch!

    Assume we have:
    NSString *stringa = @"huhu";
    NSString *stringb = @"huhu";
    BOOL result = [stringa compare:stringb] == NSOrderedSame;

    And print it out like this:
    NSLog(@"[@\"%@\" compare:@\"%@\"] == NSOrderedSame is %@ ",
    stringa, stringb, result ? @"yes":@"no");

    Then we get:
    [@"huhu" compare:@"huhu"] == NSOrderedSame is yes
    If we call instead
    stringb = @"not huhu";
    result = [stringa compare:stringb] == NSOrderedSame;

    We will get:
    [@"huhu" compare:@"not huhu"] == NSOrderedSame is no
    Of course, nobody warns us when we use a nil pointer instead:
    stringa = nil;
    result = [stringa compare:stringb] == NSOrderedSame;

    Which of course results to:
    [(null) compare:@"not huhu"] == NSOrderedSame is yes
    Luckily, writing the code this way:
    result = [stringb compare:stringa] == NSOrderedSame;
    Results in the correct value again:
    [not huhu compare:@"(null)"] == NSOrderedSame is no

    Learnings?
    So we learned: We need to check the left object, the method receiver, for not being nil to prevent strange results. And in cases, where we compare against a constant object, we might as well put the constant on the left hand side, resulting in e.g.
    result = [@"huhu" compare:objectb] == NSOrderedSame;
    to prevent stumbling over nil pointers.[:]

    [:de]iWeb ist jetzt doch ganz unbrauchbar[:]

    [:de]Eine Weile lang ist iWeb ja jetzt schon nicht mehr offiziell unterstützt. Aber für einige meiner langjährigen, selten geänderten Webseiten, war es stets eines der besseren Programme um diese Webseiten ab und zu mit Text oder Daten zu versehen. Wenig Arbeit – akzeptables Aussehen.

    Nach langen Jahren wollte ich mal wieder ein paar Bilder auf eine dieser Webseiten hochladen, die ich 2008 errichtet hatte. Nun stellte ich allerdings fest, dass iWeb nur Fotos von iPhoto importieren kann und das neue Fotos von Apple nicht kennt. Da das alte iPhoto keine neuen Bilder mehr importieren kann, fehlt mir jetzt die Möglichkeit, die Webseite mal eben mit 20 neuen Fotos zu versehen.

    Nun haben wir ja im letzten Jahr für ein eBook von Othmar Kyas ein Skript für eine fast-Automatische WordPress-Installation entwickelt. In sofern war WordPress auf der Webseite wirklich recht schnell installiert. Nur das Umziehen der existierenden Webseite – das machte mir noch Sorgen. Also erst mal alles vorbereitet – und nun wird wohl alles auf freie Zeit zu Weihnachten warten müssen, bis ich wieder Zeit habe.

    Als alternative bleibt mir nur der uralte nicht-mehr-hochrüstbaren Mac-Mini mit iPhoto und iWeb und viel zu alter Software drauf. Der ist zwar offiziell ausser Betrieb, aber wenn das Umziehen der Webseite z.B. 10 Stunden dauern könnte, dann ist ein iWeb aus der Gruft am Ende doch die Zeitsparende Lösung. Mal sehen, wie ich es am Ende löse…[:]

    [:en]Xcode Asset Catalog[:]

    [:en]When using the asset catalog, I usually name the image set in the same way as the image file. E.g. I create an image set leftIcon with files leftIcon@2x.png and leftIcon@3x.png in it.

    Today I decided different.

    I created an image set named button_pressed_background and used a file called grey_background.png.

    When fetching the icon with UIImageNamed:@"...", I was not sure which name to use. It turned out, that I need to use the asset catalog image set name, e.g.
    UIImageNamed:@button_pressed_background", not the filename (which returns nil when used).

    Last question I had, was: Since I used a small grey icon to fill the complete button, is the grey on a 3x-Device the same as on the 2x device? Or do I need a 2x and 3x version of the image file, although it only contains grey pixels? I assumed no, since it looked OK. So hopefully the customers will agree…[:]

    [:de]FotoRoute[:]

    [:de]Angeregt durch die Existenz eines Fahrtensegel-Wettbewerbs des Berliner Segler-Verbandes (mehr Infos hier: http://www.berliner-segler-verband.de/fahrtenwettbewerbe.html ) sind zwei Apps durch eine Studentin und einen Azubi entstanden, die Fahrtenseglern das „Karten zeichnen“ und „loggen“ leichter machen können. Grundidee ist, dass Fotos mit Ortsinformationen helfen können, ein Logbuch und die Reiseroute festzuhalten.

    Leider sind die beiden Programmierer dieser Apps keine Fahrtensegler (und ich auch nicht) und so sind die Apps auch nie mit Fotos von einem Törn getestet worden, sondern immer nur „im Trockenen“. Natürlich sind die Apps in ihrem Leistungsumfang begrenzt, sie sind ja von Menschen, die noch in der Ausbildung sind, in kurzer Zeit geschrieben worden. Und natürlich sind sie kostenlos und ohne Werbung. Und Ihr Hauptzweck, Teil einer Prüfungsaufgabe zu sein, haben die Apps auch schon erledigt. Ob die Apps nun aber wirklich hilfreich für Segler sind, ist noch unbewiesen.

    Die eine App, geschrieben für iOS (Apple-Telefone und iPads) ist noch nicht veröffentlicht, Interessenten müssten sich per Email bei mir melden und würden dann in den Kreis der Tester aufgenommen.
    Die andere App, geschrieben für Telefone und Tablets mit Android, kann zwar nur eine Karte aus den Geodaten von Fotos zeichnen, aber so eine Karte ist ja auch ein Teil der Dokumentation beim Fahrten-Wettbewerb. Die App ist schon im Google Play Store veröffentlicht und hier zu finden:
    https://play.google.com/store/apps/details?id=com.smallapps.fotoroute

    Ich würde mich jedenfalls über Rückmeldungen freuen![:]

    [:de]Streichholzspiel über 1000 mal geladen[:]

    [:de]Das Streichholzspiel ist ein Knobelspiel in dem durch Umlegen von Streichhölzern aus einer falschen Gleichung eine richtige Gleichung gemacht werden soll. Screenshots wie die App bei uns unter Android aussieht hier: https://play.google.com/store/apps/details?id=com.smallapps.streichholzspielfree

    Die App war eine Idee meines Vaters und die Umsetzung war die erste App meines Sohnes – das ganze ist also ein relativ familiäres Projekt. Fertig war die App am 21.10.2013, jetzt hat es fast genau 2 Jahre gedauert, bis 1000 Downloads der kostenlosen App zusammen waren.

    Jetzt könnte ich viel über die App reden, aber ich würde gerne mal ein paar Statistiken mit Euch teilen, die Google mir zu der App im Play Store anzeigt. Ich betone besser gleich mal, dass das alles Standard Google Statistiken sind, dass unsere App nichts nach Hause sendet und dass ich nicht im Detail weiss, wie Google diese Daten sammelt und wie zuverlässig diese Daten sind. Ich gehe aber davon aus, dass Google sich bei der Installation und bei der Deinstallation einer App eine Benachrichtigung schickt.

    Schauen wir uns zuerst den Verlauf der Downloads über die letzten 2 Jahre an.
    Es fällt auf, dass der Verlauf fast linear aussieht, von Zunahme oder von Beschleunigung nichts zu merken. Es gibt also keinen Lawineneffekt. Kein Wunder – so beliebt wie MatheBildschirmfoto 2015-11-04 um 09.56.41 im allgemeinen ist, kann ich mir kaum vorstellen, dass sich z.B. pro Schulklasse mehr als drei Leute für das Spiel interessieren. Allerdings gibt es immer mal wieder kurzzeitige „Sprints“ – offensichtlich werden wir also doch weiter empfohlen – nur eben in kleineren Kreisen.

    Bildschirmfoto 2015-11-04 um 10.03.34Dann würde ich Euch gerne eine Statistik zeigen, aus der ich sicher nicht all zu viel heraus lesen sollte. Da die App in Deutsch besser läuft als international, sind auch die Deutschen Netzbetreiber ganz oben. Warum allerdings E-Plus vor der Telekom ist, ist mir schleierhaft – wer dazu eine Idee hat, immer her damit.

    Bildschirmfoto 2015-11-04 um 10.03.11Hier nun die Spracheinstellungen der Nutzer. Warum Rumänisch oder Portugiesisch so weit vorne sind, weiss ich auch nicht. Gehen wir mal davon aus, dass es da ein paar lokale Fans gibt.

    Bildschirmfoto 2015-11-04 um 10.02.57So ähnlich aber doch ganz anders ist die Ländereinstellung. Denn in dieser Sicht wird klar, dass die Spracheinstellung „britisches Englisch“ eben meist für indische Downloads galt und nicht etwa für britische Downloads. Und wenn man weiss, dass Indien mehrere Mathe-Genies hervor gebracht hat und viele Programmierer hat, dann findet man es sicher auch natürlich, dass Indien mit seinen vielen Mathematik-Begeisterten die Liste der internationalen Downloads anführt. Ob verwunderlich oder nicht, aber wir haben bei der Entwicklung der App nicht eine Sekunde daran gedacht, wer die App wo toll finden wird. In sofern sind wir doch einigermaßen überrascht, dass wir eine App für Deutsche und Inder geschrieben zu haben scheinen.

    Bildschirmfoto 2015-11-04 um 10.00.34Diese Statistik zeigt, welche Geräte die App herunter geladen haben. Leider ist das ja über 2 Jahre verteilt, so dass die Erkenntnis nicht so groß ist, finde ich. Vielleicht wäre ein Verlauf interessanter – wann welches Gerät das Download-Stärkste war und wie lange.

    Bildschirmfoto 2015-11-04 um 10.00.04Und auch bei dieser Statistik ist der lange Zeitraum von zwei Jahren nicht so richtig hilfreich und auch hier wäre ein Verlauf sicher besser.[:]

    [:de]XML Sequenz ganz unerwartet[:]

    [:de]Immer mal wieder muss man als Mobiler Entwickler JSON oder XML Dokumente zusammenstellen und versenden um Daten und Objekte mit anderen Apps oder Servern auszutauschen. Sich dabei an die erwartete Syntax zu halten fällt manchmal schwerer und manchmal leichter. Wenn eine Definition der Syntax in Form eines .xsd Datei (XSD = XML Schema Definition) existiert, ist es um so leichter. Aber man muss sie leider auch richtig lesen.

    Nun ist das Lesen einer .xsd-Datei ja nicht wirklich schwer, aber so eine Datei ist manchmal schon ganz schön lang und so kommt es, dass man schon mal ein Detail übersieht. So ist es eben eine Selbstverständlichkeit, wenn man bei einer vorgeschriebenen Sequenz die Reihenfolge einhält.

    Nun werden Sequenzen allerdings auch gerne mal so verwendet, dass die Forderung nach ihrer Reihenfolge eher eine zahnlose ist, also nicht so wichtig ist, indem die einzelnen Elemente der Sequenz optional sind und die Sequenz beliebig häufig wiederholt werden kann. So kann in einer vorgeschriebenen Sequenz von a b c durchaus c b a erlaubt sein, wenn die Sequenz dreimal wiederholt werden kann und alle Elemente optional sind. Dann ist die erste runde c, dann b, dann a gegeben. Nach der 10. l sofern kann es schon mal sein, dass man eine Sequenz beim lesen nicht so ernst nimmt, wie es der Fall wäre, wenn man

    In einem Fall, in dem eine Definitionsdatei vorhanden war, verarbeitete der Server die Daten in einer Sequenz. Allerdings brach er immer wieder nach 3 von 4 Elementen ab. Nach einigem Testen und einem erneuten Blick in die Definitionsdatei war klar: Die Erwartung einer „zahnlosen Sequenz“ war falsch. Diese Definition legte Wert darauf, alle Elemente nur einmal und damit in der richtigen Reihenfolge erscheinen. Kaum war das bewerkstelligt, wurden auch alle Elemente vom Server erkannt.

    Eine Sequenz ist eben manchmal eine echte Forderung und manchmal ein zahnloser Tiger. Der Tipp des Tages könnte also lauten: Achten Sie auf die Details und machen sich die Reihenfolge lieber wie vorgeschrieben, dann versteht Sie auch der Server.
    [:]

    [:de]Regattakalender 2015 Update[:]

    [:de]Regattakalender-Update 2015:
    – Die 2015er Daten zur Regattakalender-App sind online

    – Ebenso gibt es 2015er Versionen der Apps für Android und iOS

    – Die neue Android-Version kann jetzt auch Regatten als Termin eintragen (Danke an unseren Praktikanten Kirill dafür), wie das die Apple Version schon seit letztem Jahr konnte. Die Android-App lädt sich die Daten runter, muss aber danach noch mal gestartet werden. Am besten „ganz neu starten“: Lange auf den Home-Button drücken und dann die App in der Liste aller Apps nach oben wischen. Danach die App neu starten. Sorry, falls das nervt, wir schauen mal, ob wir das besser machen können

    – die Apple Version hat einen Bug Fix erhalten, der sie daran gehindert hat, die neuen Daten nach dem runter laden auch anzuzeigen. Apple hat die Version am 3.4.2015 freigegeben.[:]