GoogleCast集成简介

最近由于需要维护这一方面的东西,随即看了一下网络文档。发现中文圈还比较少。这篇就作为我的记录。详细的信息建议在在Google Cast官方文档里面查看,非常的全。Google Cast之前叫做Google Chromecast,可以把它理解成为一个SDK。硬件可以实现这样的SDK,例如国外的一些盒子,FireTV,PCCW的盒子以及谷歌自己的Chromecast硬件设备。它的作用就是能将手机,Pad,浏览器的内容投射到连接有Chromecast设备的屏幕上。挺方便的,在家看个YouTube或者在工作场所需要投屏展示内容的时候,都非常的便利。

Google Cast 分为两端:sender和receiver。就拿U2B举例子,在Android手机安装的软件叫做sender,在盒子里相应接收响应请求的叫做receiver。一般来Google自家的程序会有一个默认的由谷歌开发的receiver,当然还可以通过API自定义一个可以处理定制化的sender消息的receiver,例如TED的receiver。


Receiver的结构挺有意思,其实就是一个能运行Chrome的硬件设备,通过网络去请求某个服务器里面的HTML&CSS&JS,然后打开这个网页播放视频。

Google Cast SDK v3 Codelab基本涵盖了日常开发需要的步骤,引入SDK,添加CastButton,增加MiniController,添加Notification和LockScreen等等,非常详细,建议好好利用。

添加CastButton

首先我们需要给程序添加一个CastButton,有两种方法。一直是在Activity的Menu里面添加一个Item,另外一种是通过普通的Layout xml文件来添加。

以Menu的形式添加

menu.xml

1
2
3
4
5
6
<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"
/>

然后在onCreateOptionMenu(Menu menu)里面获取到这个MenuItem后通过CastButtonFactory初始化。

1
2
getMenuInflater().inflate(R.menu.main, menu);    
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu, R.id.media_route_menu_item);

在Layout文件里面添加

前提是需要你的Activity继承自FragmentActivity

1
2
3
4
5
6
7
<android.support.v7.app.MediaRouteButton       
android:id="@+id/media_route_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:mediaRouteTypes="user"
android:visibility="gone" />

在Activity中也是一样,通过id找到这个空间,通过CastButtonFactory初始化。

1
2
mMediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);   
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), mMediaRouteButton);

监听GoogleCast的连接状态

一般情况,我们需要在用户播放视频的时候,点击右上角的Cast Button进行投射的时候,需要关闭当前的播放界面。所以,需要监听Cast的连接状态。Cast一共有四种状态:

  • NO_DEVICES_AVAILABLE:没有设备可用,即周围没有GoogleCast设备
  • NOT_CONNECTED:有设备可用,但是没有连接
  • CONNECTING:建立连接
  • CONNECTED:已经连接成功

可以通过CastStateListener来监听这四种状态控制逻辑。需要注意的是,Connecting是一个中间状态,在这个时候给GoogleCast发送数据是不行的,很有可能通过Session得到的remoteClient是个空。另外值得一提的是,Connected在隔一段时间没有发送数据的话,会自动断开到Not-Connected状态。

手动控制GoogleCast状态

在某些情况下,我们需要手动的控制Cast的状态,例如,在用户切换一个配置文件或者登出的时候,需要Stop当前的Cast。这个时候一般分为两种。

Stop当前的Cast,但保持连接(即Cast会到目标Receiver的idle状态)

1
2
3
4
5
CastContext castContext = CastContext.getSharedInstance(this);  
SessionManager sessionManager = castContext.getSessionManager();
if (sessionManager != null){
sessionManager.getCurrentCastSession().getRemoteMediaClient().stop();
}

通过获取到远程的remoteMediaClient调用stop方法即可。这里需要注意的是,如果是首次进入App的时候,没有Cast的sessionManager,所以需要做一下判断。

Disconnected当前的Cast(即Cast会恢复成GoogleCast默认的idle状态)

要想Disconnected方法还挺多,搜寻了一下SOF,基本都是这两种。

  • 通过获取SessionManager,调用endCurrentSession(true)来实现

    sessionManager.endCurrentSession(true); //获取SessionManager的方法见上面

  • 通过MediaRouter的unSelect方法传递一个reason。

    这里需要注意的是这四个参数只是用来描述断开连接的reason,不要被名字给迷惑了,在方法的注释当中写的有。
    @param reason The reason for disconnecting the current route.
    这样调用就可以了 MediaRouter.getInstance(this).unselect(MediaRouter.UNSELECT_REASON_DISCONNECTED);

  • 如果sender和receiver的时间没有同步的话,例如相差十来分钟,可能会导致无法cast
-------------The End-------------
请我喝一杯啤酒~