如何使用Chromecast - 投放按鈕操作

如何使用Chromecast - 投放按鈕操作

情境

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

說明

Chromecast 投放按鈕操作

完整程式碼

如果你需要完整程式碼,可以到 GitHub 觀看或下載。

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

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

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