Qt im Mer!

Mit Qt die erste eigene Sailfish-OS-App entwickeln
Kommentare

Die Weiten des Ozeans haben auf Betriebssystemanbieter eine geradezu magische Wirkung. Samsung nannte seine Plattform bada, was auf Koreanisch soviel wie Meer bedeutet. Jolla wandelt mit dem Qt-basierten Mer – das fehlende E ist kein Tippfehler – auf ähnlichen Spuren.

Sailfish OS ist ein quelloffenes, Unix-artiges Handybetriebssystem, das als mehr oder weniger direkter Nachfolger von MeeGo/Maemo anzusehen ist. Die Plattform wird seit mehr als einem Jahr auf Handys der Firma Jolla ausgeliefert, ein per Crowdfunding finanziertes Tablet wurde am Mobile World Congress am großzügigen Stand der Firma vorgeführt.

Auch wenn die Finnen bisher keine weiteren Lizenznehmer finden konnten, ist das System – anders als so manche Vaporware – real und in Stückzahlen verfügbar. Wer ein Sailfish-OS-Telefon haben möchte, kauft es; die bei Canonical notwendigen Kapriolen entfallen komplett.

Android-Entwickler können ihre Programme in einer hier nicht näher besprochenen Runtime ausführen, während Freunde des in Qt existierenden geistigen Eigentums mit minimalem Aufwand zu neuem Leben verhelfen.

Das SDK

Der Gutteil der Jolla-Dokumentation zeigt unter Ubuntu entstandene Screenshots. Wir wollen unsere ersten Schritte mit Ubuntu 14.04 bewerkstelligen. Vor der Installation des SDKs muss man die VirtualBox-Laufzeitumgebung herunterladen. Öffnen Sie dazu ein Terminal und geben Sie den Befehl sudo apt-get install virtualbox ein.

Öffnen Sie im nächsten Schritt in einem Browser Ihrer Wahl, und laden Sie die zu Ihrem Betriebssystem passende Version des Installationsassistenten herunter. Aufgrund der vergleichsweise gemächlichen Internetanbindung sollten Sie dafür einige Minuten Zeit vorsehen. Das eigentliche Deployment erfolgt dann durch folgendes Kommando:

chmod +x SailfishOSSDK-Beta-1502-Qt5-linux-64-offline.run 
./SailfishOSSDK-Beta-1502-Qt5-linux-64-offline.run 

Im Moment kann das SDK nur für einen User installiert werden: Wer die Setup-Routine mit sudo aufruft, wird mit einer höflichen Fehlermeldung auf dieses Defizit hingewiesen. Eine weitere Einschränkung betrifft den Aufenthaltsort von Projektdateien – sie müssen normalerweise im Home-Verzeichnis liegen; eine Änderung dieses Ordners ist während der Installation im in Abbildung 1 gezeigten Fenster möglich.

Abb. 1: Wahlfreiheit sieht anders aus

Abb. 1: Wahlfreiheit sieht anders aus

Nach dem Start präsentiert sich das Sailfish SDK wie ein normaler Qt-Creator, der um den Unterpunkt „Sailfish OS“ erweitert wurde. Der erste Unterschied zeigt sich beim Erstellen eines neuen Projekts – statt der von anderen Systemen bekannten Projektvorlagen bietet das SDK hier nur den Typ „SailfishOS Qt Quick Application“ an.

Im Rahmen der Projekterstellung dürfen Sie das zu verwendende Kit auswählen – wer sich auf die Arbeit mit virtuellen Maschinen beschränkt, entscheidet sich für das i486-Kit. Wenn Sie Ihre App in den Store oder auf ein echtes Gerät deployen möchten, so sollten Sie stattdessen beide Kits auswählen.

Als Projektname wurde „SUSSailfish1“ auserkoren: Dies ist – anders als bei Symbian und Co. – an späterer Stelle noch von Bedeutung. Die restlichen Einstellungen bleiben fürs Erste unverändert, was zum in Abbildung 2 gezeigten Projektskelett führt.

Abb. 2: Das Sailfish-OS-Projektskelett realisiert eine vergleichsweise komplexe Applikation

Abb. 2: Das Sailfish-OS-Projektskelett realisiert eine vergleichsweise komplexe Applikation

Sailfish, hop!

Aufgrund der vergleichsweise hohen Komplexität wollen wir uns das Projektskelett in Aktion ansehen, bevor wir seine Einzelteile analysieren. Jolla kompiliert Programme normalerweise in einer virtuellen Maschine, die im Rahmen des Kompilationsprozesses angeworfen wird. Der Emulator liegt in Form einer weiteren VM vor.

Qt Creator bietet bei geöffneten Sailfish-OS-Projekten auf der linken Unterseite zwei zusätzliche Buttons an, die das Anwerfen des nur bei X86 verfügbaren Emulators und der immer benötigten Build-VM erlauben. Die Farbe des über dem Symbols befindlichen Overlays gibt den Betriebszustand an: Grün bedeutet startbereit, grau bedeutet in Arbeit, rot entspricht betriebsbereit.

Stellen Sie Ihre Fragen zu diesen oder anderen Themen unseren entwickler.de-Lesern oder beantworten Sie Fragen der anderen Leser.

Starten Sie Emulator und Build-VM, und klicken Sie danach wie gewohnt auf den Play-Button. Ein umgekehrter Ronamatic Stroke sorgt dafür, dass die in Abbildung 3 gezeigte Startseite der Applikation das Dialogfenster zum Öffnen des zweiten Formulars anbietet.

Abb. 3: Eine Wischgeste von oben nach unten öffnet das Menü

Abb. 3: Eine Wischgeste von oben nach unten öffnet das Menü

Komische Initialisierung

Ein Blick auf die in Abbildung 2 gezeigte Projektstruktur genügt, um den Aufbau zu erkennen: Sailfish OS arbeitet auf Basis von QML. In SUSSailfish1.cpp findet sich folgender Code:

#include <sailfishapp.h>
int main(int argc, char *argv[])
{
  return SailfishApp::main(argc, argv);
}

Der hier aus Platzgründen nicht abgedruckte Kommentar weist darauf hin, dass das direkte Anwerfen einer SailfishApp-Klasse zum Laden der Datei /qml/template.qml führt. Leider findet sich diese in unserem Projekt nicht – die einzige als Einstiegspunkt geeignete Datei wäre /qml/SUSSailfish1.qml. Ihr Inhalt beweist uns, dass diese Annahme richtig ist (Listing 1).

import QtQuick 2.0
import Sailfish.Silica 1.0
import "pages"
ApplicationWindow
{
  initialPage: Component { FirstPage { } }
  cover: Qt.resolvedUrl("cover/CoverPage.qml")
}

Jollas Silica-Stack arbeitet mit als Page bezeichneten Unterobjekten. Eine Page entspricht – normalerweise – dem Inhalt eines Formulars, die in an initialPage übergebene Seite erscheint nach dem Laden des Programms am Bildschirm. cover nimmt eine Referenz auf ein Objekt entgegen, das für das Rendern der „Vorschau“ der App zuständig ist.

Des Rätsels Lösung findet sich in der für die Steuerung des Builds notwendigen .pro-Datei, wo der Name der zu generierenden Applikation über die Target-Eigensachaft festgelegt wird: TARGET = SUSSailfish1.

Achten Sie darauf, dass das Ändern des Projektnamens Modifikationen an diversen Projektdateien voraussetzt. Die in der .pro-Datei enthaltenen Kommentare dienen als erster Anhaltspunkt – mit einfachem Ändern der Target-Eigenschaft ist es unter Sailfish OS jedenfalls nicht getan.

CoverPage.qml kann seine Stärken nur dann ausspielen, wenn Sie Ihr Programm wie in Abbildung 4 „minimieren“. Das File ist für die Deklaration der Miniaturansicht von Applikationen wichtig – ein Thema, dem wir uns an späterer Stelle zuwenden wollen.

Abb. 4: Eine Wischgeste nach links versetzt Sailfish OS in den Taskmanager-Modus.

Abb. 4: Eine Wischgeste nach links versetzt Sailfish OS in den Taskmanager-Modus.

Der Inhalt der beiden Formulardateien ist für erfahrene QML-Entwickler nicht wirklich interessant. Die Files realisieren auf dem Page-Objekt basierende Formulare, denen auf mehr oder weniger aufwändige Art und Weise Inhalte eingeschrieben werden.

Ändere mich

QML bietet einen JavaScript-Interpreter an, für die Realisierung komplexerer Programmlogik sollten Sie jedoch schon aufgrund der rigideren Syntaxüberprüfung C++ bevorzugen. Leider ist unser Projektskelett dafür eher schlecht als recht geeignet: Die main()-Methode bietet keine Möglichkeit an, um Beziehungen zwischen Steuerelement und Backend-Logik herzustellen.

QML erlaubt das „Beleben“ von in C++ gehaltenen Objekten. Wir könnten eine aus QML instanziierbare Engine erstellen, die vom ApplicationWindow mitgestartet wird. Als alter Hase in Sachen Qt ist mir diese Vorgehensweise unsympathisch: QML-Dateien sind Widgets, die von der Programm-Engine angeworfen werden. Dazu muss main() gemäß des in Listing 2 gezeigten Schemas angepasst werden.

int main(int argc, char *argv[])
{
  QGuiApplication* myApplication=SailfishApp::application(argc, argv);
  QQuickView* myView=SailfishApp::createView();
  myView->setSource(SailfishApp::pathTo("qml/SUSSailfish1.qml"));
  myView->show();
  return myApplication->exec();
}

Die neue Version von main() ist im Grunde genommen nur eine manuelle Implementierung der in SailfishApp::main() enthaltenen Logik. Wir erstellen eine Instanz von QGuiApplication, der eine QQuickView samt dazugehörenden Inhalten eingeschrieben wird. Show() schiebt den Inhalt auf den Bildschirm, während exec() ganz wie in alten Tagen für das eigentliche Anwerfen der Anwendung verantwortlich ist.

QML orientiert sich bis zu einem gewissen Grad an HTML. Die am Bildschirm erscheinenden Steuerelemente sind in eine strenge, an den DOM-Baum erinnernde Hierarchie eingebunden. Daraus folgt, dass sich die bei der Arbeit mit HTML etablierten Parsing-Methoden auch unter Sailfish OS lohnen.

Als erstes Werkzeug wollen wir uns eine kleine Methode erstellen, die ein Wurzelobjekt nach dem ersten Vorkommnis eines Widgets mit einem bestimmten Namen durchsucht. Dies ist insofern hilfreich, als QML-Elemente benannt werden können: Das leidige Suchen der passenden Instanz wird so zu einer vergleichsweise schnell zu bewerkstelligenden Aufgabe (Listing 3).

QObject* recursiveFind(QObject *_item, QString _name)
{
  if(_item->objectName()==_name)
  {
    return _item;
  }
  QObject* myResult=NULL;
  QObjectList myList=_item->children();
  for(int i=0;i<myList.count();i++)
  {
    QObject* innerElement=myList[i];
    myResult=recursiveFind(innerElement, _name);
    if(myResult!=NULL) return myResult;
  }
  return myResult;
}

recursiveFind implementiert eine klassische rekursive Suche. Die Funktion stellt im ersten Schritt fest, ob das an sie übergebene Objekt rein zufällig schon das Gesuchte ist. Ist dies der Fall, so wandert es direkt in die Ausgabe. Ist dies nicht der Fall, so nimmt recursiveFind die Kinder des Steuerelements ins Visier. children() liefert eine Liste aller Kinder zurück; jedes von ihnen startet einen neuen Durchlauf von recursiveFind().

Das korrekte Funktionieren der Methode lässt sich durch Code nach folgendem Schema prüfen:

if(recursiveFind(myView->rootObject(), "ErsteSeite")!=NULL)
  qDebug("Seite gefunden");

Achten Sie darauf, dass QML-Objekte „zwei Namen“ haben. id dient dem Ansprechen aus QML-Code heraus, während objectName 1:1 in das im Hintergrund lebende QObject übertragen wird und dort über die objectName()-Methode abrufbar ist.

Zum Funktionieren des oben genannten Snippets müssen Sie FirstPage.qml nach folgendem Schema anpassen:

Page {
  id: page
  objectName:"ErsteSeite"
Abb. 5: recursiveFind hat die modifizierte Seite erfolgreich gefunden

Abb. 5: recursiveFind hat die modifizierte Seite erfolgreich gefunden

Die Widgets

Nach diesen einführenden Überlegungen ist es nun an der Zeit, Interaktion zwischen Engine und Benutzerinterface zu realisieren. Dazu müssen wir die Seite um einige Steuerelemente erweitern, um diese zur Generierung von Events einzuspannen.

Öffnen Sie die Datei FirstPage.qml, und ersetzen Sie das Column-Element durch den in Listing 4 gezeigten Codeblock:

Column {
  id: column
  spacing: Theme.paddingLarge
  PageHeader {
    title: qsTr("UI Template")
  }
  TextField {
    width: page.width
    placeholderText: "Dateneingabe erbeten!"
  }
  Row{
    width:parent.width
    Button{
    text: "1"
    width: parent.width/3
  }
  Button{
    text: "2"
    width: parent.width/3
  }
  Button{
    text: "3"
    width: parent.width/3
  }
}

Columns richten die in ihnen enthaltenen Elemente übereinander aus. Wir beginnen mit dem Einpflegen eines PageHeaders, der für die in den vorigen Abbildungen gezeigte Kopfzeile verantwortlich ist. Im nächsten Schritt folgt eine Textbox, zu guter Letzt ein Row-Steuerelement mit drei Buttons.

Die Entwickler von Silica haben sich bei der Arbeit an ihrem GUI-Stack Inspiration bei Research in Motion geholt: Veränderungen der Höhe eines Buttons führten während meiner Tests reproduzierbar zu chaotischen Darstellungsfehlern. Wir beschränken uns aus diesem Grund auf das abgedruckte Listing, das zu dem in Abbildung 6 gezeigten Formular führt.

Abb. 6: Unsere Steuerelemente sind am Platz

Abb. 6: Unsere Steuerelemente sind am Platz

QML-erfahrene Entwickler monieren an dieser Stelle mitunter die Verwendung der starren Positioner-Klasse Row. Dies liegt daran, dass Jolla das Modul mit den QML-Layouts bisher nicht portiert hat – es führt derzeit kein Weg daran vorbei, die Elementpositionen wie hier gezeigt von Hand zu berechnen.

QML, zur Zweiten

Wenn das hier nur schematisch angerissene Formular in einer realen Applikation zum Einsatz kommt, so sollten Sie die ewig gleichen Buttons in eine eigene Klasse auslagern. Dazu genügt es, eine .qml-Datei mit dem gewünschten Namen zu erstellen und das Markup dorthin zu verfrachten.

Die nächste Station unseres nur aus didaktischer Sicht interessanten Beispiels besteht darin, das Anklicken der Buttons mit einer Aktion zu verdrahten. Dazu müssen wir den onClicked-Handler gemäß folgendem Schema überschreiben:

Button {
  text: "1"
  width: parent.width/3
  onClicked: {
    myField.text=  myField.text + "1"
  }
}

Wir drucken hier aus Platzgründen nur die für den ersten Button notwendigen Änderungen ab. Die weiteren Buttons verhalten sich analog. Zwecks direkter Ansprechbarkeit muss das TextField noch eine ID erhalten:

TextField {
  id: myField
  width: page.width
  placeholderText: "Dateneingabe erbeten!"
}

QML-Hasser könnten die vom Button emittierten Ereignisse in Richtung des C++-Frameworks schicken, wo die Anpassung des Inhalts der Textbok erfolgt. Diese auch als QML-C++-Pingpong bezeichnete Vorgehensweise steigert die Koppelung des Projekts immens und führt zu Instabilitäten – was sich in JavaScript regeln lässt, sollte auch dort geregelt werden.

Die Engine soll erst nach erfolgreicher Eingabe über den im Textfeld befindlichen String informiert werden. Dazu sind zwei Modifikationen notwendig; das Elternelement bekommt eine Signaldeklaration eingeschrieben:

Page {
  id: page
  objectName:"ErsteSeite"
  signal textReady(string _t)
}

Im Senden-Knopf findet sich fortan eine Methode, die den Inhalt der Textbox einsammelt und per Signal in die Welt hinausschickt:

Button{
  text: "Fertig"
  width: parent.width
  onClicked:{page.textReady(myField.text);}
}

QML implementiert Signale als Funktionen, die zum Abfeuern aufgerufen werden müssen. Da unser Signal einen Parameter vom Typ String überträgt, wandert der aktuelle Inhalt des Textfelds per Signal zum Empfänger. Fehleranfälliges Herumfuhrwerken in der DOM-Struktur kann dadurch ersatzlos entfallen.

Auf Seite des C++-Codes ist ein Objekt erforderlich, das sich ins Signal-Slot-System einbindet. Dies lässt sich durch Ableitung von QObject bewerkstelligen – der Header von SUSEngine sieht so aus:

class SUSEngine : public QObject
{
  Q_OBJECT
  ...
public slots:
  void textReady(QString _what);
};

Unsere vergleichsweise einfache Implementierung beschränkt sich darauf, den im Rahmen des Signals angelieferten Wert in die Debuggerkonsole zu schreiben:

void SUSEngine::textReady(QString _what)
{
  qDebug() << _what;
}

main() ist für die Erstellung einer Klasseninstanz und für die Verdrahtung zwischen QML und C++ zuständig (Listing 5).

int main(int argc, char *argv[])
{
  ...
  QObject* emitter=recursiveFind(myView->rootObject(), "ErsteSeite");
  SUSEngine *myEngine=new SUSEngine();
  emitter->connect(emitter,SIGNAL(textReady(QString)),myEngine,SLOT(textReady(QString)));
  return myApplication->exec();
}

An dieser Stelle sei ein Hinweis zum inneren Aufbau des Signal-Slot-Systems erlaubt. SIGNAL und SLOT sind Makros, welche die an sie übergebenen Definitionen in Strings umwandeln. Die eigentliche Verbindung erfolgt während der Laufzeit durch Reflektion, eine Überprüfung der Gültigkeit erfolgt während der Kompilation nicht.

Damit ist unsere Reise durch die Welt der QML-C++-Interoperation für diesen Artikel beendet: Im Internet und in unserem Schwestermagazin „Windows Developer“ finden sich Tutorials, die einfache und komplexe Kommunikationsszenarien beschreiben.

Übersetze mich!

Lokalisierte Applikationen profitieren von besseren Platzierungen in Suchmaschinen – ein Gutteil der Welt spricht kein Englisch. Jolla dürfte als Nachfolgerunternehmen der für Lokalisierungswütigkeit bekannten Firma Nokia Entwicklern sehr positiv gegenüberstehen, die ihre Programme in möglichst vielen Sprachen anbieten.

Qt begegnet diesem Problem durch ein Übersetzungsframework. Wenn Sie Ihre Applikation auf Basis von Linguist aufbauen, so müssen Sie sich um die Mechanik keine Gedanken machen; das Framework tauscht Strings während der Programmausführung automatisch aus.

Zu übersetzende Strings müssen in eine spezielle Methode eingeschlossen werden. Im Fall von QObject-basiertem Code handelt es sich dabei um tr(), während QML-Nutzer qsTr verwenden:

TextField {
  id: myField
  width: page.width
  placeholderText: qsTr("Dateneingabe erbeten!")
}

Für die eigentliche Internationalisierung sind Sprachdatenbankdateien erforderlich. Sie lassen sich automatisch generieren. Führen Sie das lupdate-Werkzeug nach folgendem Schema aus, um alle in der Applikation befindlichen Strings zu extrahieren:

~/SUSSailfish1$ lupdate SUSSailfish1.pro 
Updating 'translations/SUSSailfish1-de.ts'... 
  Found 0 source text(s) (0 new and 0 already existing) 
  Kept 5 obsolete entries

Von QtGUI umsteigende Entwickler laufen an dieser Stelle in eine Falle: Wer das für die Aktualisierung der Sprachdatenbank zuständige lupdate-Werkzeug direkt auf die .pro-Datei ansetzt, bekommt nur jene Strings, die im C++-Teil des Programms enthalten sind.

Dieses Problem lässt sich durch Einführung einer zusätzlichen Passage der .pro-Datei beheben, in der die .qml-Dateien als Source-Elemente definiert sind. lupdate_only sorgt als Umgebungsvariable dafür, dass die für den Compiler ungenießbaren Quelldateien nur für lupdate sichtbar sind:

lupdate_only{
  SOURCES = qml/pages/FirstPage.qml
}

Neue Sprachen entstehen durch Einfügen einer weiteren Übersetzungsdeklaration in der .pro-Datei. Die nach dem Minus folgende Zeichenkette legt dabei die Zielsprache fest. Dieses Snippet generiert eine für Deutschland vorgesehene .ts-Datei: TRANSLATIONS += translations/SUSSailfish1-de.ts

Die generierten .ts-Dateien lassen sich mit einem als Linguist bezeichneten Werkzeug bearbeiten. Langjährige praktische Erfahrung zeigt, dass die meisten technischen Übersetzer mit dem auch unter Windows und Mac OS X lauffähigen Produkt nach kurzer Einschulung ohne Probleme zurechtkommen. Windows-Nutzer können das Programm sogar auf einen USB-Stick kopieren, um ihren Übersetzern die Installation des Qt-SDKs zu ersparen.

Nach dem Speichern der Files sorgt lrelease für die Generierung der zur Laufzeit erforderlichen Datenbanken. Vor der Auslieferung verlangt der Jolla-Launcher noch nach etwas Liebe. In der .desktop-Datei sollte die neue Sprache bei der Deklaration des App-Namens gemäß dem folgenden Schema etwas Aufmerksamkeit bekommen: Name[de]=SUSSailfish1

Tanz das Cover

Sailfish OS ist voll multitaskingfähig. Das unter Android häufige Eliminieren von Views ist in der Plattform nicht vorgesehen. Eine Wischgeste von links in die Bildschirmmitte öffnet eine als Home bezeichnete Ansicht, in der die gerade geöffneten Programme durch ihre Miniaturansichten abgebildet werden.

Die sind interaktiv; das Betriebssystem erlaubt das Einblenden von Buttons, die direkt aus der Home-Ansicht heraus aktivierbar sind. Das Projektskelett nutzt sie zur Realisierung eines Play- und eines Pause-Knopfes, die für Medienplayer hilfreich wären.

Die Miniaturansicht unseres Programms wurde weiter oben bereits vorgestellt. Sie entsteht durch das in der Datei CoverPage.qml befindliche Markup, das im Fall unseres Programms so aussieht wie in Listing 6 zu sehen.

CoverBackground {
  Label {
    id: label
    anchors.centerIn: parent
    text: qsTr("My Cover")
  }
  CoverActionList {
    id: coverAction
    CoverAction {
      iconSource: "image://theme/icon-cover-next"
    }
    CoverAction {
      iconSource: "image://theme/icon-cover-pause"
    }
  }
}

Das hier abgedruckte Snippet realisiert die „Maximalvariante“ des im Coversystem Möglichen. CoverBackground dient als Master-Klasse, die mit einem Label und einer CoverActionList versehen wird. In der CoverActionList finden sich zwei Buttons – die maximal erlaubte Anzahl.

Applikationen müssen ihren Nutzern nicht unbedingt Kontextoptionen anbieten. Im Fall von Spielen oder wissenschaftlichen Taschenrechnern wäre das kontraproduktiv.

CoverPlaceholder bietet in dieser Situation eine attraktive Alternative. Wer seinen CoverBackground mit einer parametrierten Instanz der Klasse ausstattet, hat seine Schuldigkeit getan:

CoverPlaceholder {
  text: "Add content"
  icon.source: "my-application.png"
}

An den Hafen

Jolla-Apps werden über einen als Harbor bezeichneten App Store vertrieben, der auf neue Inhalte wartet. Die Finnen versprechen seit der Auslieferung, bezahlte Applikationen „bald“ zu unterstützen – bisher hat sich das Feature noch nicht materialisiert. Als Paketmanager kommt dabei RPM zum Einsatz, der Paketgenerierungsprozess erinnert im Großen und Ganzen an den vom Desktop bekannten Vorgang.

Im Harbor vertriebene Pakete müssen einige besondere Dateien enthalten, die im FAQ aufgelistet sind. Beim Portieren von existierendem geistigen Eigentum müssen Sie mit zwei gravierenden Einschränkungen leben: QtWidgets und QtOpenGL sind nicht erlaubt. Darauf basierende Programme werden automatisch aus dem Store geworfen.

Nach dem Upload beginnt ein von Nokias Ovi Store inspirierter QA-Lauf, der einige Zeit in Anspruch nehmen kann. Neben einem automatisierten Check dürfte er auch manuelle Arbeitsschritte enthalten – es dürfte schwierig sein, QtGUI-basierte Programme durch Obfuscation der Bibliothek „durchzuschummeln“.

Die andere Hälfte

Der Tod des Visors und der legendären iPaq-3xxx-Serie beerdigte das Konzept des erweiterbaren Handcomputers: Zum Anschluss von externer Peripherie ist wertvoller Platz notwendig, der von Seiten der Hersteller lieber in dünnere Produkte investiert wird.

Jolla umgeht dieses Problem durch die kreative Nutzung der Geräterückwand. Sie ist mit einer Gruppe elektrischer Kontakte ausgestattet, die das Ansprechen von anzuschließender Peripherie erlauben. Dieses Konzept funktioniert auch in der Praxis – neben einer in diversen Videos gezeigten externen Tastatur bieten Partner der Finnen eine Rückwand mit LEDs an, die auf den Spuren der XPERIA-Smartphones wandelt.

Als Kommunikationsstandard kommt der aus der Halbleiterelektronik bekannte I2C-Bus zum Einsatz; Jolla arbeitet mit einer Taktrate von 400 kHZ und einer Signalspannung von 1.8V. Daraus ergibt sich eine vergleichsweise geringe Übertragungsgeschwindigkeit; die Realisierung eines Kamera-Backs ist über diese Schnittstelle mit Sicherheit nicht möglich.

Besonders innovativ ist, dass jedes „Cape“ mit einem NFC-Tag ausgestattet sein muss. Die auf ihm gespeicherten Informationen dienen dem Telefon zum Herunterladen der passenden Treiberapplikation – eine Art Plug and Play des einundzwanzigsten Jahrhunderts.

Der beim Herunterladen des SDKs abzunickende Lizenzvertrag verbietet die kommerzielle Nutzung der angebotenen Informationen. Wer eine Erweiterung für das Smartphone der Finnen entwickeln möchte, muss mit dem Business-Development-Team Kontakt aufnehmen. Über die genauen Lizenzbedingungen sind bisher keine Informationen nach Außen gedrungen.

Dokumentation auf Tauchstation

Nach einer im Jahr 2014 erfolgten Reorganisation von sailfishos.org gibt es keine öffentlich zugängliche Dokumentation für Silica mehr. Informationen zu den diversen Klassen finden Sie, indem Sie das Jolla SDK öffnen und den Hilfemodus aktivieren. Wechseln Sie danach in die Rubrik SailFish, die sich aufgrund der alphabetischen Anordnung auf der Unterseite der Liste befindet (Abb. 7).

Abb. 7: Das Alphabet ist nicht auf Seiten des Sailfish-Teams

Abb. 7: Das Alphabet ist nicht auf Seiten des Sailfish-Teams

Online bieten die Entwickler einige Hinweise zum Design des Betriebssystems an. Sie sind dann von Interesse, wenn Sie das Benutzerinterface Ihrer Applikation stark an das Aussehen des restlichen Betriebssystems anpassen wollen – für einen Testballon nicht unbedingt notwendig.

Die im vorigen Abschnitt erwähnten FAQ zum Store enthalten zudem einige wertvolle Hinweise auf die im Betriebssystem enthaltenen Bibliotheken. Die Finnen gehen im Bereich des Positionings einen Eigenweg: Statt QtLocation und QtPositioning kommt ein DBUS-API zum Einsatz.

Fazit

Jolla konnte der Versuchung nicht widerstehen, sein Betriebssystem mit einem eigenen GUI-Stack auszustatten. Für Besitzer von bestehendem geistigen Eigentum ergeben sich hierdurch Änderungen; wer den QWidgets nutzt, muss ein neues Benutzerinterface entwerfen.

Wer das nicht nur unter Sailfish OS verfügbare Qt in seinem Unternehmen einsetzt, sollte den Finnen auf jeden Fall eine Chance geben. Der ethnische Aufbau ihres Heimatmarktes sorgt dafür, dass „Nokia 2“ in dieser Region nie unter einen gewissen Mindest-Marktanteil fallen wird. Innovative Erweiterungen und der für Open-Source-Heads spürbare „Knuddel-Faktor“ des im Vergleich zu Samsung und Co. kleinen Unternehmens sorgen für weitere Fans.

Besitzer von Android- oder iOS-IP können Sailfish OS als Impuls für eine Portierung in Richtung von Qt nutzen. Das von Digia erstklassig verwaltete Framework deckt alle wichtigen Handyplattformen ab und steht mittlerweile sogar für Windows Phone zur Verfügung. Nutzer bekommen so vergleichsweise preiswert Zugang zu diversen Plattformen – viel versprechende Systeme lassen sich im Notfall nachträglich „nativisieren“.

Mobile Technology

Mobile TechnologyDieser Artikel ist im Mobile Technology erschienen. Mobile Technology ist der Wegbegleiter für alle, die sich professionell mit der Entwicklung für mobile Devices und den Möglichkeiten, die der Markt des Mobile Business und Marketing bereithält, beschäftigen.

Natürlich können Sie das Mobile Technology über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Mobile Technology ferner im Abonnement oder als Einzelheft erhältlich.

Aufmacherbild: Mermaid silhouette, beautiful young women von Shutterstock.com / Urheberrecht: Alex Pix

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -