การควบคุมสื่อผ่าน MediaSession

1. บทนำ

อัปเดตล่าสุด: 2020-09-09

การเพิ่ม MediaSession รอบการเล่นวิดีโอมีประโยชน์อย่างไร

เซสชันสื่อเป็นลิงก์สำคัญระหว่างแพลตฟอร์ม Android กับแอปสื่อ ซึ่งไม่เพียงแต่แจ้งให้ Android ทราบว่ากำลังเล่นสื่ออยู่เพื่อให้สามารถส่งต่อการดำเนินการกับสื่อไปยังเซสชันที่ถูกต้องได้ แต่ยังแจ้งให้แพลตฟอร์มทราบว่ากำลังเล่นอะไรอยู่และจะควบคุมได้อย่างไรด้วย

การเปิดเผย MediaSession ผ่านแอปของคุณมีประโยชน์มากมายที่ผู้ใช้จะได้รับ ลองดูตัวอย่างที่ยอดเยี่ยมต่อไปนี้

Google Assistant

ผู้ใช้โต้ตอบกับสื่อในแอปของคุณได้อย่างง่ายดายผ่านคำสั่งเสียง เช่น "หยุดชั่วคราว" "เล่นต่อ" และ "ถัดไป" นอกจากนี้ยังใช้ข้อมูลเมตาจากสื่อเพื่อรับคำตอบเกี่ยวกับสิ่งที่กำลังเล่นอยู่ได้ด้วย

Android TV

ในประสบการณ์การใช้งานบนหน้าจอขนาดใหญ่ แอป Android TV สามารถใช้รีโมตคอนโทรลทั่วไปสำหรับผู้ใช้ที่มีทีวีที่รองรับ HDMI-CEC ได้ ระบบจะส่งต่อคำสั่งที่ออกโดยปุ่มเล่น/หยุดชั่วคราว หยุด ถัดไป และก่อนหน้าไปยังแอปของคุณ

การควบคุมสื่อบนหน้าจอ

ตั้งแต่ Android 4.0 (ระดับ API 14) เป็นต้นไป ระบบจะเข้าถึงสถานะการเล่นและข้อมูลเมตาของเซสชันสื่อได้ ฟังก์ชันนี้ช่วยให้หน้าจอล็อกแสดงส่วนควบคุมสื่อและอาร์ตเวิร์กได้ ลักษณะการทำงานนี้จะแตกต่างกันไปตามเวอร์ชันของ Android

สื่อพื้นหลัง

คุณควบคุมสื่อได้ในทุกสถานการณ์เหล่านี้ แม้ว่าแอปที่เล่นสื่อจะทำงานในเบื้องหลังอยู่ก็ตาม

Ambient Computing

การเปิดเผยสื่อของคุณพร้อมข้อมูลเกี่ยวกับสิ่งที่กำลังเล่นและวิธีควบคุมสื่อจะช่วยเชื่อมต่ออุปกรณ์ต่างๆ เพื่อให้ผู้ใช้โต้ตอบกับสื่อได้หลายวิธีตามที่ต้องการ

สิ่งที่คุณจะสร้าง

ใน 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 หากพบปัญหา

10e3b5c652186d57.png

หากระบบขอให้คุณใช้ Gradle เวอร์ชันล่าสุด ให้อัปเดต

โปรดสละเวลาสักครู่เพื่อทำความเข้าใจพื้นฐานเกี่ยวกับวิธีออกแบบแอป โปรดทราบว่ามีกิจกรรม 2 อย่าง ได้แก่ SampleChooserActivity และ PlayerActivity เราจะใช้เวลาที่เหลือของโค้ดแล็บใน PlayerActivity ซึ่งเป็นที่ที่สื่อเล่นจริง ดังนั้นให้เปิดคลาสนี้แล้วไปที่ส่วนถัดไป

3. สร้างเซสชันสื่อและจัดการสถานะของเซสชัน

สร้างเซสชันสื่อ

เปิด PlayerActivity.java คลาสนี้สร้าง ExoPlayer และจัดการฟังก์ชันต่างๆ เช่น การแสดงวิดีโอบนหน้าจอ ในกิจกรรมนี้ เราจะเชื่อมต่อ ExoPlayer กับเซสชันสื่อ

ประกาศฟิลด์ 2 รายการต่อไปนี้ที่ด้านบนของคลาส เราจะใช้ฟิลด์เหล่านี้ตลอดทั้งส่วนนี้

private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;

คุณจะต้องเพิ่มทรัพยากร Dependency ของโปรเจ็กต์ "extension-mediasession" ลงใน build.gradle ระดับโมดูลสำหรับ "Module: demo" ดังนี้

implementation project(path: ':extension-mediasession')

โปรดทราบว่า Android Studio ช่วยคุณเพิ่มทรัพยากร Dependency นี้ได้โดยอัตโนมัติหากคุณวางเมาส์เหนือข้อผิดพลาดในการแก้ไข MediaSessionConnector

60055e4ad54fbb97.png

สุดท้าย ให้แก้ไขการนำเข้าชั้นเรียนโดยเพิ่มข้อมูลต่อไปนี้

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);
  }
  ...
}

มาลองใช้เดโมกัน

  1. แนบอุปกรณ์ Android หรือเริ่มโปรแกรมจำลอง
  2. ตรวจสอบว่าได้เลือก "demo" เพื่อเรียกใช้จากแถบเครื่องมือ Android Studio แล้ว cb1ec4e50886874f.png
  3. คลิก 9d8fb3a9ddf12827.png จากแถบเครื่องมือ Android Studio
  4. เมื่อแอปเปิดขึ้นในอุปกรณ์แล้ว ให้เลือกสตรีมวิดีโอที่จะเล่น
  5. เมื่อการเล่นเริ่มขึ้น ให้ลองใช้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
  1. นอกจากนี้ ให้ดูว่า Android มองเห็นเซสชันสื่อของคุณอย่างไร โดยคุณสามารถตรวจสอบว่าระบบรองรับการดำเนินการใดบ้างได้โดยดูที่ช่องการดำเนินการ หมายเลขที่คุณเห็นที่นี่คือการรวมรหัสการดำเนินการตามที่ประกาศไว้ในออบเจ็กต์ PlaybackState วิธีดูเซสชันสื่อที่กำลังทำงานมีดังนี้ adb shell dumpsys media_session
  2. หากใช้อุปกรณ์จริงที่มีไมโครโฟน ให้ลองเรียกใช้ Google Assistant และออกคำสั่งเสียง เช่น "หยุดชั่วคราว" "เล่นต่อ" "กรอไปข้างหน้า 1 นาที"

b8dda02a6fb0f6a4.png *ตัวอย่าง 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 แล้วถามว่า "เปิดอะไรอยู่"

6c7fc0cb853cbc38.png

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
);

มาดูกันอีกครั้งว่าแพลตฟอร์มจะแสดงข้อมูลนี้อย่างไร

  1. เริ่มวิดีโอเหมือนเดิม
  2. ดูว่า Android เห็นข้อมูลเมตาจากเซสชันสื่อของคุณอย่างไรโดยการเรียกใช้ adb shell dumpsys media_session
  3. ค้นหาบรรทัดที่มีข้อมูลเมตาและสังเกตว่ามีชื่อและคำอธิบายรวมอยู่และเชื่อมโยงกับ 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 จากแหล่งที่มา และเราขอแนะนำให้คุณดึงข้อมูลการอ้างอิงสำหรับ 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.+'

เอกสารอ้างอิง