הדף הזה מכיל קטעי קוד ותיאורים של התכונות שזמינות לאפליקציית Custom Web Receiver.
- רכיב
cast-media-playerשמייצג את ממשק המשתמש של הנגן המובנה שמסופק עם Web Receiver. - עיצוב מותאם אישית דמוי CSS לרכיב
cast-media-playerכדי לעצב רכיבים שונים בממשק המשתמש, כמוbackground-image,splash-imageו-font-family. - רכיב סקריפט לטעינת מסגרת Web Receiver.
- קוד JavaScript ליירוט הודעות ולטיפול באירועים.
- הוספה לתור להפעלה אוטומטית.
- אפשרויות להגדרת ההפעלה.
- אפשרויות להגדרת ההקשר של Web Receiver.
- אפשרויות להגדרת פקודות שנתמכות על ידי אפליקציית Web Receiver.
- קריאת JavaScript להפעלת אפליקציית Web Receiver.
הגדרות ואפשרויות של האפליקציה
הגדרת האפליקציה
CastReceiverContext היא המחלקה החיצונית ביותר שחשופה למפתח, והיא מנהלת את הטעינה של הספריות הבסיסיות ומטפלת באתחול של Web Receiver SDK. ערכת ה-SDK מספקת ממשקי API שמאפשרים למפתחי אפליקציות להגדיר את ערכת ה-SDK באמצעות CastReceiverOptions.
ההגדרות האלה נבדקות פעם אחת בכל הפעלה של האפליקציה, ומועברות ל-SDK כשמגדירים את הפרמטר האופציונלי בקריאה ל-start.
בדוגמה הבאה אפשר לראות איך לשנות את פעולת ברירת המחדל לזיהוי אם חיבור של שולח עדיין פעיל. אם מקלט האינטרנט לא מצליח לתקשר עם השולח במשך maxInactivity שניות, נשלח אירוע SENDER_DISCONNECTED. ההגדרות שבהמשך מבטלות את הזמן הקצוב לתפוגה. האפשרות הזו יכולה להיות שימושית כשמנפים באגים, כי היא מונעת מאפליקציית Web Receiver לסגור את הסשן של Chrome Remote Debugger כשאין שולחים מחוברים במצב IDLE.
const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);
הגדרת הנגן
בזמן טעינת התוכן, ה-Web Receiver SDK מספק דרך להגדיר משתני הפעלה כמו מידע על DRM, הגדרות של ניסיונות חוזרים ו-request handlers באמצעות cast.framework.PlaybackConfig.
המידע הזה מטופל על ידי PlayerManager ונבדק בזמן יצירת הנגנים. הנגנים נוצרים בכל פעם שמועבר עומס חדש ל-Web Receiver SDK. שינויים ב-PlaybackConfig אחרי שהנגן נוצר נבדקים בטעינת התוכן הבאה. ה-SDK מספק את השיטות הבאות לשינוי של PlaybackConfig.
CastReceiverOptions.playbackConfigכדי לשנות את אפשרויות ברירת המחדל של ההגדרות כשמפעילים אתCastReceiverContext.PlayerManager.getPlaybackConfig()כדי לקבל את ההגדרות הנוכחיות.-
PlayerManager.setPlaybackConfig()כדי לשנות את ההגדרה הנוכחית. ההגדרה הזו חלה על כל הטעינות הבאות, או עד שהיא תוחלף שוב. -
PlayerManager.setMediaPlaybackInfoHandler()כדי להחיל הגדרות נוספות רק על קובץ המדיה שנטען, בנוסף להגדרות הקיימות. ה-handler נקרא ממש לפני יצירת הנגן. השינויים שיבוצעו כאן לא יהיו קבועים ולא ייכללו בשאילתות ל-getPlaybackConfig(). כשהמערכת טוענת את קובץ המדיה הבא, היא קוראת שוב ל-handler הזה.
בדוגמה הבאה אפשר לראות איך מגדירים את PlaybackConfig כשמפעילים את CastReceiverContext. ההגדרה מבטלת בקשות יוצאות לקבלת מניפסטים. ה-handler מציין שצריך לשלוח בקשות Access-Control של CORS באמצעות פרטי כניסה כמו קובצי Cookie או כותרות של הרשאות.
const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});
בדוגמה הבאה אפשר לראות איך לשנות את ברירת המחדל של PlaybackConfig באמצעות ה-getter וה-setter שסופקו ב-PlayerManager. ההגדרה קובעת שהנגן ימשיך את הפעלת התוכן אחרי שקטע אחד נטען.
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);
בדוגמה הבאה אפשר לראות איך לשנות את PlaybackConfig לבקשת טעינה ספציפית באמצעות ה-handler של פרטי הפעלת המדיה. ה-handler קורא ל-method getLicenseUrlForMedia שמוטמעת באפליקציה כדי לקבל את ה-licenseUrl מה-contentId של הפריט הנוכחי.
playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
const mediaInformation = loadRequestData.media;
playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);
return playbackConfig;
});
רכיב event listener
ה-Web Receiver SDK מאפשר לאפליקציית Web Receiver לטפל באירועים של הנגן. רכיב ה-event listener מקבל פרמטר cast.framework.events.EventType (או מערך של הפרמטרים האלה) שמציין את האירועים שאמורים להפעיל את ה-listener. מערכים מוגדרים מראש של cast.framework.events.EventType שמועילים לניפוי באגים נמצאים ב-cast.framework.events.category.
הפרמטר של האירוע מספק מידע נוסף על האירוע.
לדוגמה, אם אתם רוצים לדעת מתי משודר שינוי ב-mediaStatus, אתם יכולים להשתמש בלוגיקה הבאה כדי לטפל באירוע:
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
cast.framework.events.EventType.MEDIA_STATUS, (event) => {
// Write your own event handling code, for example
// using the event.mediaStatus value
});
יירוט הודעות
ערכת ה-SDK של Web Receiver מאפשרת לאפליקציית Web Receiver ליירט הודעות ולהריץ קוד בהתאמה אישית על ההודעות האלה. מיירט ההודעות מקבל פרמטר
cast.framework.messages.MessageType
שמציין את סוג ההודעה שצריך ליירט.
ה-interceptor צריך להחזיר את הבקשה ששונתה או Promise שמתקבל עם ערך הבקשה ששונתה. החזרה של null תמנע את ההפעלה של ה-handler של הודעות ברירת המחדל. פרטים נוספים זמינים במאמר טעינת מדיה.
לדוגמה, אם רוצים לשנות את נתוני בקשת הטעינה, אפשר להשתמש בלוגיקה הבאה כדי ליירט ולשנות אותם:
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_FAILED);
if (!loadRequestData.media) {
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
if (!loadRequestData.media.entity) {
return loadRequestData;
}
return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
if (!asset) {
throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
}
loadRequestData.media.contentUrl = asset.url;
loadRequestData.media.metadata = asset.metadata;
loadRequestData.media.tracks = asset.tracks;
return loadRequestData;
}).catch(reason => {
error.reason = reason; // cast.framework.messages.ErrorReason
return error;
});
});
context.start();
טיפול בשגיאות
אם מתרחשות שגיאות ב-message interceptor, אפליקציית Web Receiver צריכה להחזיר את הערכים המתאימים של cast.framework.messages.ErrorType ו-cast.framework.messages.ErrorReason.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_CANCELLED);
if (!loadRequestData.media) {
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
...
return fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
...
return loadRequestData;
}).catch(reason => {
error.reason = reason; // cast.framework.messages.ErrorReason
return error;
});
});
יירוט הודעות לעומת רכיב event listener
אלה כמה מההבדלים העיקריים בין יירוט הודעות לבין רכיב event listener:
- רכיב event listener לא מאפשר לשנות את נתוני הבקשה.
- השימוש הטוב ביותר ברכיב event listener הוא להפעלת ניתוח נתונים או פונקציה בהתאמה אישית.
playerManager.addEventListener(cast.framework.events.category.CORE,
event => {
console.log(event);
});
- יירוט הודעות מאפשר לכם להאזין להודעה, ליירט אותה ולשנות את נתוני הבקשה עצמה.
- יירוט הודעות מתאים במיוחד לטיפול בלוגיקה מותאמת אישית בנוגע לנתוני בקשות.
המדיה בטעינה
MediaInformation מספק מאפיינים רבים לטעינת מדיה בהודעה cast.framework.messages.MessageType.LOAD, כולל entity, contentUrl ו-contentId.
- המאפיין
entityהוא המאפיין המומלץ לשימוש בהטמעה גם באפליקציית השולח וגם באפליקציית המקבל. המאפיין הוא כתובת URL של קישור עומק שיכולה להיות פלייליסט או תוכן מדיה. האפליקציה צריכה לנתח את כתובת ה-URL הזו ולאכלס לפחות אחד משני השדות האחרים. - השדה
contentUrlתואם לכתובת ה-URL של התוכן שהנגן ישתמש בה כדי לטעון את התוכן. לדוגמה, כתובת ה-URL הזו יכולה להפנות למניפסט DASH. - המאפיין
contentIdיכול להיות כתובת URL של תוכן שניתן להפעלה (בדומה למאפייןcontentUrl) או מזהה ייחודי של התוכן או הפלייליסט שנטענים. אם משתמשים במאפיין הזה כמזהה, האפליקציה צריכה לאכלס כתובת URL שניתן להפעיל ב-contentUrl.
מומלץ להשתמש ב-entity כדי לאחסן את המזהה האמיתי או את הפרמטרים העיקריים, ולהשתמש ב-contentUrl לכתובת ה-URL של המדיה. דוגמה לכך מוצגת בקטע הקוד הבא, שבו ה-entity נמצא בבקשת ה-LOAD וה-contentUrl שניתן להפעלה מאוחזר:
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
...
if (!loadRequestData.media.entity) {
// Copy the value from contentId for legacy reasons if needed
loadRequestData.media.entity = loadRequestData.media.contentId;
}
return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
loadRequestData.media.contentUrl = asset.url;
...
return loadRequestData;
});
});
תכונות המכשיר
השיטה getDeviceCapabilities מספקת מידע על מכשיר ה-Cast המחובר ועל מכשיר הווידאו או האודיו שמחובר אליו. השיטה getDeviceCapabilities מספקת מידע תמיכה ל-Google Assistant, ל-Bluetooth ולמסך ולמכשירי האודיו המחוברים.
ה-method הזו מחזירה אובייקט שאפשר לשלוח אליו שאילתה על ידי העברת אחד מהערכים שצוינו כדי לקבל את יכולת המכשיר עבור אותו ערך. הערכים המוגדרים מראש מוגדרים ב-cast.framework.system.DeviceCapabilities.
בדוגמה הזו, המערכת בודקת אם מכשיר ה-Web Receiver יכול להפעיל HDR ו-DolbyVision (DV) באמצעות המקשים IS_HDR_SUPPORTED ו-IS_DV_SUPPORTED, בהתאמה.
const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
const deviceCapabilities = context.getDeviceCapabilities();
if (deviceCapabilities &&
deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
// Write your own event handling code, for example
// using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
}
if (deviceCapabilities &&
deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
// Write your own event handling code, for example
// using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
}
});
context.start();
טיפול באינטראקציות של משתמשים
המשתמשים יכולים לבצע פעולות באפליקציית Web Receiver דרך אפליקציות שולחות (אינטרנט, Android ו-iOS), פקודות קוליות במכשירים עם Assistant מובנית, שליטה באמצעות מגע במסכים חכמים ושלטים רחוקים במכשירי Android TV. ערכת ה-SDK של Cast מספקת ממשקי API שונים שמאפשרים לאפליקציית Web Receiver לטפל באינטראקציות האלה, לעדכן את ממשק המשתמש של האפליקציה באמצעות מצבי פעולות של משתמשים, ואם רוצים, לשלוח את השינויים כדי לעדכן את שירותי הקצה העורפי.
פקודות מדיה נתמכות
המצבים של הרכיבים האינטראקטיביים מופעלים על ידי
MediaStatus.supportedMediaCommands
באפליקציות של השולח ב-iOS וב-Android, באפליקציות של המקלט ובאפליקציות של השלט הרחוק
שפועלות במכשירי מגע, ובאפליקציות של המקלט במכשירי Android TV. כשהמאפיין Command מופעל במאפיין, הלחצנים שקשורים לפעולה הזו מופעלים. אם לא מגדירים ערך, הלחצן מושבת. אפשר לשנות את הערכים האלה ב-Web Receiver באמצעות:
- משתמשים ב-
PlayerManager.setSupportedMediaCommandsכדי להגדיר את ה-Commandsהספציפי. - הוספת פקודה חדשה באמצעות
addSupportedMediaCommands - הסרת פקודה קיימת באמצעות
removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
cast.framework.messages.Command.PAUSE);
כשהמקבל מכין את ה-MediaStatus המעודכן, הוא יכלול את השינויים במאפיין supportedMediaCommands. כשהסטטוס משודר, אפליקציות השולח המחוברות מעדכנות את הלחצנים בממשק המשתמש שלהן בהתאם.
מידע נוסף על פקודות מדיה נתמכות ומכשירי מגע זמין במדריך של Accessing UI controls.
ניהול המצבים של פעולות המשתמשים
כשהמשתמשים מבצעים פעולות בממשק המשתמש או שולחים פקודות קוליות, הם יכולים לשלוט בהפעלת התוכן ובמאפיינים שקשורים לפריט שמופעל. בקשות ששולטות בהפעלה מטופלות באופן אוטומטי על ידי ה-SDK. בקשות שמשנות את המאפיינים של הפריט שמופעל כרגע, כמו פקודת LIKE, דורשות שאפליקציית המקבל תטפל בהן. ה-SDK מספק סדרה של ממשקי API לטיפול בבקשות מהסוגים האלה. כדי לתמוך בבקשות האלה, צריך לבצע את הפעולות הבאות:
- מגדירים את
MediaInformationuserActionStatesעם ההעדפות של המשתמש כשקובץ המדיה נטען. - ליירט
USER_ACTIONהודעות ולקבוע את הפעולה המבוקשת. - כדי לעדכן את ממשק המשתמש, צריך לעדכן את
MediaInformationUserActionState.
קטע הקוד הבא מיירט את הבקשה של LOAD ומאכלס את MediaInformation של LoadRequestData. במקרה כזה, המשתמש אוהב את התוכן שנטען.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
const userActionLike = new cast.framework.messages.UserActionState(
cast.framework.messages.UserAction.LIKE);
loadRequestData.media.userActionStates = [userActionLike];
return loadRequestData;
});
קטע הקוד הבא מיירט את ההודעה USER_ACTION ומטפל בקריאה לקצה העורפי עם השינוי המבוקש. לאחר מכן, הוא מבצע קריאה כדי לעדכן את UserActionState במקלט.
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
(userActionRequestData) => {
// Obtain the media information of the current content to associate the action to.
let mediaInfo = playerManager.getMediaInformation();
// If there is no media info return an error and ignore the request.
if (!mediaInfo) {
console.error('Not playing media, user action is not supported');
return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
}
// Reach out to backend services to store user action modifications. See sample below.
return sendUserAction(userActionRequestData, mediaInfo)
// Upon response from the backend, update the client's UserActionState.
.then(backendResponse => updateUserActionStates(backendResponse))
// If any errors occurred in the backend return them to the cast receiver.
.catch((error) => {
console.error(error);
return error;
});
});
קטע הקוד הבא מדמה קריאה לשירות לקצה העורפי. הפונקציה בודקת את UserActionRequestData כדי לראות את סוג השינוי שהמשתמש ביקש, ומבצעת קריאה לרשת רק אם הפעולה נתמכת על ידי הקצה העורפי.
function sendUserAction(userActionRequestData, mediaInfo) {
return new Promise((resolve, reject) => {
switch (userActionRequestData.userAction) {
// Handle user action changes supported by the backend.
case cast.framework.messages.UserAction.LIKE:
case cast.framework.messages.UserAction.DISLIKE:
case cast.framework.messages.UserAction.FOLLOW:
case cast.framework.messages.UserAction.UNFOLLOW:
case cast.framework.messages.UserAction.FLAG:
case cast.framework.messages.UserAction.SKIP_AD:
let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
setTimeout(() => {resolve(backendResponse)}, 1000);
break;
// Reject all other user action changes.
default:
reject(
new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
}
});
}
קטע הקוד הבא מקבל את UserActionRequestData ומוסיף או מסיר את UserActionState מ-MediaInformation. עדכון של UserActionState של MediaInformation משנה את המצב של הכפתור שמשויך לפעולה המבוקשת. השינוי הזה בא לידי ביטוי בממשק המשתמש של אמצעי הבקרה במסך החכם, באפליקציית השלט הרחוק ובממשק המשתמש של Android TV. הוא גם משודר באמצעות הודעות MediaStatus יוצאות כדי לעדכן את ממשק המשתמש של הבקר המורחב לשולחים ב-iOS וב-Android.
function updateUserActionStates(backendResponse) {
// Unwrap the backend response.
let mediaInfo = backendResponse.mediaInfo;
let userActionRequestData = backendResponse.userActionRequestData;
// If the current item playing has changed, don't update the UserActionState for the current item.
if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
return;
}
// Check for existing userActionStates in the MediaInformation.
// If none, initialize a new array to populate states with.
let userActionStates = mediaInfo.userActionStates || [];
// Locate the index of the UserActionState that will be updated in the userActionStates array.
let index = userActionStates.findIndex((currUserActionState) => {
return currUserActionState.userAction == userActionRequestData.userAction;
});
if (userActionRequestData.clear) {
// Remove the user action state from the array if cleared.
if (index >= 0) {
userActionStates.splice(index, 1);
}
else {
console.warn("Could not find UserActionState to remove in MediaInformation");
}
} else {
// Add the UserActionState to the array if enabled.
userActionStates.push(
new cast.framework.messages.UserActionState(userActionRequestData.userAction));
}
// Update the UserActionState array and set the new MediaInformation
mediaInfo.userActionStates = userActionStates;
playerManager.setMediaInformation(mediaInfo, true);
return;
}
פקודות קוליות
פקודות המדיה הבאות נתמכות כרגע ב-Web Receiver SDK למכשירים עם Assistant מובנית. ההטמעות של הפקודות האלה כברירת מחדל נמצאות ב-cast.framework.PlayerManager.
| פקודה | תיאור |
|---|---|
| Play | הפעלה או המשך הפעלה ממצב מושהה. |
| השהיה | השהיית התוכן שמופעל כרגע. |
| הקודם | דילוג לקובץ המדיה הקודם בתור המדיה. |
| הבא | דילוג לקובץ המדיה הבא בתור המדיה. |
| הפסקה | הפסקת המדיה שמופעלת כרגע. |
| ללא חזרה | השבתת החזרה על קובצי מדיה בתור אחרי שהקובץ האחרון בתור מסתיים. |
| חזרה על סינגל | חזרה על המדיה שמופעלת כרגע ללא הגבלת זמן. |
| חזרה על הכול | חזרה על כל הפריטים בתור אחרי שהפריט האחרון בתור הופעל. |
| חזרה על הכול והפעלה אקראית | אחרי שהפריט האחרון בתור יסיים לפעול, התור יופעל בסדר אקראי וכל הפריטים בתור יופעלו שוב. |
| הפעלה אקראית | הפעלה בסדר אקראי של קובצי המדיה בתור המדיה. |
| הפעלה או השבתה של כתוביות סמויות | הפעלה או השבתה של כתוביות סמויות במדיה. אפשר גם להפעיל או להשבית את התכונה לפי שפה. |
| דילוג לנקודת זמן מוחלטת | מעבר לזמן המוחלט שצוין. |
| דילוג לזמן יחסי לזמן הנוכחי | מדלג קדימה או אחורה לפי פרק הזמן שצוין ביחס לזמן ההפעלה הנוכחי. |
| משחק חדש | הפעלה מחדש של המדיה שמופעלת כרגע, או הפעלה של קובץ המדיה האחרון שהופעל אם שום דבר לא מופעל כרגע. |
| הגדרת מהירות ההפעלה | לשנות את מהירות ההפעלה של המדיה. הטיפול בזה אמור להתבצע כברירת מחדל. אתם יכולים להשתמש במיירט ההודעות SET_PLAYBACK_RATE כדי לשנות את בקשות התעריפים הנכנסות. |
פקודות קוליות נתמכות למדיה
כדי למנוע מצב שבו פקודה קולית מפעילה פקודת מדיה במכשיר שתומך ב-Assistant, קודם צריך להגדיר את פקודות המדיה הנתמכות שאתם מתכננים לתמוך בהן. לאחר מכן, צריך לאכוף את הפקודות האלה על ידי הפעלת המאפיין CastReceiverOptions.enforceSupportedCommands. ממשק המשתמש בשולחי Cast SDK ובמכשירים עם מסך מגע ישתנה בהתאם להגדרות האלה. אם הדגל לא מופעל, הפקודות הקוליות הנכנסות יבוצעו.
לדוגמה, אם מאפשרים PAUSE מאפליקציות השולח וממכשירים עם מסך מגע, צריך להגדיר גם את המקלט כך שישקף את ההגדרות האלה. אם מגדירים את המדיניות הזו, כל הפקודות הקוליות הנכנסות שלא נכללות ברשימת הפקודות הנתמכות יימחקו.
בדוגמה הבאה אנחנו מספקים את CastReceiverOptions כשמפעילים את CastReceiverContext. הוספנו תמיכה בפקודה PAUSE ואכפנו את הנגן כך שיתמוך רק בפקודה הזו. עכשיו, אם פקודה קולית תבקש פעולה אחרת כמו SEEK, היא תידחה. המשתמש יקבל הודעה שהפקודה עדיין לא נתמכת.
const context = cast.framework.CastReceiverContext.getInstance();
context.start({
enforceSupportedCommands: true,
supportedCommands: cast.framework.messages.Command.PAUSE
});
אפשר להחיל לוגיקה נפרדת על כל פקודה שרוצים להגביל. מסירים את הדגל enforceSupportedCommands, ובכל פקודה שרוצים להגביל, אפשר ליירט את ההודעה הנכנסת. כאן אנחנו מיירטים את הבקשה שסופקה על ידי ה-SDK כדי שפקודות SEEK שמונפקות למכשירים עם Assistant מובנית לא יפעילו חיפוש באפליקציית Web Receiver.
אם האפליקציה לא תומכת בפקודות מדיה מסוימות, צריך להחזיר סיבת שגיאה מתאימה, כמו NOT_SUPPORTED.
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
seekData => {
// Block seeking if the SEEK supported media command is disabled
if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
.INVALID_REQUEST);
e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
return e;
}
return seekData;
});
העברה לרקע מפעילות קולית
אם פלטפורמת Cast מעבירה את הצליל של האפליקציה לרקע בגלל פעילות של Assistant, כמו האזנה לדיבור של המשתמש או מענה, הודעת FocusState מסוג NOT_IN_FOCUS נשלחת לאפליקציית Web Receiver כשהפעילות מתחילה. הודעה נוספת עם IN_FOCUS נשלחת כשהפעילות מסתיימת.
בהתאם לאפליקציה ולמדיה שמופעלת, יכול להיות שתרצו להשהות את המדיה כשה-FocusState הוא NOT_IN_FOCUS על ידי יירוט סוג ההודעה FOCUS_STATE.
לדוגמה, כדי לספק חוויית משתמש טובה, כדאי להשהות את ההפעלה של ספר האודיו אם Assistant מגיבה לשאילתה של המשתמש.
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
focusStateRequestData => {
// Pause content when the app is out of focus. Resume when focus is restored.
if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
playerManager.pause();
} else {
playerManager.play();
}
return focusStateRequestData;
});
שפת הכתוביות שצוינה בהפעלה הקולית
אם המשתמש לא מציין במפורש את השפה של הכתוביות, השפה שבה משתמשים לכתוביות היא אותה שפה שבה נאמרה הפקודה.
במקרים כאלה, הפרמטר isSuggestedLanguage של ההודעה הנכנסת מציין אם השפה המשויכת הוצעה או התבקשה במפורש על ידי המשתמש.
לדוגמה, isSuggestedLanguage מוגדר ל-true עבור הפקודה "OK Google, turn captions on", כי השפה הוסקה מהשפה שבה נאמרה הפקודה. אם השפה נבחרה באופן מפורש, למשל "Ok Google, turn on English captions", הערך של isSuggestedLanguage מוגדר כ-false.
מטא-נתונים וליהוק קולי
כברירת מחדל, הפקודות הקוליות מטופלות על ידי Web Receiver, אבל חשוב לוודא שהמטא-נתונים של התוכן שלכם מלאים ומדויקים. כך אפשר לוודא ש-Assistant תטפל בפקודות הקוליות כמו שצריך, ושהמטא-נתונים יופיעו בצורה תקינה בסוגים חדשים של ממשקים, כמו אפליקציית Google Home ומסכים חכמים כמו Google Home Hub.
החלפת רמקול
שמירת מצב הסשן היא הבסיס להחלפת רמקול, שבה המשתמשים יכולים להעביר שידורי אודיו ווידאו קיימים בין מכשירים באמצעות פקודות קוליות, אפליקציית Google Home או מסכים חכמים. הפעלת המדיה נפסקת במכשיר אחד (המקור) וממשיכה במכשיר אחר (היעד). כל מכשיר Cast עם הקושחה העדכנית ביותר יכול לשמש כמקור או כיעד בהחלפת רמקול.
תהליך האירוע של העברת הסטרימינג הוא:
- במכשיר המקור:
- הפעלת המדיה נפסקת.
- אפליקציית Web Receiver מקבלת פקודה לשמור את מצב המדיה הנוכחי.
- אפליקציית Web Receiver נסגרת.
- במכשיר היעד:
- אפליקציית Web Receiver נטענת.
- אפליקציית Web Receiver מקבלת פקודה לשחזר את מצב המדיה שנשמר.
- הפעלת המדיה תתחדש.
הרכיבים של מצב המדיה כוללים:
- מיקום או חותמת זמן ספציפיים של השיר, הסרטון או קובץ המדיה.
- המיקום שלו בתור רחב יותר (כמו פלייליסט או תחנת רדיו של אומן).
- המשתמש המאומת.
- מצב ההפעלה (לדוגמה, מופעל או מושהה).
הפעלת התכונה "החלפת רמקול"
כדי להטמיע העברת סטרימינג ב-Web Receiver:
- מעדכנים את
supportedMediaCommandsבאמצעות הפקודהSTREAM_TRANSFER:playerManager.addSupportedMediaCommands( cast.framework.messages.Command.STREAM_TRANSFER, true);
- אם רוצים, אפשר לשנות את מנגנוני היירוט של ההודעות
SESSION_STATEו-RESUME_SESSION, כמו שמתואר בקטע שמירה על מצב הסשן. צריך לשנות את הערכים האלה רק אם צריך לאחסן נתונים בהתאמה אישית כחלק מתמונת המצב של הסשן. אחרת, הטמעת ברירת המחדל לשמירת מצבי סשן תתמוך בהחלפת רמקול.
שמירת מצב הסשן
Web Receiver SDK מספק הטמעה שמוגדרת כברירת מחדל לאפליקציות Web Receiver כדי לשמור את מצבי הסשן. לשם כך, הוא יוצר תמונת מצב של סטטוס המדיה הנוכחי, ממיר את הסטטוס לבקשת טעינה וממשיך את הסשן עם בקשת הטעינה.
במקרה הצורך, אפשר לשנות את בקשת הטעינה שנוצרה על ידי ה-Web Receiver באמצעות מנגנון היירוט של ההודעות SESSION_STATE. אם אתם רוצים להוסיף נתונים בהתאמה אישית לבקשת הטעינה, מומלץ להוסיף אותם ל-loadRequestData.customData.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.SESSION_STATE,
function (sessionState) {
// Override sessionState.loadRequestData if needed.
const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
sessionState.loadRequestData.credentials = newCredentials;
// Add custom data if needed.
sessionState.loadRequestData.customData = {
'membership': 'PREMIUM'
};
return sessionState;
});
אפשר לאחזר את הנתונים המותאמים אישית מ-loadRequestData.customData ב-RESUME_SESSION message interceptor.
let cred_ = null;
let membership_ = null;
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.RESUME_SESSION,
function (resumeSessionRequest) {
let sessionState = resumeSessionRequest.sessionState;
// Modify sessionState.loadRequestData if needed.
cred_ = sessionState.loadRequestData.credentials;
// Retrieve custom data.
membership_ = sessionState.loadRequestData.customData.membership;
return resumeSessionRequest;
});
טעינה מראש של תוכן
מקלט האינטרנט תומך בטעינה מראש של קובצי מדיה אחרי הפריט הנוכחי להפעלה בתור.
פעולת הטעינה מראש מורידה מראש כמה קטעים מהפריטים הבאים. ההגדרה מתבצעת בערך preloadTime באובייקט QueueItem (ברירת המחדל היא 20 שניות אם לא צוין ערך). הזמן מבוטא בשניות, ביחס לסוף הפריט שמופעל כרגע . אפשר להזין רק ערכים חיוביים. לדוגמה, אם הערך הוא 10 שניות, הפריט הזה ייטען מראש 10 שניות לפני שהפריט הקודם יסתיים. אם הזמן לטעינה מראש ארוך יותר מהזמן שנותר ב-currentItem, הטעינה מראש תתבצע בהקדם האפשרי. לכן, אם מציינים ערך גדול מאוד של טעינה מראש ב-queueItem, אפשר להשיג את האפקט שבכל פעם שאנחנו מפעילים את הפריט הנוכחי, אנחנו כבר טוענים מראש את הפריט הבא. עם זאת, אנחנו משאירים את ההגדרה והבחירה של הערך הזה למפתח, כי הוא יכול להשפיע על רוחב הפס ועל ביצועי הסטרימינג של הפריט שמופעל כרגע.
כברירת מחדל, הטעינה מראש תפעל בתוכן בסטרימינג מסוג HLS, DASH ו-Smooth.
קובצי וידאו רגילים בפורמט MP4 וקובצי אודיו כמו MP3 לא ייטענו מראש, כי מכשירי Cast תומכים רק ברכיב מדיה אחד ואי אפשר להשתמש בהם כדי לטעון מראש בזמן שפריט תוכן קיים עדיין פועל.
הודעות מותאמות אישית
החלפת הודעות היא שיטת האינטראקציה העיקרית באפליקציות Web Receiver.
השולח מנפיק הודעות למקלט אינטרנט באמצעות ממשקי ה-API של השולח לפלטפורמה שבה השולח פועל (Android, iOS, אינטרנט). לאובייקט האירוע (שהוא הביטוי של ההודעה) שמועבר לרכיבי ה-event listener יש רכיב נתונים (event.data) שבו הנתונים מקבלים את המאפיינים של סוג האירוע הספציפי.
אפליקציית Web Receiver יכולה להאזין להודעות במרחב שמות מסוים. כך אפליקציית Web Receiver תומכת בפרוטוקול של מרחב השמות הזה. לאחר מכן, כל שולח מחובר שרוצה לתקשר במרחב השמות הזה צריך להשתמש בפרוטוקול המתאים.
כל מרחבי השמות מוגדרים על ידי מחרוזת וחייבים להתחיל ב-"urn:x-cast:" ואחריו מחרוזת כלשהי. לדוגמה, "urn:x-cast:com.example.cast.mynamespace".
הנה קטע קוד של Web Receiver להאזנה להודעות בהתאמה אישית משולחים מחוברים:
const context = cast.framework.CastReceiverContext.getInstance();
const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
// handle customEvent.
});
context.start();
באופן דומה, אפליקציות Web Receiver יכולות לעדכן את השולחים לגבי המצב של Web Receiver על ידי שליחת הודעות לשולחים המחוברים. אפליקציית Web Receiver יכולה לשלוח הודעות באמצעות sendCustomMessage(namespace, senderId, message) ב-CastReceiverContext.
מקלט אינטרנט יכול לשלוח הודעות לשולח ספציפי, בתגובה להודעה שהתקבלה או בגלל שינוי במצב האפליקציה. בנוסף להעברת הודעות בחיבור מנקודה לנקודה (במגבלה של 64KB), אפליקציית Web Receiver יכולה גם לשדר הודעות לכל השולחים המחוברים.
Cast למכשירי אודיו
במדריך של Google Cast למכשירי אודיו מוסבר איך להפעיל אודיו בלבד.
Android TV
בקטע הזה מוסבר איך Google Web Receiver משתמש בקלט שלכם כהפעלה, ועל התאימות ל-Android TV.
שילוב האפליקציה עם השלט הרחוק
מקלט האינטרנט של Google שפועל במכשיר Android TV מתרגם את הקלט מהפקדים של המכשיר (למשל, שלט רחוק ידני) כהודעות להפעלת מדיה שמוגדרות למרחב השמות urn:x-cast:com.google.cast.media, כפי שמתואר בקטע הודעות להפעלת מדיה. האפליקציה צריכה לתמוך בהודעות האלה כדי לשלוט בהפעלת המדיה באפליקציה, ולאפשר שליטה בסיסית בהפעלה באמצעות קלט הבקרה של Android TV.
הנחיות לתאימות ל-Android TV
ריכזנו כאן כמה המלצות ובעיות נפוצות שכדאי להימנע מהן כדי לוודא שהאפליקציה תואמת ל-Android TV:
- חשוב לזכור שמחרוזת סוכן המשתמש מכילה גם את Android וגם את CrKey. יכול להיות שחלק מהאתרים יפנו לאתר לנייד בלבד כי הם מזהים את התווית Android. אל תניחו ש"Android" במחרוזת של סוכן המשתמש תמיד מציין משתמש בנייד.
- מחסנית המדיה של Android עשויה להשתמש ב-GZIP שקוף כדי לאחזר נתונים. חשוב לוודא שנתוני המדיה יכולים להגיב ל-
Accept-Encoding: gzip. - אירועי מדיה ב-HTML5 ב-Android TV עשויים להיות מופעלים בתזמונים שונים מאשר ב-Chromecast, וזה עשוי לחשוף בעיות שהיו מוסתרות ב-Chromecast.
- כשמעדכנים את המדיה, צריך להשתמש באירועים שקשורים למדיה ומופעלים על ידי רכיבי
<audio>/<video>, כמוtimeupdate,pauseו-waiting. מומלץ להימנע משימוש באירועים שקשורים לרשת כמוprogress,suspendו-stalled, כי הם בדרך כלל תלויים בפלטפורמה. בקטע אירועי מדיה מוסבר איך לטפל באירועי מדיה במקלט. - כשמגדירים את אישורי ה-HTTPS של אתר המקלט, חשוב לכלול אישורי CA של מתווכים. כדי לבדוק אם נתיב האישור המהימן של האתר כולל אישור CA עם התווית extra download, אפשר להיכנס לדף הבדיקה של Qualsys SSL. אם הוא כולל אישור כזה, יכול להיות שהוא לא ייטען בפלטפורמות שמבוססות על Android.
- ב-Chromecast דף המקלט מוצג במישור גרפי של 720p, אבל בפלטפורמות Cast אחרות, כולל Android TV, הדף יכול להיות מוצג ברזולוציה של עד 1080p. חשוב לוודא שדף המקלט משתנה בצורה חלקה ברזולוציות שונות.