為您的 Android 應用程式新增進階功能

廣告插播

Android Sender SDK 支援特定媒體串流中的廣告插斷和隨播廣告。

如要進一步瞭解廣告插播的運作方式,請參閱「Web Receiver 廣告插播總覽」。

雖然可以在傳送端和接收端指定中斷點,但建議在 Web ReceiverAndroid TV Receiver 上指定中斷點,以確保各平台行為一致。

在 Android 上,使用 AdBreakClipInfoAdBreakInfo 在載入指令中指定廣告插播時間點:

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

建立自訂管道後,傳送者可以使用 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,如果已設定) 會顯示目前投放媒體的插圖。圖片藝術作品的網址通常會包含在媒體的 MediaMetadata 中,但傳送者應用程式可能有網址的替代來源。

ImagePicker 類別定義從 MediaMetadata 的圖片清單中選取適當圖片的方法,選取依據是圖片的用途,例如通知縮圖或全螢幕背景。預設 ImagePicker 實作一律會選擇第一張圖片,或是在 MediaMetadata 中沒有圖片時傳回空值。應用程式可以將 ImagePicker 設為子類別,並覆寫 onPickImage(MediaMetadata, ImageHints) 方法來提供替代實作項目,然後使用 CastMediaOptions.BuildersetImagePicker 方法選取該子類別。ImageHintsImagePicker 提供提示,說明要在 UI 中顯示的圖片類型和大小。

自訂 Cast 對話方塊

管理工作階段生命週期

SessionManager 是管理工作階段生命週期的中心位置。SessionManager 會監聽 Android MediaRouter 路線選取狀態的變更,以開始、繼續及結束工作階段。選取路徑後,SessionManager 會建立 Session 物件,並嘗試啟動或繼續執行。取消選取路線時,SessionManager 會結束目前的工作階段。

因此,為確保 SessionManager 能妥善管理工作階段生命週期,請務必確認下列事項:

視建立 Cast 對話方塊的方式而定,您可能需要執行其他動作:

零裝置狀態

如果您建立自訂 Cast 對話方塊,自訂 MediaRouteChooserDialog 應妥善處理找不到任何裝置的情況。對話方塊應顯示指標,讓使用者清楚瞭解應用程式是否仍在嘗試尋找裝置,以及探索嘗試是否已停止。

如果您使用預設 MediaRouteChooserDialog,系統已處理零裝置狀態。

後續步驟

您已瞭解如何為 Android 傳送端應用程式新增功能。現在可以為其他平台 (iOSWeb) 建構傳送端應用程式,或建構 Web 接收器應用程式