Android Academy · บทเรียน

การเล่นเสียงและวิดีโอ

การเล่นสื่ออย่างง่ายใน Android

บทเรียน 4 จาก 413 ขั้นตอน

การเล่นเสียงและวิดีโอ เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

ก้าวต่อจากรูปภาพ: การเล่นสื่อ

Coil แสดงรูปภาพได้อย่างสวยงาม แต่แอปยังสามารถเล่นเสียงและวิดีโอได้ด้วย เช่น เสียงแจ้งเตือน พอดแคสต์ คลิปเบื้องหลัง หรือฟีดวิดีโอ Android มี API เฉพาะสำหรับสื่อ

ไลบรารีสมัยใหม่ที่แนะนำคือ Media3 (ExoPlayer) ซึ่งจัดการการสตรีม รูปแบบไฟล์ การบัฟเฟอร์ และตัวควบคุมการเล่นได้ดีกว่า MediaPlayer รุ่นเก่ามาก ในบทเรียนนี้คุณจะเล่นเสียงและวิดีโอแบบง่าย ๆ ในแอป Compose

การเพิ่มทรัพยากรที่ต้องพึ่งพาของ Media3

Media3 แบ่งออกเป็นโมดูล สำหรับแอปส่วนใหญ่ คุณต้องใช้ media3-exoplayer (กลไกเครื่องเล่น) และ media3-ui (มุมมองเครื่องเล่นสำเร็จรูป) สำหรับวิดีโอใน Compose คุณยังสามารถใช้ PlayerView ผ่าน AndroidView ได้ด้วย

// build.gradle.kts (module level)
dependencies {
    implementation("androidx.media3:media3-exoplayer:1.5.0")
    implementation("androidx.media3:media3-ui:1.5.0")
}

การสร้าง ExoPlayer

ExoPlayer สร้างขึ้นจาก Context คุณส่ง MediaItem ซึ่งอาจเป็น URL หรือไฟล์ในเครื่องให้กับมัน เรียก prepare() แล้วเริ่มเล่น เครื่องเล่นจะทำงานบนเธรดของตัวเอง จึงไม่บล็อกส่วนติดต่อผู้ใช้

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

import android.content.Context
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer

fun createPlayer(context: Context, url: String): ExoPlayer {
    val player = ExoPlayer.Builder(context).build()
    player.setMediaItem(MediaItem.fromUri(url))
    player.prepare()
    player.playWhenReady = true
    return player
}

การเล่นเสียง

สำหรับการเล่นเสียงเท่านั้น การตั้งค่าจะเหมือนเดิม เพียงระบุ URL เสียง เช่น mp3 หรือ aac ให้กับ MediaItem เนื่องจากไม่มีมุมมองให้แสดง คุณจึงควบคุมผ่านออบเจ็กต์เครื่องเล่นด้วย play(), pause() และ seekTo()

เพียงเท่านี้ก็เพียงพอสำหรับสร้างเครื่องเล่นพอดแคสต์หรือเพลง

import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer

fun playPodcast(player: ExoPlayer, audioUrl: String) {
    player.setMediaItem(MediaItem.fromUri(audioUrl))
    player.prepare()
    player.play()
}

fun togglePause(player: ExoPlayer) {
    if (player.isPlaying) player.pause() else player.play()
}

การจดจำเครื่องเล่นใน Compose

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

จับคู่แนวทางนี้กับการล้างทรัพยากรอย่างถูกต้อง (ฉากถัดไป) เพื่อไม่ให้ทรัพยากรรั่วไหล

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer

@Composable
fun rememberPlayer(url: String): ExoPlayer {
    val context = LocalContext.current
    return remember {
        ExoPlayer.Builder(context).build().apply {
            setMediaItem(MediaItem.fromUri(url))
            prepare()
        }
    }
}

การปล่อยคืนเครื่องเล่น

เครื่องเล่นจะรักษาตัวถอดรหัส บัฟเฟอร์ และโฟกัสเสียงให้ทำงานอยู่ หากลืมปล่อยคืน คุณจะทำให้หน่วยความจำรั่วไหล และเครื่องเล่นอาจยังเล่นต่อหลังจากหน้าจอหายไปแล้ว ใน Compose DisposableEffect จะเรียกใช้การล้างทรัพยากรเมื่อ composable ออกจากองค์ประกอบ

เรียก player.release() ที่นั่นเสมอ

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.media3.exoplayer.ExoPlayer

@Composable
fun ManagedPlayer(player: ExoPlayer) {
    DisposableEffect(player) {
        onDispose {
            player.release()
        }
    }
    // ... use player here
}

การแสดงวิดีโอด้วย PlayerView

Media3 มี PlayerView สำเร็จรูปพร้อมตัวควบคุม Compose ไม่มี composable วิดีโอแบบเนทีฟ ดังนั้นคุณจึงฝัง View โดยใช้ AndroidView แล้วเชื่อมต่อเครื่องเล่นเข้ากับ View

วิธีนี้มีปุ่มเล่น/หยุดชั่วคราว แถบเลื่อนตำแหน่ง และโหมดเต็มหน้าจอให้พร้อมใช้งาน

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView

@Composable
fun VideoPlayer(player: ExoPlayer, modifier: Modifier = Modifier) {
    AndroidView(
        factory = { context ->
            PlayerView(context).apply {
                this.player = player
            }
        },
        modifier = modifier
    )
}

หน้าจอวิดีโอแบบสมบูรณ์

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

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView

@Composable
fun VideoScreen(videoUrl: String) {
    val context = LocalContext.current
    val player = remember {
        ExoPlayer.Builder(context).build().apply {
            setMediaItem(MediaItem.fromUri(videoUrl))
            prepare()
            playWhenReady = true
        }
    }
    DisposableEffect(Unit) { onDispose { player.release() } }

    AndroidView(
        factory = { PlayerView(it).apply { this.player = player } },
        modifier = Modifier.fillMaxWidth().height(220.dp)
    )
}

การติดตามสถานะการเล่น

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

เพิ่มตัวรับฟังเมื่อหน้าจอปรากฏ และนำออกเมื่อทำลายองค์ประกอบ

import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer

fun observe(player: ExoPlayer, onPlaying: (Boolean) -> Unit): Player.Listener {
    val listener = object : Player.Listener {
        override fun onIsPlayingChanged(isPlaying: Boolean) {
            onPlaying(isPlaying)
        }
        override fun onPlaybackStateChanged(state: Int) {
            when (state) {
                Player.STATE_BUFFERING -> { /* show spinner */ }
                Player.STATE_READY -> { /* ready */ }
                Player.STATE_ENDED -> { /* finished */ }
            }
        }
    }
    player.addListener(listener)
    return listener
}

การหยุดชั่วคราวเมื่อแอปไปอยู่เบื้องหลัง

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

วิธีนี้ป้องกันไม่ให้เล่นวิดีโอที่ผู้ใช้มองไม่เห็น และช่วยประหยัดแบตเตอรี่

import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.media3.exoplayer.ExoPlayer

@Composable
fun PauseWithLifecycle(player: ExoPlayer) {
    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_PAUSE -> player.pause()
                Lifecycle.Event.ON_RESUME -> player.play()
                else -> {}
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
    }
}

เสียงเบื้องหลังด้วย MediaSession

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

แนวทางนี้มีรายละเอียดมากขึ้น แต่แนวคิดหลักคือการเปิดให้เข้าถึงเครื่องเล่นของคุณผ่าน MediaSession

import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService

class PlaybackService : MediaSessionService() {
    private var session: MediaSession? = null

    override fun onCreate() {
        super.onCreate()
        val player = ExoPlayer.Builder(this).build()
        session = MediaSession.Builder(this, player).build()
    }

    override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = session

    override fun onDestroy() {
        session?.run { player.release(); release() }
        session = null
        super.onDestroy()
    }
}

ตรวจสอบอย่างรวดเร็ว

ในหน้าจอ Compose ที่ถือ ExoPlayer อยู่ คุณควรใช้ API ใดของ Compose เพื่อปล่อยคืนเครื่องเล่นเมื่อหน้าจอออกจากองค์ประกอบ

สรุปทบทวน

คุณได้เพิ่มการเล่นเสียงและวิดีโอแล้ว:

  • ใช้ Media3 ExoPlayer ซึ่งเป็นตัวแทนสมัยใหม่ของ MediaPlayer
  • สร้างเครื่องเล่น กำหนด MediaItem เรียก prepare() จากนั้นเรียก play()
  • ใน Compose ให้ remember เครื่องเล่นและปล่อยคืนใน DisposableEffect ผ่าน onDispose
  • แสดงวิดีโอโดยฝัง PlayerView ด้วย AndroidView
  • ติดตามสถานะด้วย Player.Listener และใช้ MediaSessionService สำหรับเสียงเบื้องหลัง

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

เริ่มต้นได้ฟรี

เรียนรู้ Kotlin ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
36
บทเรียน
152

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

บทเรียน “การเล่นเสียงและวิดีโอ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การเล่นเสียงและวิดีโอ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การเล่นเสียงและวิดีโอ”

การเล่นสื่ออย่างง่ายใน Android คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การเล่นเสียงและวิดีโอ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม

ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การโหลดรูปภาพด้วย Coil
  2. ตัวแทนและสถานะข้อผิดพลาด
  3. การแคชและประสิทธิภาพ
  4. การเล่นเสียงและวิดีโอ
← กลับไปที่ Android Academy