ภาพรวม
ตัวอย่างนี้สาธิตการใช้ MediaPlayer ผ่าน Singleton Pattern เพื่อจัดการการเล่นเสียง/เพลงแบบรวมศูนย์ ป้องกันการสร้าง MediaPlayer หลายอินสแตนซ์ และจัดการ Resource ให้ถูกต้อง
ขั้นตอนการสร้าง
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → File → New Project → กรอกรายละเอียด
ขั้นตอนที่ 2: จัดรูปแบบหน้าจอ (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/show"
android:text="เล่นเพลงจาก Singleton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
ขั้นตอนที่ 3: เขียนโค้ด MainActivity (src/MainActivity.java)
package com.example.andy.myapplication;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button show;
SingleTonExample singletonExample;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = findViewById(R.id.show);
singletonExample = SingleTonExample.getInstance();
singletonExample.init(getApplicationContext());
show.setOnClickListener(v -> {
MediaPlayer player = singletonExample.getSingletonMedia();
player.start();
});
}
@Override
protected void onDestroy() {
super.onDestroy();
singletonExample.releaseMediaPlayer();
}
}
ขั้นตอนที่ 4: สร้างคลาส Singleton (SingleTonExample.java)
package com.example.andy.myapplication;
import android.content.Context;
import android.media.MediaPlayer;
public class SingleTonExample {
private static MediaPlayer mediaPlayer;
private static SingleTonExample ourInstance = new SingleTonExample();
private Context appContext;
private SingleTonExample() { }
public static synchronized SingleTonExample getInstance() {
return ourInstance;
}
public void init(Context context) {
if (appContext == null) {
this.appContext = context;
}
}
private Context getContext() {
return appContext;
}
public static Context get() {
return getInstance().getContext();
}
public static MediaPlayer getSingletonMedia() {
if (mediaPlayer == null) {
// สร้าง MediaPlayer จาก raw resource
mediaPlayer = MediaPlayer.create(get(), R.raw.sample);
// ตั้งค่า Looping หากต้องการ
// mediaPlayer.setLooping(true);
}
return mediaPlayer;
}
public static void releaseMediaPlayer() {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
}
public static boolean isPlaying() {
return mediaPlayer != null && mediaPlayer.isPlaying();
}
public static void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
public static void seekTo(int position) {
if (mediaPlayer != null) {
mediaPlayer.seekTo(position);
}
}
}
การเตรียมไฟล์เสียง
วางไฟล์เสียง (เช่น sample.mp3) ในโฟลเดอร์ res/raw/ หากไม่มีโฟลเดอร์ ให้สร้างใหม่: New → Android Resource Directory → Resource type: raw
การทดสอบ
รันแอปพลิเคชัน หน้าจอเริ่มต้นแสดงตามภาพ

คลิกปุ่ม จะเล่นเพลงจาก Singleton Class
ข้อดีของ MediaPlayer Singleton
- ใช้ Memory น้อยกว่า (มีเพียงอินสแตนซ์เดียว)
- ควบคุมการเล่น/หยุด/พัก ได้จากทุกจุดในแอป
- เหมาะสำหรับ Background Music, Notification Sound
ข้อควรระวังและ Best Practices
1. Lifecycle Management
// ใน Application Class
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
SingleTonExample.init(this);
}
@Override
public void onTerminate() {
super.onTerminate();
SingleTonExample.releaseMediaPlayer();
}
}
2. Audio Focus Management (สำคัญ!)
// เพิ่มใน MediaPlayer Singleton
private AudioManager audioManager;
private AudioManager.OnAudioFocusChangeListener focusListener;
public void init(Context context) {
this.appContext = context;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
focusListener = focusChange -> {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mediaPlayer != null && !mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mediaPlayer != null) mediaPlayer.setVolume(0.2f, 0.2f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
pause();
break;
}
};
}
public boolean requestFocus() {
return audioManager.requestAudioFocus(focusListener,
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
== AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
public void abandonFocus() {
audioManager.abandonAudioFocus(focusListener);
}
3. การจัดการ Error และ Completion
mediaPlayer.setOnCompletionListener(mp -> {
// ทำเมื่อเล่นจบ (เช่น เล่นเพลงถัดไป)
});
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
// จัดการ Error
return true; // true = จัดการเอง
});
mediaPlayer.setOnPreparedListener(mp -> {
// พร้อมเล่นแล้ว
mp.start();
});
แนวทางทันสมัย: Media3/ExoPlayer
Google แนะนำให้ใช้ Media3 ExoPlayer แทน MediaPlayer เดิม เพราะ:
- รองรับ Format ให้กว้างขึ้น (DASH, HLS, SmoothStreaming)
- จัดการ Audio Focus อัตโนมัติ
- มี Cache, Offline Support
- Customizable และ Extensible
// ExoPlayer Singleton (Modern)
@Singleton
class MediaPlayerManager @Inject constructor(@ApplicationContext Context context) {
private ExoPlayer exoPlayer;
fun getPlayer(): ExoPlayer {
if (exoPlayer == null) {
exoPlayer = ExoPlayer.Builder(context).build()
}
return exoPlayer!!
}
fun release() {
exoPlayer?.release()
exoPlayer = null
}
}