הוספה של תכונות מתקדמות לאפליקציית Android

הפסקות למודעות

Android Sender SDK מספק תמיכה בהפסקות למודעות ובמודעות נלוות בסטרימינג של מדיה נתון.

למידע נוסף על אופן הפעולה של הפסקות למודעות, קראו את הסקירה הכללית בנושא הפסקות למודעות במכשירי קצה לאינטרנט.

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

ב-Android, מציינים הפסקות למודעות בפקודת טעינה באמצעות AdBreakClipInfo ו-AdBreakInfo:

Kotlin
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)
Java
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" />
Kotlin
// 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) {
    }
}
Java
// 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:

Kotlin
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")
    }
}
Java
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:

Kotlin
try {
    mCastSession.setMessageReceivedCallbacks(
        mHelloWorldChannel.namespace,
        mHelloWorldChannel)
} catch (e: IOException) {
    Log.e(TAG, "Exception while creating channel", e)
}
Java
try {
    mCastSession.setMessageReceivedCallbacks(
            mHelloWorldChannel.getNamespace(),
            mHelloWorldChannel);
} catch (IOException e) {
    Log.e(TAG, "Exception while creating channel", e);
}

אחרי שיוצרים את הערוץ המותאם אישית, השולח יכול להשתמש ב-method‏ sendMessage כדי לשלוח הודעות מחרוזות לנמען דרך הערוץ הזה:

Kotlin
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)
        }
    }
}
Java
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 להפעלה אוטומטית ולתורים.

שינוי ברירת המחדל לבחירת תמונות בווידג'טים של חוויית המשתמש

רכיבים שונים של המסגרת (כלומר תיבת הדו-שיח של 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 ינהל את מחזורי החיים של הסשנים בצורה תקינה, צריך לוודא את הדברים הבאים:

בהתאם לאופן שבו יוצרים את תיבת הדו-שיח של ההעברה (cast), יכול להיות שתצטרכו לבצע פעולות נוספות:

  • אם יוצרים תיבת דו-שיח של העברה באמצעות MediaRouteChooserDialog ו-MediaRouteControllerDialog, תיבת הדו-שיח הזו תעדכן את בחירת המסלול ב-MediaRouter באופן אוטומטי, כך שאין צורך לבצע שום פעולה.
  • אם הגדרתם את לחצן ההעברה (cast) באמצעות CastButtonFactory.setUpMediaRouteButton(Context, Menu, int) או CastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton), תיבת הדו-שיח נוצרת בפועל באמצעות MediaRouteChooserDialog ו-MediaRouteControllerDialog, כך שאין צורך לבצע שום פעולה.
  • במקרים אחרים, תצטרכו ליצור תיבת דו-שיח בהתאמה אישית להעברה (cast), ולכן תצטרכו לפעול לפי ההוראות שלמעלה כדי לעדכן את מצב בחירת המסלול ב-MediaRouter.

מצב אפס מכשירים

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

אם אתם משתמשים ב-MediaRouteChooserDialog שמוגדר כברירת מחדל, המצב 'אפס מכשירים' כבר מטופל.

השלבים הבאים

זהו הסיום של התכונות שאפשר להוסיף לאפליקציית השליחה ל-Android. עכשיו אפשר ליצור אפליקציית שליחה לפלטפורמה אחרת (iOS או אינטרנט), או ליצור אפליקציית קליטה לאינטרנט.