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