In aller Munde ist grade das feine Tool „Scriptable“. Mit diesem könnt Ihr eigene Scripte für iOS implementieren, ohne Euch groß mit Apple’s Programmiersprachen oder Infrastruktur auseinandersetzen zu müssen. Alles, was Ihr benötigt, sind JavaScript-Kenntnisse.
In diesem Tutorial zeige ich Euch, wie Ihr ein erstes Widget mit Scriptable implementieren könnt. Dabei gehe ich insbesondere darauf ein, wie Ihr das Script auf einem Windows PC oder Mac implementiert und dann mit wenig Aufwand direkt auf dem Smartphone testen könnt.
JavaScript-Kenntnisse setze ich voraus, es geht hier also nicht um das Erlernen von JavaScript, sondern mit bereits vorhandenen Kenntnissen möglichst schnell zu einem ersten Ergebnis zu kommen.
Die Beispielapplikation – Instagram Followers
Da es schon unzählige Beispiele für Kalender, Wetter und Uhrzeit im Netz zu finden gibt, habe ich mir etwas (hoffentlich) neues ausgedacht. Ziel ist ein Widget, welches zu einem beliebigen Instagram-Account anzeigt, wieviele Follower aktuell dem Account folgen.
Den fertigen Progammcode, den Ihr wie unten dann beschrieben einfach ausprobieren könnt, findet Ihr hier:
https://github.com/bestmacfly/Sriptable-Instagram-Follower-Widget
So wird am Ende das fertige Ergebnis aussehen:
Erste Schritte
Zunächst ladet Ihr Scriptable aus dem App Store herunter. Nach dem Start der App werden Euch bereits einige Beispielscripte präsentiert, aber wir wollen hier direkt mit der Implementierung unseres eigenen Widgets beginnen. Daher legt direkt über das +-Symbol ein neues Script an:
Ihr landet direkt im Fenster für den Quellcode des neuen Scripts. Dieses ignorieren wir erst einmal, wer möchte denn schon mit der Smartphonetastatur Programmcode implementieren?
Interessant ist an dieser Stelle aber der Bereich ganz links unten:
Hier könnt Ihr die Einstellungen zum Script anpassen, zu diesem Zeitpunkt interessiert uns insbesondere der Name des Scripts, dies könnte beispielsweise so aussehen, passt dies einfach nach Belieben an:
Bearbeiten des Scripts über einen PC
Die eigentliche Entwicklungsarbeit leistet Ihr am Besten über einen PC mit entsprechender Entwicklungsumgebung. In meinem Fall Windows sowie VSCode, Windows und VSCode könnt Ihr natürlich beliebig gegen Eure Vorlieben austauschen. Der hier beschriebene Weg sollte unabhängig von Betriebssystem und IDE funktionieren.
Die spannende Frage nun: Wie bekommen wir das oben angelegte Script auf den PC, und wie können wir das oben angelegte Script auch wieder zurück auf das Smartphone transferieren?
Per Default legt Scriptable einen Ordner in Eurer iCloud ab und speichert dort alle Scripte. Auf Eure iCloud könnt Ihr praktischerweise auch von Eurem PC aus zugreifen, hierzu müsst Ihr lediglich die entsprechenden Tools von Apple auf dem PC installieren. Unter Windows findet Ihr diese beispielsweise im Microsoft Store.
Nach der Installation findet Ihr im Explorer einen neuen Ordner iCloud Drive und hier tatsächlich den Unterordner Scriptable. Dieser enthält nun auch das Script, welches wir vorhin über Scriptable angelegt haben:
Ihr könnt nun das Script mit der Entwicklungsumgebung Eurer Wahl bearbeiten und verändern, beim Speichern wird das Script automatisch über die iCloud zurück zum Smartphone übertragen.
Im Internet kursieren verschiedene Meinungen zu iDrive – die Synchronisation würde nicht immer sauber funktionieren. Sollte iDrive bei Euch Schwierigkeiten machen, könnt Ihr auch jederzeit auf eine Alternative wie z.B. Google Drive oder Dropbox ausweichen. In den allgemeinen App-Einstellungen von Scriptable findet Ihr nämlich über die Option File Bookmarks die Möglichkeit, weitere Ordner zu Scriptable hinzuzufügen:
Hier könnt Ihr eine Datei eines anderen Dienstes (oder auch einen ganzen Ordner) ganz einfach zu Scriptable hinzufügen. So kommt Ihr dann auch komplett ohne iDrive aus.
Implementierung des Widgets – Verwendete API’s
Bei der Implementierung des Widgets könnt Ihr ganz normales JavaScript verwenden. Als Scriptumgebung steht Euch JavaScriptCore zur Verfügung. Hierbei handelt es sich um Apple’s JavaScript-Umgebung, welche derzeit auf ECMAscript 6 basiert und zusätzlich eine Apple-spezifische API mitbringt (welche an dieser Stelle allerdings für uns uninteressant ist).
Spannend für die Implementierung des Widgets ist da vielmehr die Scritable-eigene API, welche Ihr hier abrufen könnt: https://docs.scriptable.app/
Für dieses Beispiel sind folgende Scriptable-Klassen interessant:
- Request: Klasse zum Absetzen von http-Requests. Wird im Widget genutzt, um die Profilseite des Instagram-Benutzers abzurufen.
- Font: Zugriff auf die zur Verfügung stehenden iOS-Fonts
- Color: Zugriff auf Farben.
- Image: Bereitstellen von Bilddaten. Im Widget wird hierüber das Profilbild (Avatar) des Instagramnutzers gehalten.
- ListWidget: Die Klasse, die die Daten des eigentlichen Widgets hält. Im Prinzip handelt es sich hierbei um die Leinwand, die Ihr nur noch bemalen müsst.
- WidgetImage: Image-Klasse für Bilder in Widgets, über welche das Bild manipuliert werden kann (Beispielsweise die Darstellungsgröße).
- WidgetText: Text-Klasse für auf Widgets dargestellten Text, um die Textdarstellung zu beeinflussen.
- Script: Allgemeine Scriptingklasse. Über diese übergebt Ihr am Ende Euer Widget an Scriptable.
Weiterhin wichtig: Jedes Script kann einen Eingabeparamter erhalten. In unserem Fall nutzen wir den Eingabeparamter, um den Accountnamen von Instagram abzufragen. Leider ist derzeit nur ein Eingabeparameter möglich, welcher auch nicht weiter benannt werden kann, was das ganze für den Endanwender etwas sperrig gestaltet.
Auszüge aus dem Code
Wie oben beschrieben, findet Ihr hier den vollständigen und funktionsfähigen Code:
https://github.com/bestmacfly/Sriptable-Instagram-Follower-Widget
Auf die scriptablespezifischen Stellen möchte ich hier etwas detaillierter eingehen. Über das immer bereitstehende Objekt args habt Ihr Zugriff auf den Eingangsparameter:
let account = args.widgetParameter;
if (!account)
account = "YOUR DEFAULT ACCOUNT"
In unserem Fall wird hier der Instagram Accountname erwartet. Achtung: Es sollte abgesichert werden, dass der Parameter ggf. einmal nicht vorhanden ist, daher in obigem Beispiel die Hinterlegung eines Defaultaccounts, welches Ihr beim Ausprobieren entsprechend anpassen müsst.
Über die Request-Klasse wird dann die Profilseite abgerufen und über die Methode loadString der HTML-Quelltext des Profils geliefert:
let req = new Request(url);
let html = await req.loadString();
Das extrahieren der Followerzahl aus dem HTML ist dann klassisches JavaScript. Interessant ist dann noch das Auslesen des Profilbildes. Ist die URL zum Profilbild einmal aus dem HTML ermittelt, wird das Bild wie oben über das Requestobjekt geladen, diesmal unter Verwendung der Methode loadImage:
let req = new Request(url)
let image = await req.loadImage()
Als Rückgabewert erhaltet Ihr ein Objekt vom Typ Image, welches Ihr dann direkt im Widget weiterverwenden und zur Anzeige bringen könnt.
Nun sind alle notwendigen Informationen gesammelt (Followerzahl und Avatar), diese müssen wir nun in ein Widget verpacken. Hierzu dient das Widgetobjekt, hier ein längerer Codeauszug:
let widget = new ListWidget();
widget.backgroundColor = Color.black();
if (avatar) {
const wimg = widget.addImage(avatar)
wimg.centerAlignImage();
wimg.imageSize = new Size(60, 60)
}
widget.addSpacer()
let wFollowers = widget.addText(followers);
wFollowers.font = Font.mediumRoundedSystemFont(detailFontSize)
wFollowers.textColor = detailColor;
wFollowers.centerAlignText();
Zunächst kann die Optik des Widgets über verschiedene Attribute angepasst werden, in unserem Fall wird der Hintergrund auf schwarz gesetzt. Es wird dabei nicht auf einen HEX-Code für die Farbe zurückgegriffen, sondern wir bedienen uns der Klasse Color, welche für alle Farboperationen verwendet wird.
Über die Methode addImage kann der zuvor geladene Avatar dem Widget hinzugefügt werden. Wichtig: .addImage gibt Euch ein Objekt vom Typ WidgetImage zurück, über welches Ihr dann die Optik des Bildes beeinflussen könnt (im Beispiel wird die Größe reduziert und das Bild zentriert dargestellt). Die Anpassung der Optik erfolgt also erst, nachdem das Bild zum Widget hinzugefügt wurde.
Dies gilt analog für zu formatierenden Text. Die Anzahl der Follower wird erst dem Widget hinzugefügt. Das zurückgegebene Objekt vom Typ WidgetText wird dann verwendet, um die Darstellung zu beeinflussen (Schriftart, Größe etc.).
Zum Abschluss muss das Widget noch an Scriptable zurückgegeben und zur Anzeige gebracht werden. Weiterhin muss die Beendigung des Scripts kommuniziert werden:
Script.setWidget(widget);
widget.presentSmall();
Script.complete();
Interessant ist hier presentSmall: iOS sieht drei verschiedene Größen von Widgets vor, dieses Beispiel basiert auf der kleinsten Variante. Theoretisch könnt Ihr Euer Script abhängig von der gewünschten Größe auch dynamisch in small / medium oder large mit unterschiedlichen Informationen darstellen lassen. Die vom Anwender geforderte Widgetgröße ist über config.widgetFamiliy jederzeit abfragbar.
Testen und Debugging
Nach jedem Speichern steht Euch das Script direkt innerhalb von Scriptable zur Verfügung. Durch Anklicken des Scripts wird dieses ausgeführt und das Widget zur Anzeige gebracht.
Leider steht seitens Scriptable kein Debugger zur Verfügung. In der Entwicklungsumgebung auf dem PC wiederum kann auch kein Debugging erfolgen, da die Scripte hier nicht lauffähig sind. Daher bleibt im Fehlerfalle nur die klassische Konsolenausgabe, mittels console.log können Logausgaben erzeugt werden. Führt Ihr Euer Script direkt über Scriptable aus, könnt Ihr die Konsolenausgaben dann einsehen:
Durch drücken der 3 in obigem Beispiel habt Ihr dann Zugriff auf die konkreten Logausgaben.
Last but not least: Einrichten des Widgets auf dem Homescreen
Seit Ihr mit der Ausgabe des Scripts soweit zufrieden, müsst Ihr nur noch das Widget Eurem Homescreen hinzufügen. Fügt daher auf Eurem Homescreen an der passenden Stelle ein neues Widget hinzu und wählt Scriptable aus:
Wählt dann die kleine Variante des Widgets und schließt das Hinzufügen ab. Auf dem Homescreen taucht nun zunächst folgendes auf:
Solange das Widget noch „wackelt“, drückt Ihr einmal auf das Widget, Ihr gelangt dann in einen Konfigurationsdialog. In diesem wählt Ihr Euer Script aus und definiert nun auch den Scriptparameter mit Eurem Accountnamen.
Damit habt Ihr die Einrichtung abgeschlossen und das Widget sollte nun auf Eurem Homescreen seine Arbeit verrichten. Ihr könnt übrigens nicht steuern, wann sich der Inhalt des Scripts aktualisiert. Üblicherweise geschieht dies ca. alle 5 Minuten. Befindet sich Euer Smartphone jedoch im Stromsparmodus, fährt iOS die Ausführungshäufigkeit entsprechend herunter.
Zum Abschluss
Sollte Euch mein kleines Scriptable Tutorial gefallen haben, würde ich mich über einen kleinen Einwurf in die Kaffeekasse freuen:
https://www.paypal.com/paypalme/markmescher/2,99
Wie groß der Kaffee werden soll, dürft Ihr natürlich frei entscheiden 🙂
Das Widget soll hier nur als erstes Beispiel dienen. Ihr habt viele weitere Möglichkeiten, mit Scriptable tolle Ideen umzusetzen. Beispielsweise lassen sich durch die mögliche Siri-Integration Automatisierungsscripte implementieren, spielt einfach ein wenig herum. Tolle Anregungen lassen sich hier finden:
Auf dieser Seite findet Ihr unzählige Beispielscripte, die Ihr direkt nutzen und als Anregung verwenden könnt.
Für Fragen aller Art bietet sich folgende Seite an:
Es lassen sich auch hier hunderte Beispiele finden, die nur darauf warten, ausprobiert zu werden. Auch wird Euch hier gerne bei Problemen weitergeholfen.
Solltet Ihr Anregungen zu diesem Tutorial haben, freue ich mich über Eure Kommentare!
Danke für das Tutorial, es war sehr hilfreich.
Danke für deine ausführliche Anleitung. Besonders die Kurzbeschreibung der relevanten Klassen aus der Scriptable API
als Übertragungsmedium würde ich git und WorkingCopy empfehlen.
Hallo Andreas, WorkingCopy kannte ich noch nicht, danke für den Tipp. Werde ich mal ausprobieren!
Git und WorkingCopy klingen gut, allerdings habe ich schon aus dem Artikel nicht verstanden, wie ich Skripte von außen nach Scriptable bekomme (alohe ohne iCloud, da ich auf Linux entwickle). Soweit ich das Bookmark Feature verstehe, macht es Dateien innerhalb von Skripten verfügbar, aber nicht Skripte an sich. Übersehe ich hier etwas?
Hallo Mario,
das Bookmark Feature ist genau, was Du suchst. Hiermit kannst Du ein Verzeichnis definieren, welches von Scriptable dann wie das eigene Scriptverzeichnis verwendet wird. Hier könntest Du z.B. ein Nextcloud-Verzeichnis angeben und dort dann über Linux Deine Scripte ablegen, in Scriptable stehen diese dann umgehend zur Verfügung.
Pingback: Scriptable Tutorial Part 2 – Files – unleserlich.info
Pingback: Scriptable Tutorial Teil 5 – Tabellen – unleserlich.info