Statische Karten

Mithilfe einfacher REST APIs können Sie statische Karten einfügen, aktualisieren, lesen und löschen. Außerdem können Sie einer statischen Karte Objekte wie einen Ort oder Medien anhängen.

Funktionsweise

Statische Karten werden standardmäßig rechts neben der Uhr angezeigt und enthalten Informationen, die für den Nutzer zum Zeitpunkt der Zustellung relevant sind. Sie erfordern jedoch nicht wie Livekarten sofortige Aufmerksamkeit und Nutzer können die Karte in Ruhe lesen oder die darin enthaltenen Informationen nutzen.

Wenn Glassware statische Karten in die Zeitachse einfügt, kann Glass einen Benachrichtigungston abspielen, um Nutzer zu informieren. Alle vorherigen statischen Karten werden ebenfalls nach rechts verschoben und verschwinden nach 7 Tagen oder wenn 200 Karten neuer sind.

Verwendung

Mithilfe von statischen Karten können Sie Nutzern regelmäßige Benachrichtigungen senden, wenn etwas Wichtiges passiert. Beispiel: Ein Nachrichtendienst, der die wichtigsten Nachrichten in Echtzeit sendet. Über das Menüelement OPEN_URI können Sie auch Livekarten oder Immersionen über statische Mirror API-Karten starten. So können Sie hybride Interaktionen erstellen, bei denen statische Karten als Benachrichtigungen und eine Livekarte oder ein immersiver Modus für eine interaktivere Nutzung verwendet werden.

Eine vollständige Liste der möglichen Vorgänge für Zeitachsenelemente finden Sie in der Referenzdokumentation.

Statische Karten einfügen

Wenn du statische Karten (Zeitachsenelemente) einfügen möchtest, POSTE eine JSON-Darstellung eines Zeitachsenelements an den REST-Endpunkt.

Die meisten Felder in einem Zeitachsenelement sind optional. In seiner einfachsten Form enthält ein Zeitachsenelement nur eine kurze Textnachricht, wie in diesem Beispiel:

Roh-HTTP

POST /mirror/v1/timeline HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}
Content-Type: application/json
Content-Length: 26

{ "text": "Hello world" }

Java

TimelineItem timelineItem = new TimelineItem();
timelineItem.setText("Hello world");
service.timeline().insert(timelineItem).execute();

Python

timeline_item = {'text': 'Hello world'}
service.timeline().insert(body=timeline_item).execute()

Bei Erfolg erhalten Sie einen 201 Created-Antwortcode mit einer vollständigen Kopie des erstellten Elements. Für das vorherige Beispiel könnte eine erfolgreiche Antwort so aussehen:

Roh-HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
 "kind": "glass#timelineItem",
 "id": "1234567890",
 "selfLink": "https://www.googleapis.com/mirror/v1/timeline/1234567890",
 "created": "2012-09-25T23:28:43.192Z",
 "updated": "2012-09-25T23:28:43.192Z",
 "etag": "\"G5BI0RWvj-0jWdBrdWrPZV7xPKw/t25selcGS3uDEVT6FB09hAG-QQ\"",
 "text": "Hello world"
}

Das eingefügte Element, das in der Zeitachse des Nutzers angezeigt wird, sieht so aus:

Zeitachsenelement mit Anhang einfügen

Ein Bild sagt mehr als tausend Worte – und das ist viel mehr, als in ein Zeitachsenelement passt. Dazu können Sie einem Zeitachsenelement auch Bilder und Videos anhängen. Hier ein Beispiel für das Einfügen eines Zeitachsenelements mit einem angehängten Foto:

Roh-HTTP

POST /upload/mirror/v1/timeline HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}
Content-Type: multipart/related; boundary="mymultipartboundary"
Content-Length: {length}

--mymultipartboundary
Content-Type: application/json; charset=UTF-8

{ "text": "A solar eclipse of Saturn. Earth is also in this photo. Can you find it?" }
--mymultipartboundary
Content-Type: image/jpeg
Content-Transfer-Encoding: binary

[binary image data]
--mymultipartboundary--

Java

TimelineItem timelineItem = new TimelineItem();
timelineItem.setText("Hello world");
InputStreamContent mediaContent = new InputStreamContent(contentType, attachment);
service.timeline().insert(timelineItem, mediaContent).execute();

Python

timeline_item = {'text': 'Hello world'}
media_body = MediaIoBaseUpload(
    io.BytesIO(attachment), mimetype=content_type, resumable=True)
service.timeline().insert(body=timeline_item, media_body=media_body).execute()

Ein Zeitachsenelement mit angehängtem Bild sieht auf Google Glass in etwa so aus:

Video anhängen

Wenn du Videodateien an deine Zeitachsenelemente anfügst, empfehlen wir, das Video zu streamen, anstatt die gesamte Nutzlast auf einmal hochzuladen. Die Google Mirror API unterstützt Streaming mit HTTP Live Streaming, progressivem Download und dem Realtime Streaming Protocol (RTSP). RTSP wird häufig von Firewalls blockiert. Verwenden Sie daher nach Möglichkeit die anderen Optionen.

Wenn Sie ein Video streamen möchten, verwenden Sie den integrierten Menüpunkt PLAY_VIDEO und geben Sie die URL des Videos als payload des Menüpunkts an. Weitere Informationen finden Sie unter Vordefinierte Menüpunkte hinzufügen und Unterstützte Medienformate.

Paginierung

Sie können Zeitachsenelemente, die nicht auf eine einzelne Zeitachsenkarte passen, aber ansonsten mit derselben Karte verknüpft werden sollten, auf mehrere Seiten aufteilen. Alle Seiten mit Paginierung haben dieselbe timeline.id und daher dieselben Menüpunkte. Wenn ein Nutzer auf ein paginarisiertes Zeitachsenelement tippt, wird der Menüpunkt Weitere Informationen angezeigt.

Die Zeitachsenelemente, die text enthalten, werden von Glass automatisch paginiert. Wenn Glass html automatisch auf mehrere Seiten aufteilen soll, verwenden Sie das article-Tag mit der Klasseneigenschaft auto-paginate, wie im folgenden Beispiel:

<article class="auto-paginate">
 <h3>Very long list</h3>
 <ul>
   <li>First item</li>
   <li>Second item</li>
   <li>Third item</li>
   <li>Fourth item</li>
   <li>Fifth item</li>
   <li>Sixth item</li>
   <li>...</li>
 </ul>
<article>

Wenn Sie die Paginierung manuell vornehmen möchten, verwenden Sie das article-Tag für den Inhalt, der auf jeder Karte angezeigt werden soll. Glass zeigt den Inhalt jedes article-Tags auf einer separaten Karte in der Zeitleiste an. Mit dem folgenden HTML-Code kannst du beispielsweise ein paginarisiertes Zeitleistenelement erstellen:

<article>
 <section>
   <p>First page</p>
 </section>
</article>

<article>
 <section>
   <p>Second page</p>
 </section>
</article>

<article>
 <section>
   <p>Third page</p>
 </section>
</article>

Standardmäßig wird die erste Karte des paginaten Zeitachsenelements als Titelkarte angezeigt und noch einmal, wenn der Nutzer den Menüpunkt Mehr anzeigen auswählt. Wenn die erste Karte nicht mehr angezeigt werden soll, nachdem auf Weitere Informationen getippt wurde, können Sie die CSS-Klasse cover-only für das erste <article>-Tag angeben:

<article class="cover-only">
...

Die cover-only-Klasse unterstützt auch automatisch paginaierte Zeitachsenelemente:

<article class="auto-paginate cover-only">
...

Bündelung

Mit Bündeln können Sie ähnliche, aber unterschiedliche Elemente gruppieren, z. B. einzelne Nachrichten in einem E-Mail-Thread. Sets haben eine Haupt-Coverkarte, auf die Nutzer tippen können, um eine untergeordnete Zeitachse mit den anderen Karten im Set aufzurufen. Sets unterscheiden sich von normalen Zeitachsenkarten durch eine Ecke oben rechts auf der Titelkarte des Sets.

Wenn du Zeitachsenelemente bündeln möchtest, gib für sie denselben Wert für bundleId ein. Das zuletzt hinzugefügte Element ist die Titelkarte des Sets.

Die folgenden Bilder zeigen eine Set-Coverkarte mit der Ecke oben rechts und zwei Set-Karten darunter.

Zeitachsenelemente lesen

Ihr Dienst kann auf alle Zeitachsenelemente zugreifen, die er erstellt hat, und auf alle Zeitachsenelemente, die für ihn freigegeben wurden. So listen Sie die Zeitleistenelemente auf, die für Ihren Dienst sichtbar sind.

Roh-HTTP

GET /mirror/v1/timeline HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}

Java

TimelineItem timelineItem = new TimelineItem();
service.timeline().list().execute();

Python

service.timeline().list().execute()

Mit anderen REST-Vorgängen können Sie Zeitachsenelemente abrufen, aktualisieren und löschen.

Auf Anhänge zugreifen

Sie können über eine Array-Property namens attachments auf Anhänge zu einem Zeitachsenelement zugreifen. Sie können die Binärdaten eines Anhangs dann über das Attribut contentUrl des Anhangs oder über den Anhängeendpunkt abrufen.

Roh-HTTP

GET /mirror/v1/timeline/{itemId}/attachments/{attachmentId} HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer {auth token}

Java

TimelineItem item = service.timeline().get(itemId).execute();
String attachmentId = item.getAttachments().get(0).getId();
service.attachments().get(itemId, attachmentId).executeAsInputStream();

Menüpunkte erstellen

Über Menüpunkte können Nutzer Aktionen anfordern, die sich auf die Zeitachsenkarte beziehen. Es gibt zwei Arten von Menüpunkten: integrierte Menüpunkte und benutzerdefinierte Menüpunkte.

Über die integrierten Menüpunkte können Sie auf spezielle Funktionen von Glass zugreifen, z. B. eine Zeitachsenkarte vorlesen, zu einem Ort navigieren, ein Bild teilen oder auf eine Nachricht antworten:

Mit benutzerdefinierten Menüpunkten können Sie in Ihrer Anwendung ein Verhalten festlegen, das für Ihr Glassware-Produkt spezifisch ist. Außerdem können Sie ein Menüpunktsymbol bereitstellen, das zu Ihrem Branding passt.

Vordefinierte Menüpunkte hinzufügen

Sie können Ihren Zeitleistenelementen integrierte Menüpunkte hinzufügen, indem Sie beim Einfügen den Platzhalter menuItems array ausfüllen. Wenn Sie einen vordefinierten Menüpunkt verwenden möchten, müssen Sie nur die action jedes menuItem ausfüllen.

Roh-HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
  "text": "Hello world",
  "menuItems": [
    {
      "action": "REPLY"
    }
  ]
}

Benutzerdefinierte Menüpunkte definieren

Wenn die vordefinierten Menüpunkte nicht für Sie geeignet sind, können Sie benutzerdefinierte Menüpunkte mit eigenen Aktionen erstellen. Gehen Sie dazu so vor, wenn Sie ein Zeitachsenelement einfügen oder aktualisieren:

  • Geben Sie CUSTOM für menuItem.action an.
  • Geben Sie eine menuItem.id an. Wenn Nutzer auf den benutzerdefinierten Menüpunkt tippen, wird in Ihrem Glassware-Konto eine Benachrichtigung mit menuItem.id gesendet. So können Sie die Quelle der Benachrichtigung ermitteln.
  • Geben Sie menuItem.values an, um ein iconUrl und ein displayName hinzuzufügen, das auf Google Glass angezeigt wird. Verweisen Sie für das iconUrl auf ein weißes PNG-Bild mit einem transparenten Hintergrund und einer Größe von 50 × 50 Pixeln.
  • Geben Sie eine displayTime an. Wenn Sie kein displayTime angeben, wird das Zeitachsenelement an den Anfang der Zeitachse verschoben, wenn Nutzer auf den benutzerdefinierten Menüpunkt tippen.

Roh-HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
  "text": "Hello world",
  "displayTime": "2013-08-08T22:47:31-07:00",
  "menuItems": [
    {
      "action": "CUSTOM",
      "id": "complete"
      "values": [{
        "displayName": "Complete",
        "iconUrl": "http://example.com/icons/complete.png"
      }]
    }
  ]
}

Nutzern erlauben, Ihre Zeitachsenkarte anzupinnen

Sie können einen Menüpunkt erstellen, mit dem Nutzer die Zeitachse anpinnen können. Dadurch wird die Zeitachse dauerhaft links neben der Hauptuhrkarte angezeigt. Nutzer können die Karte auch über dasselbe Menüelement loslösen.

Der Menüpunkt „Anpinnen“ ist ein vordefinierter Menüpunkt. Sie müssen also nur TOGGLE_PINNED action für eine menuItem angeben.

Roh-HTTP

HTTP/1.1 201 Created
Date: Tue, 25 Sep 2012 23:30:11 GMT
Content-Type: application/json
Content-Length: 303

{
  "text": "You can pin or unpin this card.",
 "menuItems": [
    {
      "action": "TOGGLE_PINNED"
    }
  ...
 ]
}

Abos

Mit der Mirror API kannst du Benachrichtigungen abonnieren, die gesendet werden, wenn der Nutzer bestimmte Aktionen auf einem Zeitachsenelement ausführt oder sein Standort aktualisiert wurde. Wenn Sie eine Benachrichtigung abonnieren, geben Sie eine Rückruf-URL an, über die die Benachrichtigung verarbeitet wird.

Benachrichtigungen erhalten

Eine Benachrichtigung von der Mirror API wird als POST-Anfrage mit einem JSON-Anfragetext an den abonnierten Endpunkt gesendet.

Roh-HTTP

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "UPDATE",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer",
  "userActions": [
    {
      "type": "<TYPE>",
      "payload": "<PAYLOAD>"
    }
  ]
}

Java

import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.mirror.model.Notification;

import java.io.IOException;
import java.io.InputStream;
// ...

public class MyClass {
  // ...

  /**
    * Parse a request body into a Notification object.
    *
    * @param requestBody The notification payload sent by the Mirror API.
    * @return Parsed notification payload if successful, {@code null} otherwise.
    */
  static Notification parseNotification(InputStream requestBody) {
    try {
      JsonFactory jsonFactory = new JacksonFactory();

      return jsonFactory.fromInputStream(requetBody, Notification.class);
    } catch (IOException e) {
      System.out.println("An error occurred: " + e);
      return null;
    }
  }

  // ...
}

Python

import json

def parse_notification(request_body):
  """Parse a request body into a notification dict.

  Params:
    request_body: The notification payload sent by the Mirror API as a string.
  Returns:
    Dict representing the notification payload.
  """
  return json.load(request_body)

Dein Dienst muss der API mit dem HTTP-Statuscode 200 OK antworten, wenn kein Fehler aufgetreten ist. Wenn dein Dienst mit einem Fehlercode antwortet, versucht die Mirror API möglicherweise, die Benachrichtigung noch einmal an deinen Dienst zu senden.

Benachrichtigungstypen

Die Mirror API sendet für verschiedene Ereignisse eine unterschiedliche Benachrichtigungsnutzlast.

Antworten

Der Nutzer hat über den integrierten Menüpunkt REPLY auf deinen Zeitachseneintrag geantwortet:

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "INSERT",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer",
  "userActions": [
    {
      "type": "REPLY"
    }
  ]
}

Das itemId-Attribut ist auf die ID des Elements festgelegt, das Folgendes enthält:

  • Das Attribut inReplyTo ist auf das ID des Zeitachsenelements festgelegt, auf das geantwortet wird.
  • Das text-Attribut ist auf die Texttranskription festgelegt.
  • Das Attribut recipients ist auf das creator des Zeitachsenelements festgelegt, auf das es sich bezieht, sofern vorhanden.

Beispiel:

{
  "kind": "glass#timelineItem",
  "id": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "inReplyTo": "3236e5b0-b282-4e00-9d7b-6b80e2f47f3d",
  "text": "This is a text reply",
  "recipients": [
    {
      "id": "CREATOR_ID",
      "displayName": "CREATOR_DISPLAY_NAME",
      "imageUrls": [
        "CREATOR_IMAGE_URL"
      ]
    }
  ]
}

Löschen

Der Nutzer hat ein Zeitachsenelement gelöscht:

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "DELETE",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer",
  "userActions": [
    {
      "type": "DELETE"
    }
  ]
}

Das Attribut itemId ist auf die ID des gelöschten Elements festgelegt. Das Element enthält keine anderen Metadaten als seine ID und die Property isDeleted.

Benutzerdefinierter Menüpunkt ausgewählt

Der Nutzer hat einen benutzerdefinierten Menüpunkt ausgewählt, der von deinem Dienst festgelegt wurde:

{
  "collection": "timeline",
  "itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
  "operation": "UPDATE",
  "userToken": "harold_penguin",
  "userActions": [
    {
      "type": "CUSTOM",
      "payload": "PING"
    }
  ]
}

Das Attribut itemId ist auf die ID des Menüpunkts festgelegt, den der Nutzer ausgewählt hat.

Das Array userActions enthält die Liste der benutzerdefinierten Aktionen, die der Nutzer für dieses Element ausgeführt hat. Ihr Dienst sollte diese Aktionen entsprechend verarbeiten.

Standortaktualisierung

Für den aktuellen Nutzer ist ein neuer Standort verfügbar:

{
  "collection": "locations",
  "itemId": "latest",
  "operation": "UPDATE",
  "userToken": "harold_penguin",
  "verifyToken": "random_hash_to_verify_referer"
}

Wenn Ihre Glassware-Anwendung ein Standortupdate erhält, senden Sie eine Anfrage an den Endpunkt glass.locations.get, um den aktuellsten bekannten Standort abzurufen. Ihr Glassware-Gerät erhält alle zehn Minuten Standortaktualisierungen.

Sprachbefehl

Der Nutzer hat einen Sprachbefehl aktiviert, z. B.: „Hey Glass, mach mir eine Notiz: Cat Stream, Chipotles Geburtstag ist morgen.“ Die folgende Benachrichtigung wird an Ihr Glassware-Gerät gesendet:

{
  "collection": "timeline",
  "operation": "INSERT",
  "userToken": "chipotle's_owner",
  "verifyToken": "mew mew mew",
  "itemId": "<ITEM_ID>",
  "userActions": [
    {type: "LAUNCH"}
  ]
}

Diese Benachrichtigung unterscheidet sich von anderen Benachrichtigungen durch den LAUNCH-Wert in der Property userActions.

Du kannst dann den Wert in itemId verwenden, um das Zeitachsenelement abzurufen:

{
  "id": "<ITEM_ID>",
  "text": "Chipotle's birthday is tomorrow",
  "recipients": [
    {"id": "CAT_STREAM"}
  ]
}

Die Property recipients enthält die id des Kontakts, die den verwendeten Sprachbefehl darstellt.