הפסקות למודעות
ערכת ה-SDK של Android Sender תומכת בהפסקות למודעות ובמודעות נלוות בתוך סטרימינג נתון של מדיה.
בסקירה הכללית על הפסקות למודעות ב-Web Receiver מוסבר איך פועלות הפסקות למודעות.
אפשר לציין הפסקות גם באפליקציית השולח וגם באפליקציית המקלט, אבל מומלץ לציין אותן ב-Web Receiver וב-Android TV Receiver כדי לשמור על התנהגות עקבית בכל הפלטפורמות.
ב-Android, מציינים הפסקות למודעות בפקודת טעינה באמצעות AdBreakClipInfo ו-AdBreakInfo:
val breakClip1: AdBreakClipInfo = AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build() val breakClip2: AdBreakClipInfo = … val breakClip3: AdBreakClipInfo = … val break1: AdBreakClipInfo = AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build() val mediaInfo: MediaInfo = MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build() val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build() remoteMediaClient.load(mediaLoadRequestData)
AdBreakClipInfo breakClip1 = new AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build(); AdBreakClipInfo breakClip2 = … AdBreakClipInfo breakClip3 = … AdBreakInfo break1 = new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build(); MediaInfo mediaInfo = new MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build(); MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build(); remoteMediaClient.load(mediaLoadRequestData);
הוספת פעולות בהתאמה אישית
אפליקציית השולח יכולה להרחיב את
MediaIntentReceiver
כדי לטפל בפעולות בהתאמה אישית או לשנות את ההתנהגות שלה. אם הטמעתם MediaIntentReceiver משלכם, אתם צריכים להוסיף אותו למניפסט וגם להגדיר את השם שלו ב-CastMediaOptions. בדוגמה הזו יש פעולות בהתאמה אישית שמחליפות את הפעולות של הפעלת מדיה מרחוק, לחיצה על כפתור המדיה וסוגים אחרים של פעולות.
// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
// In your OptionsProvider var mediaOptions = CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name) .build() // Implementation of MyMediaIntentReceiver internal class MyMediaIntentReceiver : MediaIntentReceiver() { override fun onReceiveActionTogglePlayback(currentSession: Session) { } override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) { } override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) { } }
// In your OptionsProvider CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName()) .build(); // Implementation of MyMediaIntentReceiver class MyMediaIntentReceiver extends MediaIntentReceiver { @Override protected void onReceiveActionTogglePlayback(Session currentSession) { } @Override protected void onReceiveActionMediaButton(Session currentSession, Intent intent) { } @Override protected void onReceiveOtherAction(Context context, String action, Intent intent) { } }
הוספת ערוץ בהתאמה אישית
כדי שאפליקציית השולח תוכל לתקשר עם אפליקציית המקלט, האפליקציה צריכה ליצור ערוץ בהתאמה אישית. השולח יכול להשתמש בערוץ המותאם אישית כדי לשלוח הודעות מחרוזת למקבל. כל ערוץ מותאם אישית מוגדר על ידי מרחב שמות ייחודי, וחייב להתחיל בקידומת urn:x-cast:, לדוגמה, urn:x-cast:com.example.custom. אפשר להגדיר כמה ערוצים בהתאמה אישית, ולכל אחד מהם יהיה מרחב שמות ייחודי. אפליקציית המקלט יכולה גם לשלוח ולקבל הודעות באמצעות אותו מרחב שמות.
הערוץ המותאם אישית מוטמע באמצעות הממשק Cast.MessageReceivedCallback:
class HelloWorldChannel : MessageReceivedCallback { val namespace: String get() = "urn:x-cast:com.example.custom" override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) { Log.d(TAG, "onMessageReceived: $message") } }
class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return "urn:x-cast:com.example.custom"; } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { Log.d(TAG, "onMessageReceived: " + message); } }
אחרי שהאפליקציה השולחת מחוברת לאפליקציה המקבלת, אפשר ליצור את הערוץ בהתאמה אישית באמצעות השיטה setMessageReceivedCallbacks:
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
אחרי שיוצרים את הערוץ בהתאמה אישית, השולח יכול להשתמש ב-method sendMessage כדי לשלוח הודעות מחרוזת למקלט דרך הערוץ הזה:
private fun sendMessage(message: String) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.namespace, message) .setResultCallback { status -> if (!status.isSuccess) { Log.e(TAG, "Sending message failed") } } } catch (e: Exception) { Log.e(TAG, "Exception while sending message", e) } } }
private void sendMessage(String message) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message) .setResultCallback( status -> { if (!status.isSuccess()) { Log.e(TAG, "Sending message failed"); } }); } catch (Exception e) { Log.e(TAG, "Exception while sending message", e); } } }
תמיכה בהפעלה אוטומטית
עיינו בקטע ממשקי API להפעלה אוטומטית ולהוספה לתור.
שינוי בחירת התמונות לווידג'טים של חוויית המשתמש (UX)
רכיבים שונים של המסגרת (כלומר תיבת הדו-שיח של Cast, הבקר המיניאטורי וה-UIMediaController, אם הם מוגדרים כך) יציגו גרפיקה של המדיה שמועברת כרגע. כתובות ה-URL של הגרפיקה של התמונה בדרך כלל כלולות ב-MediaMetadata של המדיה, אבל יכול להיות שלאפליקציית השליחה יש מקור חלופי לכתובות ה-URL.
הכיתה
ImagePicker
מגדירה אמצעי לבחירת תמונה מתאימה מרשימת התמונות
ב-MediaMetadata, על סמך השימוש בתמונה, למשל, תמונה ממוזערת של התראה או רקע במסך מלא. ההטמעה של ImagePicker כברירת מחדל תמיד בוחרת את התמונה הראשונה, או מחזירה ערך null אם אין תמונה זמינה ב-MediaMetadata. האפליקציה יכולה ליצור מחלקת משנה של ImagePicker ולבטל את השיטה onPickImage(MediaMetadata, ImageHints) כדי לספק הטמעה חלופית, ואז לבחור את מחלקת המשנה הזו באמצעות השיטה setImagePicker של CastMediaOptions.Builder.
ImageHints
מספק רמזים ל-ImagePicker לגבי הסוג והגודל של התמונה שצריך לבחור כדי להציג בממשק המשתמש.
התאמה אישית של תיבות הדו-שיח של Cast
ניהול מחזור החיים של סשן
SessionManager הוא המקום המרכזי לניהול מחזור החיים של הסשן. SessionManager מקשיב לשינויים במצב בחירת המסלול של Android MediaRouter כדי להתחיל, להמשיך ולסיים סשנים. כשבוחרים מסלול, SessionManager יוצר אובייקט Session ומנסה להפעיל או להמשיך אותו. כשמבטלים את הבחירה במסלול, SessionManager מסיים את הסשן הנוכחי.
לכן, כדי לוודא ש-SessionManager מנהל את מחזורי החיים של הסשנים כמו שצריך, אתם צריכים לוודא ש:
- בתיבת הדו-שיח של בורר המסלולים, מפעילים את
MediaRouter.selectRoute(MediaRouter.RouteInfo)כשהמשתמש בוחר מכשיר. - בתיבת הדו-שיח של בקר המסלול (במצב מחובר או במצב העברה), מפעילים את
MediaRouter.unselect(int)כשהמשתמש מפסיק את ההעברה.
בהתאם לאופן שבו אתם יוצרים את תיבות הדו-שיח של Cast, יכול להיות שתצטרכו לבצע פעולות נוספות:
- אם אתם יוצרים תיבות דו-שיח של Cast באמצעות
MediaRouteChooserDialogו-MediaRouteControllerDialog, תיבות הדו-שיח האלה יעדכנו את בחירת הנתיב ב-MediaRouterבאופן אוטומטי, ולא תצטרכו לעשות שום דבר. - אם הגדרתם את הכפתור להפעלת Cast באמצעות
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)אוCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton), תיבות הדו-שיח נוצרות בפועל באמצעותMediaRouteChooserDialogו-MediaRouteControllerDialog, כך שגם במקרה הזה אין צורך לעשות דבר. - במקרים אחרים, תצטרכו ליצור תיבות דו-שיח מותאמות אישית של Cast, ולכן תצטרכו לפעול לפי ההוראות שלמעלה כדי לעדכן את מצב בחירת המסלול ב-
MediaRouter.
מצב של אפס מכשירים
אם אתם יוצרים תיבות דו-שיח מותאמות אישית של Cast, ה-MediaRouteChooserDialog המותאם אישית צריך לטפל כראוי במקרה שבו לא נמצאו מכשירים. בתיבת הדו-שיח צריכים להיות אינדיקטורים שמבהירים למשתמשים מתי האפליקציה עדיין מנסה למצוא מכשירים ומתי ניסיון הגילוי כבר לא פעיל.
אם אתם משתמשים ב-MediaRouteChooserDialog שמוגדר כברירת מחדל, המצב של אפס מכשירים כבר מטופל.
השלבים הבאים
אלה כל התכונות שאפשר להוסיף לאפליקציית השליחה ל-Android. עכשיו אתם יכולים ליצור אפליקציית שליחה לפלטפורמה אחרת (iOS או אינטרנט), או ליצור אפליקציית Web Receiver.