Giới thiệu
Ví dụ này minh họa cách mở giao diện hệ thống để người dùng chọn âm thanh thông báo (notification sound) từ danh sách có sẵn. Sử dụng RingtoneManager.ACTION_RINGTONE_PICKER với type TYPE_NOTIFICATION.
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 (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="Mở danh sách âm thanh" />
<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 test âm thanh" />
</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;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
private String selectedRingtoneUri = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// MỞ DANH SÁCH ÂM THANH THÔNG BÁO HỆ THỐNG
public void setRingtone(View view) {
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
// CHỈ HIỂN THỊ ÂM THANH LOẠI NOTIFICATION
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Chọn âm thanh thông báo");
// HIỂN THỊ LỰA CHỌN HIỆN TẠI (NẾU CÓ)
if (selectedRingtoneUri != null) {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(selectedRingtoneUri));
} else {
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, (Uri) null);
}
// KHÔNG CHO PHÉP CHỌN "SILENT" (TÙY CHỌN)
// intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
// KHÔNG CHO PHÉP CHỌN "DEFAULT" (TÙY CHỌN)
// intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
startActivityForResult(intent, 100); // Request code 100
}
// TẠO THÔNG BÁO ĐỂ TEST ÂM THANH
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("Test Âm Thanh");
mBuilder.setContentText(selectedRingtoneUri != null ? "Âm thanh tùy chỉnh" : "Âm thanh mặc định");
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
// ÁP DỤNG ÂM THANH ĐÃ CHỌN
if (selectedRingtoneUri != null) {
mBuilder.setSound(Uri.parse(selectedRingtoneUri));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "Test Sound Channel", importance);
// CẤU HÌNH SOUND CHO CHANNEL (OPTIONAL)
if (selectedRingtoneUri != null) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
notificationChannel.setSound(Uri.parse(selectedRingtoneUri), audioAttributes);
}
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
Toast.makeText(this, "Đã gửi thông báo test", Toast.LENGTH_SHORT).show();
}
// XỬ LÝ KẾT QUẢ CHỌN ÂM THANH
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100 && resultCode == Activity.RESULT_OK && data != null) {
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (uri != null) {
this.selectedRingtoneUri = uri.toString();
String name = uri.getLastPathSegment();
Toast.makeText(this, "Đã chọn: " + name, Toast.LENGTH_LONG).show();
} else {
// User chọn "Default ringtone" hoặc "Silent"
this.selectedRingtoneUri = null;
Toast.makeText(this, "Sử dụng âm thanh mặc định", Toast.LENGTH_SHORT).show();
}
} else if (requestCode == 100 && resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(this, "Đã hủy chọn âm thanh", 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>
Các Extra quan trọng của RingtonePicker
| Extra | Loại | Mô tả |
|---|---|---|
EXTRA_RINGTONE_TYPE |
int | Loại: TYPE_RINGTONE, TYPE_NOTIFICATION, TYPE_ALARM, TYPE_ALL |
EXTRA_RINGTONE_TITLE |
String | Tiêu đề dialog chọn |
EXTRA_RINGTONE_EXISTING_URI |
Uri | Uri đang chọn (để highlight) |
EXTRA_RINGTONE_SHOW_DEFAULT |
boolean | Hiện mục "Default" (mặc định true) |
EXTRA_RINGTONE_SHOW_SILENT |
boolean | Hiện mục "Silent" (mặc định true) |
EXTRA_RINGTONE_PICKED_URI |
Uri (return) | Uri user đã chọn (trả về trong onActivityResult) |
Lưu trữ lựa chọn người dùng
// Lưu vào SharedPreferences
SharedPreferences prefs = getSharedPreferences("settings", MODE_PRIVATE);
prefs.edit().putString("notification_sound_uri", selectedRingtoneUri).apply();
// Khôi phục
String savedUri = prefs.getString("notification_sound_uri", null);
if (savedUri != null) {
selectedRingtoneUri = savedUri;
}
Áp dụng cho Notification Channel (Android 8+)
// Khi tạo channel
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Tên kênh", IMPORTANCE_HIGH);
if (selectedRingtoneUri != null) {
AudioAttributes attrs = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
channel.setSound(Uri.parse(selectedRingtoneUri), attrs);
}
notificationManager.createNotificationChannel(channel);
Chạy thử nghiệm
- Chạy app trên thiết bị thật
- Nhấn "Mở danh sách âm thanh" → Chọn một âm thanh từ danh sách hệ thống
- Nhấn "Tạo thông báo test âm thanh"
- Nghe âm thanh phát ra (nếu thiết bị không ở chế độ Do Not Disturb/Silent)
Lưu ý
- Emulator thường không phát âm thanh → test trên thiết bị thật
- Danh sách âm thanh phụ thuộc vào OEM (Samsung, Xiaomi, Pixel khác nhau)
- User có thể thêm âm thanh riêng vào thư mục
Notifications/trên storage - Từ Android 12, có thể dùng
MediaStoređể liệt kê âm thanh tùy chỉnh