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

توضّح هذه الصفحة كيفية استخدام واجهة برمجة التطبيقات الخاصة بميزة "المشاهدة مع الآخرين" لدعم سيناريو المشاهدة مع الآخرين.

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

لإعداد المكتبة للاستخدام، يجب أن يعمل تطبيق المشاركة المباشرة على إعداد عنصر 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 بأنّ المستخدم أوقف تشغيل الوسائط مؤقتًا أو ألغى الإيقاف المؤقت حتى يتمكّن تطبيق 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));
  }
}