1. บทนำ
อัปเดตล่าสุด 09-09-2020
การเพิ่ม MediaSession ในการเล่นวิดีโอมีประโยชน์อย่างไร
เซสชันสื่อเป็นลิงก์ที่สำคัญระหว่างแพลตฟอร์ม Android กับแอปสื่อ ฟีเจอร์ดังกล่าวไม่เพียงแค่แจ้งให้ Android ทราบว่ากำลังเล่นสื่อ เพื่อให้สามารถส่งต่อการทำงานของสื่อไปยังเซสชันที่ถูกต้อง แต่ยังให้ข้อมูลแก่แพลตฟอร์มว่ากำลังเล่นสื่ออะไรและสามารถควบคุมได้อย่างไร
การแสดง MediaSession ผ่านแอปมีประโยชน์ต่างๆ ที่ผู้ใช้จะชื่นชอบ ตัวอย่างที่ยอดเยี่ยมส่วนหนึ่งมีดังนี้
Google Assistant
ผู้ใช้สามารถโต้ตอบกับสื่อในแอปได้ง่ายๆ ผ่านคำสั่งเสียง เช่น "หยุดชั่วคราว" "เล่นต่อ" และ "ถัดไป" นอกจากนี้ยังใช้ข้อมูลเมตาจากสื่อเพื่อหาคำตอบเกี่ยวกับสิ่งที่กำลังเล่นอยู่ได้ด้วย
Android TV
ในการใช้งานหน้าจอขนาดใหญ่ แอป Android TV สามารถใช้รีโมตคอนโทรลทั่วไปสำหรับผู้ใช้ที่มีทีวีที่รองรับ HDMI-CEC คำสั่งที่มาจากปุ่มเล่น/หยุดชั่วคราว หยุด ถัดไป และก่อนหน้าจะถ่ายทอดไปยังแอปของคุณ
การควบคุมสื่อบนหน้าจอ
ตั้งแต่ Android 4.0 (API ระดับ 14) ระบบสามารถเข้าถึงสถานะการเล่นและข้อมูลเมตาของเซสชันสื่อ ฟังก์ชันการทำงานนี้จะช่วยให้หน้าจอล็อกแสดงตัวควบคุมสื่อและอาร์ตเวิร์กได้ ลักษณะการทำงานนี้จะแตกต่างกันไปตามเวอร์ชันของ Android
สื่อที่เล่นอยู่เบื้องหลัง
คุณควบคุมสื่อได้ในสถานการณ์เหล่านี้แม้ว่าแอปที่กำลังเล่นสื่อจะทำงานอยู่ในเบื้องหลัง
การประมวลผล แอมเบียนท์
การเปิดเผยสื่อที่มีข้อมูลเกี่ยวกับสิ่งที่กำลังเล่นและวิธีการควบคุมสื่อจะสามารถเชื่อมโยงระหว่างอุปกรณ์ต่างๆ เพื่อให้ผู้ใช้สามารถโต้ตอบกับสื่อได้ด้วยวิธีที่หลากหลายตามต้องการ
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะได้ขยายตัวอย่าง 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 อย่าง ได้แก่ SampleSelectrActivity และ PlayerActivity เราจะใช้เวลาที่เหลือของ Codelab ใน PlayerActivity ซึ่งเป็นที่ที่สื่อเล่นนั้นจริงๆ ดังนั้นให้เปิดชั้นเรียนนี้และไปที่ส่วนถัดไป
3. สร้างเซสชันสื่อและจัดการสถานะ
สร้างเซสชันสื่อ
เปิด PlayerActivity.java
คลาสนี้จะสร้าง ExoPlayer และจัดการฟังก์ชันต่างๆ เช่น การแสดงภาพวิดีโอไปยังหน้าจอ โดยในกิจกรรมนี้ เราจะเชื่อมต่อ ExoPlayer กับเซสชันสื่อ
ประกาศ 2 ช่องต่อไปนี้ที่ด้านบนของชั้นเรียน เราจะใช้ช่องเหล่านี้ตลอดทั้งส่วนนี้
private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;
คุณจะต้องเพิ่ม "ส่วนขยาย-เซสชันสื่อ" Dependency ของโปรเจ็กต์ลงใน build.gradle
ระดับโมดูลสำหรับ "โมดูล: การสาธิต":
implementation project(path: ':extension-mediasession')
โปรดทราบว่า Android Studio สามารถช่วยคุณเพิ่มทรัพยากร Dependency นี้โดยอัตโนมัติหากคุณวางเมาส์เหนือข้อผิดพลาดที่กำลังแก้ไข 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 หรือเริ่มโปรแกรมจำลอง
- อย่าลืม "สาธิต" ให้เรียกใช้จากแถบเครื่องมือ 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()
การเพิ่ม TimesQueueNavigator
ExoPlayer จะแสดงโครงสร้างของสื่อในรูปแบบลำดับเวลา โปรดสละเวลาสักครู่เพื่ออ่านออบเจ็กต์ไทม์ไลน์ของ ExoPlayer เพื่อดูรายละเอียดเกี่ยวกับกระบวนการนี้ การใช้โครงสร้างนี้จะทำให้เรารู้เมื่อเนื้อหามีการเปลี่ยนแปลงและแสดงข้อมูลเมตาของรายการที่กำลังเล่นอยู่เมื่อระบบถาม
ในการดำเนินการดังกล่าว เราจะกำหนด ScheduleQueueNavigator ค้นหาอินสแตนซ์ MediaSessionConnector ใน initializePlayer()
และเพิ่มการใช้งาน ScheduleQueueNavigator หลังจาก 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 แทน ซึ่งจะช่วยให้คุณติดตามรุ่นล่าสุดได้ง่ายดายยิ่งขึ้น
เพียงแทนที่ทรัพยากร Dependency ของโปรเจ็กต์ เช่น
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.+'