I am trying to programmatically add a contact in Android. Here is my code:
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int rawContactInsertIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE,"Google")
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME,"user1#gmail.com") .build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID,rawContactInsertIndex)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract
.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,rawContactInsertIndex)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType)
.build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
Context ctx = getApplicationContext();
CharSequence txt = "Contact " + name +" added successfully";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(ctx, txt, duration);
toast.show();
} catch (Exception e) {
Toast.makeText(getApplicationContext(),"error",Toast.LENGTH_LONG).show();
}
Am I doing this correctly? How can I add an account name and account type?
NOTE: I don't have any account created. Is it mandatory to have account in order to add a contact?
Contact API storing contact as an invisible contact: How to make it visible? check this i hope it will be useful!
there is no need of creating any account in the phone!... i think their is some default account to do that!
Related
I don't know what I am doing wrong while inserting contact into phonebook.
here is the code to insert.
public static void AddMultipleContact(Context context, String name , String numbers, String Data4){
ContentResolver resolver = context.getContentResolver();
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int rawContactInsertIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.RawContacts.CONTENT_URI, true))
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.withValue(ContactsContract.RawContacts.SOURCE_ID, sourceId)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers) // Number of the person
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
.build()); // Type of mobile number
android.util.Log.e(TAG, "AddMultipleContact:-------------- NAME = " + name);
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(ContactsContract.RawContacts.Data.MIMETYPE,MIMETYPE)
.withValue(Data.DATA1, sourceId)
.withValue(Data.DATA3, Data4)
.build());
try {
ContentProviderResult[] results = resolver.applyBatch(ContactsContract.AUTHORITY, ops);
}
catch (Exception e) {
e.printStackTrace();
}
}
As you can see i am also printing log for name.
android.util.Log.e(TAG, "AddMultipleContact:-------------- NAME = " + name);
Here i am sending contactName and contactNumber to this method.
the name what I am passing is suppose ex: "A.Bcdef"
but the name what I am seeing in the phonebook is "A. Bcdef"
It is adding extra space after period(.).
Please help me. I am not getting any solution on google, or not able to search exactly what I want to search.
Thanks in advance.
I SOLVED THIS BY Changing this line
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
to
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name)
GIVEN_NAME is taking the same name what we passed as value
There are other parameters like
DISPLAY_NAME, GIVEN_NAME, FAMILY_NAME, PREFIX, MIDDLE_NAME, SUFFIX, PHONETIC_GIVEN_NAME, PHONETIC_MIDDLE_NAME, PHONETIC_FAMILY_NAME, FULL_NAME_STYLE, PHONETIC_NAME_STYLE
I really don't know what actually these all means.
But when i added name as 'Testing,123' while creating a contact, then the name appears to be like '123 Testing'.
So I thought it is automatically thinking like what is 'middleName' and 'lastName' based on SpecialCharacters.
I developing an app in which I need to store data related to a contact.
I list the contacts in a recycleView using a cursor and each itemView has a star button to set the contact as favorite (not the same as the system).
I managed to store the data in ContactsContract.Data, doing this:
private void addContactData(long contactId, String displayName, boolean favorite) {
// displayName same as the value for Contacts.DISPLAY_NAME_PRIMARY
ArrayList<ContentProviderOperation> ops =
new ArrayList<>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, CUSTOM_ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, CUSTOM_ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.CONTACT_ID, contactId)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
.build());
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, CustomData.CONTENT_ITEM_TYPE)
.withValue(CustomData.IS_FAVORITE, favorite)
.build());
try {
ContentProviderResult[] contentProviderResults = cr.applyBatch(ContactsContract.AUTHORITY, ops);
return contactUri;
} catch (RemoteException | OperationApplicationException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
return null;
}
}
The problem I have is when two contacts have the exact same name ej. "Tom" and "Tom" if I press the fav button, is adding a third contact that is even listed in the device contacts app.
Some search guied me to add more data to distinguish the contacts using:
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.build());
// OR
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email)
.build());
And it worked just fine, except if the fields are equals in both contacts. What do I need to avoid this behavior, and Why the CONTACT_ID isn't enough to do this kind of operations?
You need to tell Android to merge the new RawContact you've just created with some (one or more) existing RawContacts.
You do that using the AggregationException table, adding a row for each such "link".
See: https://stackoverflow.com/a/40869351/819355
Code snippet:
Builder builder = ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, yourNewRawContact);
builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, someExistingRawContact);
ContentProviderOperation op = builder.build();
I want my android app's connection to be added in an existing contact. I am sending my all contacts of Phonebook to server(with Name,Phone Number, and Contact ID) to check which contacts are registered for my app. I will send back to client app the contact IDs which are matched.
Now I want to add connection to those contacts in my Phonebook based on those returned IDs.
How can I add app connection by editing the contact based on one of returned contact ID?
Thanks
Try with this code, it will give you desired output
public static void addContact(Context context, MyContact contact) {
ContentResolver resolver = context.getContentResolver();
// add condition that you want to check
String where= RawContacts.ACCOUNT_TYPE + " = ? AND " +RawContacts.DISPLAY_NAME_PRIMARY+"=?";
//values of that condotion
String[] value=new String[] { AccountGeneral.ACCOUNT_TYPE ,contact.name};
resolver.delete(RawContacts.CONTENT_URI, where, value);
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI, true))
.withValue(RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME)
.withValue(RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE)
//.withValue(RawContacts.SOURCE_ID, 12345)
//.withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI, true))
.withValue(RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME)
.withValue(RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE)
.withValue(Settings.UNGROUPED_VISIBLE, 1)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.GIVEN_NAME, contact.name)
.withValue(StructuredName.FAMILY_NAME, contact.lastName)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "12342145")
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, "sample#email.com")
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, MIMETYPE)
.withValue(Data.DATA1, 12345)
.withValue(Data.DATA2, "sample")
.withValue(Data.DATA3, "sample")
.build());
try {
ContentProviderResult[] results = resolver.applyBatch(ContactsContract.AUTHORITY, ops);
i++;
if (results.length == 0)
;
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Account type id
*/
public static final String ACCOUNT_TYPE = "com.test.app";
/**
* Account name
*/
public static final String ACCOUNT_NAME = "Test";
public static void addContact(Context context, User contact) {
ContentResolver resolver = context.getContentResolver();
resolver.delete(RawContacts.CONTENT_URI, RawContacts.ACCOUNT_TYPE
+ " = ?", new String[] { AccountConstants.ACCOUNT_TYPE });
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation
.newInsert(
addCallerIsSyncAdapterParameter(
RawContacts.CONTENT_URI, true))
.withValue(RawContacts.ACCOUNT_NAME,
AccountConstants.ACCOUNT_NAME)
.withValue(RawContacts.ACCOUNT_TYPE,
AccountConstants.ACCOUNT_TYPE)
// .withValue(RawContacts.SOURCE_ID, 12345)
// .withValue(RawContacts.AGGREGATION_MODE,
// RawContacts.AGGREGATION_MODE_DISABLED)
.build());
ops.add(ContentProviderOperation
.newInsert(
addCallerIsSyncAdapterParameter(Settings.CONTENT_URI,
true))
.withValue(RawContacts.ACCOUNT_NAME,
AccountConstants.ACCOUNT_NAME)
.withValue(RawContacts.ACCOUNT_TYPE,
AccountConstants.ACCOUNT_TYPE)
.withValue(Settings.UNGROUPED_VISIBLE, 1).build());
ops.add(ContentProviderOperation
.newInsert(
addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.GIVEN_NAME, contact.getFullname())
.withValue(StructuredName.FAMILY_NAME, contact.getFullname())
.build());
ops.add(ContentProviderOperation
.newInsert(
addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,
contact.getPhoneNumber()).build());
ops.add(ContentProviderOperation
.newInsert(
addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA,
contact.getEmail()).build());
ops.add(ContentProviderOperation
.newInsert(
addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, MIMETYPE)
.withValue(Data.DATA1, contact.getFullname())
.withValue(Data.DATA2, contact.getEmail())
.withValue(Data.DATA3, contact.getHomeAddress()).build());
try {
ContentProviderResult[] results = resolver.applyBatch(
ContactsContract.AUTHORITY, ops);
if (results.length == 0)
AppLog.d(TAG, "Failed to add.");
} catch (Exception e) {
AppLog.e(TAG, e.getMessage(), e);
}
}
Problem - Currently the code is adding new contact but not merging it into existing contact based on Phone number. Is there anything I have to do before adding the contact? I would like to display my app account inside Contact same as Whats App.
I have implemented SyncService, SyncAdapter, Authenticator, contacts.xml and other classes required for the project. The only thing not working is showing contact inside the default Contact app instead of creating new contact.
<ContactsSource xmlns:android="http://schemas.android.com/apk/res/android" >
<ContactsDataKind
android:detailColumn="data2"
android:detailSocialSummary="true"
android:icon="#drawable/ic_launcher"
android:mimeType="vnd.android.cursor.item/com.test.app"
android:summaryColumn="data3" />
</ContactsSource>
I had the same problem on Android 6.1 and as I heard, this issue is present since Lollipop. Every implementation on the web shows that the contact matching should work based on phone number. And it works on earlier systems - I tried it on KitKat and it works like a charm. But since Android 5.0 contacts don't match somehow.
Fortunately phone number is not the only parameter the matching depends on - there is also displayname. So the working implementation should look like this:
// as displayName pass the retrieved ContactsContract.Contacts.DISPLAY_NAME
#Override
public void addContact(#Nonnull final String displayName, #Nonnull final String phone) {
final ContentResolver resolver = context.getContentResolver();
final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.RawContacts.CONTENT_URI, true))
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.build());
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.build());
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
.build());
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, YOUR_MIMETYPE)
.withValue(ContactsContract.Data.DATA1, 12345)
.withValue(ContactsContract.Data.DATA2, "user")
.withValue(ContactsContract.Data.DATA3, "action")
.build());
try {
resolver.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
}
}
I left the phoneNumber in case the contact doesn't have any displayname - then it would at least match on earlier Android versions.
i want to enter contact list: "contact_name" , and "contact_number" into phone's contact list i used following code for that :
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
//------------------------------------------------------ Names
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name).build());
//------------------------------------------------------ Mobile Number
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
.build());
// Asking the Contact provider to create a new
// contact
try
{
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
}
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Exception: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
it run successfully, but i want to prevent insertion of duplicate entry,
for that i have used below link but could not find out proper solution
contact exists in contacts