البطاقات الثابتة

يمكنك إدراج البطاقات الثابتة وتحديثها وقراءتها وحذفها باستخدام واجهات برمجة تطبيقات REST البسيطة. بالإضافة إلى ذلك، يمكنك إرفاق الكائنات ببطاقة ثابتة، مثل موقع أو وسائط.

آلية عملها

تقع البطاقات الثابتة إلى يمين ساعة Glass افتراضيًا وتعرض المعلومات ذات الصلة بالمستخدم في وقت التسليم. ومع ذلك، لا تتطلّب هذه البطاقات اهتمامًا فوريًا، مثل البطاقات المباشرة، ويمكن للمستخدمين اختيار قراءة البطاقة أو اتّخاذ إجراء من خلالها في وقت فراغهم.

عندما يدرج Glassware بطاقات ثابتة في المخطط الزمني، قد يشغّل Glass تنبيهًا صوتيًا لتنبيه المستخدمين. يتم أيضًا تحويل جميع البطاقات الثابتة السابقة إلى اليمين وتختفي من المخطط الزمني بعد 7 أيام أو عندما تكون 200 بطاقة أحدث.

حالات الاستخدام

تُعد البطاقات الثابتة وسيلة رائعة لإرسال إشعارات دورية إلى المستخدمين عند حدوث أشياء مهمة. على سبيل المثال، خدمة إرسال الأخبار التي ترسل أهم الأخبار عند حدوثها. ويمكن أيضًا بدء استخدام البطاقات الثابتة لواجهة برمجة تطبيقات النسخ المطابق البطاقات المباشرة أو الدمجات من خلال عنصر القائمة OPEN_URI. ويتيح لك ذلك إنشاء تفاعلات مختلطة تستخدم البطاقات الثابتة كإشعارات وبطاقة مباشرة أو اندماجًا كاملاً للحصول على تجربة أكثر تفاعلية.

للحصول على قائمة كاملة بالعمليات المحتملة لعناصر المخطط الزمني، راجع الوثائق المرجعية.

إدراج بطاقات ثابتة

لإدراج بطاقات ثابتة (عناصر المخطط الزمني)، يجب نشر تمثيل JSON لعنصر في المخطط الزمني إلى نقطة نهاية REST.

معظم الحقول في عنصر المخطط الزمني اختيارية. في أبسط صوره، يحتوي عنصر المخطط الزمني على رسالة نصية قصيرة فقط، كما في المثال التالي:

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()

عند النجاح، ستتلقى رمز استجابة 201 Created مع نسخة كاملة من العنصر الذي تم إنشاؤه. بالنسبة إلى المثال السابق، قد تبدو الاستجابة الناجحة على النحو التالي:

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"
}

يظهر العنصر المدرج الذي يظهر في المخطط الزمني للمستخدم على النحو التالي:

إدراج عنصر في المخطط الزمني مع مرفق

الصورة أبلغ من ألف كلمة؛ وهي قيمة أكبر مما يمكنك استيعابه في عنصر المخطط الزمني. ولهذه الغاية، يمكنك أيضًا إرفاق الصور ومقاطع الفيديو بعنصر في المخطط الزمني. في ما يلي مثال على كيفية إدراج عنصر مخطط زمني مع مرفق صورة:

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()

يظهر عنصر المخطط الزمني الذي يحتوي على صورة مرفقة بهذا الشكل على Glass:

جارٍ إرفاق الفيديو

في حال إرفاق ملفات فيديو بعناصر المخطط الزمني، ننصحك ببث الفيديو بدلاً من تحميل البيانات الأساسية دفعة واحدة. تدعم Google Mirror API البث باستخدام البث المباشر عبر HTTP، والتنزيل التدريجي، وبروتوكول البث في الوقت الفعلي (RTSP). غالبًا ما يتم حظر بروتوكول RTSP باستخدام الجدران النارية، لذا استخدِم الخيارات الأخرى عندما يكون ذلك ممكنًا.

لبث الفيديو، استخدم PLAY_VIDEO عنصر القائمة المضمن وحدد عنوان URL للفيديو ليكون payload. راجع إضافة عناصر قائمة مدمجة وتنسيقات وسائط متوافقة للحصول على مزيد من المعلومات.

الترقيم

يمكنك تقسيم عناصر المخطط الزمني التي لا تتناسب مع بطاقة جدول زمني واحدة، ولكن يجب ربطها بالبطاقة نفسها. تتشارك العناصر المقسمة إلى صفحات عناصر timeline.id نفسها، وبالتالي تحتوي على المجموعة نفسها من عناصر القائمة. عندما ينقر المستخدم على عنصر مخطط زمني مقسم إلى صفحات، يظهر عنصر قائمة قراءة المزيد.

تعمل خدمة Glass على تقسيم العناصر في المخطط الزمني التي تعرض تلقائيًا text. لضبط خيار Glass تلقائيًا على صفحات html، استخدِم علامة article مع ضبط سمة الفئة على auto-paginate كما في المثال التالي:

<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>

لتقسيم الصفحات يدويًا، استخدم علامة article للمحتوى الذي تريد عرضه على كل بطاقة. يعرض Glass محتويات كل علامة article في بطاقة منفصلة للجدول الزمني الفرعي. على سبيل المثال، يمكنك إنشاء عنصر مخطط زمني مقسم إلى صفحات باستخدام شفرة HTML التالية:

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

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

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

بشكل تلقائي، يتم عرض البطاقة الأولى للعنصر في المخطط الزمني المقسم إلى صفحات كبطاقة غلاف ويتم عرضها مرة أخرى عندما يحدد المستخدم عنصر القائمة قراءة المزيد. لمنع ظهور البطاقة الأولى مرّة أخرى بعد النقر على قراءة المزيد، يمكنك تحديد فئة CSS cover-only للعلامة الأولى <article>:

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

تدعم الفئة cover-only أيضًا عناصر المخطط الزمني المقسّمة تلقائيًا:

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

تجميع

تسمح لك التجميع بتجميع العناصر ذات الصلة ولكن المميزة معًا، مثل الرسائل الفردية في سلسلة محادثات عبر البريد الإلكتروني. تحتوي الحزم على بطاقة غلاف رئيسية ينقر عليها المستخدم لعرض مخطط زمني فرعي يحتوي على البطاقات الأخرى في الحزمة. ويتم تمييز الحِزَم عن بطاقات المخطط الزمني العادي عن طريق طيّ الزاوية في الزاوية العلوية اليسرى لبطاقة غلاف الحزمة.

لحزمة عناصر المخطط الزمني، أنشِئ القيمة نفسها للسمة bundleId. العنصر الذي تمت إضافته مؤخرًا هو بطاقة غلاف الحزمة.

تُظهر الصور التالية بطاقة غلاف حزمة مع طي في الزاوية في الجانب العلوي الأيسر وبطاقتين مضمنتين تحتها.

قراءة عناصر المخطط الزمني

يمكن للخدمة الوصول إلى جميع عناصر المخطط الزمني التي أنشأتها، وجميع عناصر المخطط الزمني التي تمت مشاركتها معها. في ما يلي كيفية إدراج عناصر المخطط الزمني التي تكون مرئية لخدمتك.

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()

ويمكنك استخدام عمليات REST الأخرى للحصول على عناصر المخطط الزمني وتحديثها وحذفها.

الوصول إلى المرفقات

يمكنك الوصول إلى المرفقات لعنصر تسلسل زمني من خلال موقع مصفوفة يُسمَّى attachments. يمكنك بعد ذلك الحصول على البيانات الثنائية لمرفق من خلال الخاصية contentUrl للمرفق أو باستخدام نقطة نهاية المرفقات.

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();

إنشاء أصناف في القائمة

تتيح عناصر القائمة للمستخدمين إمكانية طلب الإجراءات ذات الصلة ببطاقة المخطط الزمني، وتأتي في شكلين: عناصر القائمة المضمّنة وعناصر القائمة المخصصة.

توفر عناصر القائمة المدمجة إمكانية الوصول إلى وظائف خاصة توفرها الزجاج، مثل قراءة بطاقة المخطط الزمني بصوت عالٍ أو الانتقال إلى موقع أو مشاركة صورة أو الرد على رسالة:

تتيح عناصر القائمة المخصصة لتطبيقك الكشف عن سلوك خاص بـ Glassware، ويمكنك أيضًا تقديم رمز عنصر قائمة ليتناسب مع علامتك التجارية.

إضافة عناصر القائمة المضمّنة

يمكنك إضافة عناصر القائمة المضمّنة إلى عناصر المخطط الزمني عن طريق تعبئة menuItems array عند إدراجها. لاستخدام عنصر قائمة مدمج، ما عليك سوى تعبئة action كل menuItem.

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"
    }
  ]
}

تحديد عناصر القائمة المخصصة

إذا لم تكن عناصر القائمة المضمّنة مناسبة لك، يمكنك إنشاء عناصر قائمة مخصّصة باستخدام الإجراءات الخاصة بك من خلال تنفيذ ما يلي عند إدراج عنصر محدّد في المخطط الزمني أو تعديله:

  • تحديد CUSTOM لـ menuItem.action.
  • حدِّد menuItem.id. عندما ينقر المستخدمون على عنصر القائمة المخصص، يتلقى Glassware إشعارًا مع تعبئة menuItem.id. يتيح لك هذا تحديد مصدر الإشعار.
  • يمكنك تحديد menuItem.values لإضافة iconUrl وdisplayName الذي يظهر على Glass. أشِر إلى صورة بحجم 50 × 50 بكسل باللون الأبيض مع خلفية شفافة لـ iconUrl.
  • حدِّد displayTime. وفي حال عدم تحديد displayTime، يتم نقل عنصر المخطط الزمني إلى مقدّمة المخطط الزمني كلما نقر المستخدمون على عنصر القائمة المخصّص.

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"
      }]
    }
  ]
}

السماح للمستخدمين بتثبيت بطاقة المخطط الزمني

يمكنك إنشاء عنصر في القائمة يسمح للمستخدمين بتثبيت بطاقة المخطط الزمني، والتي تعرض بشكل دائم بطاقة المخطط الزمني على يمين بطاقة الساعة الرئيسية. ويمكن للمستخدمين أيضًا إزالة تثبيت البطاقة باستخدام عنصر القائمة نفسه.

عنصر قائمة التثبيت هو عنصر قائمة مدمج، لذا ما عليك سوى تقديم TOGGLE_PINNED action لـ menuItem.

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"
    }
  ...
 ]
}

الاشتراكات

تتيح لك Mirror API الاشتراك في الإشعارات التي يتم إرسالها عند اتخاذ المستخدم لإجراءات محددة بشأن عنصر في المخطط الزمني أو عند تحديث الموقع الجغرافي للمستخدم. عند الاشتراك في إشعار، يمكنك تقديم عنوان URL لرد الاتصال الذي يعالج الإشعار.

تلقي الإشعارات

يتم إرسال إشعار من Mirror API كطلب POST إلى نقطة النهاية المشترَكة التي تحتوي على نص الطلب JSON.

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)

يجب أن تستجيب خدمتك لواجهة برمجة التطبيقات برمز حالة HTTP 200 OK إذا لم يحدث خطأ. إذا كانت خدمتك تستجيب برمز خطأ، قد تحاول واجهة برمجة تطبيقات Mirror إعادة إرسال الإشعار إلى خدمتك.

أنواع الإشعارات

ترسل Mirror API حمولة إشعارات مختلفة لأحداث مختلفة.

الردّ

لقد ردّ المستخدم على عنصر المخطط الزمني باستخدام عنصر القائمة REPLY المضمّن:

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

تم ضبط السمة itemId على ID للسلعة التي تحتوي على:

  • تم تعيين السمة inReplyTo إلى ID لعنصر المخطط الزمني الذي يتم الرد عليه.
  • تم ضبط text على النص المُحوَّل من صوت.
  • recipients إلى creator في عنصر المخطط الزمني الذي هو رد عليه، إن وجد.

مثال:

{
  "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"
      ]
    }
  ]
}

حذف

حذف المستخدم عنصر المخطط الزمني:

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

يتم تعيين السمة itemId على رقم تعريف العنصر المحذوف. لم يعُد العنصر يحتوي على بيانات وصفية بخلاف معرّفه وسمة isDeleted.

تم اختيار عنصر قائمة مخصّص

اختار المستخدم عنصر قائمة مخصص تم تعيينه من خلال خدمتك:

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

يتم ضبط السمة itemId على رقم تعريف عنصر القائمة الذي اختاره المستخدم.

تحتوي المصفوفة userActions على قائمة بالإجراءات المخصصة التي اتخذها المستخدم على هذا العنصر. يجب أن تتولى خدمتك هذه الإجراءات وفقًا لذلك.

تحديث الموقع

يتوفر موقع جديد للمستخدم الحالي:

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

عندما تتلقى Glassware تحديث الموقع، أرسل طلبًا إلى نقطة glass.locations.get لاسترداد آخر موقع معروف. يتلقى جهاز Glassware تحديثات الموقع كل عشر دقائق.

بطلب صوتي

نشَّط المستخدم طلبًا صوتيًا، مثل: "Ok Glass، تدوين ملاحظة، مجموعة بث القطط، تاريخ ميلاد شيبّل هو غدًا". يتم إرسال الإشعار التالي إلى Glassware:

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

ويتم تمييز هذا الإشعار عن الإشعارات الأخرى من خلال القيمة LAUNCH في السمة userActions.

يمكنك عندئذٍ استخدام القيمة في itemId لجلب عنصر المخطط الزمني:

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

تشتمل الخاصية recipients على id لجهة الاتصال التي تمثل الأمر الصوتي المستخدم.