How can I set a ringtone for an individual contact on Android?

How can I apply a ringtone to only the selected contact?

I have found a way to set the default ringtone that applies to all contacts, but that is not my goal.

I want an application to have a button ("Apply ringtone to contact") that, when clicked, starts an activityForResult displaying a list of all contacts on the phone. When a contact is selected, the contact activity closes and returns with a URI to the contact. Then the app needs to apply the selected ringtone to that specific contact.

The code for displaying and selecting contacts by an activity is already implemented and seems to work on the app.


You can use ContactsContract.Contacts which has a column CUSTOM_RINGTONE (which is a read/write column!) for this purpose.

Uri contactUri;
ContentValues values = new ContentValues();
values.put(ContactsContract.Contacts.CUSTOM_RINGTONE, 
    newRingtoneUri.toString());
context.getContentResolver().update(contactUri, values, where, args);

Furthermore, you may find this discussion useful (code taken from there).


I know this was so late, but i'm posting here because above one not worked for me

ContentValues values = new ContentValues();

    ContentResolver resolver = getContentResolver();

    File file = new File(Environment.getExternalStorageDirectory() + "/Test/ArjunMovieTelugu.mp3");
    if(file.exists()) {

        Uri oldUri = MediaStore.Audio.Media.getContentUriForPath(file.getAbsolutePath());
        resolver.delete(oldUri, MediaStore.MediaColumns.DATA + "=\"" + file.getAbsolutePath() + "\"", null);


        String contact_number = "CONTACT_NUMBER";
        Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, contact_number);

        // The columns used for `Contacts.getLookupUri`
        String[] projection = new String[]{
                ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY
        };

        Cursor data = getContentResolver().query(lookupUri, projection, null, null, null);

        if (data != null && data.moveToFirst()) {
            data.moveToFirst();
            // Get the contact lookup Uri
            long contactId = data.getLong(0);
            String lookupKey = data.getString(1);
            Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);

            values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
            values.put(MediaStore.MediaColumns.TITLE, "Beautiful");
            values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
            values.put(MediaStore.Audio.Media.IS_RINGTONE, true);

            Uri uri = MediaStore.Audio.Media.getContentUriForPath(file.getAbsolutePath());
            Uri newUri = resolver.insert(uri, values);

            if(newUri != null){
                String uriString = newUri.toString();
                values.put(ContactsContract.Contacts.CUSTOM_RINGTONE, uriString);
                Log.e("Uri String for " + ContactsContract.Contacts.CONTENT_URI, uriString);
                long updated = resolver.update(contactUri, values,null, null);

                Toast.makeText(RingtoneChange.this, "Updated : " + updated, Toast.LENGTH_LONG).show();
            }

            data.close();
        }


    } else {
        Toast.makeText(RingtoneChange.this, "File does not exist", Toast.LENGTH_LONG).show();
    }

Note: We have to add runtime permissions for marsh mallow as

int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;

private  boolean checkAndRequestPermissions() {
int readExternal = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
int writeExternal = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readContacts = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS);
int writeContacts = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_CONTACTS);

List<String> listPermissionsNeeded = new ArrayList<>();

if (readExternal != PackageManager.PERMISSION_GRANTED) {
    listPermissionsNeeded.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (writeExternal != PackageManager.PERMISSION_GRANTED) {
    listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (readContacts != PackageManager.PERMISSION_GRANTED) {
    listPermissionsNeeded.add(android.Manifest.permission.READ_CONTACTS);

}
if (writeContacts != PackageManager.PERMISSION_GRANTED) {
    listPermissionsNeeded.add(android.Manifest.permission.WRITE_CONTACTS);

}

if (!listPermissionsNeeded.isEmpty()){
    ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray
            (new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
    return false;
}
return true;
}

and also include all these permissions in Manifest file as

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />