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

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

10e3b5c652186d57.png

หากระบบขอให้ใช้ 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 ดังนี้

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. อย่าลืม "สาธิต" ให้เรียกใช้จากแถบเครื่องมือ 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()

การเพิ่ม 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 แล้วถามว่า "เปิดอะไรอยู่"

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 แทน ซึ่งจะช่วยให้คุณติดตามรุ่นล่าสุดได้ง่ายดายยิ่งขึ้น

เพียงแทนที่ทรัพยากร 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.+'

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