Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีใช้ Android MediaPlayer แบบ Singleton

ภาพรวม

ตัวอย่างนี้สาธิตการใช้ 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

การทดสอบ

รันแอปพลิเคชัน หน้าจอเริ่มต้นแสดงตามภาพ

วิธีใช้ Android MediaPlayer แบบ Singleton

คลิกปุ่ม จะเล่นเพลงจาก 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
    }
}