Giới thiệu
Ví dụ này minh họa cách cho phép người dùng chọn âm thanh tùy chỉnh (ringtone) từ danh sách hệ thống, sau đó phát âm thanh đó khi thông báo xuất hiện. Sử dụng RingtoneManager.ACTION_RINGTONE_PICKER.
Các bước thực hiện
Bước 1: Tạo dự án mới
Tạo project Android Studio mới.
Bước 2: Layout với 2 nút (res/layout/activity_main.xml)
<?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:id="@+id/btnSetRingtone"
android:onClick="setRingtone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:text="Chọn nhạc chuông" />
<Button
android:id="@+id/btnCreateNotification"
android:onClick="createNotification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
android:text="Tạo thông báo với âm thanh đã chọn" />
</RelativeLayout>
Bước 3: MainActivity (src/MainActivity.java)
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 chosenRingtoneUri = null; // Lưu URI âm thanh đã chọn
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// MỞ HỘP THOẠI CHỌN RINGTONE HỆ THỐNG
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, "Chọn âm thanh thông báo");
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
chosenRingtoneUri != null ? Uri.parse(chosenRingtoneUri) : null);
startActivityForResult(intent, 5); // Request code 5
}
// TẠO THÔNG BÁO VỚI ÂM THANH TÙY CHỈNH
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("Thông báo có âm thanh tùy chỉnh");
mBuilder.setContentText("Âm thanh: " + (chosenRingtoneUri != null ? "Đã chọn" : "Mặc định"));
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
// ÁP DỤNG ÂM THANH ĐÃ CHỌN
if (chosenRingtoneUri != null) {
mBuilder.setSound(Uri.parse(chosenRingtoneUri));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "Kênh Âm Thanh Tùy Chỉnh", importance);
// CẤU HÌNH ÂM THANH MẶC ĐỊNH CHO KÊNH (ghi đè bởi setSound)
if (chosenRingtoneUri != null) {
notificationChannel.setSound(Uri.parse(chosenRingtoneUri),
new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build());
}
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
}
// NHẬN KẾT QUẢ TỪ RINGTONE PICKER
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 5 && resultCode == Activity.RESULT_OK && data != null) {
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (uri != null) {
this.chosenRingtoneUri = uri.toString();
Toast.makeText(this, "Đã chọn: " + uri.getLastPathSegment(), Toast.LENGTH_SHORT).show();
} else {
this.chosenRingtoneUri = null;
Toast.makeText(this, "Sử dụng âm thanh mặc định", Toast.LENGTH_SHORT).show();
}
}
}
}
Bước 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>
</intent-filter>
</activity>
</application>
</manifest>
Giải thích chi tiết
1. RingtoneManager.ACTION_RINGTONE_PICKER
Mở hệ thống chọn âm thanh built-in. Các loại:
TYPE_RINGTONE- Nhạc chuông gọiTYPE_NOTIFICATION- Âm thanh thông báo (ngắn)TYPE_ALARM- Báo thứcTYPE_ALL- Tất cả
2. setSound() trên Builder vs Channel
| Phương pháp | Phạm vi | Ưu tiên |
|---|---|---|
builder.setSound(uri) |
Chỉ thông báo này | Cao nhất |
channel.setSound(uri, attributes) |
Tất cả noti trong channel | Thấp hơn builder |
| Notification.DEFAULT_SOUND | Hệ thống mặc định | Thấp nhất |
3. Âm thanh từ file raw/assets
// File: res/raw/custom_sound.mp3
Uri customSound = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.custom_sound);
mBuilder.setSound(customSound);
4. AudioAttributes (API 21+) - Bắt buộc cho Channel sound
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
notificationChannel.setSound(uri, audioAttributes);
Lưu ý quan trọng
- User có thể tắt âm thanh thông báo trong Settings hệ thống
- Do Not Disturb mode có thể chặn âm thanh
- Notification Channel sound chỉ áp dụng cho notification KHÔNG có setSound()
- Trên Android 8+, sound được quản lý bởi Channel, không phải Builder
- File âm thanh nên ngắn (< 5s), format .ogg/.mp3, đặt trong
res/raw/
Chạy thử nghiệm
- Chạy app → Nhấn "Chọn nhạc chuông" → Chọn một âm thanh từ danh sách
- Nhấn "Tạo thông báo với âm thanh đã chọn"
- Nghe âm thanh phát ra (nếu không rung/đèn)
- Thử không chọn → dùng âm thanh mặc định