I have made an contact application. I am able to delete contact from samsung and moto but in MI(XIOMI) unable to delete contact. It display popup with message "Contact can't delete by third party apps. My code
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
String[] args = new String[]{id};
ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
.withSelection(ContactsContract.RawContacts.CONTACT_ID + "=?", args).build());
try {
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException | OperationApplicationException e) {
}
Was the RawContact created on your app's Account using your SyncAdapter?
Anyway, try this:
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
rawContactUri = rawContactUri.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
ContentProviderOperation.newDelete(rawContactUri).build();
Related
I am trying to delete a contact from phone contacts. The contact gets deleted from phone contacts but it's not getting deleted from the server-side (Google contacts) and when the Google contact sync triggers then that deleted contact re-appears. Below is my code.
public static void deleteContact(long rawid, ContentResolver contentResolver) {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
Uri uri = ContactsContract.RawContacts.CONTENT_URI
.buildUpon()
.appendQueryParameter(
ContactsContract.CALLER_IS_SYNCADAPTER,
"true")
.build();
ops.add(ContentProviderOperation
.newDelete(uri)
.withSelection(
ContactsContract.RawContacts._ID + " = ?",
new String[]{Long.toString(rawid)})
.build());
try {
contentResolver.applyBatch(
ContactsContract.AUTHORITY,
ops);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
}
}
You should try with ContactsContract.CALLER_IS_SYNCADAPTER as false in your code. While set to true, the contact is permanently deleted from the database. But when the next sync happens the contact is synched back. How Google sync checks for deleted contacts, is using a deleted flag which is set only if you set ContactsContract.CALLER_IS_SYNCADAPTER as false. Below is a snippet of code from the ContactsProvider class (contentprovider for contacts datastore)
if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) {
// When a raw contact is deleted, a SQLite trigger deletes the parent contact.
// TODO: all contact deletes was consolidated into ContactTableUtil but this one can't
// because it's in a trigger. Consider removing trigger and replacing with java code.
// This has to happen before the raw contact is deleted since it relies on the number
// of raw contacts.
db.delete(Tables.PRESENCE, PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null);
count = db.delete(Tables.RAW_CONTACTS, RawContacts._ID + "=" + rawContactId, null);
mTransactionContext.get().markRawContactChangedOrDeletedOrInserted(rawContactId);
} else {
count = markRawContactAsDeleted(db, rawContactId, callerIsSyncAdapter);
}
I'm trying to add my application icon to all existing contacts . my intent is to get contact by tapping user on my application icon to open app and send this contact to cloud. i could create contact by application and add my app MimeType to this and get save contact but i want to update all existing contact with my app icon this is my code that inserts my app mimeType to all contacts but it doesn`t work
Cursor cursor = context.getContentResolver().query(Data.CONTENT_URI, new String[] { Data.RAW_CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.CONTACT_ID },
null,
null,
null);
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
do {// get id of contact and update all contact
id = cursor.getInt(0);
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, id)
.withValue(ContactsContract.Data.MIMETYPE, MIMETYPE)
.withValue(Data.DATA1, "profile1")
.withValue(Data.DATA2, "profile2")
.withValue(Data.DATA3, "profile3")
.build());
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e1) {
e1.printStackTrace();
Log.i("Error =>>" + e1.getMessage());
}
while(cursor.moveNext())
and please help me!thanks
You can check this link. There's helpful example.
https://github.com/nemezis/SampleContacts/tree/master/src/com/nemezis/sample/contacts
How do I update the display name for a contact? The operation in the code below completes without throwing anything and appears to work - that is, when I requeried the ContactsContract.Contact table, a row came back with the name changed. However, when I tried running the stock "people" app on my tablet, it crashed. Evidentally I did something wrong.
Here is the code. Early on, it fetches an id from the aggregate contacts as follows, where key is the lookup_key:
String[] projection = new String[] {
Contacts._ID, // 0
Contacts.DISPLAY_NAME, // 1
};
Uri uri = Uri.parse (Contacts.CONTENT_LOOKUP_URI + "/" + key);
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query (uri, projection, null, null, null);
if (!cursor.moveToNext()) // move to first (and only) row.
throw new IllegalStateException ("contact no longer exists for key");
origId = cursor.getLong(0);
cursor.close();
Then, after the user has done his edits, I call this block of code to update the display_name:
ArrayList<ContentProviderOperation> opers = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
String[] args = { Long.toString (origId) };
builder = ContentProviderOperation.newUpdate (Data.CONTENT_URI);
builder.withSelection (RawContacts.CONTACT_ID + "=?", args);
builder.withValue(CommonDataKinds.StructuredName.DISPLAY_NAME, name);
opers.add(builder.build());
ContentProviderResult[] results = null;
try {
results = getContentResolver().applyBatch(ContactsContract.AUTHORITY, opers);
} catch ...
I realize I don't need the ContentProviderOperation for this example; that's for later when I have more stuff to update.
To be honest, I'm pretty confused about which ID I'm actually using. The names aren't that clear to me and I may be using the wrong ID for this operation.
For what it's worth, looking at results after the update I saw a result code of 5. I can't find any documentation for that, so have no idea if that is significant.
The IDs (and altering contacts in general) can be pretty confusing... I had some dramas getting my head around them as well.
Here is some working code I use for updating. The main difference I can see is how you are declaring the raw ID; it needs to be included in as a content value.
Cursor cursor = _context.getContentResolver().query(contactUri,
new String[] { Contacts._ID }, null, null, null);
try {
if (cursor.moveToFirst()) {
String rawContactId = cursor.getString(0);
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ContentValues contentValues = new ContentValues();
contentValues.put(Data.RAW_CONTACT_ID, rawContactId);
contentValues
.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
contentValues.put(
ContactsContract.CommonDataKinds.Phone.NUMBER,
phoneNumber);
contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_WORK);
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValues(contentValues).build());
String contactId = contactUri.getLastPathSegment();
ops.add(ContentProviderOperation
.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.CONTACT_ID
+ "=? AND "
+ ContactsContract.Data.MIMETYPE
+ "=?",
new String[] {
contactId,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE })
.withValue(
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
newName).build());
result = _context.getContentResolver().applyBatch(
ContactsContract.AUTHORITY, ops);
}
} finally {
cursor.close();
}
hopefully it helps!
Answer above is generally correct. However, when I inserted
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
and then tried to do newUpdate
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME
with code as above - it made contact displayed in Contacts app with name mixed of old and new data. I found out inserting and updating ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME for example works as I expect. In Contacts app on my Android 4x when editing contact I cannot see family and given separately, look to me DISPLAY_NAME is made of them by Android.
iam adding a contact to the device using this code
long Contact_Id = 100;
ContentValues pCV =new ContentValues();
pCV.put(Contacts.People.NAME, "test");
pCV.put(ContactsContract.Contacts._ID, Contact_Id);
Uri newContactUri = insertContentValues(cResolver,
Contacts.People.CONTENT_URI, pCV);
i want to add this contact to a certain Account. iam using this code below
ContentResolver cResolver = context.getContentResolver();
cResolver.insert(uri, ContactsContract.RawContacts.CONTENT_URI,
getAccountType());
public ContentValues getAccountType() {
ContentValues cv = new ContentValues();
cv.put(ContactsContract.RawContacts.ACCOUNT_TYPE, "com.sonyericsson.localcontacts");
cv.put(ContactsContract.RawContacts.ACCOUNT_NAME, "Phone contacts");
return cv;
}
this code actually is adding a new contact to the "Phone contacts" Account. but i want to add the contact that i added above ("test") to be added to the "Phone contacts".
how can i do so?
You can try both the solution as per your choice/requirement.Both are working perfectly
To add contact open directly edit activity
try {
Intent addContactIntent = new Intent(Intent.ACTION_INSERT);
addContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
addContactIntent.putExtra(ContactsContract.Intents.Insert.PHONE, number);
addContactIntent.putExtra("finishActivityOnSaveCompleted", true);
context.startActivity(addContactIntent);
} catch (Exception e) {
e.printStackTrace();
}
option to create contact or add contact to existing contact
try {
Intent i = new Intent(Intent.ACTION_INSERT_OR_EDIT);
i.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
// i.putExtra(ContactsContract.Intents.Insert.NAME, "TESTTEST");
i.putExtra(ContactsContract.Intents.Insert.PHONE, number);
context.startActivity(i);
} catch (Exception e) {
e.printStackTrace();
}
After searching I have found that the best way to insert a Contact to the Local Phone contacts is to assign the ACCOUNT_TYPE, ACCOUNT_NAME to null take a look at this Link
I want to create a new contact group. I can query the group and display all the group names but I can't create a group in android I tried as creating contacts method but not created...
ContentResolver cr = this.getContentResolver();
groupValues = new ContentValues();
Log.e("Group","start");
groupValues.put(android.provider.Contacts.GroupMembership.GROUP_ID, 4);
groupValues.put(android.provider.Contacts.GroupMembership.NAME, "Sriseshaa");
groupValues.put(android.provider.Contacts.GroupMembership.PERSON_ID, 1);
cr.insert(android.provider.Contacts.GroupMembership.CONTENT_URI, groupValues);
i found the answer.i found in two ways but i dont know which is correct or best way to use.i am sharing those here..
its simple way like adding contact,
ContentValues groupValues;
create group()
{
ContentResolver cr = this.getContentResolver();
groupValues = new ContentValues();
groupValues.put(ContactsContract.Groups.TITLE, "MyContactGroup");
cr.insert(ContactsContract.Groups.CONTENT_URI, groupValues);
}
Another method using ContentProviderOperation
private void createGroup() {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Groups.CONTENT_URI)
.withValue(ContactsContract.Groups.TITLE, "SRI").build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
Log.e("Error", e.toString());
}
}
Thanks
adithi's answer is enough for Android 4.2.2, in which the name of Contacts manager application is "Contacts" , but the group created by that code will not show on Android 4.4,6 in which the name of Contacts manager application is "People".
The group would show up after adding the account type/name information while insertion happens.
private void createGroup() {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Groups.CONTENT_URI)
.withValue(
ContactsContract.Groups.TITLE,
Constants.CC_CONTACT_GROUP_TITLE)
.withValue(
ContactsContract.Groups.ACCOUNT_TYPE,
Constants.CC_CONTACT_GROUP_ACCOUNT_TYPE)
.withValue(
ContactsContract.Groups.ACCOUNT_NAME,
Constants.CC_CONTACT_GROUP_ACCOUNT_NAME)
.build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
Log.e("Error", e.toString());
}
}
Why are you specifying group ID with groupValues.put(android.provider.Contacts.GroupMembership.GROUP_ID, 4); Its androids job to determined the group ID, you cant specify it because you don't know whether this id is already taken or not.