Docs

Die Bibliothek

Bibliothek hinzufügen

Die Bibliothek zeichnet jeden Bezahlbildschirm für dich. Du fügst ihre Ordner, eine Berechtigung, eine kleine Konfigurationsdatei und eine Zeile Code hinzu.

Die Dateien

Lade die Bibliothek im Tab Installieren deiner App herunter. Sie entpackt sich in einen Ordner wearcheckout.

PfadWas es tut
lib/watch/app/Pay.mcApps: die Prüfung bei unserem Server, der aus der Serverantwort gezeichnete Kaufbildschirm, sein Zeitlimit und die Freischaltung mit Ton und Vibration.
lib/watch/glance/PayScope.mcactive(), unlocked() und trialLeft(), annotiert mit (:glance): für Apps ohne Hintergrunddienst.
lib/watch/glance-bg/PayScope.mcDasselbe, annotiert mit (:glance, :background): für Apps mit Hintergrunddienst. Nutze genau eine der beiden.
lib/watch/face/PayFace.mc, PayFaceScope.mcZifferblätter und Datenfelder: die Prüfung im Hintergrund, drawQr und der Einstellungslink. Siehe Zifferblätter und Datenfelder.
lib/watch/extras/PayExtras.mcNur wenn du Bewertungen und Antworten verkaufst oder eine Shopseite nutzt: die Bewertungsfrage, deine Antworten und der Bildschirm „Gekauft?“. Siehe Extras in deiner App. Uhren älter als Connect IQ 3.1 überspringen ihn.
lib/watch/export/PayExport.mcNur wenn du Export aufs Handy verkaufst: die Daten deiner App als Tabelle, auf der Uhr verschlüsselt, mit Link ans Handy des Käufers.
lib/watch/feeds/PayFeeds.mcNur wenn deine App Datenfeeds nutzt: Wetter, Sonne und Mond, Gebetszeiten, Gezeiten und mehr. Siehe Datenfeeds.
lib/watch/resources/strings/pay.xmlDie 4 Zeilen, die der Kaufbildschirm ohne Server zeigt, auf Englisch.
lib/watch/resources-<lang>/strings/pay.xmlDieselben 4 Zeilen in den 7 anderen Sprachen.

Zu deinem Projekt hinzufügen

Entpacke die Bibliothek neben dem Ordner deiner App:

IntervalTimer/
    manifest.xml
    monkey.jungle
    resources/
    source/
        PaywallConfig.mc
wearcheckout/
    lib/watch/...

Füge dann ihre Ordner zu deiner jungle-Datei hinzu:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance
base.resourcePath = resources;../wearcheckout/lib/watch/resources
  • Nur relative Pfade. Ein Leerzeichen in einem absoluten Pfad macht die jungle-Datei kaputt.
  • Oder kopiere die Dateien. In deine eigenen Ordner source und resources kopiert (und in jeden Ordner resources-<lang>), braucht die Bibliothek keine jungle-Zeile.
  • Keine Annotationen nötig. Ein Build für jede Uhr. Der Subscreen der Instinct wird zur Laufzeit gefunden.

Mit Hintergrunddienst

Hat deine App einen eigenen Hintergrunddienst, nutze glance-bg statt glance, annotiere PaywallConfig mit (:glance, :background) und füge die Berechtigung Background hinzu. Jeglicher (:background)-Code lässt den Compiler diese Berechtigung verlangen, deshalb gibt es zwei Versionen.

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance-bg

Netzwerk erlauben

Die Uhr fragt unseren Server über die Verbindung des Handys oder, bei Uhren mit WLAN, per WLAN. Füge die Berechtigung Communications hinzu:

manifest.xml
<iq:permissions>
    <iq:uses-permission id="Communications"/>
</iq:permissions>

PaywallConfig.mc

Lade sie im Tab Installieren deiner App herunter: Sie enthält die echte Adresse deiner App. Die Adresse ist öffentlich, kein Geheimnis.

source/PaywallConfig.mc
// PaywallConfig.mc: from your dashboard (Interval Timer). Public, not a secret.
import Toybox.Lang;

(:glance)
module PaywallConfig {
    const URL = "https://pay.example/api/K7Q2/c";   // your app's address
    const TRIAL_DAYS = 7;
}
  • URL: die Adresse deiner App. Jede Prüfung geht dorthin.
  • TRIAL_DAYS: weglassen für keine Testphase. Halte den Wert gleich wie die Testphase im Dashboard: Die Uhr zählt nie mehr Tage als TRIAL_DAYS.
  • Die Annotation passt zu dem PayScope.mc, das du nutzt: (:glance) oder (:glance, :background) mit glance-bg.

Die eine Zeile

Gib in getInitialView() deine Ansichten über die Bibliothek zurück:

source/YourApp.mc
return Paywall.gate([new MainView(), new MainDelegate()]);   // the whole app is paid for
return Paywall.start([new MainView(), new MainDelegate()]);  // or: only some features are
  • gate startet die Testphase, fragt den Server, wenn es Zeit ist, und zeigt im gesperrten Zustand den Kaufbildschirm statt deiner App. BACK verlässt die App. Nach dem Bezahlen öffnet BACK oder START deine eigenen Ansichten.
  • start öffnet deine App wie gewohnt, mit dem Kaufbildschirm einmal am Ende der Testphase. Jede bezahlte Funktion prüft dann zuerst:
source/HistoryDelegate.mc
if (Paywall.unlocked()) { showHistory(); } else { Paywall.open(); }

Bei beiden öffnet ein Kauf auf dem Handy bei geschlossenem Kaufbildschirm die Freischaltung von selbst, sobald die Uhr davon erfährt. Bezahlte Funktionen sperren listet jeden Aufruf.

Ein Premium-Eintrag in deinen Einstellungen

Der Eintrag „Premium“ in einem Einstellungsmenü öffnet den Kaufbildschirm. Ist schon einer offen, bekommst du diesen: Es gibt nie einen zweiten.

source/SettingsDelegate.mc
Paywall.open();

Daten löschen

Hat deine App eine Option „Daten löschen“, behalte die Schlüssel, die Paywall.keys() zurückgibt. Der Rest kommt beim nächsten Start vom Server zurück.

source/SettingsDelegate.mc
// Delete data: everything except the payment keys
var st = Application.Storage;
var keep = Paywall.keys();
var saved = [];
for (var i = 0; i < keep.size(); i++) {
    saved.add(st.getValue(keep[i]));
}
st.clearValues();
for (var j = 0; j < keep.size(); j++) {
    if (saved[j] != null) {
        st.setValue(keep[j], saved[j]);
    }
}

Extras in deiner App

Drei der bezahlten Extras brauchen einen eigenen Ordner, damit Apps ohne sie klein bleiben. Uhr-Statistiken brauchen keinen.

Bewertungen und Antworten, und „Gekauft?“

Füge den Ordner extras hinzu und schalte ihn dann vor der einen Zeile ein:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance;../wearcheckout/lib/watch/extras
source/YourApp.mc
PayExtras.on();
return Paywall.gate([new MainView(), new MainDelegate()]);
  • Die Bewertungsanfrage erscheint an Tag 3, 7 oder 14: die Sterne, dann ein QR-Code, der deine Store-Seite und eine Nachricht an dich öffnet.
  • Deine Antwort erscheint einmal über deiner App. Auf kleinen Uhren braucht eine lange Antwort zwei Bildschirme: START zeigt den Rest.
  • „Gekauft?“ zeigt einmal den Code einer neuen Uhr, wenn ihr Käufer zuerst auf deiner Shopseite bezahlt hat.
  • Ohne den Ordner bekommen die Uhren dieser App keine Abfrage, deine Antworten warten auf dem Server, und ein Käufer von der Shopseite scannt den normalen Kaufbildschirm. Uhren älter als Connect IQ 3.1 überspringen den Ordner ebenfalls.

Aufs Handy exportieren

Füge den Ordner export hinzu, biete den Export an, solange PayExport.ready() true ist, und starte ihn mit einer Methode, die jeweils eine Zeile zurückgibt:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance;../wearcheckout/lib/watch/export
source/ExportDelegate.mc
// Row 0 is the header; rows 1 to n are your data.
function row(i as Number) as Array {
    if (i == 0) { return ["Date", "Minutes"]; }
    var s = sessions[i - 1];
    return [s[:date], s[:minutes]];
}

if (PayExport.ready()) {
    PayExport.start(method(:row), sessions.size());
}
  • Werte können Text, Zahlen, true oder false oder null sein.
  • Den Rest macht die Bibliothek: Sie sendet die verschlüsselten Teile und dann den Link als Garmin Connect-Benachrichtigung an das Handy des Käufers. Der Käufer tippt darauf, und sein Handy öffnet die Tabelle. START sendet den Link erneut. Für den Link muss das Handy des Käufers mit der Uhr verbunden sein.
  • Formeln laufen nie. Text, der mit =, +, - oder @ beginnt, bekommt zuerst ein ' davor.

Datenfeeds

Füge den Ordner feeds hinzu und frag einen Feed dort ab, wo deine App ihn braucht. Deine Methode bekommt den HTTP-Code und die Antwort:

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/app;../wearcheckout/lib/watch/glance;../wearcheckout/lib/watch/feeds
source/MainView.mc
PayFeeds.get("weather", {
    "lat" => lat, "lon" => lon,
    "tz" => System.getClockTime().timeZoneOffset
}, method(:onWeather));

function onWeather(code as Number, data as Dictionary or Null) as Void {
    if (code == 200) {
        temp = data["now"]["temp"];
        WatchUi.requestUpdate();
    }
}
  • Die Feeds: Sonne, Mond, Gebetszeiten, Weltuhr, Wechselkurse, Wetter, Wetterwarnungen (USA), Erdbeben, Polarlichter, Gezeiten (USA) und Feiertage. Parameter und Felder jedes Feeds stehen auf der Seite Datenfeeds im Dashboard, wo du sie ausprobieren kannst.
  • Auf der Uhr gespeichert. Jede Antwort gilt für ihre ttl in Sekunden. Fragst du früher erneut, für denselben Feed und fast denselben Ort, kommt die gespeicherte Antwort sofort zurück, ohne Anfrage.
  • Orte sind in Grad. Zeiten kommen als Unix-Sekunden, Einheiten metrisch.
  • Zeig die Zeile der Quelle, wo die Karte des Feeds eine verlangt, zum Beispiel „Weather: MET Norway“.
  • Andere Codes liefern null: 403 heißt, Extras sind für diese App aus, 429 oder 503 heißt, später erneut versuchen, ein negativer Code kommt von Garmin (kein Handy, kein Netz). Testuhren haben jeden Feed kostenlos.
  • Kosten: 2 $ pro Million Anfragen von Live-Uhren, auf deiner Monatsrechnung. Eine auf der Uhr gespeicherte Antwort kostet nichts.

Uhr-Statistiken

Kein Code: Das Modell der Uhr kommt mit jeder Prüfung. Um auch die Versionen deiner App zu sehen, füge PaywallConfig eine Version hinzu:

source/PaywallConfig.mc
const VERSION = "1.3";

Sprachen

Die Bibliothek spricht Englisch, Deutsch, Französisch, Spanisch, Portugiesisch, Koreanisch und Chinesisch (vereinfacht und traditionell). Die Sprache der Uhr entscheidet. Jede andere Sprache bekommt Englisch.

  • Die Bildschirme kommen von unserem Server in der Sprache der Uhr, eine Textkorrektur braucht also kein App-Update.
  • Nur 4 Zeilen liegen auf der Uhr, für den Fall, dass der Server noch nicht geantwortet hat.
StringEnglischWann es erscheint
PwWaitWird geladen…Vor der ersten Antwort
PwPhoneOfflineKein Handy, Bluetooth oder Internet
PwBusySpäterDer Server hat nicht richtig geantwortet
PwBackBACK: schließenGanz ohne Antwort

Füge pro Sprache eine jungle-Zeile hinzu. Dein eigener Ordner steht zuerst; lass diesen Teil bei einer Sprache weg, für die deine App keinen Ordner hat.

monkey.jungle
base.lang.deu = resources-deu;../wearcheckout/lib/watch/resources-deu
base.lang.fre = resources-fre;../wearcheckout/lib/watch/resources-fre
base.lang.spa = resources-spa;../wearcheckout/lib/watch/resources-spa
base.lang.por = resources-por;../wearcheckout/lib/watch/resources-por
base.lang.kor = resources-kor;../wearcheckout/lib/watch/resources-kor
base.lang.zhs = resources-zhs;../wearcheckout/lib/watch/resources-zhs
base.lang.zht = resources-zht;../wearcheckout/lib/watch/resources-zht

Was du prüfen solltest

  • Der Namens-String deiner App. Ohne Antwort zeigt der Kaufbildschirm deinen String AppName. Behalte diesen String in deinen Ressourcen.
  • Timer. Der Kaufbildschirm nutzt einen Timer, PayExtras noch einen. Uhren erlauben nur wenige, und „Too Many Timers“ beendet die App: Nutzt deine schon zwei oder mehr, prüfe, dass du im Limit bleibst.
  • Gehaltene Tasten. Wer eine Taste zu lange hält, öffnet das Menü der Uhr. Der Kaufbildschirm reagiert nur auf kurzes Drücken.
  • Ältere Aufrufe funktionieren weiter. Paywall.startTrial(); Paywall.launch(); in getInitialView() und Paywall.showOver() in onShow() deines ersten Bildschirms tun, was gate und start in einer Zeile tun.
Esc