1. ภาพรวม
Codelab นี้จะสอนวิธีแก้ไขแอป Android TV ที่มีอยู่เพื่อรองรับการแคสต์และการสื่อสารจากแอปตัวส่ง Cast ที่มีอยู่
Google Cast และ Cast Connect คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยังทีวีได้ เซสชัน Google Cast ทั่วไปประกอบด้วยคอมโพเนนต์ 2 อย่าง ได้แก่ แอปพลิเคชันผู้ส่งและแอปพลิเคชันผู้รับ แอปพลิเคชันผู้ส่ง เช่น แอปบนอุปกรณ์เคลื่อนที่หรือเว็บไซต์ เช่น YouTube.com จะเริ่มต้นและควบคุมการเล่นของแอปพลิเคชันตัวรับการแคสต์ แอปพลิเคชันตัวรับการแคสต์คือแอป HTML 5 ที่ทำงานในอุปกรณ์ Chromecast และ Android TV
ระบบจะจัดเก็บสถานะเกือบทั้งหมดในเซสชัน Cast ไว้ในแอปพลิเคชันผู้รับ เมื่อสถานะอัปเดต เช่น มีการโหลดรายการสื่อใหม่ ระบบจะกระจายสถานะสื่อไปยังผู้ส่งทุกคน การออกอากาศเหล่านี้มีสถานะปัจจุบันของเซสชันการแคสต์ แอปพลิเคชันผู้ส่งใช้สถานะสื่อนี้เพื่อแสดงข้อมูลการเล่นใน UI
Cast Connect สร้างขึ้นจากโครงสร้างพื้นฐานนี้ โดยมีแอป Android TV ทำหน้าที่เป็นตัวรับ คลัง Cast Connect ช่วยให้แอป Android TV ของคุณรับข้อความและออกอากาศสถานะสื่อได้ราวกับเป็นแอปพลิเคชันตัวรับ Cast
เราจะสร้างอะไร
เมื่อทำ Codelab นี้เสร็จแล้ว คุณจะใช้แอปแคสต์ของผู้ส่งเพื่อแคสต์วิดีโอไปยังแอป Android TV ได้ นอกจากนี้ แอป Android TV ยังสื่อสารกับแอปผู้ส่งผ่านโปรโตคอลแคสต์ได้ด้วย
สิ่งที่คุณจะได้เรียนรู้
- วิธีเพิ่มคลัง Cast Connect ลงในแอป ATV ตัวอย่าง
- วิธีเชื่อมต่ออุปกรณ์ส่งสัญญาณแคสต์และเปิดแอป ATV
- วิธีเริ่มเล่นสื่อในแอป ATV จากแอปส่ง Cast
- วิธีส่งสถานะสื่อจากแอป ATV ไปยังแอปผู้ส่ง Cast
สิ่งที่คุณต้องมี
- Android SDK เวอร์ชันล่าสุด
- Android Studio เวอร์ชันล่าสุด โดยต้องเป็นเวอร์ชัน
Chipmunk | 2021.2.1
ขึ้นไป - อุปกรณ์ Android TV ที่เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอปและการแก้ไขข้อบกพร่องผ่าน USB
- โทรศัพท์ Android ที่เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอปและการแก้ไขข้อบกพร่อง USB
- สาย USB สำหรับเชื่อมต่อโทรศัพท์ Android และอุปกรณ์ Android TV กับคอมพิวเตอร์สำหรับพัฒนาซอฟต์แวร์
- ความรู้พื้นฐานเกี่ยวกับการพัฒนาแอปพลิเคชัน Android โดยใช้ Kotlin
2. รับโค้ดตัวอย่าง
คุณสามารถดาวน์โหลดโค้ดตัวอย่างทั้งหมดลงในคอมพิวเตอร์ได้...
และแตกไฟล์ ZIP ที่ดาวน์โหลด
3. เรียกใช้แอปตัวอย่าง
ก่อนอื่น มาดูว่าแอปตัวอย่างที่เสร็จสมบูรณ์มีลักษณะเป็นอย่างไร แอป Android TV ใช้ UI ของ Leanback และโปรแกรมเล่นวิดีโอพื้นฐาน ผู้ใช้สามารถเลือกวิดีโอจากรายการซึ่งจะเล่นบนทีวีเมื่อเลือก ผู้ใช้ยังแคสต์วิดีโอไปยังแอป Android TV ได้ด้วยแอปส่งบนอุปกรณ์เคลื่อนที่ที่มาพร้อมแอป
ลงทะเบียนอุปกรณ์ของนักพัฒนาแอป
หากต้องการเปิดใช้ความสามารถของ Cast Connect สําหรับการพัฒนาแอปพลิเคชัน คุณต้องลงทะเบียนหมายเลขซีเรียลของ Google Cast ของอุปกรณ์ Android TV ที่จะใช้ใน แผงควบคุมสําหรับนักพัฒนาแอป Cast คุณดูหมายเลขซีเรียลได้โดยไปที่การตั้งค่า > ค่ากำหนดของอุปกรณ์ > Google Cast > หมายเลขซีเรียลใน Android TV โปรดทราบว่าหมายเลขนี้แตกต่างจากหมายเลขซีเรียลของอุปกรณ์จริง และต้องได้รับจากวิธีการที่อธิบายไว้ข้างต้น
หากไม่ได้ลงทะเบียน Cast Connect จะใช้งานได้กับแอปที่ติดตั้งจาก Google Play Store เท่านั้นเนื่องจากเหตุผลด้านความปลอดภัย หลังจากเริ่มกระบวนการลงทะเบียนไปแล้ว 15 นาที ให้รีสตาร์ทอุปกรณ์
ติดตั้งแอปผู้ส่งสำหรับ Android
หากต้องการทดสอบการส่งคำขอจากอุปกรณ์เคลื่อนที่ เรามีแอปพลิเคชันผู้ส่งแบบง่ายที่เรียกว่า Cast Videos เป็นไฟล์ mobile-sender-0629.apk
ในการดาวน์โหลดไฟล์ ZIP ของซอร์สโค้ด เราจะใช้ ADB เพื่อติดตั้ง APK หากคุณติดตั้ง Cast Video เวอร์ชันอื่นไว้แล้ว โปรดถอนการติดตั้งเวอร์ชันนั้นจากโปรไฟล์ทั้งหมดในอุปกรณ์ก่อนดำเนินการต่อ
- เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอปและการแก้ไขข้อบกพร่อง USB ในโทรศัพท์ Android
- เสียบสาย USB ข้อมูลเพื่อเชื่อมต่อโทรศัพท์ Android กับคอมพิวเตอร์สำหรับพัฒนาซอฟต์แวร์
- ติดตั้ง
mobile-sender-0629.apk
ในโทรศัพท์ Android
- คุณดูแอปส่งวิดีโอแคสต์ได้ในโทรศัพท์ Android
ติดตั้งแอป Android TV
วิธีการต่อไปนี้อธิบายวิธีเปิดและเรียกใช้แอปตัวอย่างที่เสร็จสมบูรณ์ใน Android Studio
- เลือกนําเข้าโปรเจ็กต์ในหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโปรเจ็กต์...
- เลือกไดเรกทอรี
app-done
จากโฟลเดอร์โค้ดตัวอย่าง แล้วคลิก "ตกลง" - คลิก File >
Sync Project with Gradle Files
- เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอปและการแก้ไขข้อบกพร่อง USB ในอุปกรณ์ Android TV
- ADB เชื่อมต่อกับอุปกรณ์ Android TV แล้ว อุปกรณ์ควรแสดงใน Android Studio
- คลิกปุ่ม
Run คุณควรเห็นแอป ATV ชื่อ Cast Connect Codelab ปรากฏขึ้นหลังจากผ่านไป 2-3 วินาที
มาเล่น Cast Connect ด้วยแอป ATV
- ไปที่หน้าจอหลักของ Android TV
- เปิดแอปส่งวิดีโอแคสต์จากโทรศัพท์ Android คลิกปุ่มแคสต์
แล้วเลือกอุปกรณ์ ATV
- แอป Cast Connect Codelab ATV จะเปิดขึ้นใน ATV และปุ่มแคสต์ในอุปกรณ์ส่งจะระบุว่าเชื่อมต่อแล้ว
- เลือกวิดีโอจากแอป ATV แล้ววิดีโอจะเริ่มเล่นบน ATV
- ตอนนี้คุณจะเห็นตัวควบคุมขนาดเล็กที่ด้านล่างของแอปผู้ส่งในโทรศัพท์มือถือ คุณสามารถใช้ปุ่มเล่น/หยุดชั่วคราวเพื่อควบคุมการเล่นได้
- เลือกวิดีโอจากโทรศัพท์มือถือแล้วเล่น วิดีโอจะเริ่มเล่นบน ATV และตัวควบคุมแบบขยายจะแสดงในอุปกรณ์เคลื่อนที่ที่ส่ง
- ล็อกโทรศัพท์ และเมื่อปลดล็อก คุณควรเห็นการแจ้งเตือนบนหน้าจอล็อกเพื่อควบคุมการเล่นสื่อหรือหยุดแคสต์
4. เตรียมโปรเจ็กต์เริ่มต้น
เมื่อเรายืนยันการผสานรวม Cast Connect ของแอปที่เสร็จสมบูรณ์แล้ว เราจะต้องเพิ่มการรองรับ Cast Connect ลงในแอปเริ่มต้นที่คุณดาวน์โหลด ตอนนี้คุณพร้อมที่จะต่อยอดจากโปรเจ็กต์เริ่มต้นโดยใช้ Android Studio แล้ว โดยทำดังนี้
- เลือกนําเข้าโปรเจ็กต์ในหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโปรเจ็กต์...
- เลือกไดเรกทอรี
app-start
จากโฟลเดอร์โค้ดตัวอย่าง แล้วคลิก "ตกลง" - คลิก File >
Sync Project with Gradle Files
- เลือกอุปกรณ์ ATV แล้วคลิกปุ่ม
Run เพื่อเรียกใช้แอปและสำรวจ UI
การออกแบบแอป
แอปแสดงรายการวิดีโอให้ผู้ใช้เลือกดู ผู้ใช้สามารถเลือกวิดีโอที่จะเล่นบน Android TV ได้ แอปประกอบด้วยกิจกรรมหลัก 2 อย่าง ได้แก่ MainActivity
และ PlaybackActivity
กิจกรรมหลัก
กิจกรรมนี้มี Fregment (MainFragment
) รายการวิดีโอและข้อมูลเมตาที่เกี่ยวข้องได้รับการกําหนดค่าในคลาส MovieList
และมีการเรียกใช้เมธอด setupMovies()
เพื่อสร้างรายการออบเจ็กต์ Movie
ออบเจ็กต์ Movie
แสดงถึงเอนทิตีวิดีโอที่มีชื่อ คำอธิบาย ภาพขนาดย่อ และ URL ของวิดีโอ ออบเจ็กต์ Movie
แต่ละรายการจะเชื่อมโยงกับ CardPresenter
เพื่อแสดงภาพปกวิดีโอพร้อมชื่อและสตูดิโอ และส่งไปยัง ArrayObjectAdapter
เมื่อเลือกรายการ ระบบจะส่งผ่านออบเจ็กต์ Movie
ที่เกี่ยวข้องไปยัง PlaybackActivity
PlaybackActivity
กิจกรรมนี้มี Fregment (PlaybackVideoFragment
) ซึ่งโฮสต์ VideoView
ที่มี ExoPlayer
, ตัวควบคุมสื่อบางรายการ และพื้นที่ข้อความเพื่อแสดงคำอธิบายของวิดีโอที่เลือก และอนุญาตให้ผู้ใช้เล่นวิดีโอบน Android TV ผู้ใช้สามารถใช้รีโมตคอนโทรลเพื่อเล่น/หยุดชั่วคราว หรือกรอการเล่นวิดีโอ
ข้อกำหนดเบื้องต้นของ Cast Connect
Cast Connect ใช้บริการ Google Play เวอร์ชันใหม่ที่กำหนดให้แอป ATV ของคุณต้องอัปเดตเพื่อใช้เนมสเปซ AndroidX
หากต้องการรองรับ Cast Connect ในแอป Android TV คุณต้องสร้างและรองรับเหตุการณ์จากเซสชันสื่อ ไลบรารี Cast Connect จะสร้างสถานะสื่อตามสถานะของเซสชันสื่อ คลัง Cast Connect ยังใช้เซสชันสื่อเพื่อส่งสัญญาณเมื่อได้รับข้อความบางอย่างจากผู้ส่ง เช่น ข้อความหยุดชั่วคราว
5. การกำหนดค่าการรองรับ Cast
แท็กเริ่มการทำงาน
อัปเดตไฟล์ build.gradle
ของแอปให้รวมทรัพยากร Dependency ของไลบรารีที่จำเป็น โดยทำดังนี้
dependencies {
....
// Cast Connect libraries
implementation 'com.google.android.gms:play-services-cast-tv:20.0.0'
implementation 'com.google.android.gms:play-services-cast:21.1.0'
}
ซิงค์โปรเจ็กต์เพื่อยืนยันว่าโปรเจ็กต์สร้างโดยไม่มีข้อผิดพลาด
การเริ่มต้น
CastReceiverContext
เป็นออบเจ็กต์แบบ Singleton เพื่อประสานงานการโต้ตอบทั้งหมดของ Cast คุณต้องติดตั้งใช้งานอินเทอร์เฟซ ReceiverOptionsProvider
เพื่อระบุ CastReceiverOptions
เมื่อเริ่มต้น CastReceiverContext
สร้างไฟล์ CastReceiverOptionsProvider.kt
แล้วเพิ่มคลาสต่อไปนี้ลงในโปรเจ็กต์
package com.google.sample.cast.castconnect
import android.content.Context
import com.google.android.gms.cast.tv.ReceiverOptionsProvider
import com.google.android.gms.cast.tv.CastReceiverOptions
class CastReceiverOptionsProvider : ReceiverOptionsProvider {
override fun getOptions(context: Context): CastReceiverOptions {
return CastReceiverOptions.Builder(context)
.setStatusText("Cast Connect Codelab")
.build()
}
}
จากนั้นระบุผู้ให้บริการตัวเลือกผู้รับภายในแท็ก <application>
ของไฟล์ AndroidManifest.xml
ของแอป
<application>
...
<meta-data
android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.sample.cast.castconnect.CastReceiverOptionsProvider" />
</application>
หากต้องการเชื่อมต่อกับแอป ATV จากอุปกรณ์ส่ง Cast ให้เลือกกิจกรรมที่ต้องการเปิด ในโค้ดแล็บนี้ เราจะเปิดMainActivity
ของแอปเมื่อเริ่มเซสชัน Cast ในไฟล์ AndroidManifest.xml
ให้เพิ่มตัวกรอง Intent การเริ่มใช้งานใน MainActivity
<activity android:name=".MainActivity">
...
<intent-filter>
<action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
วงจรชีวิตของบริบทของอุปกรณ์รับการแคสต์
คุณควรเริ่ม CastReceiverContext
เมื่อเปิดแอปและหยุด CastReceiverContext
เมื่อระบบย้ายแอปของคุณไปยังเบื้องหลัง เราขอแนะนำให้คุณใช้ LifecycleObserver
จากคลัง androidx.lifecycle เพื่อจัดการการเรียกใช้ CastReceiverContext.start()
และ CastReceiverContext.stop()
เปิดไฟล์ MyApplication.kt
เริ่มต้นบริบทแคสต์โดยการเรียก initInstance()
ในเมธอด onCreate
ของแอปพลิเคชัน ในคลาส AppLifeCycleObserver
start()
CastReceiverContext
เมื่อแอปพลิเคชันกลับมาทำงานต่อ และ stop()
เมื่อแอปพลิเคชันหยุดชั่วคราว
package com.google.sample.cast.castconnect
import com.google.android.gms.cast.tv.CastReceiverContext
...
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
CastReceiverContext.initInstance(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver())
}
class AppLifecycleObserver : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
Log.d(LOG_TAG, "onResume")
CastReceiverContext.getInstance().start()
}
override fun onPause(owner: LifecycleOwner) {
Log.d(LOG_TAG, "onPause")
CastReceiverContext.getInstance().stop()
}
}
}
การเชื่อมต่อ MediaSession กับ MediaManager
MediaManager
เป็นพร็อพเพอร์ตี้ของ CastReceiverContext
แบบ Singleton ซึ่งจะจัดการสถานะสื่อ จัดการ Intent การโหลด แปลข้อความเนมสเปซสื่อจากผู้ส่งเป็นคําสั่งสื่อ และส่งสถานะสื่อกลับไปยังผู้ส่ง
เมื่อสร้าง MediaSession
คุณจะต้องระบุโทเค็น MediaSession
ปัจจุบันให้กับ MediaManager
ด้วยเพื่อให้ทราบว่าต้องส่งคำสั่งไปที่ไหนและดึงข้อมูลสถานะการเล่นสื่อ ในไฟล์ PlaybackVideoFragment.kt
ให้ตรวจสอบว่า MediaSession
ได้รับการเริ่มต้นก่อนที่จะตั้งค่าโทเค็นเป็น MediaManager
import com.google.android.gms.cast.tv.CastReceiverContext
import com.google.android.gms.cast.tv.media.MediaManager
...
class PlaybackVideoFragment : VideoSupportFragment() {
private var castReceiverContext: CastReceiverContext? = null
...
private fun initializePlayer() {
if (mPlayer == null) {
...
mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
...
castReceiverContext = CastReceiverContext.getInstance()
if (castReceiverContext != null) {
val mediaManager: MediaManager = castReceiverContext!!.getMediaManager()
mediaManager.setSessionCompatToken(mMediaSession!!.getSessionToken())
}
}
}
}
เมื่อคุณเผยแพร่ MediaSession
เนื่องจากไม่มีการเล่น คุณควรตั้งค่าโทเค็น Null ใน MediaManager
ดังนี้
private fun releasePlayer() {
mMediaSession?.release()
castReceiverContext?.mediaManager?.setSessionCompatToken(null)
...
}
มาเรียกใช้แอปตัวอย่างกัน
คลิกปุ่ม Run เพื่อติดตั้งใช้งานแอปในอุปกรณ์ ATV, ปิดแอป แล้วกลับไปที่หน้าจอหลักของ ATV จากอุปกรณ์ที่ส่ง ให้คลิกปุ่มแคสต์
แล้วเลือกอุปกรณ์ ATV คุณจะเห็นแอป ATV เปิดขึ้นในอุปกรณ์ ATV และสถานะปุ่มแคสต์เชื่อมต่ออยู่
6. กำลังโหลดสื่อ
ระบบจะส่งคําสั่งโหลดผ่าน Intent ที่มีชื่อแพ็กเกจที่คุณกําหนดไว้ในคอนโซลนักพัฒนาซอฟต์แวร์ คุณต้องเพิ่มตัวกรอง Intent ที่กําหนดไว้ล่วงหน้าต่อไปนี้ในแอป Android TV เพื่อระบุกิจกรรมเป้าหมายที่จะรับ Intent นี้ ในไฟล์ AndroidManifest.xml
ให้เพิ่มตัวกรอง Intent ของโหลดลงใน PlayerActivity
ดังนี้
<activity android:name="com.google.sample.cast.castconnect.PlaybackActivity"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
การจัดการคําขอโหลดใน Android TV
ตอนนี้กิจกรรมได้รับการกําหนดค่าให้รับ Intent ที่มีคําขอโหลดแล้ว เราจะต้องจัดการกับ Intent นี้
แอปเรียกเมธอดส่วนตัวชื่อ processIntent
เมื่อกิจกรรมเริ่มต้น เมธอดนี้มีตรรกะในการประมวลผล Intent ที่เข้ามา หากต้องการจัดการคําขอโหลด เราจะแก้ไขเมธอดนี้และส่ง Intent เพื่อประมวลผลเพิ่มเติมโดยการเรียกเมธอด onNewIntent
ของอินสแตนซ์ MediaManager
หาก MediaManager
ตรวจพบว่า Intent เป็นคำขอโหลด ระบบจะดึงออบเจ็กต์ MediaLoadRequestData
ออกจาก Intent และเรียกใช้ MediaLoadCommandCallback.onLoad()
แก้ไขเมธอด processIntent
ในไฟล์ PlaybackVideoFragment.kt
เพื่อจัดการ Intent ที่มีคำขอโหลด
fun processIntent(intent: Intent?) {
val mediaManager: MediaManager = CastReceiverContext.getInstance().getMediaManager()
// Pass intent to Cast SDK
if (mediaManager.onNewIntent(intent)) {
return
}
// Clears all overrides in the modifier.
mediaManager.getMediaStatusModifier().clear()
// If the SDK doesn't recognize the intent, handle the intent with your own logic.
...
}
ต่อไปเราจะขยายคลาสนามธรรม MediaLoadCommandCallback
ซึ่งจะลบล้างเมธอด onLoad()
ที่เรียกโดย MediaManager
เมธอดนี้จะรับข้อมูลของคำขอโหลดและแปลงเป็นออบเจ็กต์ Movie
เมื่อแปลงแล้ว ภาพยนตร์จะเล่นโดยโปรแกรมเล่นในเครื่อง จากนั้น MediaManager
จะอัปเดตด้วย MediaLoadRequest
และออกอากาศ MediaStatus
ไปยังผู้ส่งที่เชื่อมต่ออยู่ สร้างคลาสส่วนตัวที่ฝังอยู่ชื่อ MyMediaLoadCommandCallback
ในไฟล์ PlaybackVideoFragment.kt
import com.google.android.gms.cast.MediaLoadRequestData
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.cast.MediaError
import com.google.android.gms.cast.tv.media.MediaException
import com.google.android.gms.cast.tv.media.MediaCommandCallback
import com.google.android.gms.cast.tv.media.QueueUpdateRequestData
import com.google.android.gms.cast.tv.media.MediaLoadCommandCallback
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import android.widget.Toast
...
private inner class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
override fun onLoad(
senderId: String?, mediaLoadRequestData: MediaLoadRequestData): Task<MediaLoadRequestData> {
Toast.makeText(activity, "onLoad()", Toast.LENGTH_SHORT).show()
return if (mediaLoadRequestData == null) {
// Throw MediaException to indicate load failure.
Tasks.forException(MediaException(
MediaError.Builder()
.setDetailedErrorCode(MediaError.DetailedErrorCode.LOAD_FAILED)
.setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
.build()))
} else Tasks.call {
play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
// Update media metadata and state
val mediaManager = castReceiverContext!!.mediaManager
mediaManager.setDataFromLoad(mediaLoadRequestData)
mediaLoadRequestData
}
}
}
private fun convertLoadRequestToMovie(mediaLoadRequestData: MediaLoadRequestData?): Movie? {
if (mediaLoadRequestData == null) {
return null
}
val mediaInfo: MediaInfo = mediaLoadRequestData.getMediaInfo() ?: return null
var videoUrl: String = mediaInfo.getContentId()
if (mediaInfo.getContentUrl() != null) {
videoUrl = mediaInfo.getContentUrl()
}
val metadata: MediaMetadata = mediaInfo.getMetadata()
val movie = Movie()
movie.videoUrl = videoUrl
movie.title = metadata?.getString(MediaMetadata.KEY_TITLE)
movie.description = metadata?.getString(MediaMetadata.KEY_SUBTITLE)
if(metadata?.hasImages() == true) {
movie.cardImageUrl = metadata.images[0].url.toString()
}
return movie
}
เมื่อกําหนดการเรียกกลับแล้ว เราจําเป็นต้องลงทะเบียนการเรียกกลับนั้นกับ MediaManager
ต้องลงทะเบียนการโทรกลับก่อนเรียกใช้ MediaManager.onNewIntent()
เพิ่ม setMediaLoadCommandCallback
เมื่อเริ่มต้นผู้เล่น
private fun initializePlayer() {
if (mPlayer == null) {
...
mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
...
castReceiverContext = CastReceiverContext.getInstance()
if (castReceiverContext != null) {
val mediaManager: MediaManager = castReceiverContext.getMediaManager()
mediaManager.setSessionCompatToken(mMediaSession.getSessionToken())
mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback())
}
}
}
มาเรียกใช้แอปตัวอย่างกัน
คลิกปุ่ม Run เพื่อติดตั้งใช้งานแอปในอุปกรณ์ ATV จากอุปกรณ์ที่ส่ง ให้คลิกปุ่มแคสต์
แล้วเลือกอุปกรณ์ ATV แอป ATV จะเปิดขึ้นในอุปกรณ์ ATV เลือกวิดีโอบนอุปกรณ์เคลื่อนที่ แล้ววิดีโอจะเริ่มเล่นบน ATV ตรวจสอบว่าคุณได้รับการแจ้งเตือนในโทรศัพท์ที่มีการควบคุมการเล่นหรือไม่ ลองใช้ตัวควบคุม เช่น หยุดชั่วคราว วิดีโอในอุปกรณ์ ATV ควรหยุดชั่วคราว
7. การรองรับคำสั่งการควบคุม Cast
ตอนนี้แอปพลิเคชันปัจจุบันรองรับคําสั่งพื้นฐานที่เข้ากันได้กับเซสชันสื่อ เช่น เล่น หยุดชั่วคราว และกรอ อย่างไรก็ตาม คำสั่งควบคุม Cast บางรายการจะใช้ไม่ได้ในเซสชันสื่อ คุณต้องลงทะเบียน MediaCommandCallback
เพื่อรองรับคำสั่งควบคุม Cast เหล่านั้น
เพิ่ม MyMediaCommandCallback
ลงในอินสแตนซ์ MediaManager
โดยใช้ setMediaCommandCallback
เมื่อเริ่มต้นโปรแกรมเล่น
private fun initializePlayer() {
...
castReceiverContext = CastReceiverContext.getInstance()
if (castReceiverContext != null) {
val mediaManager = castReceiverContext!!.mediaManager
...
mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
}
}
สร้างคลาส MyMediaCommandCallback
เพื่อลบล้างเมธอด เช่น onQueueUpdate()
เพื่อรองรับคำสั่งควบคุม Cast ดังต่อไปนี้
private inner class MyMediaCommandCallback : MediaCommandCallback() {
override fun onQueueUpdate(
senderId: String?,
queueUpdateRequestData: QueueUpdateRequestData
): Task<Void> {
Toast.makeText(getActivity(), "onQueueUpdate()", Toast.LENGTH_SHORT).show()
// Queue Prev / Next
if (queueUpdateRequestData.getJump() != null) {
Toast.makeText(
getActivity(),
"onQueueUpdate(): Jump = " + queueUpdateRequestData.getJump(),
Toast.LENGTH_SHORT
).show()
}
return super.onQueueUpdate(senderId, queueUpdateRequestData)
}
}
8. การทำงานกับสถานะสื่อ
การแก้ไขสถานะสื่อ
Cast Connect จะได้รับสถานะสื่อพื้นฐานจากเซสชันสื่อ หากต้องการรองรับฟีเจอร์ขั้นสูง แอป Android TV สามารถระบุและลบล้างพร็อพเพอร์ตี้สถานะเพิ่มเติมผ่าน MediaStatusModifier
MediaStatusModifier
จะทำงานกับ MediaSession
ที่คุณตั้งค่าไว้ใน CastReceiverContext
เสมอ
ตัวอย่างเช่น หากต้องการระบุ setMediaCommandSupported
เมื่อทริกเกอร์การเรียกกลับ onLoad
ให้ทำดังนี้
import com.google.android.gms.cast.MediaStatus
...
private class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
fun onLoad(
senderId: String?,
mediaLoadRequestData: MediaLoadRequestData
): Task<MediaLoadRequestData> {
Toast.makeText(getActivity(), "onLoad()", Toast.LENGTH_SHORT).show()
...
return Tasks.call({
play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
...
// Use MediaStatusModifier to provide additional information for Cast senders.
mediaManager.getMediaStatusModifier()
.setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT, true)
.setIsPlayingAd(false)
mediaManager.broadcastMediaStatus()
// Return the resolved MediaLoadRequestData to indicate load success.
mediaLoadRequestData
})
}
}
การสกัดกั้น MediaStatus ก่อนส่ง
คุณสามารถระบุ MediaStatusWriter
ใน MediaManager
เพื่อทำการแก้ไขเพิ่มเติมใน MediaStatus
ก่อนที่จะออกอากาศไปยังผู้ส่งที่เชื่อมต่อได้ ซึ่งคล้ายกับ MessageInterceptor
ของ Web Receiver SDK
ตัวอย่างเช่น คุณสามารถตั้งค่าข้อมูลที่กําหนดเองใน MediaStatus
ก่อนส่งไปยังผู้ส่งที่ใช้อุปกรณ์เคลื่อนที่ได้ ดังนี้
import com.google.android.gms.cast.tv.media.MediaManager.MediaStatusInterceptor
import com.google.android.gms.cast.tv.media.MediaStatusWriter
import org.json.JSONObject
import org.json.JSONException
...
private fun initializePlayer() {
if (mPlayer == null) {
...
if (castReceiverContext != null) {
...
val mediaManager: MediaManager = castReceiverContext.getMediaManager()
...
// Use MediaStatusInterceptor to process the MediaStatus before sending out.
mediaManager.setMediaStatusInterceptor(
MediaStatusInterceptor { mediaStatusWriter: MediaStatusWriter ->
try {
mediaStatusWriter.setCustomData(JSONObject("{myData: 'CustomData'}"))
} catch (e: JSONException) {
Log.e(LOG_TAG,e.message,e);
}
})
}
}
}
9. ขอแสดงความยินดี
ตอนนี้คุณทราบวิธีเปิดใช้ Cast ในแอป Android TV โดยใช้ไลบรารี Cast Connect แล้ว
ดูรายละเอียดเพิ่มเติมได้ที่คู่มือนักพัฒนาแอป /cast/docs/android_tv_receiver