[SOLVED] Setting custom_ringtone on contact works on some android phones and not others


This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under
CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

Issue

The problem is that contact gets assigned a ringtone on xiaomi phone android 8.0 but not on a samsung phone with the same android version. In both phones, it displays a toast that ringtone has been set successfully but when I call on xiaomi phone, ringtone is changed but when I call on samsung phone, ringtone is the default one.

Here is the relevant code:

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

RingtoneActivity.java

setRingtoneContact is called when user taps a button to set contact ringtone.

static  final int PICK_CONTACT=1;

public void setRingtoneContact(String pathString){

    // contact_selected_ringtone is a global variable
    contact_selected_ringtone = pathString;

    Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
    startActivityForResult(intent, PICK_CONTACT);

}

User selects a contact and we receive result in onActivityResult.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT) {
        String phoneNo = null;
        String name = null;

        Uri uri = data.getData();
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);

        if (cursor.moveToFirst()) {
            int phoneIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
            int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);

            phoneNo = cursor.getString(phoneIndex);
            name = cursor.getString(nameIndex);

            Log.e("onActivityResult()", phoneIndex + " " + phoneNo + " " + nameIndex + " " + name);

            setForContact(phoneNo);

        }
        cursor.close();
    }
}

This is the function which actually sets the custom_ringtone for a contact.

public void setForContact(String contact){
    // The Uri used to look up a contact by phone number
    final Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, contact);
    // The columns used for `Contacts.getLookupUri`
    final String[] projection = new String[] {
            ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY
    };

    final Cursor data = getContentResolver().query(lookupUri, projection, null, null, null);
    data.moveToFirst();
    try {
        // Get the contact lookup Uri
        final long contactId = data.getLong(0);
        final String lookupKey = data.getString(1);
        final Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
        if (contactUri == null) {
            // Invalid arguments
            return;
        }
        final File file = new File(contact_selected_ringtone);
        if (file.exists()){
            final String value = Uri.fromFile(file).toString();

            final ContentValues values = new ContentValues(1);
            values.put(ContactsContract.Contacts.CUSTOM_RINGTONE, value);
            try {
                int rows = getContentResolver().update(contactUri, values, null, null);
                if (rows > 0) {
                    Toasty.info(getApplicationContext(),getResources().getString(R.string.ringtone_contact_success),Toast.LENGTH_LONG).show();
                }
            } catch (NullPointerException ex) {
                Log.e("contact_exception", ex.toString());
            }

        }else{
            Toast.makeText(this, "file not exist", Toast.LENGTH_SHORT).show();
        }
    } finally {

        data.close();
    }
}

We’ve been at this problem for 2 days now, and we researched everywhere. There were some questions on stackoverflow too, which were doing this same thing. This solution works, but not on all phones. Hoping for a solution.

This is my first question on stackoverflow so please guide me if I’m not following guidelines.

Solution

Well, I solved this problem. I’m posting the solution here.

I changed the setForContact function in RingtoneActivity.java. Here’s the code:

public void setForContact(String contact){
    // Create File object for the specified ring tone path
    // contact_selected_ringtone is a global variable which has the full path to ringtone
    File f=new File(contact_selected_ringtone);

    // Insert the ring tone to the content provider
    ContentValues content_value=new ContentValues();
    content_value.put(MediaStore.MediaColumns.DATA, f.getAbsolutePath());
    content_value.put(MediaStore.MediaColumns.TITLE, f.getName());
    content_value.put(MediaStore.MediaColumns.SIZE, f.length());
    content_value.put(MediaStore.MediaColumns.MIME_TYPE,"audio/mp3");
    content_value.put(MediaStore.Audio.Media.ARTIST, getString(R.string.app_name));
    content_value.put(MediaStore.Audio.Media.IS_ALARM, false);
    content_value.put(MediaStore.Audio.Media.IS_MUSIC, false);
    content_value.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
    content_value.put(MediaStore.Audio.Media.IS_RINGTONE, true);

    Uri uri = MediaStore.Audio.Media.getContentUriForPath(f.getAbsolutePath());
    getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "="" + f.getAbsolutePath() + """, null);

    Uri newUri = getContentResolver().insert(uri, content_value);

    // The Uri used to look up a contact by phone number
    final Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, contact);

    final String[] projection = new String[] {
            ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY
    };

    final Cursor data = getContentResolver().query(lookupUri, projection, null, null, null);
    data.moveToFirst();
    try {
        // Get the contact lookup Uri
        final long contactId = data.getLong(0);
        final String lookupKey = data.getString(1);
        final Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
        String str = data.getString(data.getColumnIndexOrThrow("_id"));
        Uri localUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, str);
        if (contactUri == null) {
            // Invalid arguments
            return;
        }

        final File file = new File(contact_selected_ringtone);
        final String value = Uri.fromFile(file).toString();

        // Apply the custom ringtone_app
        final ContentValues values = new ContentValues();
        values.put(ContactsContract.Data.RAW_CONTACT_ID, contactId);
        values.put(ContactsContract.Data.CUSTOM_RINGTONE, newUri.toString());
        try {
            int rows = getContentResolver().update(localUri, values, null, null);
            if (rows > 0) {
                Toasty.info(getApplicationContext(),getResources().getString(R.string.ringtone_contact_success),Toast.LENGTH_LONG).show();
            }
        } catch (NullPointerException ex) {
            Log.e("contact_exception", ex.toString());
        }

    } finally {
        data.close();
    }
}

Hope it helps someone else.

Answered By – Oukaasha Habib

people found this article helpful. What about you?