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
Answer Checked By - Willingham (JavaFixing Volunteer)