การเล่นเสียงและวิดีโอ
การเล่นสื่ออย่างง่ายใน Android
การเล่นเสียงและวิดีโอ เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การโหลดรูปภาพด้วย Coil
- ตัวแทนและสถานะข้อผิดพลาด
- การแคชและประสิทธิภาพ
- การเล่นเสียงและวิดีโอ