1. סקירה כללית
בשיעור הזה תלמדו איך לשנות אפליקציית וידאו קיימת באינטרנט כדי להפעיל Cast של תוכן במכשיר שתומך ב-Google Cast.
מה זה Google Cast?
מערכת Google Cast מאפשרת למשתמשים להעביר תוכן מטלפון נייד לטלוויזיה. המשתמשים יוכלו להשתמש בנייד שלהם כשלט רחוק להפעלת מדיה בטלוויזיה.
Google Cast SDK מאפשר לכם להרחיב את האפליקציה כדי לשלוט בטלוויזיה או במערכת סאונד. באמצעות Cast SDK אפשר להוסיף את רכיבי ממשק המשתמש הנדרשים על סמך רשימת המשימות לעיצוב של Google Cast.
רשימת המשימות לעיצוב של Google Cast מסופקת כדי להפוך את חוויית המשתמש של Cast לפשוטה וצפויה בכל הפלטפורמות הנתמכות.
מה אנחנו הולכים ליצור?
בסיום ה-Codelab הזה, תהיה לך אפליקציית וידאו של Chrome, שדרכה אפשר להעביר סרטונים למכשיר Google Cast.
מה תלמדו
- איך מוסיפים את Google Cast SDK לאפליקציית וידאו לדוגמה.
- איך מוסיפים את לחצן ההעברה כדי לבחור מכשיר Google Cast.
- איך מתחברים למכשיר Cast ומפעילים מקלט מדיה.
- איך מעבירים סרטון באמצעות Cast.
- איך משלבים Cast Connect
מה נדרש
- דפדפן Google Chrome בגרסה העדכנית ביותר.
- שירות אירוח HTTPS, כמו אירוח Firebase או ngrok.
- מכשיר Google Cast, כמו Chromecast או Android TV, עם הגדרת גישה לאינטרנט.
- טלוויזיה או צג עם כניסת HDMI.
- כדי לבדוק את השילוב של Cast Connect, נדרש מכשיר Chromecast with Google TV, אבל הוא לא נדרש בשאר השלבים של Codelab. אם אין לכם תמיכה, אפשר לדלג על השלב הוספת תמיכה של Cast Connect בסוף המדריך.
ניסיון
- נדרש ידע קודם בפיתוח אתרים.
- נדרש גם ידע קודם על צפייה בטלוויזיה :)
איך תשתמשו במדריך הזה?
איזה דירוג מגיע לחוויה שלך עם הבנייה של אפליקציות אינטרנט?
איזה דירוג מגיע לדעתך לחוויית הצפייה בטלוויזיה?
2. קבלת קוד לדוגמה
אפשר להוריד את כל הקוד לדוגמה למחשב...
ופותחים את קובץ ה-ZIP שהורדתם.
3. הרצת האפליקציה לדוגמה
קודם נראה איך נראית אפליקציית הדוגמה המושלמת. האפליקציה היא נגן וידאו בסיסי. המשתמש יכול לבחור סרטון מרשימה ואז להפעיל את הסרטון באופן מקומי במכשיר או להפעיל Cast שלו למכשיר Google Cast.
כדי להשתמש בתוכן שהושלם, הוא צריך להתארח.
אם אין לכם שרת זמין לשימוש, תוכלו להשתמש ב-אירוח ב-Firebase או ב-ngrok.
הפעלת השרת
אחרי שמגדירים את השירות שבחרתם, עוברים אל app-done
ומפעילים את השרת.
בדפדפן, נכנסים לכתובת ה-URL בפורמט https של הדוגמה המתארחת.
- האפליקציה של הסרטון אמורה להופיע.
- לוחצים על הלחצן להפעלת Cast ובוחרים את מכשיר Google Cast.
- בוחרים סרטון ולוחצים על לחצן ההפעלה.
- הסרטון יתחיל לפעול במכשיר Google Cast.
אפשר ללחוץ על לחצן ההשהיה ברכיב הווידאו כדי להשהות את הסרטון במקלט. לוחצים על לחצן ההפעלה ברכיב הווידאו כדי להמשיך את ההפעלה של הסרטון.
לוחצים על הלחצן להפעלת Cast כדי להפסיק את ההעברה למכשיר Google Cast.
לפני שנמשיך, צריך להפסיק את השרת.
4. הכנת פרויקט ההתחלה
אנחנו צריכים להוסיף תמיכה ב-Google Cast לאפליקציית ההתחלה שהורדתם. ריכזנו כאן כמה מונחים של Google Cast שבהם נשתמש ב-codelab הזה:
- אפליקציית שליחה שפועלת במכשיר נייד או במחשב נייד,
- אפליקציית מקלט שפועלת במכשיר ה-Google Cast.
עכשיו אתם מוכנים להתחיל לעבוד על הפרויקט לתחילת העבודה באמצעות עורך הטקסט המועדף עליכם:
- בוחרים את הספרייה
app-start
מתוך הורדת הקוד לדוגמה. - מריצים את האפליקציה באמצעות השרת ומעיינים בממשק המשתמש.
הערה: במהלך העבודה ב-codelab הזה, תצטרכו לארח מחדש את הדוגמה בשרת שלכם, בהתאם לשירות.
עיצוב אפליקציות
האפליקציה מאחזרת רשימה של סרטונים משרת אינטרנט מרוחק ומספקת רשימה של סרטונים שהמשתמשים יכולים לעיין בהם. המשתמשים יכולים לבחור סרטון כדי לראות את הפרטים שלו או להפעיל אותו באופן מקומי במכשיר הנייד.
האפליקציה מורכבת מתצוגה ראשית אחת, שמוגדרת ב-index.html
והבקר הראשי, CastVideos.js.
index.html
קובץ ה-HTML הזה מכיל את ההצהרה על כמעט כל ממשק המשתמש של אפליקציית האינטרנט.
יש כמה קטעים של צפיות, יש לנו את div#main_video
, שמכיל את רכיב הסרטון. בקשר ל-video div שלנו, יש לנו div#media_control
, שמגדיר את כל הפקדים של רכיב הווידאו. מתחת לזה מופיע media_info
, שבו מוצגים פרטי הסרטון שמוצג. לבסוף, ה-div carousel
מציג רשימה של סרטונים ב-div.
גם הקובץ index.html
מבצע אתחול של Cast SDK, ומורה לפונקציה CastVideos
להיטען.
רוב התוכן שיאכלס את הרכיבים האלה מוגדר, מוזרק ומנוהל ב-CastVideos.js
. בואו נבחן את זה.
CastVideos.js
הסקריפט הזה מנהל את כל הלוגיקה של אפליקציית האינטרנט Cast Videos. רשימת הסרטונים והמטא-נתונים המשויכים להם שמוגדרים ב-CastVideos.js
נכללים באובייקט בשם mediaJSON
.
יש כמה קטעים עיקריים שאחראים יחד על ניהול הסרטון והפעלה שלו באופן מקומי ומרחוק. באופן כללי, זו אפליקציית אינטרנט פשוטה למדי.
CastPlayer
היא המחלקה הראשית שמנהלת את כל האפליקציה, הגדרת הנגן, בחירת מדיה וקישור אירועים אל PlayerHandler
להפעלת מדיה. CastPlayer.prototype.initializeCastPlayer
היא השיטה שמגדירה את כל הפונקציונליות של Cast. CastPlayer.prototype.switchPlayer
מעביר את המצב בין שחקן מקומי לנגן מרוחק. CastPlayer.prototype.setupLocalPlayer
ו-CastPlayer.prototype.setupRemotePlayer
מפעילים נגנים מקומיים ונגנים מרוחקים.
PlayerHandler
היא הכיתה שאחראית לניהול ההפעלה של המדיה. יש כמה שיטות אחרות שאחראיות על הפרטים של ניהול מדיה והפעלה.
שאלות נפוצות
5. הוספת הלחצן להפעלת Cast
באפליקציה שתומכת ב-Cast, הלחצן להפעלת Cast מוצג ברכיב הווידאו. לחיצה על הלחצן להפעלת Cast תציג רשימה של מכשירי Cast שהמשתמש יכול לבחור. אם המשתמש הפעיל תוכן באופן מקומי במכשיר השולח, הבחירה במכשיר Cast תתחיל או תמשיך את ההפעלה במכשיר ה-Cast הזה. בכל שלב במהלך סשן העברה, המשתמש יכול ללחוץ על לחצן ההעברה ולהפסיק את העברת האפליקציה למכשיר ההעברה. למשתמש צריכה להיות אפשרות להתחבר למכשיר Cast או להתנתק ממנו בכל מסך באפליקציה, כפי שמתואר ברשימת המשימות לעיצוב של Google Cast.
תצורה
בפרויקט ההתחלה נדרשים אותם יחסי תלות והגדרה כמו אלה של האפליקציה לדוגמה שהושלמה, אבל הפעם התוכן של app-start
מתארח.
בדפדפן, נכנסים לכתובת ה-URL https
של הדוגמה שמתארחת באתר שלכם.
זכרו: כשמבצעים שינויים, צריך לארח מחדש את הדוגמה בשרת בהתאם לשירות.
אתחול
למסגרת Cast יש אובייקט יחיד (singleton) גלובלי, CastContext
, שמרכז את כל הפעילויות של המסגרת. צריך לאתחל את האובייקט הזה בשלב מוקדם במחזור החיים של האפליקציה. בדרך כלל הוא נקרא מתוך פונקציית קריאה חוזרת (callback) שהוקצה ל-window['__onGCastApiAvailable']
, שנקראת אחרי שה-Cast SDK נטען וזמין לשימוש. במקרה הזה, מתבצעת קריאה של CastContext
ב-CastPlayer.prototype.initializeCastPlayer
, והיא מתבצעת מהקריאה החוזרת שהוזכרה למעלה.
צריך לספק אובייקט JSON מסוג options
בזמן האיפוס של CastContext
. הכיתה הזו מכילה אפשרויות שמשפיעות על ההתנהגות של המסגרת. החשוב שבהם הוא מזהה אפליקציית המקבל, שמשמש לסינון הרשימה של מכשירי Cast זמינים כך שיוצגו רק מכשירים שיכולים להפעיל את האפליקציה שצוינה וכדי להפעיל את אפליקציית המקבל כאשר מתחיל סשן Cast.
כשמפתחים אפליקציה משלכם שתומכת ב-Cast, צריך להירשם כמפתח Cast ולקבל מזהה אפליקציה לאפליקציה. ב-Codelab הזה, נשתמש במזהה אפליקציה לדוגמה.
צריך להוסיף את הקוד הבא אל index.html
בסוף הקטע body
:
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
צריך להוסיף את הקוד הבא אל index.html
כדי לאתחל את האפליקציה CastVideos
, וגם כדי לאתחל את CastContext
:
<script src="CastVideos.js"></script>
<script type="text/javascript">
var castPlayer = new CastPlayer();
window['__onGCastApiAvailable'] = function(isAvailable) {
if (isAvailable) {
castPlayer.initializeCastPlayer();
}
};
</script>
עכשיו צריך להוסיף שיטה חדשה ב-CastVideos.js
שתתאים לשיטה שרק התקשרנו אליה ב-index.html
. נוסיף שיטה חדשה, בשם initializeCastPlayer
, שמגדירה אפשרויות ב-CastContext ומאתחלת RemotePlayer
ו-RemotePlayerControllers
חדשים:
/**
* This method sets up the CastContext, and a few other members
* that are necessary to play and control videos on a Cast
* device.
*/
CastPlayer.prototype.initializeCastPlayer = function() {
var options = {};
// Set the receiver application ID to your own (created in
// the Google Cast Developer Console), or optionally
// use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
options.receiverApplicationId = 'C0868879';
// Auto join policy can be one of the following three:
// ORIGIN_SCOPED - Auto connect from same appId and page origin
// TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab
// PAGE_SCOPED - No auto connect
options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED;
cast.framework.CastContext.getInstance().setOptions(options);
this.remotePlayer = new cast.framework.RemotePlayer();
this.remotePlayerController = new cast.framework.RemotePlayerController(this.remotePlayer);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
this.switchPlayer.bind(this)
);
};
לבסוף, צריך ליצור את המשתנים עבור RemotePlayer
ו-RemotePlayerController
:
var CastPlayer = function() {
//...
/* Cast player variables */
/** @type {cast.framework.RemotePlayer} */
this.remotePlayer = null;
/** @type {cast.framework.RemotePlayerController} */
this.remotePlayerController = null;
//...
};
לחצן הפעלת Cast
עכשיו, לאחר אתחול של CastContext
, צריך להוסיף את לחצן הפעלת Cast כדי לאפשר למשתמש לבחור מכשיר Cast. ערכת ה-SDK של Cast מספקת רכיב של לחצן להפעלת Cast בשם google-cast-launcher
עם המזהה 'castbutton"
'. ניתן להוסיף אותו לרכיב הווידאו של האפליקציה על ידי הוספה של button
בקטע media_control
.
כך ייראה רכיב הלחצן:
<google-cast-launcher id="castbutton"></google-cast-launcher>
מוסיפים את הקוד הבא ל-index.html
בקטע media_control
:
<div id="media_control">
<div id="play"></div>
<div id="pause"></div>
<div id="progress_bg"></div>
<div id="progress"></div>
<div id="progress_indicator"></div>
<div id="fullscreen_expand"></div>
<div id="fullscreen_collapse"></div>
<google-cast-launcher id="castbutton"></google-cast-launcher>
<div id="audio_bg"></div>
<div id="audio_bg_track"></div>
<div id="audio_indicator"></div>
<div id="audio_bg_level"></div>
<div id="audio_on"></div>
<div id="audio_off"></div>
<div id="duration">00:00:00</div>
</div>
עכשיו מרעננים את הדף בדפדפן Chrome. לחצן להפעלת Cast אמור להופיע ברכיב הווידאו, ובלחיצה עליו הוא יציג את רשימת מכשירי ה-Cast ברשת המקומית. זיהוי המכשירים מנוהל באופן אוטומטי על ידי דפדפן Chrome. בוחרים את מכשיר ה-Cast, ואפליקציית המקלט לדוגמה תיטען במכשיר ה-Cast.
עדיין לא הוספנו תמיכה בהפעלת מדיה, ולכן אי אפשר להפעיל סרטונים במכשיר ההעברה (cast) בשלב הזה. כדי להפסיק את ההעברה, לוחצים על הלחצן להפעלת Cast.
6. העברה (cast) של תוכן סרטון
נרחיב את האפליקציה לדוגמה כך שתאפשר גם להפעיל סרטונים מרחוק במכשיר Cast. כדי לעשות זאת, עלינו להאזין לאירועים השונים שנוצרו על ידי Cast frame
הפעלת Cast של מדיה
באופן כללי, כדי להפעיל מדיה במכשיר Cast, צריך לקרות את הפעולות הבאות:
- יוצרים אובייקט
MediaInfo
JSON
מה-Cast SDK כדי ליצור מודל של פריט מדיה. - המשתמש מתחבר למכשיר Cast כדי להפעיל את אפליקציית המקבל.
- טוענים את האובייקט
MediaInfo
למכשיר המקבל ומפעילים את התוכן. - מעקב אחר סטטוס המדיה.
- שליחת פקודות הפעלה למכשיר הקולט על סמך אינטראקציות של משתמשים.
שלב 1 מסתכם במיפוי של אובייקט אחד לאובייקט אחר; MediaInfo
הוא משהו ש-Cast SDK מבין, ו-mediaJSON
הוא הסתרת פריט מדיה באפליקציה שלנו; אנחנו יכולים למפות בקלות mediaJSON
לMediaInfo
. כבר ביצענו את שלב 2 בקטע הקודם. קל לבצע את שלב 3 באמצעות Cast SDK.
באפליקציית הדוגמה CastPlayer
כבר יש הבחנה בין הפעלה מקומית לבין הפעלה מרחוק בשיטה switchPlayer
:
if (cast && cast.framework) {
if (this.remotePlayer.isConnected) {
//...
ב-Codelab הזה לא חשוב שתבינו בדיוק איך פועלת כל הלוגיקה של הנגן לדוגמה. עם זאת, חשוב להבין שיהיה צורך לשנות את נגן המדיה של האפליקציה כדי שיהיה מודע להפעלה המקומית ולהפעלה מרחוק.
בשלב הזה הנגן המקומי תמיד נמצא במצב ההפעלה המקומי כי הוא עדיין לא יודע על המצבים של ההעברה (cast). אנחנו צריכים לעדכן את ממשק המשתמש על סמך מעברי מצבים שמתרחשים ב-Cast framework. לדוגמה, אם אנחנו מתחילים להפעיל Cast, צריך להפסיק את ההפעלה המקומית ולהשבית חלק מהפקדים. באופן דומה, אם מפסיקים את ההעברה (cast) כשנמצאים בבורר התצוגה הזה, צריך לעבור להפעלה מקומית. כדי לעשות זאת, אנחנו צריכים להאזין לאירועים השונים שנוצרים על ידי מסגרת Cast.
ניהול סשן של הפעלת Cast
במסגרת Cast, סשן Cast משלב את שלבי החיבור למכשיר, הפעלה (או הצטרפות לסשן קיים), התחברות לאפליקציית מקלט ואתחול ערוץ של בקרת מדיה, במקרים הרלוונטיים. הערוץ של פקדי המדיה הוא האופן שבו מסגרת Cast שולחת ומקבלת הודעות הקשורות להפעלת מדיה מהמקלט.
סשן ההעברה יופעל באופן אוטומטי כשהמשתמש יבחר מכשיר מהלחצן 'העברה', וייפסק באופן אוטומטי כשהמשתמש יתנתק. גם החיבור מחדש לסשן של מקלט בגלל בעיות ברשת מנוהל באופן אוטומטי על ידי מסגרת ההעברה (cast).
סשנים של העברה (cast) מנוהלים על ידי CastSession
, שאפשר לגשת אליו דרך cast.framework.CastContext.getInstance().getCurrentSession()
. אפשר להשתמש בקריאות החזרה (callbacks) של EventListener
כדי לעקוב אחרי אירועי סשן, כמו יצירה, השעיה, המשך וסיום.
באפליקציה הנוכחית שלנו, כל ניהול הסשן והמצב מתבצע בשבילנו בשיטה setupRemotePlayer
. נתחיל להגדיר את זה באפליקציה על ידי הוספת הקוד הבא לקובץ CastVideos.js
:
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
this.playerHandler.setTarget(playerTarget);
// Setup remote player volume right on setup
// The remote player may have had a volume set from previous playback
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
}
var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = currentVolume + 'px';
p.style.marginTop = -currentVolume + 'px';
this.hideFullscreenButton();
this.playerHandler.play();
};
אנחנו עדיין צריכים לקשר את כל האירועים מהקריאות החוזרות (callback) ולטפל בכל האירועים שמתקבלים. זה קל מאוד לעשות, אז בואו נעשה את זה עכשיו:
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
// Add event listeners for player changes which may occur outside sender app
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
function() {
if (this.remotePlayer.isPaused) {
this.playerHandler.pause();
} else {
this.playerHandler.play();
}
}.bind(this)
);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,
function() {
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
} else {
this.playerHandler.unMute();
}
}.bind(this)
);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.VOLUME_LEVEL_CHANGED,
function() {
var newVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = newVolume + 'px';
p.style.marginTop = -newVolume + 'px';
}.bind(this)
);
// This object will implement PlayerHandler callbacks with
// remotePlayerController, and makes necessary UI updates specific
// to remote playback
var playerTarget = {};
playerTarget.play = function () {
if (this.remotePlayer.isPaused) {
this.remotePlayerController.playOrPause();
}
var vi = document.getElementById('video_image');
vi.style.display = 'block';
var localPlayer = document.getElementById('video_element');
localPlayer.style.display = 'none';
}.bind(this);
playerTarget.pause = function () {
if (!this.remotePlayer.isPaused) {
this.remotePlayerController.playOrPause();
}
}.bind(this);
playerTarget.stop = function () {
this.remotePlayerController.stop();
}.bind(this);
playerTarget.getCurrentMediaTime = function() {
return this.remotePlayer.currentTime;
}.bind(this);
playerTarget.getMediaDuration = function() {
return this.remotePlayer.duration;
}.bind(this);
playerTarget.updateDisplayMessage = function () {
document.getElementById('playerstate').style.display = 'block';
document.getElementById('playerstatebg').style.display = 'block';
document.getElementById('video_image_overlay').style.display = 'block';
document.getElementById('playerstate').innerHTML =
this.mediaContents[ this.currentMediaIndex]['title'] + ' ' +
this.playerState + ' on ' + castSession.getCastDevice().friendlyName;
}.bind(this);
playerTarget.setVolume = function (volumeSliderPosition) {
// Add resistance to avoid loud volume
var currentVolume = this.remotePlayer.volumeLevel;
var p = document.getElementById('audio_bg_level');
if (volumeSliderPosition < FULL_VOLUME_HEIGHT) {
var vScale = this.currentVolume * FULL_VOLUME_HEIGHT;
if (volumeSliderPosition > vScale) {
volumeSliderPosition = vScale + (pos - vScale) / 2;
}
p.style.height = volumeSliderPosition + 'px';
p.style.marginTop = -volumeSliderPosition + 'px';
currentVolume = volumeSliderPosition / FULL_VOLUME_HEIGHT;
} else {
currentVolume = 1;
}
this.remotePlayer.volumeLevel = currentVolume;
this.remotePlayerController.setVolumeLevel();
}.bind(this);
playerTarget.mute = function () {
if (!this.remotePlayer.isMuted) {
this.remotePlayerController.muteOrUnmute();
}
}.bind(this);
playerTarget.unMute = function () {
if (this.remotePlayer.isMuted) {
this.remotePlayerController.muteOrUnmute();
}
}.bind(this);
playerTarget.isMuted = function() {
return this.remotePlayer.isMuted;
}.bind(this);
playerTarget.seekTo = function (time) {
this.remotePlayer.currentTime = time;
this.remotePlayerController.seek();
}.bind(this);
this.playerHandler.setTarget(playerTarget);
// Setup remote player volume right on setup
// The remote player may have had a volume set from previous playback
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
}
var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = currentVolume + 'px';
p.style.marginTop = -currentVolume + 'px';
this.hideFullscreenButton();
this.playerHandler.play();
};
טעינה של מדיה
ב-Cast SDK, RemotePlayer
ו-RemotePlayerController
מספקים קבוצה של ממשקי API נוחים לניהול ההפעלה מרחוק של המדיה במכשיר המקלט. בשביל CastSession
שתומך בהפעלת מדיה, מופעים של RemotePlayer
ו-RemotePlayerController
ייווצרו באופן אוטומטי על ידי ה-SDK. כדי לגשת אליהם, יוצרים מופע של cast.framework.RemotePlayer
ומופע של cast.framework.RemotePlayerController
, בהתאמה, כפי שמוצג קודם לכן בקודלאב.
בשלב הבא, עלינו לטעון במקלט את הסרטון הנוכחי שנבחר על ידי פיתוח אובייקט MediaInfo, כדי שה-SDK יעבד ויעביר את הבקשה. כדי לעשות זאת, מוסיפים אל setupRemotePlayer
את הקוד הבא:
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
//...
playerTarget.load = function (mediaIndex) {
console.log('Loading...' + this.mediaContents[mediaIndex]['title']);
var mediaInfo = new chrome.cast.media.MediaInfo(
this.mediaContents[mediaIndex]['sources'][0], 'video/mp4');
mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();
mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;
mediaInfo.metadata.title = this.mediaContents[mediaIndex]['title'];
mediaInfo.metadata.images = [
{'url': MEDIA_SOURCE_ROOT + this.mediaContents[mediaIndex]['thumb']}];
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
this.playerHandler.loaded.bind(this.playerHandler),
function (errorCode) {
this.playerState = PLAYER_STATE.ERROR;
console.log('Remote media load error: ' +
CastPlayer.getErrorMessage(errorCode));
}.bind(this));
}.bind(this);
//...
};
עכשיו מוסיפים שיטה למעבר בין הפעלה מקומית להפעלה מרחוק:
/**
* This is a method for switching between the local and remote
* players. If the local player is selected, setupLocalPlayer()
* is run. If there is a cast device connected we run
* setupRemotePlayer().
*/
CastPlayer.prototype.switchPlayer = function() {
this.stopProgressTimer();
this.resetVolumeSlider();
this.playerHandler.stop();
this.playerState = PLAYER_STATE.IDLE;
if (cast && cast.framework) {
if (this.remotePlayer.isConnected) {
this.setupRemotePlayer();
return;
}
}
this.setupLocalPlayer();
};
לבסוף, מוסיפים שיטה לטיפול בהודעות שגיאה של Cast:
/**
* Makes human-readable message from chrome.cast.Error
* @param {chrome.cast.Error} error
* @return {string} error message
*/
CastPlayer.getErrorMessage = function(error) {
switch (error.code) {
case chrome.cast.ErrorCode.API_NOT_INITIALIZED:
return 'The API is not initialized.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.CANCEL:
return 'The operation was canceled by the user' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.CHANNEL_ERROR:
return 'A channel to the receiver is not available.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.EXTENSION_MISSING:
return 'The Cast extension is not available.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.INVALID_PARAMETER:
return 'The parameters to the operation were not valid.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE:
return 'No receiver was compatible with the session request.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.SESSION_ERROR:
return 'A session could not be created, or a session was invalid.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.TIMEOUT:
return 'The operation timed out.' +
(error.description ? ' :' + error.description : '');
}
};
עכשיו מריצים את האפליקציה, מתחברים למכשיר ההעברה (cast) ומתחילים להפעיל סרטון. הסרטון אמור להופיע במכשיר המקבל.
7. הוספת תמיכה ב-Cast Connect
ספריית Cast Connect מאפשרת לאפליקציות שולח קיימות לתקשר עם אפליקציות ל-Android TV באמצעות פרוטוקול Cast. Cast Connect מבוסס על התשתית של Cast, כשאפליקציית Android TV פועלת כמקלט.
יחסי תלות
- דפדפן Chrome מגרסה M87 ואילך
הגדרת תאימות למקלט של Android
כדי להפעיל את האפליקציה ל-Android TV, שנקראת גם Android היעדים, צריך להגדיר את הדגל androidReceiverCompatible
כ-true באובייקט CastOptions
.
מוסיפים את הקוד הבא אל CastVideos.js
בפונקציה initializeCastPlayer
:
var options = {};
...
options.androidReceiverCompatible = true;
cast.framework.CastContext.getInstance().setOptions(options);
הגדרת פרטי הכניסה להפעלה
בצד השולח, אפשר לציין את CredentialsData
כדי לייצג את מי שיצטרף לסשן. השדה credentials
הוא מחרוזת שאפשר להגדיר על ידי המשתמש, כל עוד אפליקציית ה-ATV יכולה להבין אותה. הערך של CredentialsData
מועבר לאפליקציה ב-Android TV רק במהלך ההפעלה או ההצטרפות. אם תגדירו אותה שוב בזמן החיבור, היא לא תועבר לאפליקציה ל-Android TV.
כדי להגדיר את פרטי הכניסה להפעלה, צריך להגדיר את CredentialsData
בכל שלב אחרי שאפשרויות ההפעלה מוגדרות.
מוסיפים את הקוד הבא למחלקה CastVideos.js
בפונקציה initializeCastPlayer
:
cast.framework.CastContext.getInstance().setOptions(options);
...
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
...
הגדרת פרטי כניסה בבקשה לטעינה
אם אפליקציית מכשיר האינטרנט והאפליקציה ל-Android TV מתייחסות לcredentials
באופן שונה, יכול להיות שיהיה צורך להגדיר פרטי כניסה נפרדים לכל אחד מהם. כדי לטפל בבעיה, צריך להוסיף את הקוד הבא אל CastVideos.js
בקטע playerTarget.load
בפונקציה setupRemotePlayer
:
...
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...
בהתאם לאפליקציית הנמען שאליה השולח מבצע העברה (cast), ה-SDK יטפל עכשיו באופן אוטומטי בפרטי הכניסה שבהם יש להשתמש בסשן הנוכחי.
בדיקת Cast Connect
השלבים להתקנת קובץ ה-APK של Android TV ב-Chromecast with Google TV:
- מאתרים את כתובת ה-IP של מכשיר Android TV. בדרך כלל, הוא מופיע בקטע הגדרות > רשת ואינטרנט > (שם הרשת שאליה המכשיר מחובר). בצד שמאל יוצגו הפרטים ואת כתובת ה-IP של המכשיר שלך ברשת.
- משתמשים בכתובת ה-IP של המכשיר כדי להתחבר אליו דרך ADB באמצעות הטרמינל:
$ adb connect <device_ip_address>:5555
- מחלון הטרמינל, עוברים לתיקייה ברמה העליונה של דוגמאות ה-Codelab שהורדתם בתחילת השיעור הזה ב-Codelab. לדוגמה:
$ cd Desktop/chrome_codelab_src
- כדי להתקין את קובץ ה-APK בתיקייה הזו ב-Android TV, מריצים את הפקודה:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- עכשיו אמורה להופיע אפליקציה בשם העברת סרטונים בתפריט האפליקציות שלך במכשיר Android TV.
- מריצים את קוד השליחה המעודכן לאינטרנט ויוצרים סשן העברה (cast) עם מכשיר Android TV באמצעות סמל ההעברה (cast) או על ידי בחירה באפשרות
Cast..
בתפריט הנפתח בדפדפן Chrome. פעולה זו אמורה להפעיל את האפליקציה ל-Android TV במקלט ה-Android ולאפשר לך לשלוט בהפעלה באמצעות השלט הרחוק של Android TV.
8. מזל טוב
עכשיו אתם יודעים איך להפעיל העברה (cast) באפליקציית וידאו באמצעות ווידג'טים של Cast SDK באפליקציית אינטרנט ב-Chrome.
לפרטים נוספים אפשר לעיין במדריך למפתחים של שולח אינטרנט.