Chromecast 投放按鈕操作

GivemepasS
10 min readSep 16, 2019

Chromecast 基礎概念 講到怎麼使用 Chromecast 以及一些簡易的概念,這樣一來,我們就可以進入到寫程式的步驟了。

程式碼

GitHub

首先將 chromecast 的第三方導入。

implementation 'com.google.android.gms:play-services-cast-framework:17.1.0'

這樣一來就可以使用 Chromecast 所提供的 UI 操作頁面,讓我們來開一個新專案,建立好基礎元件吧!

一開始我們先了解一下 CastContext 這個東西,從官方網站說明可以知道他是一個全域的 Context 物件,你可以透過以下語法拿到實體物件。

mCastContext = CastContext.getSharedInstance(this)

接著有一個很重要的步驟就是實作 CastOptions 介面,這個類別是用來控制我們連接到哪一個 Receiver,以及在投放過程中,如果 App 進入到背景模式播放,我們的 Notification 那邊會出現一個常駐訊息,點選以後的行為也是在這邊進行操作的。

class CastOptionsProvider : OptionsProvider {
override fun getCastOptions(context: Context?): CastOptions {
val notificationOptions = NotificationOptions.Builder()
.setActions(
Arrays.asList(
MediaIntentReceiver.ACTION_SKIP_NEXT,
MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK,
MediaIntentReceiver.ACTION_STOP_CASTING
), intArrayOf(1, 2)
)
.setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
.build()
val mediaOptions = CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name)
.build()
return CastOptions.Builder()
.setReceiverApplicationId(context?.getString(R.string.app_id))
.setCastMediaOptions(mediaOptions)
.build()
}
override fun getAdditionalSessionProviders(contex: Context?): MutableList<SessionProvider>? {
return null
}
}

當你新增這個類別的時候,你會發現有三個地方需要補上檔案的,分別是:

  • app_id
  • ExpandedControlsActivity
  • 以及 AndroidMenifest 要補上 Metadata

app_id 主要對應到 app 的 Receiver,它可以讓你的 app 跟 Receiver 進行連線,所以這個 id 非常重要。

由於新增 Receiver 要收費,我們可以拿 Google 官方範例的 id 進行練習,將此 id 新增在 string.xml 內,就可以透過 R.string.app_id 進行設定了。

<resources>
<string name="app_id">4F8B3483</string>
</resources>

ExpandedControlsActivity 很有趣,當我們投放後的細節頁,就會呈現在這個畫面,而且這個畫面不需要寫太多程式,因為 Google 官方已經將大部分的畫面都實作完成了。

class ExpandedControlsActivity: ExpandedControllerActivity() {
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.expanded_controller, menu)
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item)
return true
}
}

過來這邊你發現 menu 是需要客製化的,所以我們將官方範例內的 menu 拿過來改一下。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
android:id="@+id/media_route_menu_item"
android:title=""
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
android:orderInCategory="101"
app:showAsAction="always"/>

</menu>

這邊你會看到,我們指定讓他指向androidx.mediarouter.app.MediaRouteActionProvider ,這樣一來,在點下這個按鍵的時候,就會去尋找對應的裝置來連結了。

最後我們再到 AndroidMenifest 內加入了一行宣告。

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

接著我們到 MainActivity 內新增一個區塊,裡面新增了一個 menu icon,也就是我們的投放按鈕,這個按鈕是由官方提供,所以我們可以直接在 xml 內直接設定這顆按鈕。

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.player, menu)
mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(applicationContext, menu, R.id.media_route_menu_item)
return true
}

接著新增一個 player.xml 來處理。

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >

<item
android:id="@+id/media_route_menu_item"
android:title=""
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
android:orderInCategory="101"
app:showAsAction="always" />
</menu>

可以看到也是跟 ExpandedControlsActivity 相同,都是透過 MediaRouteActionProvider 來幫忙處理。

這樣就完成了一個初步的投放按鈕設定了,執行一下專案來看看效果如何?

一開始左上角會出現一個投放按鈕,當按下去以後,會跳出周圍有顯示的裝置,記得這邊要將網路切到跟投放裝置同一個 Wifi 之下。

當我們點下去以後,就會發現投放按鈕變成連結的狀態了。

此時,我們再點選一次投放按鈕,會發現跳出一個小視窗顯示我們投放的內容,由於現在沒有投放任何內容,所以你會看到一個空空的小視窗。

這樣就初步完成我們投放效果,但是其實還有更細緻的操作處理,譬如說我們投放按鈕如果是第一次進入時,使用者並不知道怎麼操作這個按鈕,我們會顯示一個導引頁,這部分 Google 也幫我們做好了。

首先我們先加入一段程式碼。

mCastStateListener = CastStateListener { newState ->
if (newState != CastState.NO_DEVICES_AVAILABLE) {
mediaRouteMenuItem.run {
mIntroductoryOverlay?.remove()
mIntroductoryOverlay = IntroductoryOverlay.Builder(this@MainActivity, mediaRouteMenuItem)
.setTitleText(getString(R.string.introducing_cast))
.setOverlayColor(R.color.primary)
.setOnOverlayDismissedListener { mIntroductoryOverlay = null }
.build()
}
mIntroductoryOverlay?.show()
}
}

上面這段程式碼就可以簡易幫我們完成這樣的效果,它偵測到我們投放的狀態,當偵測到裝置的時候,就可以透過這段程式碼完成以下的效果。

這樣只是簡單完成投放按鈕,後續還有許多配置需要處理,就留到下一章節吧。

--

--