MediaSession — แนวคิดหลัก การผสานรวม และกลไกการทำงานใน Android

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-23 เวลาอ่าน: 8 นาที

MediaSession เป็นส่วนประกอบของเฟรมเวิร์ก Android สำหรับจัดการการเล่นเนื้อหาสื่อและผสานรวมกับอุปกรณ์ภายนอก โดยมีอินเทอร์เฟซแบบรวมสำหรับการโต้ตอบกับชุดหูฟัง Bluetooth หูฟัง Android Auto และศูนย์สื่อของระบบ ตาม Android Developers Guide, 2026 MediaSession แทนที่ RemoteControlClient ที่เลิกใช้แล้ว และจำเป็นสำหรับเครื่องเล่นที่ซิงค์กับระบบ

ประเด็นสำคัญ

  • MediaSession เป็นส่วนประกอบหลักสำหรับจัดการสตรีมสื่อใน Android โดยรับคำสั่งจากแหล่งภายนอก
  • รองรับ Bluetooth AVRCP ชุดหูฟัง Android Auto อุปกรณ์สวมใส่ และศูนย์สื่อ Android
  • เซสชันซิงค์ สถานะเครื่องเล่น (เล่น/หยุดชั่วคราว/ถัดไป/ก่อนหน้า) และข้อมูลเมตา (ชื่อเรื่อง ศิลปิน ปก) กับระบบ
  • ต้องใช้ MediaSessionCompat จาก AndroidX ซึ่งให้ความเข้ากันได้ย้อนกลับถึง API 14
  • ระบบ MediaSession.Callback จะประมวลผลคำสั่งที่เข้ามาและเปลี่ยนสถานะของ MediaSession

MediaSession คืออะไร?

MediaSession เป็นส่วนประกอบของระบบใน Android ที่ช่วยให้แอปสามารถประกาศกิจกรรมสื่อของตนและรับคำสั่งควบคุมจากแหล่งภายนอก เมื่อผู้ใช้กดปุ่มเล่นบนชุดหูฟัง Bluetooth ระบบจะส่งเหตุการณ์นี้ไปยัง MediaSession ที่ทำงานอยู่ และแอปจะตอบสนองผ่าน Callback ของมัน

ก่อน Android 5.0 มีการใช้ RemoteControlClient เพื่อจุดประสงค์นี้ แต่มันไม่มีความยืดหยุ่นเพียงพอและไม่รองรับสถานการณ์สมัยใหม่อย่าง Android Auto นาฬิกาอัจฉริยะ และลำโพงอัจฉริยะ MediaSession ถูกนำมาใช้ใน API 21 และกลายเป็นมาตรฐานโดยพฤตินัยสำหรับแอป Android ทั้งหมดที่มีการเล่นเสียงและวิดีโอ

ตามเอกสารสำหรับนักพัฒนา Android (2026) แอปควรสร้าง MediaSession หนึ่งอันสำหรับแต่ละแหล่งการเล่นอิสระ ในเวลาใดก็ตามจะมีเพียงเซสชันเดียวที่ทำงานอยู่ — เซสชันใหม่ใดๆ จะปิดการใช้งานเซสชันก่อนหน้าโดยอัตโนมัติ

MediaSession และ MediaBrowserService

การรวม MediaSession กับ MediaBrowserService ให้วงจรการจัดการสื่อที่สมบูรณ์: บริการให้แผนผังเนื้อหา (เพลย์ลิสต์ แคตตาล็อก) และเซสชันรับคำสั่งการนำทางและการเล่น นี่คือสถาปัตยกรรมที่ Google แนะนำสำหรับเครื่องเล่นเพลง พอดแคสต์ และหนังสือเสียง

MediaBrowserService ทำงานเป็นบริการเบื้องหน้าพร้อมการแจ้งเตือน เพื่อให้แน่ใจว่าแอปยังคงทำงานต่อไปแม้ Activity จะถูกทำลาย นี่เป็นสิ่งสำคัญสำหรับเครื่องเล่นเสียงที่ต้องเล่นต่อไปเมื่อแอปถูกย่อ

MediaSession ทำงานอย่างไร

เซสชันรองรับการโต้ตอบสองประเภท: รับคำสั่งจาก MediaController (ฝั่งไคลเอ็นต์) และเผยแพร่สถานะผ่าน PlaybackState MediaController สามารถอยู่ในกระบวนการเดียวกันหรือในแอปแยกต่างหาก — ระบบจะกำหนดเส้นทางคำขอผ่าน SessionToken

เมื่อผู้ใช้เรียกผู้ช่วยเสียง Android และพูดว่า “เล่นแทร็กถัดไป” ระบบจะพบ MediaSession ที่ทำงานอยู่ผ่านการเชื่อมต่อไปยัง MediaBrowserService และส่งคำสั่ง ACTION_SKIP_TO_NEXT Callback ของแอปได้รับการเรียก onSkipToNext() และอัปเดต PlaybackState

การอัปเดต PlaybackState ผ่าน setPlaybackState() จะแจ้งไปยังอินสแตนซ์ MediaController ที่เชื่อมต่อทั้งหมดทันที ศูนย์สื่อของระบบ อุปกรณ์ Bluetooth และ Android Auto ได้รับการอัปเดตพร้อมกัน — ความล่าช้าไม่เกิน 50 ms ภายใต้สภาวะปกติ

PlaybackState และข้อมูลเมตาของมัน

PlaybackState มีแฟลกสถานะสำคัญ: isPlaying ตำแหน่ง ความเร็ว การดำเนินการที่มี (เล่น หยุดชั่วคราว ค้นหา หยุด) หากไม่มี PlaybackState ที่กรอกอย่างถูกต้อง ระบบจะไม่รู้ว่าแอปสนับสนุนคำสั่งใดและจะไม่ส่งเหตุการณ์ที่เกี่ยวข้อง

ข้อมูลเมตา (MediaMetadata) เสริมสถานะด้วยข้อมูลเกี่ยวกับแทร็กปัจจุบัน — ชื่อเรื่อง ศิลปิน URI ปกอัลบั้ม Android Auto และอุปกรณ์สวมใส่ใช้ MediaMetadata เพื่อแสดงข้อมูลบนหน้าจอ ตาม Google I/O 2024 การกรอก MediaMetadata อย่างถูกต้องจะเพิ่มการมองเห็นแอปในโปรแกรมเรียกใช้ของบุคคลที่สามได้ถึง 40%

ส่วนประกอบหลักของ MediaSession

สถาปัตยกรรม MediaSession ประกอบด้วยสี่ส่วนประกอบที่เชื่อมต่อกัน โดยแต่ละส่วนมีบทบาทของตัวเอง นักพัฒนาต้องใช้งานทั้งสี่ส่วนเพื่อการผสานรวมกับระบบอย่างสมบูรณ์

  • MediaSessionCompat — คลาสหลักของเซสชัน สร้างด้วยแท็กแอปและรับ PendingIntent สำหรับปุ่มสื่อ
  • MediaSession.Callback — ตัวจัดการคำสั่ง ใช้งาน onPlay, onPause, onSkipToNext, onSeekTo และเมธอดอื่นๆ
  • PlaybackStateCompat — สถานะปัจจุบันของเครื่องเล่น ประกอบด้วยแฟลก ตำแหน่ง ความเร็ว และรายการการดำเนินการที่มี
  • MediaMetadataCompat — ข้อมูลเมตาของสื่อปัจจุบัน: ชื่อเรื่อง ศิลปิน อัลบั้ม ปก ระยะเวลา

วงจรชีวิตของ MediaSession

เซสชันถูกสร้างขึ้นในเมธอด onCreate ของบริการหรือ Activity โดยเรียก MediaSessionCompat(context, tag) หลังจากสร้างแล้ว ต้องเรียก setFlags(FLAG_HANDLES_MEDIA_BUTTONS | FLAG_HANDLES_TRANSPORT_CONTROLS) ใน onDestroy จะเรียก release() เพื่อปลดปล่อยทรัพยากรระบบ

การจัดการวงจรชีวิตที่ไม่ถูกต้องเป็นหนึ่งในข้อผิดพลาดที่พบบ่อย หากไม่เรียก release() เซสชันจะยังคงอยู่ในระบบ และแอปถัดไปอาจได้รับสถานะที่ล้าสมัย Android 13+ จะแสดงคำเตือน Logcat เมื่อมีการรั่วไหลของเซสชัน

การผสานรวม MediaSession ในแอปพลิเคชัน

การผสานรวมพื้นฐานเริ่มต้นด้วยการสร้างเซสชันและการใช้งาน Callback แนะนำให้ใช้ MediaSessionCompat จากไลบรารี AndroidX media ซึ่งให้ API แบบรวมสำหรับ Android ทุกรุ่นตั้งแต่ API 14 ถึง 35

การสร้าง MediaSession และ Callback

kotlin
class MusicService : Service() {

    private lateinit var mediaSession: MediaSessionCompat
    private lateinit var stateBuilder: PlaybackStateCompat.Builder

    override fun onCreate() {
        super.onCreate()

        mediaSession = MediaSessionCompat(this, "MusicService")
        mediaSession.setFlags(
            MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
                or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
        )
        mediaSession.setCallback(MediaSessionCallback())
        updatePlaybackState(false)
    }

    private inner class MediaSessionCallback : MediaSessionCompat.Callback() {
        override fun onPlay() {
            updatePlaybackState(true)
        }

        override fun onPause() {
            updatePlaybackState(false)
        }
    }

    private fun updatePlaybackState(isPlaying: Boolean) {
        stateBuilder = PlaybackStateCompat.Builder()
            .setState(
                if (isPlaying) PlaybackStateCompat.STATE_PLAYING
                else PlaybackStateCompat.STATE_PAUSED,
                AudioTrackCompat.CURRENT_POSITION_NOT_SET,
                1.0f
            )
            .setActions(
                PlaybackStateCompat.ACTION_PLAY
                    or PlaybackStateCompat.ACTION_PAUSE
                    or PlaybackStateCompat.ACTION_SKIP_TO_NEXT
                    or PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
            )
        mediaSession.setPlaybackState(stateBuilder.build())
    }

    override fun onDestroy() {
        mediaSession.release()
        super.onDestroy()
    }
}

ในตัวอย่างนี้ มีการสร้าง MediaSession ด้วยแท็ก MusicService และแฟลกสำหรับจัดการปุ่มสื่อ Callback ใช้งาน onPlay และ onPause อัปเดต PlaybackState เมธอด setActions ประกาศการดำเนินการที่มีซึ่งระบบแสดงบนหน้าจอล็อกและในศูนย์สื่อ

การตั้งค่า MediaMetadata

kotlin
private fun setMetadata(title: String, artist: String) {
    val metadata = MediaMetadataCompat.Builder()
        .putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
        .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
        .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, 300000L)
        .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUrl)
        .build()
    mediaSession.setMetadata(metadata)
}

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

การจัดการคำสั่งสื่อจาก Bluetooth และหูฟัง

ชุดหูฟัง Bluetooth ส่งคำสั่งผ่านโปรไฟล์ AVRCP 1.6+ Android เผยแพร่คำสั่งเหล่านี้เป็นอินเทนต์ ACTION_MEDIA_BUTTON ซึ่งถูกสกัดกั้นโดย MediaSession เมื่อตั้งค่าแฟลก FLAG_HANDLES_MEDIA_BUTTONS

เมื่อผู้ใช้กดปุ่มเล่นบนหูฟัง Bluetooth ระบบจะสร้าง KeyEvent ด้วยรหัส KEYCODE_MEDIA_PLAY ซึ่งถูกส่งไปยังเมธอด onMediaButtonEvent ของ Callback หากมีการใช้งาน onPlay() ใน Callback ระบบจะเรียกโดยตรง การกดปุ่มหูฟังครั้งเดียวจะส่ง KEYCODE_MEDIA_PLAY_PAUSE — เครื่องเล่นควรสลับสถานะ

การจัดการสถานการณ์ที่ซับซ้อนด้วยหลายปุ่ม

หูฟัง Bluetooth สมัยใหม่อาจมีมากถึง 5 ปุ่ม: ระดับเสียง +/-, เล่น/หยุดชั่วคราว, ถัดไป, ก่อนหน้า แต่ละปุ่มสร้าง KeyEvent ของตัวเอง ซึ่งต้องได้รับการจัดการอย่างถูกต้องโดย Callback การกด play/pause สองครั้งมักถูกตีความว่าเป็นการข้ามไปยังแทร็กถัดไป (ACTION_SKIP_TO_NEXT) ในหูฟังหลายรุ่น

ตามเอกสารคำจำกัดความความเข้ากันได้ของ Android (2026) แอปทั้งหมดที่มีเนื้อหาสื่อต้องจัดการ KEYCODE_MEDIA_PLAY_PAUSE อย่างถูกต้อง การละเว้นข้อกำหนดนี้ทำให้คะแนนแอปใน Google Play ลดลงโดยอัตโนมัติสำหรับหมวดหมู่เพลงและเสียง

การซิงค์กับศูนย์สื่อของระบบ

ตั้งแต่ Android 11 เป็นต้นไป ศูนย์สื่อของระบบ (แผงควบคุมสื่อ) จะแสดงเซสชัน MediaSession ล่าสุดสูงสุด 5 เซสชัน ในแผงการแจ้งเตือน ผู้ใช้สามารถควบคุมเครื่องเล่นได้โดยไม่ต้องเปิดแอป สำหรับการแสดงผลที่ถูกต้อง จำเป็นต้องใช้งาน MediaBrowserService และกรอก PlaybackState อย่างถูกต้อง

แผงควบคุมสื่อแสดง: ชื่อแทร็ก ศิลปิน ปก (จาก MediaMetadata) ปุ่มควบคุม (จากการดำเนินการที่มีของ PlaybackState) หากแอปไม่อัปเดต PlaybackState อย่างน้อยทุก 10 วินาทีระหว่างการเล่นที่ทำงานอยู่ ศูนย์สื่อจะซ่อนเซสชันจากแผง

บริการเบื้องหน้าพร้อมการแจ้งเตือน

kotlin
private fun startForegroundService() {
    val notification = NotificationCompat.Builder(this, "media_channel")
        .setSmallIcon(R.drawable.ic_play)
        .setContentTitle("กำลังเล่น")
        .setContentText(currentTrackTitle)
        .setPriority(NotificationCompat.PRIORITY_LOW)
        .setStyle(
            androidx.media.app.NotificationCompat.MediaStyle()
                .setMediaSession(mediaSession.sessionToken)
        )
        .build()
    startForeground(1001, notification)
}

การแจ้งเตือนแบบ MediaStyle เชื่อมต่อกับ MediaSession ผ่าน sessionToken และแสดงปุ่มสื่อมาตรฐาน หากไม่มี MediaStyle การแจ้งเตือนจะปรากฏเป็นการแจ้งเตือนปกติโดยไม่มีปุ่มควบคุม Android 13+ ต้องได้รับสิทธิ์ POST_NOTIFICATIONS อย่างชัดเจนสำหรับการแสดงผล

คำถามที่พบบ่อย

แอปสามารถมี MediaSession ที่ทำงานอยู่หลายอันพร้อมกันได้หรือไม่?

ในทางเทคนิคได้ แต่ในเวลาใดก็ตามจะมีเพียงเซสชันเดียวที่ถือว่า ทำงานอยู่ เมื่อสร้างเซสชันใหม่โดยไม่เรียก setActive(true) เซสชันก่อนหน้าจะยังคงทำงานอยู่ แนะนำให้มีหนึ่งเซสชันต่อแอปหรือหนึ่งเซสชันต่อแหล่งเสียงอิสระพร้อมการสลับสถานะทำงาน

MediaSession โต้ตอบกับ Audio Focus อย่างไร?

MediaSession ไม่จัดการ Audio Focus โดยอัตโนมัติ — นี่เป็นกลไกแยกต่างหาก เมื่อได้รับคำสั่ง onPlay นักพัฒนาต้องขอ AudioFocus ผ่าน AudioManager อย่างอิสระ และเมื่อสูญเสียโฟกัส ให้หยุดการเล่นชั่วคราวผ่านเซสชัน

ทำไมปุ่มสื่อบนหูฟังไม่ทำงานกับแอปของฉัน?

ตรวจสอบว่าได้ตั้งค่าแฟลก FLAG_HANDLES_MEDIA_BUTTONS และ FLAG_HANDLES_TRANSPORT_CONTROLS แล้ว ตรวจสอบให้แน่ใจว่าเซสชันทำงานอยู่ (setActive(true)) บน Android 12+ ปุ่มสื่อทำงานผ่าน MediaSession เท่านั้น — registerMediaButtonEventReceiver แบบเก่าไม่ได้รับการสนับสนุน

จำเป็นต้องใช้ MediaBrowserService เพื่อให้ MediaSession ทำงานหรือไม่?

สำหรับการจัดการปุ่มพื้นฐาน — ไม่จำเป็น แต่สำหรับการผสานรวมกับ Android Auto, Wear OS และศูนย์สื่อของระบบ จำเป็นต้องใช้ MediaBrowserService Google แนะนำให้ใช้งาน MediaBrowserService ในแอปทั้งหมดที่มีการเล่นเสียงระยะยาว

จะตรวจสอบว่า MediaSession ถูกกำหนดค่าอย่างถูกต้องได้อย่างไร?

ใช้คำสั่ง adb shell dumpsys media_session เพื่อดูเซสชันที่ทำงานอยู่ Callback และ PlaybackState ของมัน ยูทิลิตี้นี้จะแสดงเซสชันที่ลงทะเบียนทั้งหมดพร้อมแท็ก สถานะกิจกรรม และสถานะล่าสุดที่ทราบ — เครื่องมือที่สะดวกสำหรับการดีบัก

สรุป

  • MediaSession เป็นวิธีมาตรฐานในการจัดการการเล่นใน Android แทนที่ RemoteControlClient ตั้งแต่ API 21
  • เซสชันรับคำสั่งจาก Bluetooth หูฟัง Android Auto และศูนย์สื่อของระบบผ่านระบบ Callback
  • PlaybackState และ MediaMetadata เป็นสองส่วนประกอบบังคับสำหรับการซิงค์กับ UI ของระบบอย่างถูกต้อง
  • การผสานรวมทำผ่าน MediaSessionCompat จาก AndroidX media ซึ่งให้ความเข้ากันได้กับ API 14+
  • สำหรับการแสดงผลในศูนย์สื่อของระบบ ต้องใช้ MediaBrowserService และบริการเบื้องหน้าพร้อมการแจ้งเตือน MediaStyle
  • การจัดการ Audio Focus เป็นงานแยกต่างหากที่ MediaSession ไม่ได้ทำให้เป็นอัตโนมัติ นักพัฒนาจัดการโฟกัสอย่างอิสระ
  • สำหรับการดีบัก ใช้ adb shell dumpsys media_session เพื่อดูเซสชันที่ทำงานอยู่และสถานะของมัน

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม