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

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

ה-SDK של Android Sender תומך בהפסקות למודעות ובמודעות נלוות זרם מדיה נתון.

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

אפשר לציין הפסקות גם אצל השולח וגם אצל המקבל, אבל מומלץ שהן יופיעו שצוינו ב-Web Acceptr המקלט של 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 method:

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);
}

לאחר יצירת הערוץ המותאם אישית, השולח יכול להשתמש 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, ייתכן שיהיה צורך לבצע פעולות נוספות בוצע:

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

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

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

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

השלבים הבאים

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