为您的 Android 应用添加高级功能

广告插播时间点

Android Sender SDK 支持在单个视频内使用广告插播时间点和 指定媒体流。

请参阅 网络接收器广告插播概览,了解详情 以便详细了解广告插播时间点的运作方式

虽然可以为发送者和接收者指定广告插播时间点,但建议同时为发送者和接收者指定 在网络接收器中指定,然后 Android TV 接收器,以便保持一致 在不同平台上的行为

在 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" />
<ph type="x-smartling-placeholder">
</ph>
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);
        }
    }
}

支持自动播放

请参阅自动播放和Queueing API

替换用户体验 widget 的图片选择

框架的各个组件(即“投射”对话框、迷你 控制器,而 UIMediaController(如果已配置)将显示海报图片 。图片海报图片的网址通常为 包含在媒体的 MediaMetadata 中,但发送器应用可能有 这些网址的备用来源

通过 ImagePicker 类定义了一种从图片列表中选择适当图片的方法。 在 MediaMetadata 中,具体取决于图片的使用方式,例如通知 缩略图或全屏背景默认的 ImagePicker 实现 则始终选择第一张图片,或者如果 MediaMetadata。您的应用可以创建 ImagePicker 的子类并替换 onPickImage(MediaMetadata, ImageHints) 方法提供备用实现,然后选择该子类 替换为 setImagePicker CastMediaOptions.Builder 的方法。 ImageHints 用于向 ImagePicker 提供有关要 选择在界面中显示

自定义 Cast 对话框

管理会话生命周期

SessionManager 是管理会话生命周期的中心位置。SessionManager 次收听 到 Android MediaRouter 路由选择状态会更改为启动、恢复和结束会话。如果某个路线 已选择,SessionManager将创建 Session 对象并尝试启动或恢复它。取消选中某个路线后 SessionManager会结束当前会话。

因此,为确保 SessionManager 正确管理会话生命周期,您需要 必须确保:

根据您创建 Cast 对话框的方式,您可能还需要执行其他操作 完成:

零设备状态

如果您创建自定义 Cast 对话框,您的自定义 MediaRouteChooserDialog 应正确处理设备未连接的情况 找到。该对话框中应包含指示标志,以便用户清楚地了解 应用仍在尝试查找设备,且未尝试查找 。

如果您使用的是默认 MediaRouteChooserDialog,则零设备状态 已处理。

后续步骤

以上就是可以向 Android 发送者应用中添加的功能。 您现在可以针对其他平台构建发送者应用 (iOS网站),或 构建 Web Receiver 应用