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

במדריך למפתחים הזה מוסבר איך להוסיף תמיכה ב-Google Cast לאפליקציה Web Sender באמצעות 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 במכשיר שולח. אפליקציה של Web Aware מתייחסת לאפליקציה HTML/JavaScript שפועלת ב-Chromecast או במכשיר Google Cast.

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

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

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

<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

ה-framework מורכב מהרכיבים העיקריים הבאים:

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

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

לחצן הפעלת 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) על ידי קריאה לשיטה 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 MediaReceiver, שלא מחייב הרשמה, אתם יכולים להשתמש בערך קבוע שהוגדר מראש על ידי ה-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); });

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

אפשר לגשת למשתני מצב של הנגן ב-RemotePlayer. כל האינטראקציות עם RemotePlayer, כולל קריאות חוזרות (callback) ופקודות של אירועי מדיה, מטופלות באמצעות 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 עם מסגרות של קישור נתונים, כמו Polymer או 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;
  });

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

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

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

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

כדי לעקוב אחרי מצב הסשן, מוסיפים האזנה ל-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;
    }
  })

לניתוק, למשל אם המשתמש לוחץ על הלחצן 'הפסקת העברה' בתיבת הדו-שיח 'העברה', אפשר להוסיף האזנה לסוג האירוע 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
    }
  });

המשתמש יכול לשלוט ישירות בסיום ההעברה באמצעות לחצן ההעברה ב-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.