ภาพรวม
การเล่นเสียง Notification ใน Android สามารถทำได้หลายวิธี ขึ้นอยู่กับจุดประสงค์: ใช้เสียง Default ของระบบ, เสียง Custom, หรือเล่นเสียงด้วยตนเองผ่าน MediaPlayer
วิธีที่ 1: ใช้เสียง Default ของระบบ (แนะนำส่วนใหญ่)
ให้ระบบจัดการเสียงผ่าน Notification Channel (API 26+) หรือ Builder (API < 26)
// API 26+ : ตั้งค่าที่ Channel
channel.setSound(
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION),
new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build()
);
// API < 26 : ตั้งค่าที่ Builder
builder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
วิธีที่ 2: เล่นเสียงด้วย MediaPlayer แบบ Manual
เหมาะเมื่อต้องการเล่นเสียงทันทีโดยไม่สร้าง Notification หรือควบคุมการเล่นได้ (Pause, Stop, Loop)
MainActivity.java
package app.tutorialspoint.com.notifyme;
import android.app.NotificationManager;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import androidx.core.app.NotificationCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String DEFAULT_CHANNEL_ID = "default";
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnPlaySound = findViewById(R.id.btnCreateNotification);
btnPlaySound.setOnClickListener(v -> playNotificationSound());
}
private void playNotificationSound() {
// 1. ดึง URI เสียง Notification Default ของระบบ
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// หรือ TYPE_RINGTONE, TYPE_ALARM
// 2. สร้าง MediaPlayer และเล่น
try {
if (mediaPlayer != null) {
mediaPlayer.release();
}
mediaPlayer = MediaPlayer.create(getApplicationContext(), alarmSound);
mediaPlayer.setOnCompletionListener(mp -> {
mp.release();
mediaPlayer = null;
});
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
// 3. แสดง Notification พร้อมกัน (ถ้าต้องการ)
showNotification();
}
private void showNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, DEFAULT_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Sound Test")
.setContentText("Notification sound played via MediaPlayer")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify((int) System.currentTimeMillis(), builder.build());
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
}
}
ประเภทเสียง Default ของระบบ (RingtoneManager)
| ค่าคงที่ | คำอธิบาย |
|---|---|
| TYPE_RINGTONE | เสียงโทรเข้า |
| TYPE_NOTIFICATION | เสียงแจ้งเตือนทั่วไป (Default) |
| TYPE_ALARM | เสียงนาฬิกาปลุก |
| TYPE_ALL | รวมทุกประเภท |
วิธีที่ 3: ใช้ Custom Sound จาก res/raw
// วางไฟล์เสียงใน res/raw/notification_sound.mp3
Uri customSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
getPackageName() + "/raw/notification_sound.mp3");
// ใช้กับ MediaPlayer
MediaPlayer mp = MediaPlayer.create(context, customSound);
mp.start();
// หรือใช้กับ Notification Channel (API 26+)
channel.setSound(customSound, audioAttributes);
การจัดการ Audio Focus (สำคัญ)
เมื่อเล่นเสียงด้วย MediaPlayer ควรขอ Audio Focus เพื่อไม่ตัดเสียงแอปอื่น (เพลง, วิดีโอ)
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
AudioFocusRequest focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
.setOnAudioFocusChangeListener(focusChange -> {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
// หยุดชั่วคราว
mediaPlayer.pause();
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// เล่นต่อ
mediaPlayer.start();
}
})
.build();
int result = audioManager.requestAudioFocus(focusRequest);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mediaPlayer.start();
}
Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:id="@+id/btnCreateNotification"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Play Notification Sound"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.tutorialspoint.com.notifyme">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
สรุปการเลือกวิธี
| สถานการณ์ | วิธีที่แนะนำ |
|---|---|
| Notification ปกติ | ตั้งค่า Sound ใน Notification Channel (API 26+) หรือ Builder.setSound() (API < 26) |
| ต้องเล่นเสียงทันทีโดยไม่แสดง Notification | MediaPlayer + RingtoneManager.getDefaultUri() |
| ต้องควบคุมการเล่น (Pause, Seek, Loop) | MediaPlayer หรือ ExoPlayer |
| เสียงสำหรับ Alarm/Timer | ใช้ TYPE_ALARM + AudioAttributes.USAGE_ALARM |
| แอปเพลง/พอดคาสท์ | ExoPlayer + MediaSession + MediaController |
เคล็ดลับ: อย่าลืม release() MediaPlayer ใน onDestroy() หรือ onCompletionListener เพื่อป้องกัน Memory Leak