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

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

آلية عملها

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

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

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

تعد البطاقات الثابتة وسيلة رائعة لتقديم إشعارات دورية للمستخدمين عند حدوث أشياء مهمة. على سبيل المثال، خدمة توصيل أخبار ترسل أهم القصص الإخبارية فور حدوثها. يمكن أيضًا لبطاقات Mirror API الثابتة بدء البطاقات المباشرة أو الغامرة من خلال عنصر القائمة 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. لتقسيم html تلقائيًا إلى صفحات في Glass، استخدِم علامة 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();

جارٍ إنشاء عناصر في القائمة

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

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

وتتيح عناصر القائمة المخصصة لتطبيقك الكشف عن السلوك الخاص بـ 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. أشِر إلى صورة PNG بمقاس 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 API إعادة إرسال الإشعار إلى الخدمة.

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

ترسل 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، تدوين ملاحظة، Cat Stream، عيد ميلاد تشيبوتل غدًا". تم إرسال الإشعار التالي إلى 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 لجهة الاتصال التي تمثّل الطلب الصوتي المُستخدَم.