Jetpack Media3 กำหนดอินเทอร์เฟซ Player
ที่ระบุฟังก์ชันพื้นฐาน
สำหรับการเล่นไฟล์วิดีโอและเสียง ExoPlayer
เป็นการใช้งานเริ่มต้น
ของอินเทอร์เฟซนี้ใน Media3 เราขอแนะนำให้ใช้ ExoPlayer เนื่องจากมีชุดฟีเจอร์ที่ครอบคลุมกรณีการใช้งานการเล่นส่วนใหญ่และปรับแต่งได้เพื่อรองรับกรณีการใช้งานเพิ่มเติมที่คุณอาจมี นอกจากนี้ ExoPlayer ยัง
แยกความแตกต่างของอุปกรณ์และระบบปฏิบัติการออกเพื่อให้โค้ดทำงานได้อย่างสม่ำเสมอ
ในระบบนิเวศ Android ทั้งหมด ExoPlayer มีฟีเจอร์ต่อไปนี้
- การรองรับเพลย์ลิสต์
- รองรับการสตรีมแบบก้าวหน้าและแบบปรับอัตโนมัติหลากหลายรูปแบบ
- รองรับทั้งการแทรกโฆษณาฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์
- รองรับการเล่นที่ได้รับการป้องกันด้วย DRM
หน้านี้จะแนะนำขั้นตอนสำคัญบางอย่างในการสร้างแอปการเล่น และดูรายละเอียดเพิ่มเติมได้ที่คำแนะนำฉบับเต็มเกี่ยวกับ Media3 ExoPlayer
เริ่มต้นใช้งาน
หากต้องการเริ่มต้นใช้งาน ให้เพิ่มการอ้างอิงในโมดูล ExoPlayer, UI และ Common ของ Jetpack Media3 ดังนี้
implementation "androidx.media3:media3-exoplayer:1.7.1" implementation "androidx.media3:media3-ui:1.7.1" implementation "androidx.media3:media3-common:1.7.1"
คุณอาจต้องใช้โมดูลเพิ่มเติมจาก Media3 ด้วย โดยขึ้นอยู่กับกรณีการใช้งาน
เช่น exoplayer-dash
เพื่อเล่นสตรีมในรูปแบบ DASH
โปรดตรวจสอบว่าได้แทนที่ 1.7.1
ด้วยไลบรารีเวอร์ชันที่ต้องการแล้ว คุณดูเวอร์ชันล่าสุดได้ในบันทึกประจำรุ่น
การสร้างมีเดียเพลเยอร์
Media3 ช่วยให้คุณใช้การติดตั้งใช้งานอินเทอร์เฟซ Player
ที่รวมไว้ ExoPlayer
หรือสร้างการติดตั้งใช้งานที่กำหนดเองได้
การสร้าง ExoPlayer
วิธีที่ง่ายที่สุดในการสร้างอินสแตนซ์ ExoPlayer
มีดังนี้
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
คุณสร้างมัลติมีเดียเพลเยอร์ได้ในเมธอดวงจร onCreate()
ของ
Activity
, Fragment
หรือ Service
ที่มัลติมีเดียเพลเยอร์อยู่
Builder
มีตัวเลือกการปรับแต่งมากมายที่คุณอาจสนใจ เช่น
setAudioAttributes()
เพื่อกำหนดค่าการจัดการโฟกัสเสียงsetHandleAudioBecomingNoisy()
เพื่อกำหนดค่าลักษณะการทำงานของการเล่นเมื่อยกเลิกการเชื่อมต่ออุปกรณ์เอาต์พุตเสียงsetTrackSelector()
เพื่อกำหนดค่าการเลือกแทร็ก
Media3 มีPlayerView
คอมโพเนนต์ UI ที่คุณสามารถรวมไว้ใน
ไฟล์เลย์เอาต์ของแอป คอมโพเนนต์นี้ห่อหุ้ม PlayerControlView
สำหรับตัวควบคุมการเล่น
SubtitleView
สำหรับการแสดงคำบรรยาย และ Surface
สำหรับการแสดงผล
วิดีโอ
กำลังเตรียมโปรแกรมเล่น
เพิ่มรายการสื่อลงในเพลย์ลิสต์เพื่อ
เล่นด้วยวิธีต่างๆ เช่น
setMediaItem()
และ addMediaItem()
จากนั้นเรียกใช้ prepare()
เพื่อ
เริ่มโหลดสื่อและรับทรัพยากรที่จำเป็น
คุณไม่ควรทำตามขั้นตอนเหล่านี้ก่อนที่แอปจะทำงานในเบื้องหน้า หากเพลเยอร์อยู่ใน Activity
หรือ Fragment
แสดงว่าต้องเตรียมเพลเยอร์ในเมธอดวงจร onStart()
ใน API ระดับ 24 ขึ้นไป หรือเมธอดวงจร onResume()
ใน API ระดับ 23 ลงไป สำหรับผู้เล่นที่อยู่ในService
คุณสามารถเตรียมผู้เล่นในonCreate()
ควบคุมเพลเยอร์
หลังจากเตรียมเพลเยอร์แล้ว คุณจะควบคุมการเล่นได้โดยเรียกใช้เมธอด ในเพลเยอร์ เช่น
play()
และpause()
เพื่อเริ่มและหยุดเล่นชั่วคราวseekTo()
เพื่อไปยังตำแหน่ง ในรายการสื่อปัจจุบันseekToNextMediaItem()
และseekToPreviousMediaItem()
เพื่อเลื่อนดูเพลย์ลิสต์
คอมโพเนนต์ UI เช่น PlayerView
หรือ PlayerControlView
จะอัปเดต
ตามนั้นเมื่อเชื่อมโยงกับเพลเยอร์
ปล่อยตัวผู้เล่น
การเล่นอาจต้องใช้ทรัพยากรที่มีอยู่อย่างจำกัด เช่น ตัวถอดรหัสวิดีโอ
ดังนั้นคุณจึงควรเรียกใช้ release()
ในเพลเยอร์เพื่อเพิ่มพื้นที่ว่างในทรัพยากรเมื่อไม่จำเป็นต้องใช้เพลเยอร์อีกต่อไป
หากเพลเยอร์อยู่ใน Activity
หรือ Fragment
ให้ปล่อยเพลเยอร์ในเมธอดวงจร onStop()
ใน API ระดับ 24 ขึ้นไป หรือเมธอด onPause()
ใน API ระดับ 23 ลงไป สำหรับผู้เล่นที่อยู่ใน Service
คุณสามารถ
ปล่อยตัวใน onDestroy()
ได้
การจัดการการเล่นด้วยเซสชันสื่อ
ใน Android เซสชันสื่อจะมอบวิธีมาตรฐานในการโต้ตอบกับโปรแกรมเล่นสื่อ ข้ามขอบเขตของกระบวนการ การเชื่อมต่อเซสชันสื่อกับเพลเยอร์ ช่วยให้คุณโฆษณาการเล่นสื่อภายนอกและรับคำสั่งการเล่น จากแหล่งที่มาภายนอกได้ เช่น เพื่อผสานรวมกับตัวควบคุมสื่อของระบบในอุปกรณ์เคลื่อนที่และอุปกรณ์หน้าจอขนาดใหญ่
หากต้องการใช้เซสชันสื่อ ให้เพิ่มการอ้างอิงในโมดูลเซสชัน Media3 ดังนี้
implementation "androidx.media3:media3-session:1.7.1"
สร้างเซสชันสื่อ
คุณสร้าง MediaSession
ได้หลังจากเริ่มต้นโปรแกรมเล่นดังนี้
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Media3 จะซิงค์สถานะของ Player
กับสถานะของ
MediaSession
โดยอัตโนมัติ ซึ่งใช้ได้กับการติดตั้งใช้งาน Player
ทุกรูปแบบ รวมถึง
ExoPlayer
, CastPlayer
หรือ
การติดตั้งใช้งานที่กำหนดเอง
มอบสิทธิ์ควบคุมให้กับไคลเอ็นต์อื่นๆ
แอปไคลเอ็นต์สามารถใช้ตัวควบคุมสื่อ
เพื่อควบคุมการเล่นเซสชันสื่อได้ หากต้องการรับคำขอเหล่านี้ ให้ตั้งค่าออบเจ็กต์
การเรียกกลับเมื่อสร้าง MediaSession
เมื่อกำลังจะเชื่อมต่อคอนโทรลเลอร์กับเซสชันสื่อ ระบบจะเรียกใช้เมธอด
onConnect()
คุณสามารถใช้ControllerInfo
ที่ระบุไว้
เพื่อตัดสินใจว่าจะยอมรับ
หรือปฏิเสธ
คำขอ ดูตัวอย่างได้ในแอปตัวอย่างของ Media3 Session
เมื่อเชื่อมต่อแล้ว คอนโทรลเลอร์จะส่งคำสั่งการเล่นไปยังเซสชันได้ จากนั้น
เซสชันจะมอบสิทธิ์คำสั่งเหล่านั้นให้แก่เพลเยอร์ เซสชันจะจัดการคำสั่งการเล่นและเพลย์ลิสต์ที่กำหนดไว้ในอินเทอร์เฟซ Player
โดยอัตโนมัติ
วิธีการเรียกกลับอื่นๆ ช่วยให้คุณจัดการได้ เช่น คำขอสำหรับ
คำสั่งการเล่นที่กำหนดเอง
และการแก้ไขเพลย์ลิสต์ โดยการเรียกกลับเหล่านี้จะมีออบเจ็กต์ ControllerInfo
เช่นเดียวกัน เพื่อให้คุณ
กำหนดการควบคุมการเข้าถึงตามคำขอแต่ละรายการได้
การเล่นสื่อขณะล็อกหน้าจอหรือขณะใช้แอปอื่น
หากต้องการเล่นสื่อต่อไปเมื่อแอปไม่ได้ทำงานอยู่เบื้องหน้า เช่น
เล่นเพลง หนังสือเสียง หรือพอดแคสต์แม้ว่าผู้ใช้จะไม่ได้เปิดแอปของคุณ
Player
และ MediaSession
ควรอยู่ในบริการที่ทำงานอยู่เบื้องหน้า Media3 มีMediaSessionService
อินเทอร์เฟซสำหรับวัตถุประสงค์นี้
การใช้ MediaSessionService
สร้างคลาสที่ขยาย MediaSessionService
และสร้างอินสแตนซ์ของ MediaSession
ในเมธอดวงจร onCreate()
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
ในไฟล์ Manifest ให้ประกาศคลาส Service
ที่มี MediaSessionService
Intent
Filter และขอสิทธิ์ FOREGROUND_SERVICE
เพื่อเรียกใช้บริการที่ทำงานอยู่เบื้องหน้า
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
สุดท้าย ในคลาสที่คุณสร้าง ให้ลบล้างเมธอด onGetSession()
เพื่อควบคุม
การเข้าถึงเซสชันสื่อของไคลเอ็นต์ ส่งคืน MediaSession
เพื่อยอมรับ
คำขอเชื่อมต่อ หรือส่งคืน null
เพื่อปฏิเสธคำขอ
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
การเชื่อมต่อกับ UI
ตอนนี้เซสชันสื่อของคุณอยู่Service
แยกจากActivity
หรือ
Fragment
ที่ UI ของเพลเยอร์อยู่ คุณสามารถใช้ MediaController
เพื่อลิงก์
เข้าด้วยกันได้ ในonStart()
ของActivity
หรือFragment
ด้วย UI ของคุณ ให้สร้างSessionToken
สำหรับMediaSession
จากนั้นใช้SessionToken
เพื่อสร้างMediaController
การสร้าง MediaController
จะเกิดขึ้น
แบบไม่พร้อมกัน
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController
ใช้การเชื่อมต่อ Player
คุณจึงใช้วิธีการเดียวกันได้ เช่น play()
และ pause()
เพื่อควบคุมการเล่น เช่นเดียวกับคอมโพเนนต์อื่นๆ อย่าลืมปล่อยMediaController
เมื่อไม่จำเป็นต้องใช้แล้ว เช่น เมธอดวงจรของonStop()
ใน Activity
โดยการเรียก MediaController.releaseFuture()
การเผยแพร่การแจ้งเตือน
บริการที่ทำงานอยู่เบื้องหน้าต้องเผยแพร่การแจ้งเตือนขณะที่ทำงานอยู่ A
MediaSessionService
จะสร้างMediaStyle
การแจ้งเตือนให้คุณโดยอัตโนมัติในรูปแบบของMediaNotification
หากต้องการแสดงการแจ้งเตือนที่กำหนดเอง ให้สร้าง
MediaNotification.Provider
ด้วย DefaultMediaNotificationProvider.Builder
หรือสร้างการติดตั้งใช้งานอินเทอร์เฟซผู้ให้บริการที่กำหนดเอง เพิ่มผู้ให้บริการลงใน MediaSession
ด้วย setMediaNotificationProvider
การโฆษณาคลังเนื้อหา
MediaLibraryService
สร้างขึ้นจาก MediaSessionService
โดยอนุญาตให้แอปไคลเอ็นต์
เรียกดูเนื้อหาสื่อที่แอปของคุณระบุ แอปไคลเอ็นต์จะใช้ MediaBrowser
เพื่อโต้ตอบ
กับ MediaLibraryService
ของคุณ
การติดตั้งใช้งาน MediaLibraryService
คล้ายกับการติดตั้งใช้งาน
MediaSessionService
ยกเว้นว่าใน onGetSession()
คุณควรแสดงผล
MediaLibrarySession
แทน MediaSession
เมื่อเทียบกับ MediaSession.Callback
แล้ว MediaLibrarySession.Callback
มีเมธอดเพิ่มเติม
ที่ช่วยให้ไคลเอ็นต์เบราว์เซอร์ไปยังส่วนต่างๆ ของเนื้อหาที่บริการห้องสมุดของคุณ
นำเสนอได้
เช่นเดียวกับ MediaSessionService
ให้ประกาศ MediaLibraryService
ในไฟล์
Manifest และขอสิทธิ์ FOREGROUND_SERVICE
เพื่อเรียกใช้บริการที่ทำงานอยู่เบื้องหน้า
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
ตัวอย่างด้านบนมีตัวกรอง Intent สำหรับทั้ง MediaLibraryService
และ MediaBrowserService
เดิม (เพื่อความเข้ากันได้แบบย้อนหลัง)
ตัวกรอง Intent เพิ่มเติมช่วยให้แอปไคลเอ็นต์ที่ใช้ MediaBrowserCompat
API
รู้จัก Service
MediaLibrarySession
ช่วยให้คุณแสดงคลังเนื้อหาในโครงสร้างแบบต้นไม้
โดยมีรูทเดียวคือ MediaItem
MediaItem
แต่ละรายการในโครงสร้างจะมีโหนด MediaItem
ย่อยกี่รายการก็ได้
คุณสามารถแสดงรูทอื่นหรือ
ทรีอื่นตามคำขอของแอปไคลเอ็นต์ ตัวอย่างเช่น ต้นไม้ที่คุณ
ส่งคืนให้ไคลเอ็นต์ที่กำลังมองหารายการสื่อที่แนะนำอาจมีเพียง
รูท MediaItem
และโหนดลูก MediaItem
ระดับเดียว
ในขณะที่ต้นไม้ที่คุณส่งคืนให้แอปไคลเอ็นต์อื่นอาจแสดง
คลังเนื้อหาที่สมบูรณ์กว่า
การสร้าง MediaLibrarySession
MediaLibrarySession
ขยาย MediaSession
API เพื่อเพิ่ม API การเรียกดูเนื้อหา เมื่อเทียบกับMediaSession
Callback
MediaLibrarySession
Callback
จะเพิ่มเมธอดต่างๆ เช่น
onGetLibraryRoot()
เมื่อไคลเอ็นต์ขอรูทMediaItem
ของโครงสร้างเนื้อหาonGetChildren()
เมื่อไคลเอ็นต์ขอรายการย่อยของMediaItem
ในโครงสร้างเนื้อหาonGetSearchResult()
เมื่อไคลเอ็นต์ขอผลการค้นหาจากแผนผังเนื้อหาสำหรับคำค้นหาที่กำหนด
เมธอดเรียกกลับที่เกี่ยวข้องจะมีออบเจ็กต์ LibraryParams
พร้อมสัญญาณเพิ่มเติมเกี่ยวกับประเภทของแผนผังเนื้อหาที่แอปไคลเอ็นต์
สนใจ