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

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

10e3b5c652186d57.png

หากระบบขอให้คุณใช้ 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

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 จากแหล่งที่มา และเราขอแนะนำให้ดึงข้อมูล 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.+'

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