1. ภาพรวม
Codelab นี้จะสอนวิธีแก้ไขแอป Android TV ที่มีอยู่เพื่อรองรับการแคสต์และการสื่อสารจากแอปผู้ส่งผู้ส่งที่มีอยู่
Google Cast และ Cast Connect คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยัง TV ได้ เซสชัน Google Cast ทั่วไปประกอบด้วยคอมโพเนนต์ 2 อย่างคือผู้ส่งและแอปพลิเคชันตัวรับ แอปพลิเคชันผู้ส่ง เช่น แอปบนอุปกรณ์เคลื่อนที่หรือเว็บไซต์ เช่น YouTube.com เริ่มต้นและควบคุมการเล่นแอปพลิเคชันเครื่องรับ Cast แอปพลิเคชันรับการแคสต์คือแอป HTML 5 ที่ทํางานในอุปกรณ์ Chromecast และ Android TV
เกือบทุกรัฐในเซสชัน Cast จะจัดเก็บไว้ในแอปพลิเคชันตัวรับ เมื่อสถานะมีการอัปเดต เช่น เมื่อโหลดสื่อใหม่ ระบบจะเผยแพร่สถานะสื่อให้กับผู้ส่งทุกคน การออกอากาศเหล่านี้จะมีสถานะปัจจุบันของเซสชันการแคสต์ แอปพลิเคชันผู้ส่งใช้สถานะสื่อนี้เพื่อแสดงข้อมูลการเล่นบน UI
Cast Connect ต่อยอดมาจากโครงสร้างพื้นฐานนี้ และแอป Android TV ของคุณจะทําหน้าที่เป็นตัวรับ ไลบรารี Cast Connect ช่วยให้แอป Android TV รับข้อความและสถานะสื่อออกอากาศเสมือนว่าเป็นแอปพลิเคชันตัวรับการแคสต์
สิ่งที่เรากําลังจะสร้าง
เมื่อเขียนโค้ดนี้เสร็จเรียบร้อยแล้ว คุณจะใช้แอปส่งของ Cast เพื่อแคสต์วิดีโอไปยังแอป 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 ในการพัฒนาแอปพลิเคชัน คุณต้องลงทะเบียนหมายเลขซีเรียลของ Chromecast ในตัวของอุปกรณ์ Android TV ที่คุณจะใช้ในแผงควบคุมสําหรับนักพัฒนาซอฟต์แวร์ Cast คุณดูหมายเลขซีเรียลได้โดยไปที่การตั้งค่า > ค่ากําหนดอุปกรณ์ > Chromecast Built-In > หมายเลขซีเรียลบน Android TV โปรดทราบว่าหมายเลขนี้แตกต่างจากหมายเลขซีเรียลของอุปกรณ์จริง และต้องมาจากวิธีการที่แจ้งไว้ข้างต้น
หากไม่ลงทะเบียน Cast Connect จะทํางานเฉพาะแอปที่ติดตั้งจาก Google Play สโตร์ด้วยสาเหตุด้านความปลอดภัย หลังจากเริ่มขั้นตอนการลงทะเบียนไป 15 นาทีแล้ว ให้รีสตาร์ทอุปกรณ์
ติดตั้งแอปผู้ส่ง Android
เพื่อทดสอบการส่งคําขอจากอุปกรณ์เคลื่อนที่ เราได้ให้แอปพลิเคชันผู้ส่งแบบง่ายที่เรียกว่า "ส่งวิดีโอ" เป็นไฟล์ mobile-sender-0629.apk
ในการดาวน์โหลดไฟล์ ZIP ของซอร์สโค้ด เราจะใช้ ADB ในการติดตั้ง APK หากคุณได้ติดตั้งวิดีโอแคสต์เวอร์ชันอื่นไว้แล้ว โปรดถอนการติดตั้งเวอร์ชันดังกล่าวจากโปรไฟล์ทั้งหมดที่อยู่ในอุปกรณ์ก่อนที่จะดําเนินการต่อ
- เปิดใช้ตัวเลือกสําหรับนักพัฒนาแอปและการแก้ปัญหา USB ในโทรศัพท์ Android
- เสียบสายข้อมูล USB เพื่อเชื่อมต่อโทรศัพท์ Android กับคอมพิวเตอร์เพื่อการพัฒนาซอฟต์แวร์
- ติดตั้ง
mobile-sender-0629.apk
ลงในโทรศัพท์ Android ของคุณ
- หาแอปผู้ส่งแคสต์วิดีโอในโทรศัพท์ Android ได้
ติดตั้งแอป Android TV
วิธีการต่อไปนี้อธิบายวิธีเปิดและเรียกใช้แอปตัวอย่างที่สมบูรณ์ใน Android Studio
- เลือกนําเข้าโครงการบนหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโครงการ...
- เลือกไดเรกทอรี
app-done
จากโฟลเดอร์โค้ดตัวอย่างแล้วคลิก OK - คลิก File >
Sync Project with Gradle Files
- เปิดใช้ตัวเลือกสําหรับนักพัฒนาแอปและการแก้ปัญหา USB ในอุปกรณ์ Android TV
- ADB จะเชื่อมต่อกับอุปกรณ์ Android TV อุปกรณ์ควรแสดงใน Android Studio
- คลิกปุ่ม
เรียกใช้ คุณจะเห็นแอป ATV ชื่อ Cast Connect Codelab ปรากฏขึ้นหลังจากผ่านไป 2-3 วินาที
เล่น Cast Connect ด้วยแอป ATV
- ไปที่หน้าจอหลักของ Android TV
- เปิดแอปส่งวิดีโอ Cast จากโทรศัพท์ Android คลิกปุ่ม "แคสต์"
และเลือกอุปกรณ์ ATV ของคุณ
- แอป Cast Connect Codelab ATV จะเปิดตัวใน ATV และปุ่ม "แคสต์" ในผู้ส่งจะระบุว่ามีการเชื่อมต่อ
- เลือกวิดีโอจากแอป ATV แล้ววิดีโอจะเริ่มเล่นใน ATV
- ในโทรศัพท์มือถือ ตัวควบคุมขนาดเล็กจะปรากฏที่ด้านล่างของแอปผู้ส่ง คุณใช้ปุ่มเล่น/หยุดชั่วคราวเพื่อควบคุมการเล่นได้
- เลือกวิดีโอจากโทรศัพท์มือถือแล้วเล่น วิดีโอจะเริ่มเล่นใน ATV และตัวควบคุมที่ขยายจะแสดงบนผู้ส่งบนอุปกรณ์เคลื่อนที่
- ล็อกโทรศัพท์และเมื่อคุณปลดล็อก คุณจะเห็นการแจ้งเตือนในหน้าจอล็อกเพื่อควบคุมการเล่นสื่อหรือหยุดแคสต์
4. เตรียมโปรเจ็กต์เริ่มต้น
ตอนนี้เรายืนยันการผสานรวม Cast Connect ที่เสร็จสมบูรณ์แล้วของแอปไปแล้ว เราจึงต้องเพิ่มการรองรับ Cast Connect ในแอปเริ่มต้นที่คุณดาวน์โหลด ตอนนี้คุณพร้อมที่จะสร้างต่อยอดจากโครงการเริ่มต้นโดยใช้ Android Studio แล้ว
- เลือกนําเข้าโครงการบนหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโครงการ...
- เลือกไดเรกทอรี
app-start
จากโฟลเดอร์โค้ดตัวอย่างแล้วคลิก OK - คลิก File >
Sync Project with Gradle Files
- เลือกอุปกรณ์ ATV แล้วคลิกปุ่ม
เรียกใช้ เพื่อเรียกใช้แอปและสํารวจ UI
การออกแบบแอป
แอปจะแสดงรายการวิดีโอสําหรับผู้ใช้ที่จะเรียกดู ผู้ใช้สามารถเลือกวิดีโอเพื่อเล่นบน Android TV ได้ แอปนี้ประกอบด้วยกิจกรรมหลัก 2 อย่าง ได้แก่ MainActivity
และ PlaybackActivity
MainActivity
กิจกรรมนี้มีส่วนย่อย (MainFragment
) รายการวิดีโอและข้อมูลเมตาที่เกี่ยวข้องจะได้รับการกําหนดค่าใน MovieList
คลาสและมีการเรียก setupMovies()
เพื่อสร้างรายการออบเจ็กต์ Movie
รายการ
ออบเจ็กต์ Movie
แสดงถึงเอนทิตีวิดีโอที่มีชื่อ คําอธิบาย รูปภาพ ภาพขนาดย่อ และ URL ของวิดีโอ ออบเจ็กต์ Movie
แต่ละรายการจะผูกกับ CardPresenter
เพื่อแสดงภาพขนาดย่อของวิดีโอที่มีชื่อและสตูดิโอ และส่งไปยัง ArrayObjectAdapter
เมื่อเลือกรายการแล้ว ระบบจะส่งออบเจ็กต์ Movie
ที่เกี่ยวข้องไปยัง PlaybackActivity
กิจกรรมการเล่น
กิจกรรมนี้จะมี Fragment (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
เป็นออบเจ็กต์เดี่ยวเพื่อประสานงานการโต้ตอบแคสต์ทั้งหมด คุณต้องใช้อินเทอร์เฟซ 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 ให้เลือกกิจกรรมที่ต้องการเปิดตัว ใน Codelab นี้ เราจะเปิดตัวแอป MainActivity
เมื่อมีการเริ่มต้นเซสชันแคสต์ ในไฟล์ AndroidManifest.xml
ให้เพิ่มตัวกรองจุดประสงค์การเปิดตัวใน 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
ซึ่งจะจัดการสถานะสื่อ จัดการจุดประสงค์ในการโหลด แปลข้อความเนมสเปซของสื่อจากผู้ส่งเป็นคําสั่งสื่อ และส่งสถานะของสื่อกลับไปยังผู้ส่ง
เมื่อสร้าง 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)
...
}
มาเรียกใช้แอปตัวอย่างกัน
คลิกปุ่มเรียกใช้เพื่อทําให้แอปในอุปกรณ์ ATV ใช้งานได้ ปิดแอปและกลับไปที่หน้าจอหลักของ ATV จากผู้ส่งของคุณ ให้คลิกปุ่ม "แคสต์"
และเลือกอุปกรณ์ ATV ของคุณ คุณจะเห็นแอป ATV เปิดขึ้นบนอุปกรณ์ ATV และมีการเชื่อมต่อปุ่ม "แคสต์"
6. กำลังโหลดสื่อ
ระบบจะส่งคําสั่งโหลดผ่าน Intent ที่มีชื่อแพ็กเกจที่คุณกําหนดไว้ใน Developer Console คุณต้องเพิ่มตัวกรอง Intent ที่กําหนดไว้ล่วงหน้าต่อไปนี้ในแอป Android TV เพื่อระบุกิจกรรมเป้าหมายที่จะได้รับ Intent นี้ ในไฟล์ AndroidManifest.xml
ให้เพิ่มตัวกรองจุดประสงค์การโหลดลงใน 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 นี้โดยที่มีคําขอการโหลดแล้ว เราจะต้องจัดการ
แอปจะเรียกเมธอดส่วนตัวชื่อ 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())
}
}
}
มาเรียกใช้แอปตัวอย่างกัน
คลิกปุ่มเรียกใช้เพื่อทําให้แอปในอุปกรณ์ ATV ใช้งานได้ จากผู้ส่งของคุณ ให้คลิกปุ่ม "แคสต์"
และเลือกอุปกรณ์ ATV ของคุณ แอป ATV จะเปิดตัวในอุปกรณ์ ATV เลือกวิดีโอบนอุปกรณ์เคลื่อนที่ วิดีโอจะเริ่มเล่นใน ATV ตรวจสอบว่าคุณได้รับการแจ้งเตือนบนโทรศัพท์ที่คุณมีการควบคุมการเล่นหรือไม่ ลองใช้ตัวควบคุม เช่น หยุดชั่วคราว วิดีโอบนอุปกรณ์ ATV ควรหยุดชั่วคราว
7. การสนับสนุนคําสั่งควบคุมการแคสต์
แอปพลิเคชันปัจจุบันรองรับคําสั่งพื้นฐานที่เข้ากันได้กับเซสชันสื่อ เช่น เล่น หยุดชั่วคราว และกรอ แต่คําสั่งตัวควบคุม 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 จะได้รับสถานะสื่อพื้นฐานจากเซสชันสื่อ แอป YouTube 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
})
}
}
การสกัดกั้น MediaMedia ก่อนส่ง
เช่นเดียวกับ MessageInterceptor
ของตัวรับสัญญาณเว็บ คุณสามารถระบุ MediaStatusWriter
ใน MediaManager
เพื่อดําเนินการแก้ไขเพิ่มเติมกับ MediaStatus
ก่อนที่จะเผยแพร่ไปยังผู้ส่งที่เชื่อมต่อ
ตัวอย่างเช่น คุณตั้งค่าข้อมูลที่กําหนดเองได้ใน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. ขอแสดงความยินดี
ตอนนี้คุณทราบวิธีแคสต์เพื่อเปิดใช้แอป Android TV โดยใช้ไลบรารี Cast Connect แล้ว
โปรดดูรายละเอียดเพิ่มเติมในคู่มือนักพัฒนาซอฟต์แวร์ /cast/docs/android_tv_receiver