تطبيق واجهة برمجة التطبيقات الخاصة بميزة "مشاهدة المحتوى مع الآخرين"

توضّح هذه الصفحة كيفية استخدام Co-Watching API لتسهيل تجربة المشاهدة مع الآخرين.

عملية الإعداد الأوّلية

لإعداد المكتبة للاستخدام، يجب أن يضبط تطبيق المشاركة المباشرة عنصر CoWatchingClient الذي يمثّل جلسة مشاهدة مشتركة.

لاستخدام حزمة تطوير البرامج (SDK) لميزة "المشاركة المباشرة في Meet"، عليك طلب الطريقة AddonClientFactory.getClient. يؤدي ذلك إلى عرض رمز AddonClient يعمل كنقطة دخول لجلسة المشاهدة مع الآخرين.

لاستخدام البرنامج، يمكنك استدعاء الطريقة newSessionBuilder من AddonClient لعرض أداة إنشاء AddonSession جديدة. تنفِّذ newSessionBuilder واجهة AddonSessionHandler لمعالجة عمليات الاستدعاء التي توفرها الإضافة للجلسة.

لبدء جلسة، أضِف الطريقة withCoWatching إلى أداة الإنشاء.

يعرض نموذج الرمز البرمجي التالي إعدادًا أساسيًا لكائن العميل "المشاهدة مع الآخرين":

Java

class AwesomeVideoAddonSessionHandler implements AddonSessionHandler {}

// For sample implementation, see the "Manage remote state" section below.
class AwesomeVideoCoWatchingHandler implements CoWatchingHandler {}

public ListenableFuture<AddonSession> initialSetup() {
  AddonClient meetClient = AddonClientFactory.getClient();
  return meetClient
      .newSessionBuilder(
          new AwesomeVideoAddonSessionHandler())
      .withCoWatching(new AwesomeVideoCoWatchingHandler())
      .begin();
}

إرسال إشعارات إلى إجراءات المستخدم

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

يمكنك التحكّم في حالة المشاهدة مع الآخرين بالطُرق التالية:

  • CoWatchingClient.notifyBuffering: لإشعار Meet بأنّ الوسائط غير جاهزة للتشغيل بسبب التخزين المؤقت، أو بسبب تبديل سابق للوسائط أو "بحث الوسائط" أو التكدس الطبيعي في الشبكة.
  • CoWatchingClient.notifyEnded: لإشعار Meet بأنّ مشغّل الوسائط وصل إلى نهاية محتوى الوسائط الحالية.
  • CoWatchingClient.notifyPauseState إبلاغ Meet بأنّ المستخدم أوقف تشغيل الوسائط مؤقتًا أو أعاد عرضها لكي يطابق هذا الإجراء للمستخدمين الآخرين
  • CoWatchingClient.notifyPlayoutRate: لإشعار Meet بأنّ المستخدم عدَّل معدل تشغيل الوسائط إلى قيمة جديدة (مثلاً 1.25x).
  • CoWatchingClient.notifyQueueUpdate: إشعار Meet بتغيير قائمة الانتظار، ليتمكّن تطبيق Meet من النسخ المطابق لغيره من المستخدمين.
  • CoWatchingClient.notifyReady: لإشعار Meet باكتمال التخزين المؤقت وبأن الوسائط جاهزة للتشغيل، بدءًا من الطابع الزمني المقدّم.
  • CoWatchingClient.notifySeekToTimestamp: لإشعار Meet بأنّ المستخدم قد طلب نقطة تشغيل الوسائط، حتى يتمكن تطبيق Meet من النسخ المطابق لهذا الإجراء للمستخدمين الآخرين
  • CoWatchingClient.notifySwitchedToMedia: إشعار Meet بأنّ المستخدم بدَّل الوسائط، لذلك يمكن لتطبيق Meet تمرير ذلك إلى مستخدمين آخرين. تحتوي أيضًا على خيار التحديث المتزامن لقائمة الانتظار.

يعرض نموذج الرمز البرمجي التالي كيفية إشعار المستخدمين:

Java

public void onVideoPaused(Duration currentTimestamp) {
  // Use Meet to broadcast the pause state to ensure other participants also pause.
  this.session.getCoWatching().notifyPauseState(/* paused= */ true, currentTimestamp);
};

إدارة الحالة عن بُعد

لتطبيق التحديثات الواردة من مشاركين عن بُعد، عليك توفير طريقة Meet لإدارة حالة تشغيل الوسائط المحلية مباشرةً باستخدام استدعاء CoWatchingHandler.onCoWatchingStateChanged().

يحتاج تطبيق Meet أيضًا إلى استرداد الوضع الحالي لعرض الوسائط من خلال معاودة الاتصال بـ CoWatchingHandler.onStateQuery(). ويُطلق على ذلك اسم بانتظام، لذا يجب كتابتها على الشكل التالي: (على سبيل المثال، <100 ملي ثانية).

يعرض نموذج الرمز البرمجي التالي طريقة تنفيذ لـ CoWatchingHandler:

Java

class AwesomeVideoCoWatchingHandler implements CoWatchingHandler {
  /** Applies incoming playback state to the local video. */
  public void onCoWatchingStateChanged(CoWatchingState newState) {
    // Handle transition to new video.
    if (!newState.mediaId().equals(this.videoPlayer.videoUrl)) {
      this.videoPlayer.loadVideo(newState.mediaId());
    }

    // Only adjust the local video playout if it's sufficiently diverged from the timestamp in the
    // applied update.
    if (newState
            .mediaPlayoutPosition()
            .minus(this.videoPlayer.videoTimestamp)
            .compareTo(Duration.ofMillis(500))
        > 0) {
      this.videoPlayer.seek(newState.mediaPlayoutPosition());
    }

    // Update pause state, if necessary.
    if (newState.playbackState().equals(PLAY) && this.videoPlayer.isPaused) {
      this.videoPlayer.unpause();
    } else if (newState.playbackState().equals(PAUSE) && !this.videoPlayer.isPaused) {
      this.videoPlayer.pause();
    }
  }

  /** Returns local video playback state. */
  public Optional<QueriedCoWatchingState> onStateQuery() {
    return Optional.of(QueriedCoWatchingState.of(
      /* mediaPlayoutPosition= */ this.videoPlayer.videoTimestamp));
  }
}