15

I've seen plenty of examples of how to set a default ringtone, but what I'm more interested in is being able populate a drop down box list filled with the available ringtones on the phone. So the list that people see when they change their ringtone in the android settings, I want to be able to list all of those.

The closest thing I've found is here, but again this is just for setting the default ringtone. Any ideas anyone? It can be in or out of ringtonemanager.

Community
  • 1
  • 1
user877244
  • 171
  • 1
  • 1
  • 5

2 Answers2

27

This will return you the title and uri of all the ringtones available. Do with them what you wish!

public Map<String, String> getNotifications() {
    RingtoneManager manager = new RingtoneManager(this);
    manager.setType(RingtoneManager.TYPE_RINGTONE);
    Cursor cursor = manager.getCursor();

    Map<String, String> list = new HashMap<>();
    while (cursor.moveToNext()) {
        String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
        String notificationUri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX) + "/" + cursor.getString(RingtoneManager.ID_COLUMN_INDEX);

        list.put(notificationTitle, notificationUri);
    }

    return list;
}
olfek
  • 3,210
  • 4
  • 33
  • 49
Murphybro2
  • 2,207
  • 1
  • 22
  • 36
  • 5
    To get correct ringtone uri you need to add a value of cursor.getString(RingtoneManager.ID_COLUMN_INDEX)). So it will be Uri uri = Uri.parse(notificationUri + "/" + cursor.getString(RingtoneManager.ID_COLUMN_INDEX)). After that you can get a ringtone by RingtoneManager.getRingtone(context, uri) and play it, for example. – blyabtroi Oct 14 '15 at 06:54
  • @blyabtroi Thank you. You saved my day! – shinilms Jan 02 '17 at 11:44
  • how to get title/name of ringtone – Sagar Mar 09 '18 at 13:29
16

RingtoneManager is what you are looking for. You just need to use setType to set TYPE_RINGTONE and then iterate over the Cursor provided by getCursor.

This is a working example of an hypothetical method that returns an array of URIs, with the only slight difference that it's looking for alarms instead of ringtones:

RingtoneManager ringtoneMgr = new RingtoneManager(this);
ringtoneMgr.setType(RingtoneManager.TYPE_ALARM);
Cursor alarmsCursor = ringtoneMgr.getCursor();
int alarmsCount = alarmsCursor.getCount();
if (alarmsCount == 0 && !alarmsCursor.moveToFirst()) {
    return null;
}
Uri[] alarms = new Uri[alarmsCount];
while(!alarmsCursor.isAfterLast() && alarmsCursor.moveToNext()) {
    int currentPosition = alarmsCursor.getPosition();
    alarms[currentPosition] = ringtoneMgr.getRingtoneUri(currentPosition);
}
alarmsCursor.close();
return alarms;
Diego
  • 5,326
  • 1
  • 35
  • 32
  • I got a `StaleDataException` (*Attempted to access a cursor after it has been closed.*) when putting the phone to sleep and waking it up again after using this code. Not closing the cursor seems to fix it — I suppose `RingtoneManager` returns a managed cursor? – eflorico Feb 02 '14 at 21:17
  • 1
    @eWolf The `getCursor` [docs](https://developer.android.com/reference/android/media/RingtoneManager.html#getCursor%28%29) state: `The returned cursor will be the same cursor returned each time this method is called, so do not close() the cursor. The cursor can be deactivate() safely. If RingtoneManager(Activity) was not used, the caller should manage the returned cursor through its activity's life cycle to prevent leaking the cursor.` – user650881 Nov 18 '14 at 09:48
  • @user650881: weird thing is that [deactivate](https://developer.android.com/reference/android/database/Cursor.html#deactivate%28%29) is deprecated since API 16 (Android 4.1 JellyBean). [Looking at the code](https://github.com/android/platform_frameworks_base/blob/kitkat-release/media/java/android/media/RingtoneManager.java#L360) it seems like the best solution is to create a new instance of RingtoneManager to have a new valid cursor (or to keep the cursor until it is really used). – Diego Nov 18 '14 at 10:16
  • how to get name/title of ringtone I am using`Ringtone r = RingtoneManager.getRingtone(this, ringtoneURI) String ringToneName = r.getTitle(this)` on oppo I am not getting real name ` – Sagar Mar 09 '18 at 13:31
  • @SagarHudge Its easier like this `rm.getRingtone(rmCursor.position).getTitle(context)` – olfek Jun 14 '18 at 18:30
  • Should be accessing ringtone info like this: `cursor.getString(RingtoneManager.URI_COLUMN_INDEX);`. It is much faster, see answer [here](https://stackoverflow.com/a/29697808/812919) – olfek Dec 15 '18 at 13:41