ส่วนนี้จะอธิบายวิธีแยกแอปมีเดียเพลเยอร์ออกเป็นตัวควบคุมสื่อ (สำหรับ UI) และเซสชันสื่อ (สำหรับเพลเยอร์จริง) โดยจะอธิบายสถาปัตยกรรมของแอปสื่อ 2 แบบ ได้แก่ การออกแบบไคลเอ็นต์/เซิร์ฟเวอร์ที่เหมาะสำหรับแอปเสียง และการออกแบบกิจกรรมเดียวสำหรับวิดีโอเพลเยอร์ นอกจากนี้ ยังแสดงวิธีทำให้แอปสื่อ ตอบสนองต่อการควบคุมฮาร์ดแวร์และทำงานร่วมกับแอปอื่นๆ ที่ใช้สตรีมเอาต์พุตเสียง ด้วย
ผู้เล่นและ UI
โดยปกติแล้ว แอปพลิเคชันมัลติมีเดียที่เล่นเสียงหรือวิดีโอจะมี 2 ส่วน ได้แก่
- โปรแกรมเล่นที่รับสื่อดิจิทัลและแสดงเป็น วิดีโอและ/หรือเสียง
- UI ที่มีตัวควบคุมการขนส่งเพื่อเรียกใช้เพลเยอร์และแสดงสถานะของเพลเยอร์ (ไม่บังคับ)
ใน Android คุณสามารถสร้างเพลเยอร์ของคุณเอง ตั้งแต่ต้น หรือจะเลือกจากตัวเลือกต่อไปนี้ก็ได้
- คลาส MediaPlayer มีฟังก์ชันพื้นฐานสำหรับเพลเยอร์แบบเรียบง่ายที่รองรับรูปแบบเสียง/วิดีโอและแหล่งข้อมูลที่พบบ่อยที่สุด
- ExoPlayer
เป็นไลบรารีโอเพนซอร์สที่สร้างขึ้นบนคอมโพเนนต์เฟรมเวิร์กสื่อระดับล่าง
เช่น
MediaCodec
และAudioTrack
ExoPlayer รองรับฟีเจอร์ประสิทธิภาพสูง เช่น DASH ซึ่งMediaPlayer
ไม่มี คุณปรับแต่งโค้ด ExoPlayer ได้ ซึ่งจะช่วยให้เพิ่มคอมโพเนนต์ใหม่ๆ ได้ง่าย ExoPlayer ใช้ได้กับ Android เวอร์ชัน 4.1 ขึ้นไปเท่านั้น
เซสชันสื่อและตัวควบคุมสื่อ
แม้ว่า API สำหรับ UI และเพลเยอร์จะกำหนดได้ตามต้องการ แต่ลักษณะของการ โต้ตอบระหว่างทั้ง 2 ส่วนนั้นโดยพื้นฐานแล้วจะเหมือนกันสำหรับแอป เครื่องเล่นสื่อทั้งหมด เฟรมเวิร์ก Android กำหนด 2 คลาส ได้แก่ เซสชันสื่อและเครื่องมือควบคุมสื่อ ซึ่งกำหนดโครงสร้างที่ชัดเจนสำหรับการสร้างแอปมีเดียเพลเยอร์
เซสชันสื่อและตัวควบคุมสื่อจะสื่อสารกันโดยใช้ การเรียกกลับที่กำหนดไว้ล่วงหน้าซึ่งสอดคล้องกับการดำเนินการของเพลเยอร์มาตรฐาน (เล่น หยุดชั่วคราว หยุด ฯลฯ) รวมถึงการเรียกที่กำหนดเองที่ขยายได้ซึ่งคุณใช้เพื่อกำหนดลักษณะการทำงานพิเศษ เฉพาะสำหรับแอปของคุณ
เซสชันสื่อ
เซสชันสื่อมีหน้าที่รับผิดชอบการสื่อสารทั้งหมดกับเพลเยอร์ ซึ่งจะซ่อน API ของเพลเยอร์จากส่วนอื่นๆ ของแอป โดยจะเรียกใช้เพลเยอร์จาก เซสชันสื่อที่ควบคุมเพลเยอร์เท่านั้น
เซสชันจะแสดงสถานะของผู้เล่น (กำลังเล่น/หยุดชั่วคราว)
และข้อมูลเกี่ยวกับสิ่งที่กำลังเล่น เซสชันจะรับการเรียกกลับจากตัวควบคุมสื่ออย่างน้อย 1 ตัวได้
ซึ่งจะช่วยให้แอปควบคุมเพลเยอร์ได้ รวมถึงอุปกรณ์เสริมที่ใช้ Wear OS และ Android Auto ตรรกะที่ตอบกลับการเรียกกลับต้องสอดคล้องกัน
การตอบกลับ MediaSession
Callback ควรเหมือนกันไม่ว่าแอปไคลเอ็นต์ใด
จะเริ่ม Callback
ตัวควบคุมสื่อ
ตัวควบคุมสื่อจะแยก UI ของคุณ โค้ด UI จะสื่อสารกับ ตัวควบคุมสื่อเท่านั้น ไม่ใช่ตัวเพลเยอร์ ตัวควบคุมสื่อจะแปล การดำเนินการควบคุมการขนส่งเป็น Callback ไปยังเซสชันสื่อ นอกจากนี้ ยังได้รับ การเรียกกลับจากเซสชันสื่อทุกครั้งที่สถานะเซสชันเปลี่ยนแปลง ซึ่ง เป็นกลไกในการอัปเดต UI ที่เชื่อมโยงโดยอัตโนมัติ ตัวควบคุมสื่อจะเชื่อมต่อกับเซสชันสื่อได้ทีละ 1 เซสชันเท่านั้น
เมื่อใช้เครื่องควบคุมสื่อและเซสชันสื่อ คุณจะสามารถติดตั้งใช้งานอินเทอร์เฟซและ/หรือเพลเยอร์ต่างๆ ได้ในขณะรันไทม์ คุณเปลี่ยนลักษณะที่ปรากฏ และ/หรือประสิทธิภาพของแอปได้อย่างอิสระโดยขึ้นอยู่กับความสามารถของอุปกรณ์ที่ แอปทำงานอยู่
แอปวิดีโอเทียบกับแอปเสียง
ขณะเล่นวิดีโอ ทั้งตาและหูของคุณจะทำงาน เมื่อเล่นเสียง คุณจะฟังได้ แต่ก็สามารถทำงานกับแอปอื่นไปพร้อมกันได้ด้วย โดยมีการออกแบบที่แตกต่างกันสำหรับแต่ละกรณีการใช้งาน
แอปวิดีโอ
แอปวิดีโอต้องมีหน้าต่างสำหรับดูเนื้อหา ด้วยเหตุนี้ แอปวิดีโอจึงมัก ใช้งานเป็นกิจกรรม Android เดียว หน้าจอที่วิดีโอ ปรากฏเป็นส่วนหนึ่งของกิจกรรม
แอปเสียง
เครื่องเล่นเสียงไม่จำเป็นต้องแสดง UI เสมอไป เมื่อเริ่ม เล่นเสียงแล้ว เครื่องเล่นจะทำงานเป็นงานเบื้องหลังได้ ผู้ใช้สามารถเปลี่ยนไปใช้ แอปอื่นและทำงานไปพร้อมกับฟังเพลงต่อได้
หากต้องการใช้การออกแบบนี้ใน Android คุณสามารถสร้างแอปเสียงโดยใช้คอมโพเนนต์ 2 อย่าง ได้แก่ กิจกรรมสำหรับ UI และบริการสำหรับเพลเยอร์ หากผู้ใช้ เปลี่ยนไปใช้แอปอื่น บริการจะทำงานในเบื้องหลังได้ การแยก ส่วนประกอบทั้ง 2 ส่วนของแอปเสียงออกเป็นคอมโพเนนต์ที่แยกกันจะช่วยให้แต่ละส่วนทำงานได้อย่างมี ประสิทธิภาพมากขึ้น โดยปกติแล้ว UI จะมีอายุการใช้งานสั้นกว่าเพลเยอร์ ซึ่ง อาจทำงานได้เป็นเวลานานโดยไม่มี UI
ไลบรารีการสนับสนุนมี 2 คลาสเพื่อใช้แนวทางไคลเอ็นต์/เซิร์ฟเวอร์นี้
ได้แก่ MediaBrowserService
และ MediaBrowser
คอมโพเนนต์บริการจะ
ได้รับการติดตั้งใช้งานเป็นคลาสย่อยของ MediaBrowserService
ซึ่งมีเซสชันสื่อและ
เพลเยอร์ กิจกรรมที่มี UI และตัวควบคุมสื่อควรมี MediaBrowser
ซึ่งสื่อสารกับ MediaBrowserService
การใช้ MediaBrowserService
ช่วยให้อุปกรณ์คู่กัน (เช่น Android
Auto และ Wear) ค้นพบแอปของคุณ เชื่อมต่อกับแอป เรียกดูเนื้อหา และ
ควบคุมการเล่นได้อย่างง่ายดายโดยไม่ต้องเข้าถึงกิจกรรม UI ของแอปเลย ในความเป็นจริงแล้ว คุณสามารถเชื่อมต่อแอปหลายแอปกับ MediaBrowserService
เดียวกันได้ในเวลาเดียวกัน โดยแต่ละแอปจะมี MediaController
ของตัวเอง แอปที่ให้บริการ
MediaBrowserService
ควรจัดการการเชื่อมต่อพร้อมกันหลายรายการได้
แอปสื่อและโครงสร้างพื้นฐานด้านเสียงของ Android
แอปสื่อที่ออกแบบมาอย่างดีควร "ทำงานร่วมกันได้ดี" กับแอปอื่นๆ ที่เล่นเสียง โดยควรเตรียมพร้อมที่จะแชร์โทรศัพท์และทำงานร่วมกับแอปอื่นๆ ในอุปกรณ์ที่ใช้เสียง นอกจากนี้ยังควรตอบสนองต่อการควบคุมฮาร์ดแวร์ใน อุปกรณ์ด้วย
ลักษณะการทำงานทั้งหมดนี้อธิบายไว้ในการควบคุมเอาต์พุตเสียง
ไลบรารี media-compat
ไลบรารี media-compat มีคลาสที่เป็นประโยชน์สำหรับการสร้างแอปที่เล่นเสียงและวิดีโอ คลาสเหล่านี้ใช้ได้กับอุปกรณ์ที่ใช้ Android 2.3 (API ระดับ 9) ขึ้นไป นอกจากนี้ ยังทำงานร่วมกับฟีเจอร์อื่นๆ ของ Android เพื่อสร้างประสบการณ์การใช้งาน Android ที่สะดวกสบายและคุ้นเคย
การใช้งาน MediaSession และ MediaController ที่แนะนำคือคลาส MediaSessionCompat
และ MediaControllerCompat
ซึ่งกำหนดไว้ในไลบรารีการสนับสนุน
media-compat โดยจะแทนที่คลาส MediaSession
และ MediaController
เวอร์ชันก่อนหน้าที่เปิดตัวใน Android 5.0 (API ระดับ 21) คลาส Compat มีฟังก์ชันการทำงานเหมือนกัน แต่ช่วยให้พัฒนาแอปได้ง่ายขึ้นเนื่องจากคุณต้องเขียนโค้ดไปยัง API เพียงรายการเดียว ไลบรารีจะดูแลการทำงานร่วมกันแบบย้อนหลังโดยการแปลวิธีการของเซสชันสื่อเป็นวิธีการที่เทียบเท่าในแพลตฟอร์มเวอร์ชันเก่ากว่าเมื่อพร้อมใช้งาน
หากคุณมีแอปที่ใช้งานได้อยู่แล้วซึ่งใช้คลาสเวอร์ชันเก่า เราขอแนะนำให้อัปเดตเป็นคลาส Compat เมื่อใช้เวอร์ชันที่เข้ากันได้ คุณจะนำการเรียกใช้ทั้งหมดไปยัง registerMediaButtonReceiver()
และเมธอดทั้งหมดจาก RemoteControlClient
ออกได้
การวัดประสิทธิภาพ
ใน Android 8.0 (API ระดับ 26) ขึ้นไป getMetrics()
จะใช้ได้กับคลาสสื่อบางคลาส
โดยจะแสดงผลPersistableBundle
ออบเจ็กต์ที่มีข้อมูลการกำหนดค่า
และประสิทธิภาพ ซึ่งแสดงเป็นแผนที่ของแอตทริบิวต์และค่า
มีการกำหนดgetMetrics()
สำหรับคลาสสื่อต่อไปนี้
MediaPlayer.getMetrics()
MediaRecorder.getMetrics()
MediaCodec.getMetrics()
MediaExtractor.getMetrics()
ระบบจะรวบรวมเมตริกแยกกันสำหรับแต่ละอินสแตนซ์และจะคงอยู่ตลอดอายุการใช้งานของอินสแตนซ์ หากไม่มีเมตริกที่พร้อมใช้งาน เมธอดจะแสดงผลเป็น null เมตริกจริงที่แสดงจะขึ้นอยู่กับคลาส