Add app link in existing contact profile android - android

I am working on a application where i need to add my app link just like freecharge or whatspp in phone's existing contact profile without creating new.
I tried doing this with the following code
public static void addContactTag(Context context, String number) {
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
// Create our RawContact
ContentProviderOperation.Builder builder = ContentProviderOperation
.newInsert(RawContacts.CONTENT_URI);
builder.withValue(RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME);
builder.withValue(RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE);
operationList.add(builder.build());
// Create a Data record of common type 'Phone' for our RawContact
builder = ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, number);
operationList.add(builder.build());
// Create a Data record of custom type
// "vnd.android.cursor.item/vnd.be.ourservice.profile" to display a link
// to our profile
builder = ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, MIMETYPE);
builder.withValue(ContactsContract.Data.DATA1, number);
builder.withValue(ContactsContract.Data.DATA3, "My app");
operationList.add(builder.build());
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY,
operationList);
Log.i("addContact batch applied");
} catch (Exception e) {
Log.i("Something went wrong during creation! " + e);
e.printStackTrace();
}
}
Everything seems fine but its not updating existing contact rather its creating a new one .
Any help will be appreciated.
Thanks in advance.

The code you mentioned here is meant to write a new contact.to edit a current contact you should do something like this.
try {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(ContactsContract.CommonDataKinds.Phone._ID + "=? AND " +
Data.MIMETYPE + "='" +
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'",
new String[]{contact_id})
.withValue(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, "anything")
.build());
ContentProviderResult[] result = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
Log.w("UpdateContact", e.getMessage()+"");
for(StackTraceElement ste : e.getStackTrace()) {
Log.w("UpdateContact", "\t" + ste.toString());
}
Context ctx = getApplicationContext();
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(ctx, "Update failed", duration);
toast.show();
}
If you haven't figured this out yet, give that a go. I found updating contacts to be very tricky in getting the selection arguments right.
Accept and mark it up if this helps.
Happy coding :)

Related

Contact display name is not get edited in Android

I am trying to Edit Specific Contact's display name, but whatever I do, display name is not getting edited. I have looked all related questions, but I did not find any solution regarding this issue.
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=? AND " +
ContactsContract.CommonDataKinds.Phone.MIMETYPE + "='" +
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND "+ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID +"=?",
new String[]{id,raw})
//.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "B "+name)
//.withValue(ContactsContract.CommonDataKinds.Phone.PHONETIC_NAME, "B "+name)
//.withValue(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, "B "+name)
//.withValue(ContactsContract.Data.DISPLAY_NAME, "B "+name)
.withValue(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, "B "+name)
.build());
try {
ContentProviderResult[] result =HomeActivity.this.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
Log.e("Edit Result",result.toString());
} catch (RemoteException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
I have tried all option which are written in comments, but with ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME. It edits contact No. instead of contact name. I am trying to do this for the last 3 days, but not getting success. Please tell me what I'm doing wrong or show me the right way of editing contact name.
The name is stored in contacts database with STRUCTURED_NAME mime type. More information here
You should modify your code like this
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=? AND " +
ContactsContract.CommonDataKinds.Phone.MIMETYPE + "='" +
ContactsContract.CommonDataKinds.StructuredName + "' AND "+ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID +"=?",
new String[]{id,raw})
.withValue(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, "B "+name)
.build());
try {
ContentProviderResult[] result =HomeActivity.this.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
Log.e("Edit Result",result.toString());
} catch (RemoteException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
I would suggest that you pull out the contacts database from an emulator or a rooted phone to get a better understanding.

DIRTY in RawContacts Android

I'm new in Android and O'm trying to understand how the contacts is working on Android so please bear with me.
I implemented an Observer to observe this URI, ContactsContract.Contacts.CONTENT_URI or ContactsContract.RawContacts.CONTENT_URI.
I am getting notified, and then I query the RawContact like below to get the dirty fields,
Cursor cursor = contResv.query(ContactsContract.RawContacts.CONTENT_URI,
null, ContactsContract.RawContacts.DIRTY + " = ?", new String[] { "1" }, null);
and I do get the accounts that have been changed (Version changed) or deleted. But what I have noticed is that after few seconds I'm getting notified again but this time the dirty rows that I have been notified about in the first time are removed, the DIRTY seems to be cleared after some Sync or something.
How can I guarantee that I will get the dirty rows before it's getting updated?
Because I'm afraid that if my app restarted for some reason and then came back up and then got notified, it won't get the dirty rows as it got cleared during the restart, or any other race condition scenario.
Edit 1
After digging for few hours I think I will need to create a raw contact with the same display name. The reason for this is that I think if I do this Android will think that I'm a sync adapter and will make this raw contact entry dirty and it want be cleaned unless I do so.
I'm trying this but it's not working, taken from here
private void addContact(String accountName, String accountType,
String name, String username) {
Log.i(Commons.TAG, "Adding contact: " + name);
ArrayList operationList = new ArrayList();
ContentProviderOperation.Builder builder = ContentProviderOperation .newInsert(RawContacts.CONTENT_URI);
builder.withValue(RawContacts.ACCOUNT_NAME, null);
builder.withValue(RawContacts.ACCOUNT_TYPE, null);
//builder.withValue(RawContacts.SYNC1, username);
operationList.add(builder.build());
builder = ContentProviderOperation .newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference( ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue( ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
operationList.add(builder.build());
try {
ContentResolver mContentResolver = ContactsUpdateService.this.getContentResolver();
mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
Log.e(Commons.TAG, "Something went wrong during creation! " + e);
e.printStackTrace();
}
}
This one didn't help also
private void addContact(String accountName, String accountType,
String name, String username) {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
int rawContactInsertIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
.withValue(RawContacts.ACCOUNT_TYPE, accountType)
.withValue(RawContacts.ACCOUNT_NAME, accountName).build());
ops.add(ContentProviderOperation
.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.DISPLAY_NAME, name)
.withValue(Phone.NUMBER, "09876543")
.build());
try {
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Update multiple phone numbers in contact

I am tried to update multiple phone numbers of specific contact using following
code:
for(int j=0;j<allPhoneNumbersLength;j++)
{
PhoneInfo phoneInfo = (PhoneInfo) allPhoneNumbers.elementAt(j);
String phoneValue = phoneInfo.getValue();
int phoneType = phoneInfo.getIndex(); // phoneType = Phone.TYPE_HOME, Phone.TYPE_WORK, etc
ContentProviderOperation.Builder builderPhone = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(ContactsContract.Data.CONTACT_ID + "=?"+" AND "+ContactsContract.Data.MIMETYPE + "=?" + " AND "+Phone.TYPE+"=?", new String[]{String.valueOf(contactID), Phone.CONTENT_ITEM_TYPE, String.valueOf(phoneType)});
if(phoneType == Phone.TYPE_HOME)
{
builderPhone.withValue(Phone.NUMBER, phoneValue)
.withValue(Phone.TYPE, Phone.TYPE_HOME);
}
else if(phoneType == Phone.TYPE_WORK)
{
builderPhone.withValue(Phone.NUMBER, phoneValue)
.withValue(Phone.TYPE, Phone.TYPE_WORK);
}
else if(phoneType == Phone.TYPE_FAX_HOME)
{
builderPhone.withValue(Phone.NUMBER, phoneValue)
.withValue(Phone.TYPE, Phone.TYPE_FAX_HOME);
}
op_list.add(builderPhone.build());
}
getContentResolver().applyBatch(ContactsContract.AUTHORITY, op_list);
Using this code I am trying to update three numbers, but only "TYPE_FAX_HOME"
number is updated and other two numbers are removed from contact.
Please help me.
I've learnt from your code that, you're using the same phone number value for all the 3 types. Hence, while displaying, android will display only 1 of them for the contact. But if you actually edit the contact, there you can see that, all the 3 types have been populated with the same number.
P.S: I'm assuming that the contact for which you're trying to do the edit, already has some number populated for all the 3 types. If not, please create them and then try running your code.
Wow ... ! why you use the "if" statement ?!
your code could be like this :
for(int j=0;j<allPhoneNumbersLength;j++)
{
PhoneInfo phoneInfo = (PhoneInfo) allPhoneNumbers.elementAt(j);
int phoneType = phoneInfo.getIndex(); // phoneType = Phone.TYPE_HOME, Phone.TYPE_WORK, etc
ContentProviderOperation.Builder builderPhone = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(ContactsContract.Data.CONTACT_ID + "=?"+" AND "+ContactsContract.Data.MIMETYPE + "=?" + " AND "+Phone.TYPE+"=?", new String[]{String.valueOf(contactID), Phone.CONTENT_ITEM_TYPE, String.valueOf(phoneType)});
builderPhone.withValue(Phone.NUMBER, phoneValue)
.withValue(Phone.TYPE, phoneType);
op_list.add(builderPhone.build());
}
getContentResolver().applyBatch(ContactsContract.AUTHORITY, op_list);
I'm not Android programmer but i think the problem is in last line of code , the loop update the contact info in each step but not apply it , at the end step of the loop apply update and the last changes should be apply , if you change your code like this i think it should work , it means for each loop's step the contact info will update :
for(int j=0;j<allPhoneNumbersLength;j++)
{
PhoneInfo phoneInfo = (PhoneInfo) allPhoneNumbers.elementAt(j);
int phoneType = phoneInfo.getIndex(); // phoneType = Phone.TYPE_HOME, Phone.TYPE_WORK, etc
ContentProviderOperation.Builder builderPhone = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(ContactsContract.Data.CONTACT_ID + "=?"+" AND "+ContactsContract.Data.MIMETYPE + "=?" + " AND "+Phone.TYPE+"=?", new String[]{String.valueOf(contactID), Phone.CONTENT_ITEM_TYPE, String.valueOf(phoneType)});
builderPhone.withValue(Phone.NUMBER, phoneValue)
.withValue(Phone.TYPE, phoneType);
op_list.add(builderPhone.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, op_list);
}
Problem with Android Emulator. Code works fine in real device.
Thanks for all your help.

Rename an account on Android (AccountManager)

I'm changing the name of a published app.
Is there a quick and safe way to change the account name created via AccountManager.addAccountExplicitly so that existing info will remain intact for existing users.
If not, how can I go about changing the account name manually while preserving all the data?
I'll post an answer of my naive approach of copying everything then deleting the old, but I'm sure someone will come up with a better one (or spot some bugs in my method).
API v21 added a renameAccount() method to the AccountManager, if that helps.
From the docs:
This is equivalent to removing the existing account and adding a new
renamed account with the old account's user data.
That means for backward compatibility, you would have to manually remove the account and run through the same procedure as creating a new one (AccountManager.addAccountExplicitly() and AccountManager.setUserData()) afterwards.
Edit:
If you want to update your contacts afterwards to display the correct account name, try this (untested) code:
ContentValues contentValues = new ContentValues();
contentValues.put(ContactsContract.RawContacts.ACCOUNT_NAME, "new account name");
getContext().getContentResolver().update(ContactsContract.RawContacts.CONTENT_URI,
contentValues,
ContactsContract.RawContacts.ACCOUNT_TYPE + " = ? AND " + ContactsContract.RawContacts.ACCOUNT_NAME + " = ?",
new String[]{"your account type", "old account name"});
A naive approach of going over all the records, copying them one by one, and deleting all the old stuff...
I'm really afraid this method might fail on real world users.
private void naiveRename(ContentResolver resolver) {
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
Cursor cur = resolver.query(RawContacts.CONTENT_URI, null, RawContacts.ACCOUNT_NAME + "='"
+ "OLD NAME" + "'", null, null);
if (cur != null) {
// copy all data
while (cur.moveToNext()) {
Uri curUri = RawContacts.CONTENT_URI.buildUpon()
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
.build();
ContentProviderOperation.Builder builder = ContentProviderOperation
.newInsert(curUri);
for (int i = 0; i < cur.getColumnCount(); i++) {
String colName = cur.getColumnName(i);
if (RawContacts._ID.equals(colName) || RawContacts.VERSION.equals(colName)
|| RawContacts.CONTACT_ID.equals(colName)) {
// Skip - read only
} else if (RawContacts.ACCOUNT_NAME.equals(colName)) {
builder.withValue(RawContacts.ACCOUNT_NAME, "NEW NAME");
} else {
builder.withValue(colName, cur.getString(i));
}
}
operationList.add(builder.build());
}
// delete all old data
ContentProviderOperation.Builder builder = ContentProviderOperation
.newDelete(RawContacts.CONTENT_URI);
builder.withSelection(RawContacts.ACCOUNT_NAME + "='" + "OLD NAME" + "'", null);
try {
resolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (RemoteException e) {
// PANIC!
} catch (OperationApplicationException e) {
// OMG! WHAT TO DO?!
}
} else {
// LORDI!
}
}

Update contact detail android

I am working on the an application in which I want to update contact of particular person. When I update only contact first and last name then it working fine but I want to update full detail of contact like email address, number, postal addres etc.
Please provide me some useful link. Thanks in advance.
each field (email, name, adress) has its on mime type, which you should use
in order to update the field.
lets try to update the email for instance.
First, you should find the detail you want to update.
we will work with Data table, where each Data.RAW_CONTACT_ID represents a detail
about some contact.
So, we need to find the Data.RAW_CONTACT_ID where the id is the id of the contact you want
to edit.
Now we need to find the mimetype (the specific row which represents the detail) of
email (Email.CONTENT_ITEM_TYPE).
The data of an email is stored in the column Email.DATA - there we put the new email.
if you want a specific email type, you should add it to the query:
for example, if you want to add a home-email, then you should add Email.TYPE_HOME
to the query.
then we build a query and finally apply the change.
Here's an examle:
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
String emailParams = Data.RAW_CONTACT_ID + " = ? AND " + Data.MIMETYPE + " = ?";
String[] emailParamsWhere = new String[] { "contact_id", Email.CONTENT_ITEM_TYPE };
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI).withSelection(emailParams, emailParamsWhere).withValue(Email.DATA, "new email").withValue(Email.TYPE, Email.TYPE_HOME)
.build());
try
{
ContentProviderResult[] res = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
if (res != null)
{
return true;
}
return false;
}
catch (RemoteException e)
{
Log.d(TAG, e.getMessage());
e.printStackTrace();
}
catch (OperationApplicationException e)
{
Log.d(TAG, e.getMessage());
e.printStackTrace();
}
For updating mobile phone, use this query:
String phoneParams = Data.RAW_CONTACT_ID + " = ? AND " + Data.MIMETYPE + " = ? AND " + Phone.TYPE + " = " + Phone.TYPE_MOBILE;
String[] phoneParamsWhere = new String[] { "contact_id", Phone.CONTENT_ITEM_TYPE };
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI).withSelection(phoneParams, phoneParamsWhere).withValue(Phone.NUMBER, "mobile_number")
.withValue(Phone.TYPE, Phone.TYPE_MOBILE).build());
Hope I helped

Categories

Resources