שילוב Cast SDK באפליקציית Web Sender

במדריך הזה למפתחים מוסבר איך להוסיף תמיכה ב-Google Cast לאפליקציית WebSender באמצעות Cast SDK.

הסברים על המונחים

המכשיר הנייד או הדפדפן הם השולח ששולט בהפעלה. מכשיר Google Cast הוא המקלט, שמציג את התוכן במסך להפעלה.

Web Sender SDK מורכב משני חלקים: Framework API (cast.framework) ו-Base API (chrome.cast) באופן כללי, שליחת קריאות ל-framework API הפשוט יותר, ברמה גבוהה יותר, שמעובדת לאחר מכן על ידי Base API ברמה נמוכה יותר.

מסגרת השולח מתייחסת ל-framework API, למודול ולמשאבים המשויכים, שמספקים wrapper לפונקציונליות ברמה נמוכה יותר. אפליקציית השולח או אפליקציית Google Cast ל-Chrome מתייחסת לאפליקציית אינטרנט (HTML/JavaScript) שפועלת בדפדפן Chrome במכשיר השולח. אפליקציה של שרת אינטרנט היא אפליקציית HTML/JavaScript שפועלת ב-Chromecast או במכשיר Google Cast.

מסגרת השולח משתמשת בעיצוב אסינכרוני של קריאה חוזרת כדי לעדכן את אפליקציית השולח לגבי האירועים ולעבור בין מצבים שונים במחזור החיים של אפליקציית Cast.

טעינת הספרייה

כדי שהאפליקציה תוכל להטמיע את התכונות של Google Cast, היא צריכה לדעת את המיקום של Google Cast Web Sender SDK, כפי שמוצג בהמשך. כדי לטעון גם את Web Sender Framework API, צריך להוסיף את פרמטר השאילתה loadCastFramework של כתובת ה-URL. כל הדפים באפליקציה חייבים להפנות לספרייה באופן הבא:

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

מסגרת

ב-Web Sender SDK נעשה שימוש במרחב השמות cast.framework.*. מרחב השמות מייצג את הערכים הבאים:

  • שיטות או פונקציות שמפעילות פעולות ב-API
  • פונקציות event listener לפונקציות של Listener ב-API

המסגרת מורכבת מהרכיבים העיקריים הבאים:

  • CastContext הוא אובייקט סינגלטון שמספק מידע על מצב ההעברה הנוכחי, ומפעיל אירועים לשינויי מצב ההעברה (cast) ולהפעלת ה-Cast.
  • האובייקט CastSession מנהל את הסשן – הוא מספק מידע על המצב ומפעיל אירועים, כמו שינויים בעוצמת הקול של המכשיר, במצב ההשתקה ובמטא-נתונים של האפליקציות.
  • רכיב הלחצן Cast, שהוא רכיב HTML פשוט ומותאם אישית שמרחיבים את לחצן ה-HTML. אם הלחצן להפעלת Cast לא מספיק, אפשר להשתמש במצב Cast כדי להטמיע את הלחצן להפעלת Cast.
  • RemotePlayerController מספק את קישור הנתונים כדי לפשט את ההטמעה של הנגן המרוחק.

תיאור מלא של מרחב השמות מופיע בחומר העזר בנושא ממשק ה-API של Google Cast Web Sender.

לחצן הפעלת Cast

רכיב הלחצן להפעלת Cast באפליקציה מטופל במלואו על ידי ה-framework. זה כולל ניהול הרשאות גישה וטיפול באירועי קליקים.

<google-cast-launcher></google-cast-launcher>

לחלופין, אפשר ליצור את הלחצן באופן פרוגרמטי:

document.createElement("google-cast-launcher");

אפשר להוסיף לרכיב כל סוג של עיצוב, כמו גודל או מיקום, לפי הצורך. אפשר להשתמש במאפיין --connected-color כדי לבחור את הצבע למצב של מקלט האינטרנט המחובר, ובצבע --disconnected-color למצב הניתוק.

אתחול

אחרי טעינת ה-framework API, האפליקציה תקרא ל-handler window.__onGCastApiAvailable. חשוב לוודא שהאפליקציה מגדירה את ה-handler הזה ב-window לפני טעינת ספריית השולחים.

ב-handler הזה, מאתחלים את האינטראקציה של Cast על ידי קריאה ל-method setOptions(options) של CastContext.

למשל:

<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    initializeCastApi();
  }
};
</script>

לאחר מכן, מאתחלים את ה-API באופן הבא:

initializeCastApi = function() {
  cast.framework.CastContext.getInstance().setOptions({
    receiverApplicationId: applicationId,
    autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
  });
};

בשלב הראשון, האפליקציה מאחזרת את מופע ה-Singleton של האובייקט CastContext שסופק על ידי ה-framework. לאחר מכן היא משתמשת ב-setOptions(options) באמצעות אובייקט CastOptions כדי להגדיר את applicationID.

אם אתם משתמשים ב-Default Media Gettingr, שלא מחייב הרשמה, אתם צריכים להשתמש בקבוע מראש של Web Sender SDK כפי שמוצג בהמשך, במקום ב-applicationID:

cast.framework.CastContext.getInstance().setOptions({
  receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});

פקד מדיה

אחרי אתחול של CastContext, האפליקציה יכולה לאחזר את ה-CastSession הנוכחי בכל שלב באמצעות getCurrentSession().

var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

אפשר להשתמש ב-CastSession כדי לטעון מדיה למכשיר Cast המחובר באמצעות loadMedia(loadRequest). קודם כול, יוצרים MediaInfo באמצעות contentId ו-contentType, וגם כל מידע אחר שקשור לתוכן. לאחר מכן יוצרים ממנו LoadRequest ומגדירים את כל המידע הרלוונטי לבקשה. לסיום, מפעילים קריאה אל loadMedia(loadRequest) במכשיר CastSession.

var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  function() { console.log('Load succeed'); },
  function(errorCode) { console.log('Error code: ' + errorCode); });

ה-method loadMedia תחזיר הבטחה שאפשר להשתמש בה כדי לבצע את כל הפעולות הנדרשות להשגת תוצאה מוצלחת. אם ההבטחה נדחתה, הארגומנט של הפונקציה יהיה chrome.cast.ErrorCode.

אפשר לגשת למשתני מצב הנגן ב-RemotePlayer. כל האינטראקציות עם RemotePlayer, כולל קריאה חוזרת ופקודות של אירועי מדיה, מטופלות באמצעות RemotePlayerController.

var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);

באמצעות RemotePlayerController האפליקציה נותנת לאפליקציה שליטה מלאה במדיה בנושאים הבאים: PLAY, PAUSE, STOP ו-SEEK.

  • הפעלה/השהיה: playerController.playOrPause();
  • עצירה: playerController.stop();
  • בקשה: playerController.seek();

אפשר להשתמש ב-RemotePlayer וב-RemotePlayerController עם frameworks של קישור נתונים, כמו פולימר או Angular, כדי להטמיע נגן מרוחק.

הנה קטע קוד עבור Angular:

<button id="playPauseButton" class="playerButton"
  ng-disabled="!player.canPause"
  ng-click="controller.playOrPause()">
    {{player.isPaused ? 'Play' : 'Pause'}}
</button>
<script>
var player = new cast.framework.RemotePlayer();
var controller = new cast.framework.RemotePlayerController(player);
// Listen to any player update, and trigger angular data binding
update.controller.addEventListener(
  cast.framework.RemotePlayerEventType.ANY_CHANGE,
  function(event) {
    if (!$scope.$$phase) $scope.$apply();
  });
</script>

סטטוס מדיה

במהלך הפעלה של מדיה, מתרחשים אירועים שונים שאפשר לתעד על ידי הגדרת מאזינים לאירועים שונים ב-cast.framework.RemotePlayerEventType באובייקט RemotePlayerController.

כדי לקבל את המידע על סטטוס המדיה, השתמשו באירוע cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, שמופעל כשההפעלה משתנה וכשהפרמטר CastSession.getMediaSession().media משתנה.

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    // Use the current session to get an up to date media status.
    let session = cast.framework.CastContext.getInstance().getCurrentSession();

    if (!session) {
        return;
    }

    // Contains information about the playing media including currentTime.
    let mediaStatus = session.getMediaSession();
    if (!mediaStatus) {
        return;
    }

    // mediaStatus also contains the mediaInfo containing metadata and other
    // information about the in progress content.
    let mediaInfo = mediaStatus.media;
  });

כשמתרחשים אירועים כמו השהיה, הפעלה, המשך או דילוג, האפליקציה תצטרך לפעול עליהם ולסנכרן בינו לבין אפליקציית מקלט האינטרנט במכשיר ה-Cast. למידע נוסף, ראו עדכוני סטטוס.

איך פועל ניהול הסשנים

ב-Cast SDK מוצג הקונספט של סשן של הפעלת Cast, אמצעי שמשלב את השלבים של התחברות למכשיר, הפעלה (או הצטרפות) של אפליקציית מקלט אינטרנט, התחברות לאפליקציה הזו ואתחול ערוץ בקרת מדיה. לקבלת מידע נוסף על סשנים של הפעלת Cast ועל מחזור החיים של WebReceiver, ראו מדריך מחזור החיים של אפליקציה.

הסשנים מנוהלים על ידי המחלקה CastContext, שהאפליקציה יכולה לאחזר דרך cast.framework.CastContext.getInstance(). ביקורים בודדים מיוצגים על ידי מחלקות משנה של הכיתה Session. לדוגמה, CastSession מייצג סשנים עם מכשירי Cast. האפליקציה יכולה לגשת לסשן Cast שפעיל כרגע דרך CastContext.getCurrentSession().

כדי לעקוב אחרי מצב הסשן, מוסיפים listener ל-CastContext לסוג האירוע CastContextEventType.SESSION_STATE_CHANGED.

var context = cast.framework.CastContext.getInstance();
context.addEventListener(
  cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
  function(event) {
    switch (event.sessionState) {
      case cast.framework.SessionState.SESSION_STARTED:
      case cast.framework.SessionState.SESSION_RESUMED:
        break;
      case cast.framework.SessionState.SESSION_ENDED:
        console.log('CastContext: CastSession disconnected');
        // Update locally as necessary
        break;
    }
  })

לניתוק, למשל כשהמשתמש לוחץ על הלחצן 'הפסקת ההעברה' בתיבת הדו-שיח של הפעלת Cast, אפשר להוסיף האזנה לסוג האירוע RemotePlayerEventType.IS_CONNECTED_CHANGED ב-listener. ב-listener בודקים אם RemotePlayer מנותק. אם כן, מעדכנים את מצב הנגן המקומי לפי הצורך. למשל:

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
    if (!player.isConnected) {
      console.log('RemotePlayerController: Player disconnected');
      // Update local player to disconnected state
    }
  });

המשתמש יכול לשלוט ישירות בסיום ההעברה באמצעות לחצן הפעלת Cast של ה-framework, אבל השולח עצמו יכול להפסיק את ההעברה באמצעות האובייקט CastSession הנוכחי.

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that Web Receiver app should be stopped.
  castSession.endSession(true);
}

העברה בסטרימינג

שימור מצב הסשן הוא הבסיס להעברת השידור, שבה המשתמשים יכולים להעביר שידורי אודיו ווידאו קיימים בין מכשירים באמצעות פקודות קוליות, אפליקציית Google Home או מסכים חכמים. המדיה מפסיקה לפעול במכשיר אחד (המקור) וממשיכה במכשיר אחר (היעד). כל מכשיר Cast עם הקושחה האחרונה יכול לשמש כמקורות או יעדים בהעברה בסטרימינג.

כדי לקבל את מכשיר היעד החדש במהלך ההעברה של השידור, קוראים למספר CastSession#getCastDevice() כשמתבצעת קריאה לאירוע cast.framework.SessionState.SESSION_RESUMED.

למידע נוסף, ראו העברת סטרימינג ב-WebReceiver.