ภาพรวม
ตัวอย่างนี้สาธิตการให้ผู้ใช้เลือกเสียงแจ้งเตือน (Ringtone) เองผ่าน RingtoneManager แล้วนำไปใช้กับ Notification
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → File → New Project
ขั้นตอนที่ 2: Layout (activity_main.xml) - มีปุ่มเลือกเสียงและสร้าง Notification
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<Button
android:onClick="setRingtone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:text="set ringtone" />
<Button
android:onClick="createNotification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
android:text="Create notification" />
</RelativeLayout>
ขั้นตอนที่ 3: MainActivity - เลือกและใช้ Ringtone
package app.tutorialspoint.com.notifyme;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class MainActivity extends AppCompatActivity {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
private String chosenRingtone; // เก็บ URI เสียงที่เลือก
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
onNewIntent(getIntent());
}
// เปิด Ringtone Picker ให้ผู้ใช้เลือกเสียง
public void setRingtone(View view) {
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Select Notification Tone");
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, (Uri) null);
startActivityForResult(intent, 5); // Request code = 5
}
// สร้าง Notification ใช้เสียงที่เลือก
public void createNotification(View view) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(MainActivity.this, default_notification_channel_id);
mBuilder.setContentTitle("Notify Me");
mBuilder.setContentText("Something important!");
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
// ใช้เสียงที่ผู้ใช้เลือก (ถ้ามี)
if (chosenRingtone != null) {
mBuilder.setSound(Uri.parse(chosenRingtone));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
// ตั้งค่าเสียงที่ Channel Level (Android 8.0+)
if (chosenRingtone != null) {
notificationChannel.setSound(Uri.parse(chosenRingtone), null);
}
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == 5) {
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (uri != null) {
this.chosenRingtone = uri.toString();
Toast.makeText(this, "Selected: " + uri.getLastPathSegment(), Toast.LENGTH_SHORT).show();
} else {
this.chosenRingtone = null;
Toast.makeText(this, "Default tone selected", Toast.LENGTH_SHORT).show();
}
}
}
}
ขั้นตอนที่ 4: 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" />
<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>
</application>
</manifest>
2 วิธีการตั้งค่าเสียง Notification
วิธีที่ 1: ตั้งค่าที่ Builder Level (ต่อ Notification)
// ใช้กับ Notification ครั้งนั้นๆ เท่านั้น
mBuilder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.custom_sound));
// หรือ
mBuilder.setSound(ringtoneUri); // จาก RingtonePicker
วิธีที่ 2: ตั้งค่าที่ Channel Level (Android 8.0+ API 26+) - แนะนำ
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Name", IMPORTANCE_HIGH); // ตั้งค่าเสียงสำหรับ Channel นี้ทั้งหมด channel.setSound(ringtoneUri, null); // AudioAttributes = null ใช้ค่าเริ่มต้น notificationManager.createNotificationChannel(channel); // Notification ที่ใช้ Channel นี้จะได้เสียงนี้อัตโนมัติ mBuilder.setChannelId(CHANNEL_ID);
ประเภทเสียงที่ใช้ได้
| แหล่งที่มา | ตัวอย่าง URI | คำอธิบาย |
|---|---|---|
| System Ringtone | content://settings/system/notification_sound | เสียงเริ่มต้นของระบบ |
| RingtonePicker | content://media/internal/audio/media/123 | เสียงที่ผู้ใช้เลือกจาก Picker |
| Raw Resource | android.resource://com.example.app/raw/notification_sound | ไฟล์ .mp3/.ogg/.wav ใน res/raw/ |
| File Path | file:///storage/emulated/0/Download/mysound.mp3 | ไฟล์ใน External Storage (ต้อง Permission) |
ไฟล์เสียงใน res/raw/
- สร้างโฟลเดอร์
res/raw/(New → Android Resource Directory → raw) - วางไฟล์เสียง เช่น
notification_sound.mp3(รองรับ: mp3, ogg, wav) - ใช้ในโค้ด:
Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notification_sound)
AudioAttributes (Android 5.0+ API 21+) - แนะนำ
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
// ใช้กับ Channel
channel.setSound(ringtoneUri, audioAttributes);
// หรือใช้กับ Builder (Legacy)
mBuilder.setSound(ringtoneUri, audioAttributes);
ข้อควรระวัง
- Android 8.0+: ต้องตั้งค่าที่ Channel Level (setSound บน Builder อาจถูกข้าม)
- Do Not Disturb (DND): ผู้ใช้ตั้งค่า DND อาจบล็อกเสียง ใช้
channel.setBypassDnd(true)สำหรับการแจ้งเตือนสำคัญ - โหมด Silent/Vibrate: ระบบจะปิดเสียงอัตโนมัติตามโหมดของโทรศัพท์
- ขนาดไฟล์: ควรไม่เกิน 1-2 MB สำหรับ Notification Sound
- ความยาว: ควรสั้น 1-5 วินาที ไม่ควรยาวเกินไป
ทดสอบ
- กดปุ่ม "set ringtone" → เลือกเสียงจากรายการ
- กดปุ่ม "Create notification" → ตรวจสอบเสียงที่เล่น
- ลองตั้งโทรศัพท์เป็น Silent/Vibrate → ทดสอบอีกครั้ง
- ทดสอบบนอุปกรณ์จริง (Emulator อาจไม่มีเสียง)