1. ภาพรวม
Codelab นี้จะสอนวิธีแก้ไขแอปวิดีโอ Android ที่มีอยู่เพื่อแคสต์เนื้อหาบนอุปกรณ์ที่พร้อมใช้งาน Google Cast
Google Cast คืออะไร
Google Cast ช่วยให้ผู้ใช้แคสต์เนื้อหาจากอุปกรณ์เคลื่อนที่ไปยัง TV ได้ จากนั้นผู้ใช้จะใช้อุปกรณ์เคลื่อนที่เป็นรีโมตคอนโทรลในการเล่นสื่อบนทีวีได้
Google Cast SDK ช่วยให้คุณขยายแอปเพื่อควบคุมทีวีหรือระบบเสียงได้ Cast SDK ช่วยให้คุณเพิ่มคอมโพเนนต์ UI ที่จําเป็นได้ตามรายการตรวจสอบการออกแบบ Google Cast
รายการตรวจสอบการออกแบบ Google Cast มีไว้ให้ผู้ใช้ของ Cast ใช้งานได้ง่ายและคาดการณ์ได้ในทุกแพลตฟอร์มที่รองรับ
สิ่งที่เรากําลังจะสร้าง
หลังจากที่คุณสร้าง Codelab เสร็จแล้ว คุณจะมีแอปวิดีโอ Android ที่สามารถแคสต์วิดีโอไปยังอุปกรณ์ที่พร้อมใช้งาน Google Cast ได้
สิ่งที่คุณจะได้เรียนรู้
- วิธีเพิ่ม Google Cast SDK ลงในตัวอย่างแอปวิดีโอ
- วิธีการเพิ่มปุ่ม "แคสต์" เพื่อเลือกอุปกรณ์ Google Cast
- วิธีเชื่อมต่ออุปกรณ์ Cast และเปิดตัวรับสื่อ
- วิธีแคสต์วิดีโอ
- วิธีเพิ่มตัวควบคุม Mini mini ลงในแอป
- วิธีรองรับการแจ้งเตือนสื่อและการควบคุมหน้าจอล็อก
- วิธีเพิ่มตัวควบคุมแบบขยาย
- วิธีแสดงการวางซ้อนที่แนะนํา
- วิธีปรับแต่งวิดเจ็ตแคสต์
- วิธีผสานรวมกับ Cast Connect
สิ่งที่ต้องมี
- Android SDK เวอร์ชันล่าสุด
- Android Studio เวอร์ชัน 3.2 ขึ้นไป
- อุปกรณ์เคลื่อนที่รุ่นหนึ่งที่ใช้แอนดรอยด์ Jelly Bean 4.1 ขึ้นไป (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
จากโฟลเดอร์โค้ดตัวอย่างแล้วคลิก OK
คลิก File > Sync Project with Gradle Files
เปิดใช้งานการแก้ไขข้อบกพร่อง USB บนอุปกรณ์ Android ของคุณ บน Android 4.2 หรือสูงกว่า หน้าจอตัวเลือกสําหรับนักพัฒนาซอฟต์แวร์จะถูกซ่อนไว้โดยค่าเริ่มต้น หากต้องการแสดงหมายเลขดังกล่าว ให้ไปที่การตั้งค่า > เกี่ยวกับโทรศัพท์ แล้วแตะหมายเลขรุ่น 7 ครั้ง กลับไปที่หน้าจอก่อนหน้า ไปที่ระบบ > ขั้นสูง และแตะตัวเลือกสําหรับนักพัฒนาซอฟต์แวร์ที่อยู่ใกล้กับด้านล่าง แล้วแตะการแก้ไขข้อบกพร่อง USB เพื่อเปิดใช้งาน
เสียบอุปกรณ์ Android แล้วคลิกปุ่มเรียกใช้ใน Android Studio คุณควรเห็นแอปวิดีโอชื่อแคสต์วิดีโอปรากฏขึ้นไม่กี่วินาที
คลิกปุ่ม "แคสต์" ในแอปวิดีโอ และเลือกอุปกรณ์ Google Cast ของคุณ
เลือกวิดีโอและคลิกปุ่มเล่น
วิดีโอจะเริ่มเล่นในอุปกรณ์ Google Cast
ตัวควบคุมที่ขยายแล้วจะปรากฏขึ้น คุณสามารถใช้ปุ่มเล่น/หยุดชั่วคราวเพื่อควบคุมการเล่นได้
กลับไปยังรายการวิดีโอ
ตัวควบคุมขนาดเล็กจะปรากฏที่ด้านล่างของหน้าจอแล้ว
คลิกปุ่มหยุดชั่วคราวในตัวควบคุมขนาดเล็กเพื่อหยุดวิดีโอชั่วคราวในฝั่งผู้รับ คลิกที่ปุ่มเล่นในตัวควบคุมขนาดเล็กเพื่อเล่นวิดีโอต่อ
คลิกปุ่มหน้าแรกบนอุปกรณ์เคลื่อนที่ ดึงการแจ้งเตือนลงมา จากนั้นคุณจะเห็นการแจ้งเตือนสําหรับเซสชันแคสต์
ล็อกโทรศัพท์และเมื่อคุณปลดล็อก คุณจะเห็นการแจ้งเตือนในหน้าจอล็อกเพื่อควบคุมการเล่นสื่อหรือหยุดแคสต์
กลับไปที่แอปวิดีโอและคลิกปุ่ม "แคสต์" เพื่อหยุดแคสต์บนอุปกรณ์ Google Cast
คำถามที่พบบ่อย
4. เตรียมโปรเจ็กต์เริ่มต้น
เราจําเป็นต้องเพิ่มการสนับสนุนสําหรับ Google Cast ไปยังแอปพลิเคชันเริ่มต้นที่คุณดาวน์โหลด ต่อไปนี้คือคําศัพท์ของ Google Cast ที่เราจะใช้ใน Codelab นี้
- แอปผู้ส่งทํางานในอุปกรณ์เคลื่อนที่หรือแล็ปท็อป
- แอปตัวรับจะทํางานบนอุปกรณ์ Google Cast
ตอนนี้คุณพร้อมที่จะสร้างต่อยอดจากโครงการเริ่มต้นโดยใช้ Android Studio แล้ว
- เลือกไดเรกทอรี
app-start
จากตัวอย่างการดาวน์โหลดโค้ด (เลือกนําเข้าโปรเจ็กต์ในหน้าจอต้อนรับหรือตัวเลือกเมนูไฟล์ > ใหม่ > นําเข้าโปรเจ็กต์...) - คลิกปุ่ม
ซิงค์โครงการกับ Gradle Files
- คลิกปุ่ม
เรียกใช้เพื่อเรียกใช้แอปและสํารวจ UI
การออกแบบแอป
แอปจะดึงรายการวิดีโอจากเว็บเซิร์ฟเวอร์ระยะไกลและแสดงรายการสําหรับผู้ใช้ที่จะเรียกดู ผู้ใช้สามารถเลือกวิดีโอเพื่อดูรายละเอียดหรือเล่นวิดีโอในเครื่องบนอุปกรณ์เคลื่อนที่ได้
แอปนี้ประกอบด้วยกิจกรรมหลัก 2 อย่าง ได้แก่ VideoBrowserActivity
และ LocalPlayerActivity
ในการผสานรวมฟังก์ชัน Google Cast กิจกรรมจะต้องรับช่วงมาจาก AppCompatActivity
หรือ FragmentActivity
ระดับบนสุด ข้อจํากัดนี้มีอยู่เนื่องจากเราต้องเพิ่ม MediaRouteButton
(ซึ่งอยู่ในไลบรารีการสนับสนุนของ MediaRouter) เป็น MediaRouteActionProvider
และจะใช้ได้ต่อเมื่อกิจกรรมรับช่วงมาจากคลาสที่กล่าวถึงข้างต้นเท่านั้น ไลบรารีการสนับสนุนของ MediaRouter จะขึ้นอยู่กับไลบรารีการสนับสนุนของ AppCompat ซึ่งมีคลาสที่จําเป็น
กิจกรรมเบราว์เซอร์วิดีโอ
กิจกรรมนี้ประกอบด้วย Fragment
(VideoBrowserFragment
) รายการนี้ได้รับการสนับสนุนโดย ArrayAdapter
(VideoListAdapter
) รายการวิดีโอและข้อมูลเมตาที่เกี่ยวข้องจะโฮสต์บนเซิร์ฟเวอร์ระยะไกลเป็นไฟล์ JSON AsyncTaskLoader
(VideoItemLoader
) จะดึงข้อมูล JSON นี้ และประมวลผลเพื่อสร้างรายการออบเจ็กต์ MediaItem
ออบเจ็กต์ MediaItem
สร้างโมเดลวิดีโอและข้อมูลเมตาที่เกี่ยวข้อง เช่น ชื่อ คําอธิบาย URL ของสตรีม URL ของรูปภาพที่รองรับ และแทร็กข้อความที่เกี่ยวข้อง (สําหรับคําบรรยาย) หากมี ระบบจะส่งต่อออบเจ็กต์ MediaItem
ระหว่างกิจกรรม ดังนั้น MediaItem
จึงมีวิธียูทิลิตีในการแปลงรายการดังกล่าวเป็น Bundle
และในทางกลับกันด้วย
เมื่อตัวโหลดสร้างรายการ MediaItems
ตัวโหลดจะส่งผ่านรายการไปยัง VideoListAdapter
จากนั้นจะแสดงรายการ MediaItems
ใน VideoBrowserFragment
ผู้ใช้จะแสดงรายการภาพขนาดย่อของวิดีโอพร้อมคําอธิบายสั้นๆ ของวิดีโอแต่ละรายการ เมื่อมีการเลือกรายการ ระบบจะแปลง MediaItem
ที่สอดคล้องกันเป็น Bundle
และส่งต่อไปยัง LocalPlayerActivity
กิจกรรมของผู้เล่นในพื้นที่
กิจกรรมนี้แสดงข้อมูลเมตาเกี่ยวกับวิดีโอที่เฉพาะเจาะจงและให้ผู้ใช้เล่นวิดีโอในเครื่องบนอุปกรณ์เคลื่อนที่
กิจกรรมนี้จะมี VideoView
ตัวควบคุมสื่อบางส่วน และพื้นที่ข้อความเพื่อแสดงคําอธิบายวิดีโอที่เลือก โปรแกรมเล่นครอบคลุมส่วนบนของหน้าจอ เพื่อให้คําอธิบายของวิดีโออยู่ด้านล่าง ผู้ใช้สามารถเล่น/หยุดชั่วคราว หรือเรียกดูการเล่นวิดีโอในเครื่องได้
การอ้างอิง
เนื่องจากเราใช้ AppCompatActivity
เราจึงต้องการไลบรารีการสนับสนุนของ AppCompat เราใช้ไลบรารี Volley เพื่อจัดการรายการวิดีโอแบบไม่โหลดรูปภาพสําหรับรายการ
คำถามที่พบบ่อย
5. การเพิ่มปุ่ม "แคสต์"
แอปพลิเคชันที่พร้อมใช้งาน Cast จะแสดงปุ่ม "แคสต์" ในกิจกรรมแต่ละอย่าง การคลิกปุ่ม "แคสต์" จะแสดงรายการอุปกรณ์แคสต์ที่ผู้ใช้สามารถเลือกได้ หากผู้ใช้เล่นเนื้อหาบนอุปกรณ์เครื่องส่ง การเลือกอุปกรณ์แคสต์จะเริ่มหรือกลับมาเล่นอีกครั้งในอุปกรณ์แคสต์นั้น ผู้ใช้สามารถคลิกปุ่ม "แคสต์" และหยุดแคสต์แอปพลิเคชันไปยังอุปกรณ์แคสต์ได้ทุกเมื่อในระหว่างเซสชันการแคสต์ ผู้ใช้จะต้องสามารถเชื่อมต่อหรือยกเลิกการเชื่อมต่อจากอุปกรณ์ 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 มีออบเจ็กต์ Single Single ที่ชื่อว่า CastContext
ซึ่งจะประสานงานการโต้ตอบแคสต์ทั้งหมด
คุณต้องติดตั้งอินเทอร์เฟซ OptionsProvider
เพื่อระบุ CastOptions
ที่จําเป็นในการเริ่มต้น 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
ในเมธอด VideoBrowserActivity
Create แบบ Lazy Loading ดังนี้
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
จะเป็นผู้จัดการการค้นพบอุปกรณ์โดยอัตโนมัติ เลือกอุปกรณ์ Cast และแอปตัวรับสัญญาณตัวอย่างจะโหลดในอุปกรณ์ Cast คุณสามารถไปยังส่วนต่างๆ ระหว่างกิจกรรมการท่องเว็บและกิจกรรมในเครื่อง และสถานะของปุ่ม "แคสต์" จะซิงค์กันอยู่เสมอ
เรายังไม่ได้รองรับการใช้งานการเล่นสื่อใดๆ เลย คุณจึงยังไม่สามารถเล่นวิดีโอในอุปกรณ์ Cast ได้ คลิกปุ่ม "ส่ง" เพื่อยกเลิกการเชื่อมต่อ
6. การแคสต์เนื้อหาวิดีโอ
เราจะขยายเวลาแอปตัวอย่างให้เล่นวิดีโอระยะไกลในอุปกรณ์แคสต์ด้วย เราต้องฟังเหตุการณ์ต่างๆ ที่เฟรมเวิร์ก 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
}
การเขียนโค้ดนี้ไม่สําคัญสําหรับคุณที่จะต้องเข้าใจวิธีการทํางานของตรรกะของตัวอย่างโปรแกรมเล่นทั้งหมด คุณจะต้องเข้าใจว่าโปรแกรมเล่นสื่อของแอปจะต้องได้รับการแก้ไขให้ทราบเกี่ยวกับตําแหน่งการเล่น 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()
ได้ ระบบจะสร้างเซสชันขึ้นและแยกออกจากกันโดยอัตโนมัติเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้กับกล่องโต้ตอบแคสต์
เราต้องลงทะเบียน Listener เซสชันและเริ่มต้นตัวแปรบางอย่างที่เราจะใช้ในกิจกรรม เปลี่ยนเมธอด 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()
}
คลิกปุ่มเรียกใช้เพื่อเรียกใช้แอปในอุปกรณ์เคลื่อนที่ แคสต์วิดีโอและไปยังที่ต่างๆ จากแอปตัวอย่าง ควรมีการแจ้งเตือนสําหรับวิดีโอที่เล่นบนเครื่องรับอยู่ในขณะนี้ ล็อกอุปกรณ์เคลื่อนที่ของคุณ และหน้าจอล็อกควรแสดงตัวควบคุมสําหรับการเล่นสื่อบนอุปกรณ์ Cast ในขณะนี้
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
เมื่ออุปกรณ์แคสต์พร้อมใช้งานโดยแก้ไขเมธอด 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!!)
}
ล้างข้อมูลแอปหรือนําแอปออกจากอุปกรณ์ จากนั้นคลิกปุ่ม เรียกใช้ เพื่อเรียกใช้แอปในอุปกรณ์เคลื่อนที่ คุณควรเห็นการวางซ้อนแนะนํา (ล้างข้อมูลแอปหากโฆษณาซ้อนทับไม่แสดง)
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
ตัวเลือกการเปิดตัว
ในการเปิดใช้แอปพลิเคชัน Android TV หรือเรียกอีกอย่างว่า Android Receiver เราจําเป็นต้องตั้งค่าสถานะของ setAndroidReceiverCompatible
เป็น true ในออบเจ็กต์ LaunchOptions
ออบเจ็กต์ LaunchOptions
นี้กําหนดวิธีเปิดใช้ตัวรับและส่งต่อไปยัง CastOptions
ที่คลาส CastOptionsProvider
แสดงผล การตั้งค่าแฟล็กที่กล่าวไว้ด้านบนเป็น false
จะเปิดรีซีฟเวอร์ของเว็บสําหรับรหัสแอปที่กําหนดไว้ใน Developer Console ของ 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
- จากหน้าต่างเทอร์มินัล ให้ไปที่โฟลเดอร์ระดับบนสุดของตัวอย่าง Codelab ที่คุณดาวน์โหลดในตอนต้นของ Codelab นี้ เช่น
$ 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