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.
base.sourcePath = source;../wearcheckout/lib/watch/face<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.
// 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
| Wo | Aufruf |
|---|---|
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:
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);
}
}
}Der Einstellungslink
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>
<!-- 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 Codesidebreit auf ein weißes Quadrat, zentriert beix,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 hat | Das Zifferblatt schaltet frei |
|---|---|
| Auf die Anmelde-Benachrichtigung getippt | Binnen Sekunden |
| Code gescannt oder Einstellungslink genutzt, in den 2 Tagen nach Installation oder Ende der Testphase | Binnen 10 Minuten |
| Dasselbe, später | Binnen einer Stunde |
| Nach dem Bezahlen die Einstellungen des Zifferblatts auf dem Handy gespeichert | Bei 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:
PaywallConfigist(:background), ebenso deine KlasseAppBase, wie im Beispiel: IhrgetServiceDelegate()läuft im Hintergrund.PayBgundPayFaceScope.mcsind bereits annotiert. - Apps mit Glance:
glance/PayScope.mcundPaywallConfigsind(:glance). Ein Glance darfPaywall.active(),Paywall.unlocked()undPaywall.trialLeft()aufrufen, sonst nichts. - Apps mit eigenem Hintergrunddienst:
glance-bg/PayScope.mc,PaywallConfigals(:glance, :background)und die Berechtigung Background. - Nur in der App: alles in
Pay.mc, auchPaywall.open()sowie der Kaufbildschirm und seine Strings. Ruf es nie aus einem Glance oder Hintergrundcode auf.