Docs

Die Bibliothek

Zifferblätter und Datenfelder

Ein Zifferblatt kann keine Tastendrücke annehmen und im Vordergrund nicht aufs Netzwerk zugreifen. Deshalb fragt die Bibliothek unseren Server im Hintergrund, dein Zifferblatt zeichnet den QR-Code, wo du willst, und Garmins Anmelde-Benachrichtigung lässt Käufer ohne Scannen zahlen. Datenfelder funktionieren genauso.

So funktioniert's

  • Der Hintergrund fragt. Der Hintergrunddienst des Zifferblatts schickt unserem Server dieselbe Anfrage wie eine App, zu der Zeit, die der Server vorgegeben hat.
  • Die Uhrzeit bleibt sichtbar. Bei einem Zifferblatt ist die Uhrzeit eine Hauptfunktion, und Garmin rät von einer Bezahlschranke darüber ab. Im gesperrten Zustand zeichnet dein Zifferblatt den QR-Code, wo du willst. Ein Datenfeld zeichnet ihn in seinem eigenen Bereich.
  • Der Link steht in den Einstellungen. Das Zifferblatt schreibt seinen Kauflink auch in seine Einstellungen, die die Connect IQ-App auf dem Handy zeigt. Ein Käufer kann ihn dort ohne Scannen öffnen.
  • Die Benachrichtigung erspart den Scan. Sobald das Zifferblatt gesperrt und das Handy verbunden ist, sendet es Garmins Anmelde-Benachrichtigung. Der Käufer tippt darauf, zahlt, und das Zifferblatt schaltet sich binnen Sekunden frei.

Zu einem Zifferblatt oder Datenfeld hinzufügen

Zifferblätter und Datenfelder nutzen nur lib/watch/face: PayFace.mc und PayFaceScope.mc.

monkey.jungle
base.sourcePath = source;../wearcheckout/lib/watch/face
manifest.xml
<iq:permissions>
    <iq:uses-permission id="Background"/>
    <iq:uses-permission id="Communications"/>
</iq:permissions>

Die Konfiguration ist mit (:background) annotiert, weil der Hintergrund sie liest. Behalte TRIAL_DAYS darin und setze es auf 0 für keine Testphase: Der Teil des Zifferblatts liest es direkt.

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

(:background)
module PaywallConfig {
    const URL = "https://pay.example/api/K7Q2/c";   // your app's address
    const TRIAL_DAYS = 7;
}

Die Hooks

WoAufruf
getInitialView()Paywall.startTrial(); Paywall.schedule(false); bei jedem Start
getServiceDelegate()return [new PayBg()];
onBackgroundData(data)Paywall.take(data);
onSettingsChanged()Paywall.soon();
onUpdate(dc)if (!Paywall.unlocked()) { Paywall.drawQr(dc, x, y, side); }

Ein ganzes Zifferblatt, im gesperrten Zustand mit der Uhrzeit oben und dem Code darunter:

source/PayFaceApp.mc
import Toybox.Application;
import Toybox.Background;
import Toybox.Graphics;
import Toybox.Lang;
import Toybox.System;
import Toybox.Time;
import Toybox.WatchUi;

// A small face for measuring: the time, and the QR code under it while locked.
(:background)
class PayFaceApp extends Application.AppBase {
    function initialize() {
        AppBase.initialize();
    }

    function onStart(state as Dictionary or Null) as Void {
    }

    function getInitialView() {
        Paywall.startTrial();
        Paywall.schedule(false);
        return [new PayFaceView()];
    }

    function getServiceDelegate() {
        return [new PayBg()];
    }

    function onBackgroundData(data) as Void {
        Paywall.take(data);
    }

    // Saving the face's settings on the phone (the buy page suggests it after paying): ask now
    // (5 minutes after the last check at the soonest, Garmin's rule).
    function onSettingsChanged() as Void {
        Paywall.soon();
    }
}

class PayFaceView extends WatchUi.WatchFace {
    function initialize() {
        WatchFace.initialize();
    }

    function onUpdate(dc as Graphics.Dc) as Void {
        var w = dc.getWidth();
        var h = dc.getHeight();
        var t = System.getClockTime();
        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
        dc.clear();
        dc.drawText(w / 2, h * 30 / 100, Graphics.FONT_NUMBER_MEDIUM, t.hour.format("%02d") + ":" + t.min.format("%02d"),
            Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER);
        if (!Paywall.unlocked()) {
            Paywall.drawQr(dc, w / 2, h * 68 / 100, w * 36 / 100);
        }
    }
}

Füge eine schreibgeschützte Eigenschaft unlock hinzu. Das Zifferblatt füllt sie mit dem Kauflink aus der Antwort des Servers. Definiere den String UnlockTitle in deinen eigenen Ressourcen.

resources/settings/settings.xml
<resources>
    <!-- The buy link, written by the face from the server's answer: the phone's Connect IQ app
         shows it in this face's settings, so a buyer can open it without scanning. -->
    <properties>
        <property id="unlock" type="string"></property>
    </properties>
    <settings>
        <setting propertyKey="@Properties.unlock" title="@Strings.UnlockTitle">
            <settingConfig type="alphaNumeric" readonly="true"/>
        </setting>
    </settings>
</resources>

Den Code zeichnen

  • Paywall.drawQr(dc, x, y, side) zeichnet den Code side breit auf ein weißes Quadrat, zentriert bei x, y. Vor der ersten Antwort zeichnet es nichts.
  • Ruf es nur auf, solange !Paywall.unlocked().
  • Zeichne ihn nur bei voll eingeschaltetem Display, nie im Always-on-Modus einer AMOLED-Uhr.

Garmins Anmelde-Benachrichtigung

  • Wann sie gesendet wird: einmal, wenn eine Prüfung das Zifferblatt zum ersten Mal gesperrt findet (Testphase vorbei oder keine Testphase). Erneut jedes Mal, wenn der Käufer die Einstellungen des gesperrten Zifferblatts speichert. Nur bei verbundenem Handy: Sie braucht das Handy selbst, nicht WLAN.
  • Was der Käufer sieht: Garmins eigene Benachrichtigung auf dem Handy. Garmin schreibt den Text („<app> needs you to sign in“), und keine App kann ihn ändern. Ein Tippen darauf öffnet deine Bezahlseite im eigenen Browser von Garmin Connect.
  • Nach dem Bezahlen: Die Seite endet, das Handy gibt das Ergebnis an die Uhr weiter und der Hintergrunddienst des Zifferblatts fragt unseren Server. Das Ergebnis allein schaltet nichts frei, denn jeder könnte seine Adresse eintippen. Nur die Antwort unseres Servers schaltet frei.
  • Nie versehentlich doppelt gesendet: Der Hintergrund markiert sie selbst als gesendet (CIQ 3.2 und neuer), auch wenn das Zifferblatt nicht bald danach läuft. Auf einer Uhr, die sie nicht senden kann, funktionieren QR-Code und Einstellungslink trotzdem.

Apps senden sie nicht. Der Kaufbildschirm einer App schaltet schon etwa eine Sekunde nach dem Bezahlen frei.

Wie lange eine Freischaltung dauert

Unser Server kann eine Uhr nicht erreichen. Ein Zifferblatt erfährt erst bei seiner nächsten Prüfung von einer Zahlung, und Garmin erlaubt eine Prüfung im Hintergrund höchstens alle 5 Minuten.

Wie der Käufer bezahlt hatDas Zifferblatt schaltet frei
Auf die Anmelde-Benachrichtigung getipptBinnen Sekunden
Code gescannt oder Einstellungslink genutzt, in den 2 Tagen nach Installation oder Ende der TestphaseBinnen 10 Minuten
Dasselbe, späterBinnen einer Stunde
Nach dem Bezahlen die Einstellungen des Zifferblatts auf dem Handy gespeichertBei einer Prüfung, sobald Garmin es erlaubt: frühestens 5 Minuten nach der letzten
  • Hat eine Prüfung gesehen, dass die Bezahlseite geöffnet wurde, prüft das Zifferblatt eine halbe Stunde lang alle 5 Minuten.
  • Während der Testphase prüft das Zifferblatt an ihrem Ende, oder täglich, wenn das früher ist.
  • Nach einer fehlgeschlagenen Prüfung (kein Handy) folgt die nächste eine Stunde später.

Annotationen und Scope

Glance- und Hintergrundcode erreichen nur Code, der für sie annotiert ist. Lass die Annotationen der Bibliothek, wie sie sind, und pass deine eigenen an.

  • Zifferblätter und Datenfelder: PaywallConfig ist (:background), ebenso deine Klasse AppBase, wie im Beispiel: Ihr getServiceDelegate() läuft im Hintergrund. PayBg und PayFaceScope.mc sind bereits annotiert.
  • Apps mit Glance: glance/PayScope.mc und PaywallConfig sind (:glance). Ein Glance darf Paywall.active(), Paywall.unlocked() und Paywall.trialLeft() aufrufen, sonst nichts.
  • Apps mit eigenem Hintergrunddienst: glance-bg/PayScope.mc, PaywallConfig als (:glance, :background) und die Berechtigung Background.
  • Nur in der App: alles in Pay.mc, auch Paywall.open() sowie der Kaufbildschirm und seine Strings. Ruf es nie aus einem Glance oder Hintergrundcode auf.
Esc