1

I am currently working on a project in which I want to access the mobile contacts, So I have managed to create account with accountmanager and also able to perform Syncadapter operation. I could see my account got created in the mobile settings->Accounts. However, when I try to get all the contacts with my account with below code ,it does not work. Its showing all apps(google.com and WhatsApp.com) contacts except my app account contacts.

Cursor cursor = getContext().getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,
        new String[]{ContactsContract.RawContacts.DIRTY, ContactsContract.RawContacts.ACCOUNT_TYPE},
        null,
        null,
        null);

if (cursor != null && cursor.getCount() >0) {
    cursor.moveToFirst();
    while(!cursor.isAfterLast()) {
        Log.d("Dirty",cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.DIRTY)));
        Log.d("ACCountType",cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE)));

        cursor.moveToNext();
    }
    cursor.close();
}

What I dont understand is do I need to create ContentProvider and insert all contacts back to Contactsprovider on behalf of my account?

Naroju
  • 2,637
  • 4
  • 25
  • 44

1 Answers1

0

Not sure if you've fully understood how the ContactsProvider works.

There are a few things that you should know:

  • Every RawContact is uniquely assigned to one specific account, it can not belong to more than one account (hence your app usually can't sync existing contacts, because they already have an account).
  • All apps have the same view on all the contacts, in particular all apps can see and modify all contacts (given they have the permissions), though there are a few exceptions to that rule.
  • When you sync a contact to your account you must specify your account as shown on ContactsContract.RawContacts

    ContentValues values = new ContentValues();
    values.put(RawContacts.ACCOUNT_TYPE, accountType);
    values.put(RawContacts.ACCOUNT_NAME, accountName);
    Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values);
    long rawContactId = ContentUris.parseId(rawContactUri);
    
  • When you read contacts you get contacts of all accounts, unless you specify Uri query parameters or a selection:

    Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon()
      .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)
      .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)
      .build();
    Cursor c1 = getContentResolver().query(rawContactUri,
      RawContacts.STARRED + "<>0", null, null, null)
    

    This query returns all starred contacts of the specified account.

  • If your code operates as a sync adapter you also have to add the Uri query parameter CALLER_IS_SYNC_ADAPTER, otherwise you may get different results for many operations.

Marten
  • 3,802
  • 1
  • 17
  • 26
  • Thank you for your valuable explanation. In my application, I am not creating any activity to let the user insert contact manually, which means whenever my app is getting installed first time my app should read all the existing contacts and re insert(with CALLER_IS_SYNC_ADAPTER) into rawcontacts table on bahalf my account. then I should be able to detect changes and sync to server. Am I going in correct way? – Naroju Jun 23 '16 at 08:14
  • Depends on what you're trying to achive. What you describe will create a copy of each contact. The problem is that the original contact and your copy will eventually get out of sync. I was assuming your create a normal two-way-sync app (in which case you need to insert contacts, even without a UI). – Marten Jun 23 '16 at 08:18
  • I was assuming you create a normal two-way-sync app (in which case you need to insert contacts, even without a UI). But it sounds more like you plan to have a one-way-sync from the device to your service, basically scraping the contacts. That's not really supported by the SyncAdapter concept. – Marten Jun 23 '16 at 08:21
  • I am creating a two way sync. I am creating a ContentObserver to detect the changes like Add/delete/update of contacts and sync them to server accordingly And if there are any changes at server side then i want to update in mobile. My ultimate doubt is can I detect changes in the Contact list without creating account? – Naroju Jun 23 '16 at 08:24
  • 1
    My intention was to get the synced server contacts whenever user uninstall and install app. I tried Initially app should get all contacts and insert into raw contacts table with my account type(like google.com etc). and whenever I want to sync just get all the contacts with my account type and sync them to server. And Is there any direct direct API to grab all contacts of my accountype and send to server directly instead of grabbing all my accounttype contacts programmatically and send to server. – Naroju Jun 23 '16 at 08:43
  • The ContactsProvider is not build for that sort of synchronization. It's designed for one contact being synced to exactly one service, i.e. Google contacts to Google, Facebook contacts to Facebook etc. If you're planning to sync foreign contacts, you can't use the `DIRTY` and `DELETED` flags (because the original sync-adapter will reset them). As a result you'll always have to compare all contacts to your server state, which makes it very inefficient. Of course there are ways to optimize this, but I believe it goes beyond what should go into a single answer on stackoverflow. – Marten Jun 23 '16 at 15:46
  • Thank you, I understood what you said. I have one doubt and then will close this thread. if there are 100 contacts in my Mobile,I have registered them with my account when app got installed. if one more is added to list later (which is not registered with my account yet). then how to find that newly added contact in efficient way? because `DIRTY` and `DELETED` flags don't work as I have not registered the contact to my account yet. Any idea? – Naroju Jun 23 '16 at 17:08
  • will you please loot at this [issue](http://stackoverflow.com/questions/38012627/dirty-flag-not-getting-set-to-1-on-contact-update) – Naroju Jun 25 '16 at 05:20