1. บทนำ
อัปเดตล่าสุด: 09-09-2020
ประโยชน์ของการเพิ่ม MediaSession เกี่ยวกับการเล่นวิดีโอมีอะไรบ้าง
เซสชันสื่อเป็นลิงก์ที่ขาดไม่ได้ระหว่างแพลตฟอร์ม Android กับแอปสื่อ ไม่เพียงแต่จะแจ้งให้ Android ทราบว่ามีการเล่นสื่ออยู่เพื่อให้ส่งต่อการดำเนินการกับสื่อไปยังเซสชันที่ถูกต้องได้ แต่ยังแจ้งให้แพลตฟอร์มทราบว่ามีการเล่นอะไรอยู่และวิธีควบคุม
การเปิดเผย MediaSession ผ่านแอปของคุณมีประโยชน์หลายอย่างซึ่งผู้ใช้จะได้รับ ลองดูตัวอย่างต่อไปนี้
Google Assistant
ผู้ใช้สามารถโต้ตอบกับสื่อในแอปได้อย่างง่ายดายผ่านคำสั่งเสียง เช่น "หยุดชั่วคราว" "เล่นต่อ" และ "ถัดไป" นอกจากนี้ คุณยังใช้ข้อมูลเมตาจากสื่อเพื่อรับคำตอบเกี่ยวกับสิ่งที่กำลังเล่นอยู่ได้ด้วย
Android TV
ในแอป Android TV บนหน้าจอขนาดใหญ่ คุณจะสามารถใช้รีโมตคอนโทรลแบบดั้งเดิมสำหรับผู้ใช้ที่มีทีวีที่รองรับ HDMI-CEC ระบบจะส่งต่อคำสั่งที่ออกโดยปุ่มเล่น/หยุดชั่วคราว หยุด ถัดไป และก่อนหน้าไปยังแอป
การควบคุมสื่อบนหน้าจอ
ตั้งแต่ Android 4.0 (API ระดับ 14) เป็นต้นไป ระบบจะเข้าถึงสถานะการเล่นและข้อมูลเมตาของเซสชันสื่อได้ ฟังก์ชันการทำงานนี้ช่วยให้หน้าจอล็อกแสดงตัวควบคุมสื่อและอาร์ตเวิร์กได้ ลักษณะการทํางานนี้จะแตกต่างกันไปตามเวอร์ชัน Android
สื่อพื้นหลัง
คุณสามารถควบคุมสื่อได้ในสถานการณ์เหล่านี้ แม้ว่าแอปที่เล่นสื่อจะทำงานอยู่เบื้องหลังก็ตาม
การประมวลผล แบบแอมเบียนท์
การเปิดเผยสื่อพร้อมข้อมูลเกี่ยวกับสิ่งที่เล่นอยู่และวิธีควบคุมสื่อนั้นจะช่วยเชื่อมระหว่างอุปกรณ์ต่างๆ เพื่อให้ผู้ใช้โต้ตอบกับสื่อได้หลายวิธีตามที่ตนต้องการ
สิ่งที่คุณจะสร้าง
ในโค้ดแล็บนี้ คุณจะได้ขยายตัวอย่าง Exoplayer ที่มีอยู่เพื่อเพิ่มการรองรับเซสชันสื่อ แอปของคุณจะทำสิ่งต่อไปนี้
- แสดงสถานะใช้งานอยู่ของเซสชันสื่ออย่างถูกต้อง
- ส่งต่อการควบคุมสื่อไปยัง ExoPlayer
- ส่งข้อมูลเมตาของรายการในคิวไปยังเซสชันสื่อ
สิ่งที่คุณจะได้เรียนรู้
- เหตุผลที่เซสชันสื่อมอบประสบการณ์การใช้งานที่สมบูรณ์ยิ่งขึ้นแก่ผู้ใช้
- วิธีสร้างเซสชันสื่อและจัดการสถานะ
- วิธีเชื่อมต่อเซสชันสื่อกับ ExoPlayer
- วิธีรวมข้อมูลเมตาของรายการในคิวการเล่นไว้ในเซสชันสื่อ
- วิธีเพิ่มการดําเนินการ (ที่กําหนดเอง) เพิ่มเติม
Codelab นี้จะเน้นที่ MediaSession SDK เราไม่กล่าวถึงแนวคิดและบล็อกโค้ดที่ไม่เกี่ยวข้อง รวมถึงรายละเอียดเกี่ยวกับการใช้งาน ExoPlayer แต่มีไว้ให้คุณคัดลอกและวาง
สิ่งที่ต้องมี
- Android Studio เวอร์ชันล่าสุด (3.5 ขึ้นไป)
- ความรู้พื้นฐานเกี่ยวกับการพัฒนาแอปพลิเคชัน Android
2. การเริ่มตั้งค่า
จุดเริ่มต้นของเราคืออะไร
จุดเริ่มต้นของเราคือเดโมหลักจาก ExoPlayer การสาธิตนี้มีวิดีโอที่มีตัวควบคุมการเล่นบนหน้าจอ แต่ไม่ได้ใช้สตรีมสื่อโดยค่าเริ่มต้น นี่เป็นโอกาสที่ดีที่เราจะได้เพิ่มฟีเจอร์เหล่านี้
รับตัวอย่าง ExoPlayer
มาเริ่มกันที่ตัวอย่าง ExoPlayer โคลนที่เก็บ GitHub โดยเรียกใช้โค้ดด้านล่าง
git clone https://github.com/google/ExoPlayer.git
เปิดการสาธิต
ใน Android Studio ให้เปิดโปรเจ็กต์สาธิตหลักซึ่งอยู่ใต้ demos/main
Android Studio จะแจ้งให้คุณตั้งค่าเส้นทาง SDK คุณอาจต้องทําตามคําแนะนําสําหรับการอัปเดตเครื่องมือ IDE และ SDK หากพบปัญหา
หากระบบขอให้คุณใช้ Gradle เวอร์ชันล่าสุด ให้อัปเดตเลย
โปรดสละเวลาสักครู่เพื่อทำความเข้าใจพื้นฐานเกี่ยวกับการออกแบบแอป โปรดทราบว่ามี 2 กิจกรรม ได้แก่ SampleChooserActivity และ PlayerActivity เราจะใช้เวลาที่เหลือในโค้ดแล็บนี้กับ PlayerActivity ซึ่งเป็นส่วนที่เล่นสื่อจริงๆ ดังนั้นให้เปิดคลาสนี้และไปยังส่วนถัดไป
3. สร้างเซสชันสื่อและจัดการสถานะ
สร้างเซสชันสื่อ
เปิด PlayerActivity.java
คลาสนี้จะสร้าง ExoPlayer และจัดการฟังก์ชันต่างๆ เช่น การแสดงผลวิดีโอบนหน้าจอ ในกิจกรรมนี้ เราจะเชื่อมต่อ ExoPlayer กับเซสชันสื่อ
ประกาศ 2 ช่องต่อไปนี้ที่ด้านบนของคลาส เราจะใช้ช่องเหล่านี้ตลอดทั้งส่วนนี้
private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;
คุณจะต้องเพิ่มการพึ่งพาโปรเจ็กต์ "extension-mediasession" ลงใน build.gradle
ระดับโมดูลสําหรับ "โมดูล: demo"
implementation project(path: ':extension-mediasession')
โปรดทราบว่า Android Studio ช่วยคุณเพิ่มข้อกําหนดนี้โดยอัตโนมัติได้หากวางเมาส์เหนือข้อผิดพลาดในการแก้ไข MediaSessionConnector
สุดท้าย ให้แก้ไขการนําเข้าชั้นเรียนโดยเพิ่มข้อมูลต่อไปนี้
import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
เมื่อสร้างกิจกรรมแล้ว เราจะต้องสร้างเซสชันสื่อและตัวเชื่อมต่อเซสชันสื่อที่จะทำหน้าที่เป็นสื่อกลางระหว่างเซสชันสื่อกับ ExoPlayer
ตำแหน่งที่เหมาะสมในการแทรกคือตำแหน่งที่สร้าง ExoPlayer ด้วย ในแอปเดโม เราสามารถเพิ่มโค้ดต่อท้าย initializePlayer()
อย่าลืมเพิ่มตรรกะนี้หลังจากสร้างอินสแตนซ์ของโปรแกรมเล่น
private void initializePlayer() {
if (player == null) {
...
player = ...
...
mediaSession = new MediaSessionCompat(this, "sample");
mediaSessionConnector = new MediaSessionConnector(mediaSession);
mediaSessionConnector.setPlayer(player);
}
...
}
ปล่อยเซสชันสื่อ
ปล่อยเซสชันสื่อเมื่อไม่ต้องการใช้แล้ว เมื่อเราเผยแพร่ ExoPlayer ใน releasePlayer()
เราจะใส่โค้ดต่อไปนี้เพื่อดำเนินการดังกล่าวด้วย
private void releasePlayer() {
if (mediaSession != null) {
mediaSession.release();
}
...
}
จัดการสถานะเซสชันสื่อ
เมื่อสร้างเซสชันสื่อขึ้นมาแล้ว เราต้องตรวจสอบว่าสถานะของเซสชันแสดงอย่างถูกต้องเมื่อผู้ใช้โต้ตอบกับกิจกรรม
เมื่อผู้ใช้เริ่มกิจกรรม เซสชันสื่อควรทำงานอยู่
@Override
public void onStart() {
...
if (mediaSession != null) {
mediaSession.setActive(true);
}
}
เนื่องจากแอปพลิเคชันของเราไม่ได้เล่นสื่อในเบื้องหลัง คุณจึงต้องตรวจสอบว่าเซสชันสื่อไม่มีการใช้งานเมื่อผู้ใช้ออกจากกิจกรรม
@Override
public void onStop() {
super.onStop();
if (mediaSession != null) {
mediaSession.setActive(false);
}
...
}
มาเรียกใช้เดโมกัน
- เชื่อมต่ออุปกรณ์ Android หรือเริ่มโปรแกรมจำลอง
- ตรวจสอบว่าได้เลือก "demo" เพื่อเรียกใช้จากแถบเครื่องมือ Android Studio
- คลิก
จากแถบเครื่องมือ Android Studio
- เมื่อแอปเปิดขึ้นในอุปกรณ์แล้ว ให้เลือกสตรีมวิดีโอที่จะเล่น
- เมื่อเริ่มเล่น ให้สำรวจการใช้คำสั่ง
adb
ต่อไปนี้เพื่อควบคุมเซสชันสื่อ
adb shell media dispatch pause
adb shell media dispatch play
adb shell media dispatch play-pause
adb shell media dispatch fast-forward
adb shell media dispatch rewind
- นอกจากนี้ ให้ดูวิธีที่ Android มองเห็นเซสชันสื่อของคุณ โดยเฉพาะอย่างยิ่ง คุณสามารถตรวจสอบการดำเนินการที่รองรับได้โดยดูที่ช่องการดำเนินการ ตัวเลขที่คุณเห็นที่นี่คือการรวมรหัสการดำเนินการตามที่ประกาศไว้ในออบเจ็กต์ PlaybackState หากต้องการดูเซสชันสื่อที่ทำงานอยู่ ให้ทำดังนี้
adb shell dumpsys media_session
- หากคุณใช้อุปกรณ์ที่มีไมโครโฟน ให้ลองเรียกใช้ Google Assistant แล้วออกคำสั่งเสียง เช่น "หยุดชั่วคราว" "เล่นต่อ" "กรอไปข้างหน้า 1 นาที"
ตัวอย่าง ExoPlayer ที่ทำงานบน Android TV
4. รวมถึงข้อมูลเมตาของรายการในคิวการเล่น
ตอนนี้เราสามารถขยายฟีเจอร์ที่รองรับของเซสชันสื่อที่เราสร้าง MediaSessionConnector ไว้ก่อนหน้านี้ใน initializePlayer()
การเพิ่ม TimelineQueueNavigator
ExoPlayer แสดงโครงสร้างของสื่อเป็นไทม์ไลน์ โปรดอ่านรายละเอียดเกี่ยวกับวิธีการทำงานของการดำเนินการนี้จากออบเจ็กต์ไทม์ไลน์ของ ExoPlayer การใช้โครงสร้างนี้ช่วยให้เราทราบเมื่อเนื้อหามีการเปลี่ยนแปลงและแสดงข้อมูลเมตาของสิ่งที่กำลังเล่นอยู่เมื่อมีการถาม
เราจะกำหนด TimelineQueueNavigator เพื่อให้บรรลุเป้าหมายนี้ ค้นหาการสร้างอินสแตนซ์ของ MediaSessionConnector ใน initializePlayer()
และเพิ่มการใช้งาน TimelineQueueNavigator หลังจาก mediaSession
เริ่มต้น
mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
@Override
public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
return new MediaDescriptionCompat.Builder()
.setTitle(player.getCurrentMediaItem().mediaMetadata.title)
.setDescription("MediaDescription description for " + windowIndex)
.setSubtitle("MediaDescription subtitle")
.build();
}
});
แก้ไขปัญหาการนําเข้าชั้นเรียนโดยเพิ่มข้อมูลต่อไปนี้
import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;
โปรดทราบว่าพารามิเตอร์ windowIndex
สอดคล้องกับรายการของดัชนีนั้นในคิวการเล่น
เมื่อเพิ่มข้อมูลเมตาบางส่วนแล้ว คุณสามารถทดสอบว่า Assistant เข้าใจสิ่งที่กำลังเล่นอยู่หรือไม่ ขณะเล่นวิดีโอบน Android TV ให้เรียกใช้ Assistant แล้วถามว่า "กำลังเล่นอะไรอยู่"
5. การปรับแต่งการดําเนินการ
ผู้เล่นอาจไม่รองรับการดำเนินการบางอย่าง หรือคุณต้องการเพิ่มการรองรับการดำเนินการอื่นๆ ตอนนี้มาเจาะลึกเซสชันสื่อที่เราสร้าง MediaSessionConnector ไว้ก่อนหน้านี้ใน initializePlayer()
การประกาศการดำเนินการที่รองรับ
ลองใช้ mediaSessionConnector.setEnabledPlaybackActions()
เพื่อปรับแต่งการดำเนินการที่คุณต้องการให้เซสชันสื่อรองรับ
โปรดทราบว่าชุดที่สมบูรณ์มีดังนี้
mediaSessionConnector.setEnabledPlaybackActions(
PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_PLAY
| PlaybackStateCompat.ACTION_PAUSE
| PlaybackStateCompat.ACTION_SEEK_TO
| PlaybackStateCompat.ACTION_FAST_FORWARD
| PlaybackStateCompat.ACTION_REWIND
| PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_SET_REPEAT_MODE
| PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);
มาดูกันว่าข้อมูลนี้แสดงในแพลตฟอร์มอย่างไร
- เริ่มวิดีโอตามปกติ
- สํารวจวิธีที่ Android เห็นข้อมูลเมตาจากเซสชันสื่อโดยเรียกใช้
adb shell dumpsys media_session
- ค้นหาบรรทัดที่ข้อมูลเมตาอยู่ และตรวจสอบว่าชื่อและคําอธิบายรวมอยู่ด้วยและเชื่อมโยงกับ
com.google.android.exoplayer2.demo/sample
การเพิ่มการดำเนินการเพิ่มเติม
เราขยายเซสชันสื่อด้วยการดำเนินการเพิ่มเติมได้ ส่วนนี้จะเพิ่มการรองรับคำบรรยายเท่านั้น
การรองรับคำบรรยายวิดีโอ
การเพิ่มการรองรับคำบรรยายแทนเสียงในเซสชันสื่อช่วยให้ผู้ใช้สลับคำบรรยายแทนเสียงด้วยเสียงได้ เพิ่มข้อมูลต่อไปนี้ในตำแหน่งที่คุณเริ่มต้นการเชื่อมต่อเซสชันสื่อ
mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
@Override
public void onSetCaptioningEnabled(Player player, boolean enabled) {
Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
}
@Override
public boolean hasCaptions(Player player) {
return true;
}
@Override
public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
return false;
}
}
);
สุดท้าย ให้แก้ไขการนําเข้าที่ขาดหายไป
คุณทดสอบได้ด้วยการเรียกใช้ Google Assistant ใน Android TV แล้วพูดว่า "เปิดคำบรรยายแทนเสียง" ตรวจสอบ Logcat เพื่อดูข้อความว่ามีการเรียกใช้โค้ดนี้อย่างไร
6. ขอแสดงความยินดี
ยินดีด้วย คุณเพิ่มเซสชันสื่อลงในตัวอย่างเรียบร้อยแล้ว
คุณจะได้รับฟังก์ชันการทำงานมากมายโดยทำดังนี้
- การเพิ่มเซสชันสื่อ
- การเชื่อมต่อเซสชันสื่อกับอินสแตนซ์ของ ExoPlayer
- การเพิ่มข้อมูลเมตาและการดําเนินการเพิ่มเติม
ตอนนี้คุณทราบขั้นตอนสำคัญที่จำเป็นในการทำให้แอปสื่อสมบูรณ์ยิ่งขึ้นและมอบประสบการณ์การใช้งานที่หลากหลายมากขึ้นให้แก่ผู้ใช้แล้ว
หมายเหตุ สุดท้าย
Codelab นี้สร้างขึ้นจากตัวอย่างจากซอร์สโค้ด ExoPlayer คุณไม่จำเป็นต้องใช้ ExoPlayer จากแหล่งที่มา และเราขอแนะนำให้ดึงข้อมูล Dependency สำหรับ ExoPlayer และ MediaSessionConnector แทนเพื่อให้อัปเดตเป็นเวอร์ชันล่าสุดได้ง่ายขึ้น
ซึ่งทำได้ง่ายๆ ด้วยการแทนที่ทรัพยากรของโปรเจ็กต์ เช่น
implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')
เพื่อดึงข้อมูลจากที่เก็บ Maven เช่น
implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'