将 Android Sender 应用从 Cast SDK v2 迁移到 Cast 应用框架 (CAF)

通过以下步骤,您可以将 Android 发送器应用从 Cast SDK v2 转换为基于 CastContext singleton 的 CAF 发送器。

Cast CAF 发送端 SDK 使用 CastContext 代表您管理 GoogleAPIClient。CastContext 会为您管理生命周期、错误和回调,从而大大简化 Cast 应用的开发。

简介

  • CAF 发送方仍作为 Google Play 服务的一部分通过 Android SDK 管理器进行分发
  • 添加了新的软件包,负责遵守 Google Cast 设计核对清单 (com.google.android.gms.cast.framework.*)
  • CAF 发送方提供符合 Cast 用户体验要求的 widget;v2 不提供任何界面组件,需要您自行实现这些 widget。
  • 使用 Cast API 不再需要使用 GoogleApiClient。
  • CAF 发送器中的字幕与 v2 类似。

依赖项

V2 和 CAF 对支持库和 Google Play 服务(9.2.0 或更高版本)的依赖项相同,如支持库功能指南中所述

CAF 支持的最低 Android SDK 版本为 9 (Gingerbread)。

初始化

在 CAF 中,需要为 Cast 框架执行明确的初始化步骤。这需要初始化 CastContext singleton,并使用适当的 OptionsProvider 来指定 Web Receiver 应用 ID 和任何其他全局选项。

public class CastOptionsProvider implements OptionsProvider {

    @Override
    public CastOptions getCastOptions(Context context) {
        return new CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .build();
    }

    @Override
    public List<SessionProvider> getAdditionalSessionProviders(Context context) {
        return null;
    }
}

在应用 AndroidManifest.xml 文件的“application”标记内声明 OptionsProvider

<application>
...
    <meta-data
        android:name=
            "com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
        android:value="com.google.sample.cast.refplayer.CastOptionsProvider" />
</application>

在每个 activity 的 onCreate 方法中延迟初始化 CastContext

private CastContext mCastContext;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.video_browser);
    setupActionBar();

    mCastContext = CastContext.getSharedInstance(this);
}

在 v2 中,这些步骤不是必需的。

设备发现

在 CAF 中,当应用分别进入前台和后台时,框架会自动启动和停止发现过程。不应使用 MediaRouteSelectorMediaRouter.Callback

“投放”按钮和“投放”对话框

与 v2 中一样,这些组件由 MediaRouter 支持库提供。

投屏按钮仍由 MediaRouteButton 实现,并且可以作为菜单中的菜单项添加到您的 activity 中(使用 ActionBarToolbar)。

<item
    android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:actionProviderClass="android.support.v7.app.MediaRouteActionProvider"
    app:showAsAction="always"/>

使用 CastButtonFactory 替换每个 activity 的 onCreateOptionMenu() 方法,以将 MediaRouteButton 连接到 Cast 框架:

private MenuItem mediaRouteMenuItem;

public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    getMenuInflater().inflate(R.menu.browse, menu);
    mediaRouteMenuItem =
        CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
                                                menu,
                                                R.id.media_route_menu_item);
    return true;
}

当用户点按该按钮时,系统会自动显示“投放”对话框。

设备控制

在 CAF 中,设备控制主要由框架处理。发送器应用无需处理(也不应尝试处理)使用 GoogleApiClient 连接到设备并启动 Web 接收器应用。发送者与 Web Receiver 之间的互动现在表示为“会话”。SessionManager 类可处理会话生命周期,并根据用户手势自动启动和停止会话:当用户在 Cast 对话框中选择 Cast 设备时,会话会启动;当用户在 Cast 对话框中点按“停止投屏”按钮或发送方应用本身终止时,会话会结束。发送方应用可以通过向 SessionManager 注册 SessionManagerListener 来接收会话生命周期事件的通知。SessionManagerListener 回调定义了所有会话生命周期事件的回调方法。

CastSession 类表示与 Cast 设备的会话。该类具有用于控制设备音量和静音状态的方法,这些方法之前在 v2 中使用 Cast.CastApi 的方法完成。

在 v2 中,Cast.Listener 回调提供了有关设备状态(包括音量、静音状态、待机状态等)变化的通知。

在 CAF 中,音量/静音状态更改通知仍通过 Cast.Listener 中的回调方法传递;这些监听器通过 CastSession 注册。所有剩余的设备状态通知都通过 CastStateListener 回调进行传递;这些监听器通过 CastSession 进行注册。请务必在关联的 fragment、activity 或应用转到后台时取消注册监听器。

重新连接逻辑

与 v2 一样,CAF 会尝试重新建立因临时 WiFi 信号丢失或其他网络错误而中断的网络连接。现在,此操作是在会话级别完成的;当连接丢失时,会话可以进入“暂停”状态,当连接恢复时,会话将转换回“已连接”状态。在此过程中,框架会负责重新连接到 Web 接收器应用并重新连接任何 Cast 渠道。

此外,CAF 还添加了默认启用的自动会话恢复功能(可通过 CastOptions 停用)。如果发送方应用在 Cast 会话进行期间被发送到后台或被终止(通过滑动关闭或因崩溃而终止),当发送方应用返回前台或重新启动时,框架会尝试恢复该会话;这由 SessionManager 自动处理,该类会在任何已注册的 SessionManagerListener 实例上发出适当的回调。

自定义渠道注册

在 v2 中,自定义渠道(使用 Cast.MessageReceivedCallback 实现)会注册到 Cast.CastApi。在 CAF 中,自定义渠道会改为向 CastSession 实例注册。可以在 SessionManagerListener.onSessionStarted 回调方法中完成注册。对于媒体应用,不再需要通过 Cast.CastApi.setMessageReceivedCallbacks 显式注册媒体控制渠道;如需了解详情,请参阅下一部分。

媒体控件

v2 类 RemoteMediaPlayer 已弃用,不应再使用。在 CAF 中,它已被新的 RemoteMediaClient 类取代,该类通过更便捷的 API 提供等效功能。无需显式初始化或注册此对象;如果所连接的 Web 接收器应用支持媒体命名空间,框架会在会话开始时自动实例化该对象并注册底层媒体渠道。

RemoteMediaClient 可作为 CastSession 对象的 getRemoteMediaClient 方法进行访问。

在 v2 中,在 RemoteMediaPlayer 上发出的所有媒体请求都会通过 PendingResult 回调返回 RemoteMediaPlayer.MediaChannelResult

在 CAF 中,在 RemoteMediaClient 上发出的所有媒体请求都会通过 PendingResult 回调返回 RemoteMediaClient.MediaChannelResult,该回调可用于跟踪请求的进度和最终结果。

v2 RemoteMediaPlayer 会通过 RemoteMediaPlayer.OnStatusUpdatedListener 发送有关 Web 接收器上媒体播放器状态变化的通知。

在 CAF 中,RemoteMediaClient 通过其 RemoteMediaClient.Listener 接口提供等效的回调。可以向 RemoteMediaClient 注册任意数量的监听器,这使得多个发送方组件可以共享与会话关联的单个 RemoteMediaClient 实例。

在 v2 中,发送方应用必须承担使界面与 Web 接收器上的媒体播放器状态保持同步的负担。

在 CAF 中,类 UIMediaController 承担了大部分此类责任。

介绍性叠加层

V2 不提供介绍性叠加层界面。

CAF 提供了一个自定义视图 IntroductoryOverlay,可用于在首次向用户显示“投射”按钮时突出显示此按钮。

迷你控制器

在 v2 中,您需要在发送设备应用中从头开始实现迷你控制器。

在 CAF 中,SDK 提供了一个自定义视图 MiniControllerFragment,您可以将其添加到想要在其中显示迷你控制器的 activity 的应用布局文件中。

通知和锁定屏幕

在 v2 中,SDK 不提供通知和锁定屏幕的控制器。对于该 SDK,您需要使用 Android 框架 API 将这些功能构建到发送方应用中。

在 CAF 中,SDK 提供了一个 NotificationsOptions.Builder,可帮助您在发送设备应用中针对通知和锁定屏幕构建媒体控件。在初始化 CastContext 时,可以使用 CastOptions 启用通知和锁定屏幕控件。

public CastOptions getCastOptions(Context context) {
    NotificationOptions notificationOptions = new NotificationOptions.Builder()
            .setTargetActivityClassName(VideoBrowserActivity.class.getName())
            .build();
    CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .build();

    return new CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build();
}

展开的控制器

在 v2 中,您需要在发送设备应用中从头开始实现展开的控制器。

CAF 提供了一个 UIMediaController 辅助类,可让您轻松构建自己的扩展控制器。

CAF 添加了一个预构建的展开控制器 widget ExpandedControllerActivity,您可以直接将其添加到应用中。您不再需要使用 UIMediaController 实现自定义的展开控制器。

音频焦点

在 v2 中,您需要使用 MediaSessionCompat 来管理音频焦点。

在 CAF 中,音频焦点由系统自动管理。

调试日志记录

在 CAF 中,没有日志记录选项。

示例应用

我们提供了使用 CAF 的 Codelab 教程示例应用