1. ภาพรวม
โค้ดแล็บนี้จะสอนวิธีแก้ไขแอปวิดีโอ Android ที่มีอยู่เพื่อแคสต์เนื้อหาในอุปกรณ์ที่พร้อมใช้งาน Google Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยังทีวีได้ ผู้ใช้จะใช้อุปกรณ์เคลื่อนที่เป็นรีโมตคอนโทรลในการเล่นสื่อบนทีวีได้
Google Cast SDK ช่วยให้คุณขยายแอปเพื่อควบคุมทีวีหรือระบบเสียงได้ Cast SDK ช่วยให้คุณสามารถเพิ่มคอมโพเนนต์ UI ที่จำเป็นได้ตามรายการตรวจสอบการออกแบบของ Google Cast
รายการตรวจสอบการออกแบบ Google Cast มีไว้เพื่อให้ประสบการณ์การใช้งาน Cast ของผู้ใช้ง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ
เราจะสร้างอะไร
เมื่อเสร็จสิ้น Codelab นี้แล้ว คุณจะมีแอปวิดีโอ Android ที่จะแคสต์วิดีโอไปยังอุปกรณ์ที่พร้อมใช้งาน Google Cast ได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีเพิ่ม Google Cast SDK ลงในแอปวิดีโอตัวอย่าง
- วิธีเพิ่มปุ่ม "แคสต์" เพื่อเลือกอุปกรณ์ Google Cast
- วิธีเชื่อมต่อกับอุปกรณ์แคสต์และเปิดใช้งานตัวรับสื่อ
- วิธีแคสต์วิดีโอ
- วิธีเพิ่มตัวควบคุมขนาดเล็กของ Cast ลงในแอป
- วิธีรองรับการแจ้งเตือนสื่อและการควบคุมหน้าจอล็อก
- วิธีเพิ่มตัวควบคุมแบบขยาย
- วิธีใส่ข้อความวางซ้อนแนะนำ
- วิธีปรับแต่งวิดเจ็ตแคสต์
- วิธีผสานรวมกับ Cast Connect
สิ่งที่คุณต้องมี
- Android SDK เวอร์ชันล่าสุด
- Android Studio เวอร์ชัน 3.2 ขึ้นไป
- อุปกรณ์เคลื่อนที่ 1 เครื่องที่ใช้ Android 4.1 ขึ้นไป Jelly Bean (API ระดับ 16)
- สายข้อมูล USB เพื่อเชื่อมต่ออุปกรณ์เคลื่อนที่กับคอมพิวเตอร์การพัฒนา
- อุปกรณ์ Google Cast เช่น Chromecast หรือ Android TV ที่กำหนดค่าการเข้าถึงอินเทอร์เน็ต
- ทีวีหรือจอภาพที่มีอินพุต HDMI
- คุณต้องมี Chromecast พร้อม Google TV เพื่อทดสอบการผสานรวม Cast Connect แต่ไม่จำเป็นต้องใช้สำหรับส่วนที่เหลือของ Codelab หากไม่มี ให้ข้ามขั้นตอนเพิ่มการรองรับ Cast Connect ในช่วงท้ายของบทแนะนำนี้
ประสบการณ์การใช้งาน
- คุณจะต้องมีความรู้ด้านการพัฒนา Kotlin และ Android มาก่อน
- คุณจะต้องมีความรู้เบื้องต้นเกี่ยวกับการดูทีวีด้วย :)
คุณจะใช้บทแนะนำนี้อย่างไร
คุณจะให้คะแนนประสบการณ์การสร้างแอป Android เท่าใด
คุณจะให้คะแนนประสบการณ์ในการดูทีวีเท่าใด
2. รับโค้ดตัวอย่าง
คุณดาวน์โหลดโค้ดตัวอย่างทั้งหมดลงในคอมพิวเตอร์ได้...
และแตกไฟล์ ZIP ที่ดาวน์โหลด
3. เรียกใช้แอปตัวอย่าง
ก่อนอื่น มาดูตัวอย่างแอปตัวอย่างที่เสร็จสมบูรณ์ แอปนี้เป็นโปรแกรมเล่นวิดีโอพื้นฐาน ผู้ใช้สามารถเลือกวิดีโอจากรายการ แล้วเล่นวิดีโอในอุปกรณ์หรือแคสต์ไปยังอุปกรณ์ Google Cast ก็ได้
เมื่อดาวน์โหลดโค้ดแล้ว วิธีการต่อไปนี้อธิบายวิธีเปิดและเรียกใช้แอปตัวอย่างที่สมบูรณ์ใน Android Studio
เลือกนําเข้าโปรเจ็กต์ในหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโปรเจ็กต์...
เลือกไดเรกทอรี app-done
จากโฟลเดอร์โค้ดตัวอย่าง แล้วคลิกตกลง
คลิก File > Sync Project with Gradle Files
เปิดใช้การแก้ไขข้อบกพร่องผ่าน USB ในอุปกรณ์ Android - ใน Android 4.2 ขึ้นไป หน้าจอตัวเลือกสำหรับนักพัฒนาแอปจะซ่อนอยู่โดยค่าเริ่มต้น หากต้องการให้แสดง ให้ไปที่การตั้งค่า > เกี่ยวกับโทรศัพท์ แล้วแตะหมายเลขบิลด์ 7 ครั้ง กลับไปที่หน้าจอก่อนหน้า ไปที่ระบบ > ขั้นสูง แล้วแตะตัวเลือกสำหรับนักพัฒนาแอปบริเวณด้านล่าง จากนั้นแตะการแก้ไขข้อบกพร่อง USB เพื่อเปิด
เสียบปลั๊กอุปกรณ์ Android แล้วคลิกปุ่ม Run ใน Android Studio คุณจะเห็นแอปวิดีโอชื่อแคสต์วิดีโอปรากฏขึ้นหลังจากผ่านไป 2-3 วินาที
คลิกปุ่ม "แคสต์" ในแอปวิดีโอ แล้วเลือกอุปกรณ์ Google Cast
เลือกวิดีโอแล้วคลิกปุ่มเล่น
วิดีโอจะเริ่มเล่นในอุปกรณ์ Google Cast
ตัวควบคุมแบบขยายจะปรากฏขึ้น คุณใช้ปุ่มเล่น/หยุดชั่วคราวเพื่อควบคุมการเล่นได้
กลับไปที่รายการวิดีโอ
ตอนนี้ตัวควบคุมขนาดเล็กจะปรากฏที่ด้านล่างของหน้าจอ
คลิกปุ่มหยุดชั่วคราวในตัวควบคุมขนาดเล็กเพื่อหยุดวิดีโอบนรีซีฟเวอร์ชั่วคราว คลิกปุ่มเล่นในตัวควบคุมขนาดเล็กเพื่อเล่นวิดีโอต่ออีกครั้ง
คลิกปุ่มหน้าแรกบนอุปกรณ์เคลื่อนที่ ดึงการแจ้งเตือนลง และคุณจะเห็นการแจ้งเตือนสำหรับเซสชันการแคสต์
ล็อกโทรศัพท์และเมื่อปลดล็อก คุณควรเห็นการแจ้งเตือนบนหน้าจอล็อกเพื่อควบคุมการเล่นสื่อหรือหยุดการแคสต์
กลับไปที่แอปวิดีโอ แล้วคลิกปุ่มแคสต์เพื่อหยุดแคสต์ในอุปกรณ์ Google Cast
คำถามที่พบบ่อย
4. เตรียมเริ่มโปรเจ็กต์
เราต้องเพิ่มการรองรับ Google Cast ลงในแอปเริ่มต้นที่คุณดาวน์โหลด คําศัพท์บางอย่างของ Google Cast ที่เราจะใช้ใน Codelab นี้
- แอปผู้ส่งทำงานบนอุปกรณ์เคลื่อนที่หรือแล็ปท็อป
- แอปตัวรับที่ทำงานบนอุปกรณ์ Google Cast
ตอนนี้คุณพร้อมที่จะต่อยอดจากโปรเจ็กต์เริ่มต้นโดยใช้ Android Studio แล้ว
- เลือกไดเรกทอรี
app-start
จากการดาวน์โหลดโค้ดตัวอย่าง (เลือกนําเข้าโปรเจ็กต์ในหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโปรเจ็กต์...) - คลิกปุ่ม
ซิงค์โปรเจ็กต์กับไฟล์ Gradle
- คลิกปุ่ม
Run เพื่อเรียกใช้แอปและสำรวจ UI
การออกแบบแอป
แอปจะดึงรายการวิดีโอจากเว็บเซิร์ฟเวอร์ระยะไกลและแสดงรายการให้ผู้ใช้เรียกดู ผู้ใช้สามารถเลือกวิดีโอเพื่อดูรายละเอียดหรือเล่นวิดีโอบนอุปกรณ์เคลื่อนที่ก็ได้
แอปประกอบด้วยกิจกรรมหลัก 2 รายการ ได้แก่ VideoBrowserActivity
และ LocalPlayerActivity
หากต้องการผสานรวมฟังก์ชันการทำงานของ Google Cast กิจกรรมต้องรับค่ามาจาก AppCompatActivity
หรือ FragmentActivity
ซึ่งเป็นรายการหลัก ข้อจำกัดนี้เกิดขึ้นเนื่องจากเราต้องเพิ่ม MediaRouteButton
(ที่ให้ไว้ในไลบรารีการสนับสนุนของ MediaRouter) เป็น MediaRouteActionProvider
และจะใช้ได้ก็ต่อเมื่อกิจกรรมรับค่าจากคลาสที่กล่าวถึงข้างต้นเท่านั้น ไลบรารีการสนับสนุน MediaRouter ขึ้นอยู่กับไลบรารีการสนับสนุน AppCompat ซึ่งมีคลาสที่จำเป็น
VideoBrowserActivity
กิจกรรมนี้มี Fragment
(VideoBrowserFragment
) รายการนี้ได้รับการสนับสนุนโดย ArrayAdapter
(VideoListAdapter
) รายการวิดีโอและข้อมูลเมตาที่เกี่ยวข้องจะโฮสต์บนเซิร์ฟเวอร์ระยะไกลเป็นไฟล์ JSON AsyncTaskLoader
(VideoItemLoader
) จะดึงข้อมูล JSON นี้และประมวลผลเพื่อสร้างรายการออบเจ็กต์ MediaItem
ออบเจ็กต์ MediaItem
จะสร้างวิดีโอและข้อมูลเมตาที่เกี่ยวข้อง เช่น ชื่อ, คำอธิบาย, URL สำหรับสตรีม, URL ของรูปภาพสนับสนุน และแทร็กข้อความที่เชื่อมโยง (สำหรับคำบรรยายแทนเสียง) หากมี ระบบจะส่งออบเจ็กต์ MediaItem
ระหว่างกิจกรรม ดังนั้น MediaItem
จึงมีวิธียูทิลิตีเพื่อแปลงเป็น Bundle
และในทางกลับกันด้วย
เมื่อตัวโหลดสร้างรายการ MediaItems
โปรแกรมจะส่งผ่านรายการดังกล่าวไปยัง VideoListAdapter
ซึ่งจะแสดงรายการ MediaItems
ใน VideoBrowserFragment
ผู้ใช้จะเห็นรายการภาพปกวิดีโอพร้อมคำอธิบายสั้นๆ ของวิดีโอแต่ละรายการ เมื่อเลือกรายการ MediaItem
ที่เกี่ยวข้องจะเปลี่ยนเป็น Bundle
และส่งไปยัง LocalPlayerActivity
LocalPlayerActivity
โดยกิจกรรมนี้จะแสดงข้อมูลเมตาเกี่ยวกับวิดีโอที่เฉพาะเจาะจงและอนุญาตให้ผู้ใช้เล่นวิดีโอดังกล่าวในอุปกรณ์เคลื่อนที่
กิจกรรมจะโฮสต์ VideoView
, การควบคุมสื่อบางอย่าง และพื้นที่ข้อความเพื่อแสดงคำอธิบายของวิดีโอที่เลือก โปรแกรมเล่นวิดีโอจะบังส่วนบนของหน้าจอ ทำให้เหลือพื้นที่สำหรับคำอธิบายโดยละเอียดของวิดีโออยู่ด้านล่าง ผู้ใช้สามารถเล่น/หยุดชั่วคราว หรือกรอวิดีโอที่เล่นในเครื่อง
การอ้างอิง
เนื่องจากเราใช้ AppCompatActivity
เราจึงต้องใช้ไลบรารีการสนับสนุน AppCompat สำหรับการจัดการรายการวิดีโอและการรับรูปภาพสำหรับรายการแบบไม่พร้อมกัน เราจะใช้ไลบรารี Volley
คำถามที่พบบ่อย
5. การเพิ่มปุ่ม "แคสต์"
แอปพลิเคชันที่พร้อมใช้งาน Cast จะแสดงปุ่มแคสต์ในกิจกรรมแต่ละรายการ การคลิกปุ่มแคสต์จะแสดงรายการอุปกรณ์แคสต์ที่ผู้ใช้เลือกได้ หากผู้ใช้เล่นเนื้อหาบนอุปกรณ์ของผู้ส่ง การเลือกอุปกรณ์แคสต์จะเริ่มต้นหรือเล่นต่อในอุปกรณ์แคสต์นั้น ผู้ใช้สามารถคลิกปุ่มแคสต์และหยุดแคสต์แอปพลิเคชันไปยังอุปกรณ์แคสต์ได้ทุกเมื่อในระหว่างเซสชันแคสต์ ผู้ใช้ต้องเชื่อมต่อหรือยกเลิกการเชื่อมต่อกับอุปกรณ์แคสต์ได้ขณะทำกิจกรรมใดก็ตามในแอปพลิเคชันของคุณ ตามที่อธิบายไว้ในรายการตรวจสอบการออกแบบ Google Cast
การอ้างอิง
อัปเดตไฟล์ build.gradle ของแอปให้รวมทรัพยากร Dependency ของไลบรารีที่จําเป็น
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'androidx.mediarouter:mediarouter:1.3.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'com.google.android.gms:play-services-cast-framework:21.1.0'
implementation 'com.android.volley:volley:1.2.1'
implementation "androidx.core:core-ktx:1.8.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
ซิงค์โปรเจ็กต์เพื่อยืนยันว่าโปรเจ็กต์สร้างโดยไม่มีข้อผิดพลาด
การเริ่มต้น
เฟรมเวิร์ก Cast ประกอบด้วยออบเจ็กต์แบบ Singleton ทั่วโลก ซึ่งก็คือ CastContext
ที่ประสานงานการโต้ตอบทั้งหมดของ Cast
คุณต้องใช้อินเทอร์เฟซ OptionsProvider
เพื่อรองรับ CastOptions
ที่จำเป็นในการเริ่มต้น Singleton CastContext
ตัวเลือกที่สำคัญที่สุดคือรหัสแอปพลิเคชันของผู้รับ ซึ่งใช้เพื่อกรองผลการค้นหาอุปกรณ์แคสต์และเปิดแอปพลิเคชันที่เป็นผู้รับเมื่อเริ่มเซสชันการแคสต์
เมื่อคุณพัฒนาแอปที่พร้อมใช้งาน Cast ขึ้นมาเอง คุณจะต้องลงทะเบียนเป็นนักพัฒนาซอฟต์แวร์ Cast จากนั้นรับรหัสแอปพลิเคชันสำหรับแอปของคุณ สำหรับ Codelab นี้ เราจะใช้รหัสแอปตัวอย่าง
เพิ่มไฟล์ CastOptionsProvider.kt
ใหม่ต่อไปนี้ลงในแพ็กเกจ com.google.sample.cast.refplayer
ของโปรเจ็กต์
package com.google.sample.cast.refplayer
import android.content.Context
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.SessionProvider
class CastOptionsProvider : OptionsProvider {
override fun getCastOptions(context: Context): CastOptions {
return CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.build()
}
override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
return null
}
}
ตอนนี้ให้ประกาศ OptionsProvider
ภายในแท็ก "application
" ของไฟล์ AndroidManifest.xml
ของแอป
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.sample.cast.refplayer.CastOptionsProvider" />
เริ่มต้น CastContext
ในเมธอด onCreate ของ VideoBrowserActivity
อย่างล่าช้า
import com.google.android.gms.cast.framework.CastContext
private var mCastContext: CastContext? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.video_browser)
setupActionBar()
mCastContext = CastContext.getSharedInstance(this)
}
เพิ่มตรรกะการเริ่มต้นเดียวกันใน LocalPlayerActivity
ปุ่ม "แคสต์"
เมื่อเริ่มต้น CastContext
แล้ว เราจะต้องเพิ่มปุ่มแคสต์เพื่อให้ผู้ใช้เลือกอุปกรณ์แคสต์ได้ ปุ่มแคสต์ติดตั้งใช้งานโดย MediaRouteButton
จากไลบรารีการสนับสนุน MediaRouter คุณจะต้องเพิ่มรายการในเมนูที่เกี่ยวข้องลงในเมนูก่อน เช่นเดียวกับไอคอนการดำเนินการที่คุณเพิ่มลงในกิจกรรม (โดยใช้ ActionBar
หรือ Toolbar
)
แก้ไขไฟล์ res/menu/browse.xml
และเพิ่มรายการ MediaRouteActionProvider
ในเมนูก่อนรายการการตั้งค่า ดังนี้
<item
android:id="@+id/media_route_menu_item"
android:title="@string/media_route_menu_title"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="always"/>
ลบล้างเมธอด onCreateOptionsMenu()
ของ VideoBrowserActivity
โดยใช้ CastButtonFactory
เพื่อต่อเชื่อม MediaRouteButton
กับเฟรมเวิร์กแคสต์
import com.google.android.gms.cast.framework.CastButtonFactory
private var mediaRouteMenuItem: MenuItem? = null
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.browse, menu)
mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu,
R.id.media_route_menu_item)
return true
}
ลบล้าง onCreateOptionsMenu
ใน LocalPlayerActivity
ด้วยวิธีที่คล้ายกัน
คลิกปุ่ม เรียกใช้ เพื่อเรียกใช้แอปบนอุปกรณ์เคลื่อนที่ คุณควรเห็นปุ่มแคสต์ในแถบการดำเนินการของแอป และเมื่อคลิกปุ่มดังกล่าว ระบบจะแสดงรายการอุปกรณ์แคสต์ในเครือข่ายภายใน
CastContext
จะจัดการการค้นพบอุปกรณ์โดยอัตโนมัติ เลือกอุปกรณ์แคสต์ แล้วแอปตัวรับตัวอย่างจะโหลดในอุปกรณ์แคสต์ คุณสามารถไปยังระหว่างกิจกรรมการท่องเว็บและกิจกรรมโปรแกรมเล่นในเครื่องได้ และสถานะของปุ่ม "แคสต์" จะซิงค์กันเสมอ
เรายังไม่ได้รองรับการเล่นสื่อ คุณจึงยังเล่นวิดีโอในอุปกรณ์แคสต์ไม่ได้ คลิกปุ่ม "แคสต์" เพื่อยกเลิกการเชื่อมต่อ
6. กำลังแคสต์เนื้อหาวิดีโอ
เราจะขยายความสามารถของแอปตัวอย่างให้เล่นวิดีโอจากระยะไกลบนอุปกรณ์ Cast ได้ด้วย เราจึงต้องฟังเหตุการณ์ต่างๆ ที่สร้างขึ้นจากเฟรมเวิร์กของ Cast
การแคสต์สื่อ
ในระดับสูง หากต้องการเล่นสื่อในอุปกรณ์แคสต์ คุณต้องทำสิ่งต่อไปนี้
- สร้างออบเจ็กต์
MediaInfo
ที่จำลองรายการสื่อ - เชื่อมต่ออุปกรณ์ Cast และเปิดแอปพลิเคชันตัวรับ
- โหลดออบเจ็กต์
MediaInfo
ลงในเครื่องรับและเล่นเนื้อหา - ติดตามสถานะสื่อ
- ส่งคำสั่งการเล่นไปยังผู้รับตามการโต้ตอบของผู้ใช้
เราทำขั้นตอนที่ 2 ในส่วนก่อนหน้าไปแล้ว ขั้นตอนที่ 3 ทำได้ง่ายๆ ด้วยเฟรมเวิร์กของ Cast ขั้นตอนที่ 1 เกี่ยวข้องกับการจับคู่ออบเจ็กต์หนึ่งกับอีกออบเจ็กต์ MediaInfo
เป็นสิ่งที่เฟรมเวิร์กของ Cast เข้าใจได้ และ MediaItem
ก็เป็นการสรุปรวมของแอปสำหรับรายการสื่อ เราสามารถจับคู่ MediaItem
กับ MediaInfo
ได้โดยง่าย
แอปตัวอย่าง LocalPlayerActivity
แยกความแตกต่างระหว่างการเล่นแบบภายในกับแบบระยะไกลอยู่แล้วโดยใช้ enum นี้
private var mLocation: PlaybackLocation? = null
enum class PlaybackLocation {
LOCAL, REMOTE
}
enum class PlaybackState {
PLAYING, PAUSED, BUFFERING, IDLE
}
ใน Codelab นี้ คุณไม่จำเป็นต้องเข้าใจอย่างถ่องแท้ว่าตรรกะของโปรแกรมเล่นตัวอย่างทั้งหมดทำงานอย่างไร โปรดทราบว่าจะต้องแก้ไขโปรแกรมเล่นสื่อของแอปเพื่อให้รับรู้ตำแหน่งการเล่น 2 ตำแหน่งในลักษณะที่คล้ายกัน
ขณะนี้โปรแกรมเล่นในเครื่องจะอยู่ในสถานะการเล่นในเครื่องเสมอ เนื่องจากยังไม่ทราบข้อมูลเกี่ยวกับสถานะการแคสต์ เราจำเป็นต้องอัปเดต UI ตามการเปลี่ยนแปลงสถานะที่เกิดขึ้นในเฟรมเวิร์กของ Cast ตัวอย่างเช่น หากเริ่มแคสต์ เราต้องหยุดการเล่นในเครื่องและปิดใช้การควบคุมบางอย่าง ในทำนองเดียวกัน หากเราหยุดแคสต์ขณะที่ดำเนินการนี้อยู่ เราจะต้องเปลี่ยนไปเล่นในเครื่อง เราจึงจำเป็นต้องรับฟังเหตุการณ์ต่างๆ ที่เฟรมเวิร์กของ Cast สร้างขึ้น
การจัดการเซสชันการแคสต์
สำหรับเฟรมเวิร์กการแคสต์ เซสชันการแคสต์จะรวมขั้นตอนการเชื่อมต่ออุปกรณ์ การเปิด (หรือการเข้าร่วม) การเชื่อมต่อกับแอปพลิเคชันตัวรับสัญญาณ และการเริ่มต้นช่องทางควบคุมสื่อตามความเหมาะสม ช่องทางควบคุมสื่อคือวิธีที่เฟรมเวิร์กของ Cast ส่งและรับข้อความจากมีเดียเพลเยอร์ของเครื่องรับ
เซสชันการแคสต์จะเริ่มต้นโดยอัตโนมัติเมื่อผู้ใช้เลือกอุปกรณ์จากปุ่ม "แคสต์" และจะหยุดโดยอัตโนมัติเมื่อผู้ใช้ยกเลิกการเชื่อมต่อ นอกจากนี้ Cast SDK จะจัดการการเชื่อมต่อกับเซสชันของผู้รับอีกครั้งโดยอัตโนมัติหากมีปัญหาเกี่ยวกับเครือข่าย
มาเพิ่ม SessionManagerListener
ลงใน LocalPlayerActivity
กัน
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener
...
private var mSessionManagerListener: SessionManagerListener<CastSession>? = null
private var mCastSession: CastSession? = null
...
private fun setupCastListener() {
mSessionManagerListener = object : SessionManagerListener<CastSession> {
override fun onSessionEnded(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
onApplicationConnected(session)
}
override fun onSessionResumeFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionStarted(session: CastSession, sessionId: String) {
onApplicationConnected(session)
}
override fun onSessionStartFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionStarting(session: CastSession) {}
override fun onSessionEnding(session: CastSession) {}
override fun onSessionResuming(session: CastSession, sessionId: String) {}
override fun onSessionSuspended(session: CastSession, reason: Int) {}
private fun onApplicationConnected(castSession: CastSession) {
mCastSession = castSession
if (null != mSelectedMedia) {
if (mPlaybackState == PlaybackState.PLAYING) {
mVideoView!!.pause()
loadRemoteMedia(mSeekbar!!.progress, true)
return
} else {
mPlaybackState = PlaybackState.IDLE
updatePlaybackLocation(PlaybackLocation.REMOTE)
}
}
updatePlayButton(mPlaybackState)
invalidateOptionsMenu()
}
private fun onApplicationDisconnected() {
updatePlaybackLocation(PlaybackLocation.LOCAL)
mPlaybackState = PlaybackState.IDLE
mLocation = PlaybackLocation.LOCAL
updatePlayButton(mPlaybackState)
invalidateOptionsMenu()
}
}
}
ในกิจกรรม LocalPlayerActivity
เราอยากทราบเมื่อมีการเชื่อมต่อหรือยกเลิกการเชื่อมต่อจากอุปกรณ์ Cast เพื่อให้เราสามารถเปลี่ยนไปใช้หรือจากโปรแกรมเล่นในเครื่องได้ โปรดทราบว่าทั้งนี้ การเชื่อมต่ออาจหยุดชะงักได้ในกรณีที่แอปพลิเคชันของคุณทำงานบนอุปกรณ์เคลื่อนที่ แต่การใช้งานก็อาจหยุดชะงักได้เพราะแอปพลิเคชันอื่นของคุณ (หรือแอปพลิเคชันอื่น) ที่ทำงานบนอุปกรณ์เคลื่อนที่เครื่องอื่น
คุณเข้าถึงเซสชันที่ใช้งานอยู่ในปัจจุบันได้โดยใช้ SessionManager.getCurrentSession()
ระบบจะสร้างและแยกเซสชันออกโดยอัตโนมัติตามการโต้ตอบของผู้ใช้ที่มีกล่องโต้ตอบการแคสต์
เราต้องลงทะเบียนโปรแกรมรับฟังเซสชันและเริ่มต้นตัวแปรบางอย่างที่จะใช้ในกิจกรรม เปลี่ยนเมธอด LocalPlayerActivity
onCreate
เป็น:
import com.google.android.gms.cast.framework.CastContext
...
private var mCastContext: CastContext? = null
...
override fun onCreate(savedInstanceState: Bundle?) {
...
mCastContext = CastContext.getSharedInstance(this)
mCastSession = mCastContext!!.sessionManager.currentCastSession
setupCastListener()
...
loadViews()
...
val bundle = intent.extras
if (bundle != null) {
....
if (shouldStartPlayback) {
....
} else {
if (mCastSession != null && mCastSession!!.isConnected()) {
updatePlaybackLocation(PlaybackLocation.REMOTE)
} else {
updatePlaybackLocation(PlaybackLocation.LOCAL)
}
mPlaybackState = PlaybackState.IDLE
updatePlayButton(mPlaybackState)
}
}
...
}
กำลังโหลดสื่อ
ใน Cast SDK นั้น RemoteMediaClient
มีชุด API ที่สะดวกสำหรับจัดการการเล่นสื่อระยะไกลบนอุปกรณ์รับ สําหรับ CastSession
ที่รองรับการเล่นสื่อ SDK จะสร้างอินสแตนซ์ของ RemoteMediaClient
โดยอัตโนมัติ คุณสามารถเข้าถึงได้โดยการเรียกใช้เมธอด getRemoteMediaClient()
ในอินสแตนซ์ CastSession
เพิ่มวิธีการต่อไปนี้ลงใน LocalPlayerActivity
เพื่อโหลดวิดีโอที่เลือกในปัจจุบันบนอุปกรณ์รับ:
import com.google.android.gms.cast.framework.media.RemoteMediaClient
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.common.images.WebImage
import com.google.android.gms.cast.MediaLoadRequestData
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
if (mCastSession == null) {
return
}
val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
remoteMediaClient.load( MediaLoadRequestData.Builder()
.setMediaInfo(buildMediaInfo())
.setAutoplay(autoPlay)
.setCurrentTime(position.toLong()).build())
}
private fun buildMediaInfo(): MediaInfo? {
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
mSelectedMedia?.studio?.let { movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, it) }
mSelectedMedia?.title?.let { movieMetadata.putString(MediaMetadata.KEY_TITLE, it) }
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(0))))
movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(1))))
return mSelectedMedia!!.url?.let {
MediaInfo.Builder(it)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("videos/mp4")
.setMetadata(movieMetadata)
.setStreamDuration((mSelectedMedia!!.duration * 1000).toLong())
.build()
}
}
ตอนนี้ให้อัปเดตวิธีต่างๆ ที่มีอยู่เพื่อใช้ตรรกะเซสชันการแคสต์เพื่อรองรับการเล่นจากระยะไกล ดังนี้
private fun play(position: Int) {
startControllersTimer()
when (mLocation) {
PlaybackLocation.LOCAL -> {
mVideoView!!.seekTo(position)
mVideoView!!.start()
}
PlaybackLocation.REMOTE -> {
mPlaybackState = PlaybackState.BUFFERING
updatePlayButton(mPlaybackState)
//seek to a new position within the current media item's new position
//which is in milliseconds from the beginning of the stream
mCastSession!!.remoteMediaClient?.seek(position.toLong())
}
else -> {}
}
restartTrickplayTimer()
}
private fun togglePlayback() {
...
PlaybackState.IDLE -> when (mLocation) {
...
PlaybackLocation.REMOTE -> {
if (mCastSession != null && mCastSession!!.isConnected) {
loadRemoteMedia(mSeekbar!!.progress, true)
}
}
else -> {}
}
...
}
override fun onPause() {
...
mCastContext!!.sessionManager.removeSessionManagerListener(
mSessionManagerListener!!, CastSession::class.java)
}
override fun onResume() {
Log.d(TAG, "onResume() was called")
mCastContext!!.sessionManager.addSessionManagerListener(
mSessionManagerListener!!, CastSession::class.java)
if (mCastSession != null && mCastSession!!.isConnected) {
updatePlaybackLocation(PlaybackLocation.REMOTE)
} else {
updatePlaybackLocation(PlaybackLocation.LOCAL)
}
super.onResume()
}
สําหรับเมธอด updatePlayButton
ให้เปลี่ยนค่าของตัวแปร isConnected
ดังนี้
private fun updatePlayButton(state: PlaybackState?) {
...
val isConnected = (mCastSession != null
&& (mCastSession!!.isConnected || mCastSession!!.isConnecting))
...
}
จากนั้นคลิกปุ่ม เรียกใช้ เพื่อเรียกใช้แอปบนอุปกรณ์เคลื่อนที่ เชื่อมต่ออุปกรณ์ Cast และเริ่มเล่นวิดีโอ คุณควรเห็นวิดีโอเล่นอยู่ในเครื่องรับ
7. มินิคอนโทรลเลอร์
รายการตรวจสอบการออกแบบ Cast กําหนดให้แอป Cast ทั้งหมดต้องมีตัวควบคุมขนาดเล็กที่ปรากฏขึ้นเมื่อผู้ใช้ออกจากหน้าเนื้อหาปัจจุบัน ตัวควบคุมขนาดเล็กช่วยให้เข้าถึงได้ทันทีและการช่วยเตือนที่มองเห็นได้สำหรับเซสชันการแคสต์ปัจจุบัน
Cast SDK มีมุมมองที่กำหนดเอง MiniControllerFragment
ซึ่งสามารถเพิ่มลงในไฟล์เลย์เอาต์แอปของกิจกรรมที่คุณต้องการแสดงตัวควบคุมขนาดเล็ก
เพิ่มคําจํากัดความของข้อมูลโค้ดต่อไปนี้ที่ด้านล่างของทั้ง res/layout/player_activity.xml
และ res/layout/video_browser.xml
<fragment
android:id="@+id/castMiniController"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone"
class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment"/>
คลิกปุ่มเรียกใช้เพื่อเรียกใช้แอปและแคสต์วิดีโอ เมื่อเริ่มเล่นบนเครื่องรับ คุณจะเห็นตัวควบคุมขนาดเล็กปรากฏที่ด้านล่างของแต่ละกิจกรรม คุณควบคุมการเล่นระยะไกลได้โดยใช้มินิคอนโทรลเลอร์ หากคุณไปยังส่วนต่างๆ ระหว่างกิจกรรมการเรียกดูและกิจกรรมของโปรแกรมเล่นในเครื่อง สถานะตัวควบคุมมินิควรซิงค์กับสถานะการเล่นสื่อของตัวรับ
8. การแจ้งเตือนและหน้าจอล็อก
รายการตรวจสอบการออกแบบ Google Cast กําหนดให้แอปผู้ส่งต้องใช้การควบคุมสื่อจากการแจ้งเตือนและหน้าจอล็อก
Cast SDK มี MediaNotificationService
เพื่อช่วยแอปผู้ส่งสร้างตัวควบคุมสื่อสำหรับการแจ้งเตือนและหน้าจอล็อก ระบบจะผสานบริการนี้ในไฟล์ Manifest ของแอปโดยอัตโนมัติด้วย Gradle
MediaNotificationService
จะทำงานในเบื้องหลังเมื่อผู้ส่งกำลังแคสต์ และจะแสดงการแจ้งเตือนพร้อมภาพขนาดย่อและข้อมูลเมตาเกี่ยวกับรายการที่กำลังแคสต์ปัจจุบัน ปุ่มเล่น/หยุดชั่วคราว และปุ่มหยุด
คุณเปิดใช้การควบคุมการแจ้งเตือนและหน้าจอล็อกได้ด้วย CastOptions
เมื่อเริ่มต้น CastContext
การควบคุมสื่อสำหรับการแจ้งเตือนและหน้าจอล็อกจะเปิดอยู่โดยค่าเริ่มต้น ฟีเจอร์หน้าจอล็อกจะเปิดตราบใดที่การแจ้งเตือนเปิดอยู่
แก้ไข CastOptionsProvider
และเปลี่ยนแปลงการใช้งาน getCastOptions
ให้ตรงกับโค้ดนี้:
import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.NotificationOptions
override fun getCastOptions(context: Context): CastOptions {
val notificationOptions = NotificationOptions.Builder()
.setTargetActivityClassName(VideoBrowserActivity::class.java.name)
.build()
val mediaOptions = CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.build()
return CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.app_id))
.setCastMediaOptions(mediaOptions)
.build()
}
คลิกปุ่ม Run เพื่อเรียกใช้แอปบนอุปกรณ์เคลื่อนที่ แคสต์วิดีโอและออกจากแอปตัวอย่าง คุณควรได้รับการแจ้งเตือนสำหรับวิดีโอที่เล่นอยู่ในอุปกรณ์รับ ล็อกอุปกรณ์เคลื่อนที่และหน้าจอล็อกควรแสดงตัวควบคุมการเล่นสื่อบนอุปกรณ์แคสต์
9. การวางซ้อนช่วงแนะนำ
รายการตรวจสอบการออกแบบของ Google Cast กำหนดให้แอปผู้ส่งต้องแนะนำปุ่ม "แคสต์" แก่ผู้ใช้เดิม เพื่อแจ้งให้ทราบว่าแอปผู้ส่งรองรับการแคสต์แล้ว และยังช่วยให้ผู้ใช้ที่เพิ่งเริ่มใช้ Google Cast อีกด้วย
Cast SDK มีมุมมองที่กำหนดเอง IntroductoryOverlay
ซึ่งสามารถใช้เพื่อไฮไลต์ปุ่มแคสต์เมื่อแสดงต่อผู้ใช้เป็นครั้งแรก เพิ่มโค้ดต่อไปนี้ลงใน VideoBrowserActivity
import com.google.android.gms.cast.framework.IntroductoryOverlay
import android.os.Looper
private var mIntroductoryOverlay: IntroductoryOverlay? = null
private fun showIntroductoryOverlay() {
mIntroductoryOverlay?.remove()
if (mediaRouteMenuItem?.isVisible == true) {
Looper.myLooper().run {
mIntroductoryOverlay = com.google.android.gms.cast.framework.IntroductoryOverlay.Builder(
this@VideoBrowserActivity, mediaRouteMenuItem!!)
.setTitleText("Introducing Cast")
.setSingleTime()
.setOnOverlayDismissedListener(
object : IntroductoryOverlay.OnOverlayDismissedListener {
override fun onOverlayDismissed() {
mIntroductoryOverlay = null
}
})
.build()
mIntroductoryOverlay!!.show()
}
}
}
ตอนนี้ให้เพิ่ม CastStateListener
และเรียกใช้เมธอด showIntroductoryOverlay
เมื่ออุปกรณ์ Cast พร้อมใช้งานโดยการแก้ไขเมธอด onCreate
และลบล้างเมธอด onResume
และ onPause
ให้ตรงกับตัวอย่างต่อไปนี้
import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.cast.framework.CastStateListener
private var mCastStateListener: CastStateListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.video_browser)
setupActionBar()
mCastStateListener = object : CastStateListener {
override fun onCastStateChanged(newState: Int) {
if (newState != CastState.NO_DEVICES_AVAILABLE) {
showIntroductoryOverlay()
}
}
}
mCastContext = CastContext.getSharedInstance(this)
}
override fun onResume() {
super.onResume()
mCastContext?.addCastStateListener(mCastStateListener!!)
}
override fun onPause() {
super.onPause()
mCastContext?.removeCastStateListener(mCastStateListener!!)
}
ล้างข้อมูลแอปหรือนำแอปออกจากอุปกรณ์ จากนั้นคลิกปุ่ม Run เพื่อเรียกใช้แอปในอุปกรณ์เคลื่อนที่ และคุณควรเห็นการวางซ้อนข้อมูลเบื้องต้น (ล้างข้อมูลแอปหากการวางซ้อนไม่แสดง)
10. ตัวควบคุมที่ขยาย
รายการตรวจสอบการออกแบบของ Google Cast กำหนดให้แอปผู้ส่งต้องมีตัวควบคุมแบบขยายสำหรับสื่อที่กำลังแคสต์ ตัวควบคุมแบบขยายคือตัวควบคุมมินิเวอร์ชันเต็มหน้าจอ
Cast SDK มีวิดเจ็ตสำหรับตัวควบคุมแบบขยายที่เรียกว่า ExpandedControllerActivity
ซึ่งเป็นคลาสนามธรรมที่คุณต้องสร้างคลาสย่อยเพื่อเพิ่มปุ่มแคสต์
ขั้นแรก ให้สร้างไฟล์แหล่งข้อมูลเมนูใหม่ที่ชื่อ expanded_controller.xml
สำหรับตัวควบคุมที่ขยายแล้วเพื่อให้มีปุ่ม "แคสต์" ดังนี้
<?xml version="1.0" encoding="utf-8"?>
<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="@string/media_route_menu_title"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="always"/>
</menu>
สร้างแพ็กเกจ expandedcontrols
ใหม่ในแพ็กเกจ com.google.sample.cast.refplayer
จากนั้นสร้างไฟล์ใหม่ชื่อ ExpandedControlsActivity.kt
ในแพ็กเกจ com.google.sample.cast.refplayer.expandedcontrols
package com.google.sample.cast.refplayer.expandedcontrols
import android.view.Menu
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.google.sample.cast.refplayer.R
import com.google.android.gms.cast.framework.CastButtonFactory
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
}
}
ตอนนี้ให้ประกาศ ExpandedControlsActivity
ใน AndroidManifest.xml
ภายในแท็ก application
เหนือ OPTIONS_PROVIDER_CLASS_NAME
ดังนี้
<application>
...
<activity
android:name="com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/Theme.CastVideosDark"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.google.sample.cast.refplayer.VideoBrowserActivity"/>
</activity>
...
</application>
แก้ไข CastOptionsProvider
และเปลี่ยน NotificationOptions
และ CastMediaOptions
เพื่อตั้งค่ากิจกรรมเป้าหมายเป็น ExpandedControlsActivity
import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity
override fun getCastOptions(context: Context): CastOptions {
val notificationOptions = NotificationOptions.Builder()
.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()
}
อัปเดตเมธอด LocalPlayerActivity
loadRemoteMedia
เพื่อแสดง ExpandedControlsActivity
เมื่อโหลดสื่อระยะไกล
import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity
private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
if (mCastSession == null) {
return
}
val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
remoteMediaClient.registerCallback(object : RemoteMediaClient.Callback() {
override fun onStatusUpdated() {
val intent = Intent(this@LocalPlayerActivity, ExpandedControlsActivity::class.java)
startActivity(intent)
remoteMediaClient.unregisterCallback(this)
}
})
remoteMediaClient.load(MediaLoadRequestData.Builder()
.setMediaInfo(buildMediaInfo())
.setAutoplay(autoPlay)
.setCurrentTime(position.toLong()).build())
}
คลิกปุ่ม เรียกใช้ เพื่อเรียกใช้แอปบนอุปกรณ์เคลื่อนที่และแคสต์วิดีโอ คุณจะเห็นตัวควบคุมที่ขยายแล้ว กลับไปที่รายการวิดีโอ และเมื่อคุณคลิกตัวควบคุมขนาดเล็ก ตัวควบคุมที่ขยายแล้วจะโหลดอีกครั้ง ออกจากแอปเพื่อดูการแจ้งเตือน คลิกรูปภาพการแจ้งเตือนเพื่อโหลดตัวควบคุมที่ขยาย
11. เพิ่มการรองรับ Cast Connect
ไลบรารี Cast Connect ช่วยให้แอปพลิเคชันของผู้ส่งที่มีอยู่สามารถสื่อสารกับแอปพลิเคชัน Android TV ผ่านโปรโตคอล Cast Cast Connect สร้างขึ้นจากโครงสร้างพื้นฐานของ Cast โดยแอป Android TV จะทำหน้าที่เป็นตัวรับ
การอ้างอิง
หมายเหตุ: สำหรับการใช้ Cast Connect play-services-cast-framework
จะต้องมีค่าไม่ต่ำกว่า 19.0.0
LaunchOptions
ในการเปิดแอปพลิเคชัน Android TV หรือที่เรียกว่าตัวรับสัญญาณ Android เราต้องตั้งค่า Flag setAndroidReceiverCompatible
เป็น "จริง" ในออบเจ็กต์ LaunchOptions
ออบเจ็กต์ LaunchOptions
นี้จะกำหนดวิธีเปิดใช้งานตัวรับและส่งไปยัง CastOptions
ที่คลาส CastOptionsProvider
แสดงผล การตั้งค่า Flag ที่กล่าวถึงข้างต้นเป็น false
จะเปิดเว็บรีซีฟเวอร์สําหรับรหัสแอปที่กําหนดไว้ในคอนโซลนักพัฒนาแอปของ Cast
ในไฟล์ CastOptionsProvider.kt
ให้เพิ่มค่าต่อไปนี้ลงในเมธอด getCastOptions
import com.google.android.gms.cast.LaunchOptions
...
val launchOptions = LaunchOptions.Builder()
.setAndroidReceiverCompatible(true)
.build()
return new CastOptions.Builder()
.setLaunchOptions(launchOptions)
...
.build()
ตั้งค่าข้อมูลเข้าสู่ระบบสำหรับการเปิดใช้งาน
ทางฝั่งผู้ส่ง คุณสามารถระบุ CredentialsData
เพื่อแสดงถึงผู้ที่จะเข้าร่วมเซสชันได้ credentials
คือสตริงที่ผู้ใช้กำหนดได้ ตราบใดที่แอป ATV เข้าใจสตริงดังกล่าว ระบบจะส่ง CredentialsData
ไปยังแอป Android TV ของคุณเฉพาะในช่วงเปิดหรือเข้าร่วมเท่านั้น หากคุณตั้งค่าอีกครั้งขณะเชื่อมต่ออยู่ ระบบจะไม่ส่งข้อความดังกล่าวไปยังแอป Android TV
ในการตั้งค่าข้อมูลเข้าสู่ระบบการเปิดใช้ คุณต้องกำหนด CredentialsData
และส่งไปยังออบเจ็กต์ LaunchOptions
เพิ่มโค้ดต่อไปนี้ลงในเมธอด getCastOptions
ในไฟล์ CastOptionsProvider.kt
import com.google.android.gms.cast.CredentialsData
...
val credentialsData = CredentialsData.Builder()
.setCredentials("{\"userId\": \"abc\"}")
.build()
val launchOptions = LaunchOptions.Builder()
...
.setCredentialsData(credentialsData)
.build()
ตั้งค่าข้อมูลเข้าสู่ระบบใน LoadRequest
ในกรณีที่แอป Web Receiver และแอป Android TV จัดการ credentials
แตกต่างกัน คุณอาจต้องกำหนด credentials
แยกกันสำหรับแต่ละแอป หากต้องการแก้ปัญหานี้ ให้เพิ่มโค้ดต่อไปนี้ในไฟล์ LocalPlayerActivity.kt
ในส่วนฟังก์ชัน loadRemoteMedia
remoteMediaClient.load(MediaLoadRequestData.Builder()
...
.setCredentials("user-credentials")
.setAtvCredentials("atv-user-credentials")
.build())
ตอนนี้ SDK จะจัดการข้อมูลเข้าสู่ระบบที่จะใช้สำหรับเซสชันปัจจุบันโดยอัตโนมัติ ทั้งนี้ขึ้นอยู่กับแอปผู้รับที่ผู้ส่งกำลังแคสต์อยู่
กำลังทดสอบ Cast Connect
ขั้นตอนในการติดตั้ง APK ของ Android TV ใน Chromecast พร้อม Google TV
- ค้นหาที่อยู่ IP ของอุปกรณ์ Android TV โดยปกติแล้ว วิธีการนี้จะอยู่ในส่วนการตั้งค่า > เครือข่ายและ อินเทอร์เน็ต > (ชื่อเครือข่ายที่อุปกรณ์เชื่อมต่ออยู่) ทางด้านขวาจะแสดงรายละเอียดและ IP ของอุปกรณ์ในเครือข่าย
- ใช้ที่อยู่ IP ของอุปกรณ์เพื่อเชื่อมต่อกับอุปกรณ์ผ่าน ADB โดยใช้เทอร์มินัล:
$ adb connect <device_ip_address>:5555
- จากหน้าต่างเทอร์มินัล ให้ไปที่โฟลเดอร์ระดับบนสุดของตัวอย่างโค้ดแล็บที่คุณดาวน์โหลดไว้เมื่อเริ่มโค้ดแล็บนี้ เช่น
$ cd Desktop/android_codelab_src
- ติดตั้งไฟล์ .apk ในโฟลเดอร์นี้ลงใน Android TV โดยเรียกใช้คำสั่งต่อไปนี้
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- ตอนนี้คุณควรเห็นแอปด้วยชื่อแคสต์วิดีโอในเมนูแอปของคุณบนอุปกรณ์ Android TV แล้ว
- กลับไปที่โปรเจ็กต์ Android Studio แล้วคลิกปุ่ม "เรียกใช้" เพื่อติดตั้งและเรียกใช้แอปผู้ส่งบนอุปกรณ์เคลื่อนที่จริง ที่มุมขวาบน ให้คลิกไอคอนแคสต์ แล้วเลือกอุปกรณ์ Android TV จากตัวเลือกที่มี ตอนนี้คุณควรเห็นแอป Android TV เปิดขึ้นในอุปกรณ์ Android TV และการเล่นวิดีโอจะช่วยให้คุณควบคุมการเล่นวิดีโอได้โดยใช้รีโมต Android TV
12. ปรับแต่งวิดเจ็ตแคสต์
คุณปรับแต่งวิดเจ็ตแคสต์ได้โดยตั้งค่าสี จัดรูปแบบปุ่ม ข้อความ และรูปลักษณ์ของภาพขนาดย่อ และเลือกประเภทปุ่มที่จะแสดง
อัปเดต res/values/styles_castvideo.xml
<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
<item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
<item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
<item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
<item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
<item name="castExpandedControllerToolbarStyle">
@style/ThemeOverlay.AppCompat.ActionBar
</item>
...
</style>
ประกาศธีมที่กำหนดเองต่อไปนี้
<!-- Customize Cast Button -->
<style name="CustomMediaRouterTheme" parent="Theme.MediaRouter">
<item name="mediaRouteButtonStyle">@style/CustomMediaRouteButtonStyle</item>
</style>
<style name="CustomMediaRouteButtonStyle" parent="Widget.MediaRouter.Light.MediaRouteButton">
<item name="mediaRouteButtonTint">#EEFF41</item>
</style>
<!-- Customize Introductory Overlay -->
<style name="CustomCastIntroOverlay" parent="CastIntroOverlay">
<item name="castButtonTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Button</item>
<item name="castTitleTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Title</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Button" parent="android:style/TextAppearance">
<item name="android:textColor">#FFFFFF</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Title" parent="android:style/TextAppearance.Large">
<item name="android:textColor">#FFFFFF</item>
</style>
<!-- Customize Mini Controller -->
<style name="CustomCastMiniController" parent="CastMiniController">
<item name="castShowImageThumbnail">true</item>
<item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item>
<item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item>
<item name="castBackground">@color/accent</item>
<item name="castProgressBarColor">@color/orange</item>
</style>
<!-- Customize Expanded Controller -->
<style name="CustomCastExpandedController" parent="CastExpandedController">
<item name="castButtonColor">#FFFFFF</item>
<item name="castPlayButtonDrawable">@drawable/cast_ic_expanded_controller_play</item>
<item name="castPauseButtonDrawable">@drawable/cast_ic_expanded_controller_pause</item>
<item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item>
</style>
13. ขอแสดงความยินดี
ตอนนี้คุณก็ทราบวิธีเปิดใช้การแคสต์ในแอปวิดีโอโดยใช้วิดเจ็ต Cast SDK ใน Android แล้ว
ดูรายละเอียดเพิ่มเติมได้ที่คู่มือนักพัฒนาแอป Android Sender