Jetpack Media3 กำหนดอินเทอร์เฟซ Player
ที่แสดงฟังก์ชันการทำงานพื้นฐาน
สำหรับการเล่นไฟล์วิดีโอและไฟล์เสียง ExoPlayer
เป็นการใช้งานเริ่มต้น
ของอินเทอร์เฟซนี้ใน Media3 เราขอแนะนำให้ใช้ ExoPlayer เนื่องจากมี
ชุดคุณลักษณะที่ครอบคลุมซึ่งครอบคลุมกรณีการใช้งานส่วนใหญ่ของการเล่นและ
สามารถปรับแต่งให้รองรับ Use Case อื่นๆ เพิ่มเติม ExoPlayer ด้วย
แยกส่วนของอุปกรณ์และระบบปฏิบัติการออกเพื่อให้โค้ดทำงานได้อย่างราบรื่น
ทั่วทั้งระบบนิเวศของ Android ExoPlayer ประกอบด้วย
- การรองรับเพลย์ลิสต์
- รองรับสตรีมมิงแบบโพรเกรสซีฟและแบบปรับอัตโนมัติที่หลากหลาย
- รองรับการแทรกโฆษณาทั้งฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์
- รองรับการเล่นที่ป้องกันด้วย DRM
หน้านี้จะแนะนำขั้นตอนสำคัญในการสร้างการเล่นวิดีโอ และดูรายละเอียดเพิ่มเติมได้ในคู่มือฉบับเต็ม Media3 ExoPlayer
เริ่มต้นใช้งาน
หากต้องการเริ่มต้นใช้งาน ให้เพิ่มทรัพยากร Dependency ใน ExoPlayer, UI และโมดูลทั่วไปของ Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.4.0" implementation "androidx.media3:media3-ui:1.4.0" implementation "androidx.media3:media3-common:1.4.0"
คุณอาจต้องการโมดูลเพิ่มเติมจาก Media3 ด้วย ทั้งนี้ขึ้นอยู่กับกรณีการใช้งานของคุณ
เช่น exoplayer-dash
เพื่อเล่นสตรีมในรูปแบบ DASH
โปรดแทนที่ 1.4.0
ด้วยเวอร์ชันที่ต้องการ
ไลบรารี คุณดูบันทึกประจำรุ่นได้
เพื่อดูเวอร์ชันล่าสุด
การสร้างมีเดียเพลเยอร์
เมื่อใช้ 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 มีคอมโพเนนต์ UI ของ PlayerView
ที่คุณรวมไว้ในแอป
ใหม่ คอมโพเนนต์นี้จะสรุป 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 เซสชันสื่อจะเป็นวิธีมาตรฐานในการโต้ตอบกับสื่อ ข้ามขอบเขตของกระบวนการ การเชื่อมต่อเซสชันสื่อกับโปรแกรมเล่น อนุญาตให้คุณโฆษณาการเล่นสื่อของคุณภายนอกและเพื่อรับการเล่น จากแหล่งที่มาภายนอก เช่น เพื่อผสานรวมกับ การควบคุมสื่อของระบบในอุปกรณ์เคลื่อนที่และขนาดใหญ่ อุปกรณ์หน้าจออื่นๆ
หากต้องการใช้เซสชันสื่อ ให้เพิ่มทรัพยากร Dependency ในโมดูลเซสชัน Media3 ดังนี้
implementation "androidx.media3:media3-session:1.4.0"
สร้างเซสชันสื่อ
คุณสามารถสร้าง 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
หรือ
แบบกำหนดเองได้
ให้สิทธิ์ควบคุมกับลูกค้ารายอื่น
แอปไคลเอ็นต์ใช้ตัวควบคุมสื่อได้
เพื่อควบคุมการเล่นเซสชันสื่อของคุณ หากต้องการรับคำขอเหล่านี้ ให้ตั้งค่า
callback ออบเจ็กต์เมื่อ
เพื่อก่อสร้างMediaSession
เมื่อตัวควบคุมกำลังจะเชื่อมต่อกับเซสชันสื่อของคุณ
onConnect()
เมธอด คุณสามารถใช้ControllerInfo
ในการตัดสินใจว่าจะยอมรับ
หรือปฏิเสธ
คำขอ ดูตัวอย่างได้ในแอปเดโมเซสชัน Media3
เมื่อเชื่อมต่อแล้ว ตัวควบคุมจะส่งคำสั่งการเล่นไปยังเซสชันได้
จากนั้นจะมอบสิทธิ์คำสั่งเหล่านั้นให้กับโปรแกรมเล่น การเล่นและเพลย์ลิสต์
คำสั่งที่กำหนดในอินเทอร์เฟซ Player
ได้รับการจัดการโดยอัตโนมัติโดย
เซสชัน
คุณสามารถใช้วิธีอื่นๆ ในการติดต่อกลับได้ เช่น คําขอ
คำสั่งการเล่นแบบกำหนดเอง
และการแก้ไขเพลย์ลิสต์ Callback เหล่านี้ก็มีออบเจ็กต์ 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
ที่มี Intent MediaSessionService
กรองและขอสิทธิ์ 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()
การเผยแพร่การแจ้งเตือน
ต้องใช้บริการที่ทำงานอยู่เบื้องหน้าเพื่อเผยแพร่การแจ้งเตือนขณะใช้งาน ต
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 เพิ่มเติมจะเปิดใช้แอปไคลเอ็นต์โดยใช้ API ของ MediaBrowserCompat
เพื่อจดจำ Service
ของคุณ
MediaLibrarySession
ช่วยให้คุณแสดงคลังเนื้อหาแบบต้นไม้ได้
ที่มี MediaItem
รากเดียว MediaItem
แต่ละรายการในโครงสร้างมีได้
โหนดย่อยจำนวนเท่าใดก็ได้ MediaItem
โหนด คุณสามารถแสดงรูทที่แตกต่างกัน หรือ
โครงสร้างต้นไม้ที่แตกต่างกัน โดยอิงตามคำขอของแอปไคลเอ็นต์ เช่น ต้นไม้ที่คุณ
กลับไปยังลูกค้าที่มองหารายการสื่อที่แนะนำอาจ
มีรูท MediaItem
และโหนดย่อย MediaItem
โหนด
ขณะที่แผนผังที่คุณกลับไปยังแอปไคลเอ็นต์อื่นอาจแสดง
คลังเนื้อหาทั้งหมด
กำลังสร้าง MediaLibrarySession
MediaLibrarySession
ขยาย MediaSession
API เพื่อเพิ่ม API การเรียกดูเนื้อหา เทียบกับ
MediaSession
Callback,
การติดต่อกลับของ MediaLibrarySession
เพิ่มเมธอด เช่น
onGetLibraryRoot()
สำหรับเวลาที่ไคลเอ็นต์ขอรูทMediaItem
ของโครงสร้างเนื้อหาonGetChildren()
สำหรับเมื่อลูกค้าขอองค์ประกอบย่อยของMediaItem
ในโครงสร้างเนื้อหาonGetSearchResult()
สำหรับเวลาที่ลูกค้าขอผลการค้นหาจากโครงสร้างเนื้อหาของ คำถาม
วิธีการโทรกลับที่เกี่ยวข้องจะมี LibraryParams
ที่มีสัญญาณเพิ่มเติมเกี่ยวกับประเภทโครงสร้างเนื้อหาที่แอปไคลเอ็นต์
สนใจ