13

I would like to read contacts from ContactsContract API which belongs only to Phone / SIM and would like to avoid contacts synced from other apps like facebook and gmail. I tested my code on simulator and it works fine but on real devices it doesn't returns any result.

ContentResolver cr = AndroidContext.getContext()
                    .getContentResolver();
Cursor nativeContacts = cr.query(RawContacts.CONTENT_URI,
                    new String[] { RawContacts._ID, RawContacts.VERSION, RawContacts.CONTACT_ID },
                    RawContacts.DELETED + "<> 1 AND " + RawContacts.CONTACT_ID
                            + " IS NOT NULL AND " + RawContacts.ACCOUNT_NAME + " IS NULL AND "
                            + RawContacts.ACCOUNT_TYPE + " IS NULL", null, null);

I guess on devices the account type and name for default account is not null, what is the solution?

Rahul Choudhary
  • 3,789
  • 2
  • 30
  • 30
  • So I tried a small sample app to fetch Account type and name used in different devices. On **HTC** Account type and nme were com.htc.android.pcsc and com.android.sim while on Sony Xperia it were com.sonyerricson.contacts. So it seems all devices uses different type and name, now the question is how do I get the default account? Can I do something like this AccountManager.getAccounts()[0] and trust that this will be the default account on device. – Rahul Choudhary Feb 02 '11 at 15:07
  • Hi Rahul, everyone. I would like to know the answer to this question too. I want to extract contact information only from the phone/sim itself. – Creniale May 04 '11 at 07:15
  • `Can I do something like this AccountManager.getAccounts()[0] and trust that this will be the default account on device.` No, you can't. If the account name is empty, you can't get it from `AccountManager.getAccounts()` – Autobots Sep 24 '14 at 11:59

3 Answers3

10

I couldn't find the way to get the SIM account yet. But I'm using the code below to get the default account name and type.

public void getDefaultAccountNameAndType() {
    String accountType = "";
    String accountName = "";

    long rawContactId = 0;
    Uri rawContactUri = null;
    ContentProviderResult[] results = null;

    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); 

    ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI).withValue(RawContacts.ACCOUNT_NAME, null).withValue(RawContacts.ACCOUNT_TYPE, null).build());

    try {
        results = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        ops.clear();
    }

    for (ContentProviderResult result : results) {
        rawContactUri = result.uri;
        rawContactId = ContentUris.parseId(rawContactUri);
    }

    Cursor c = getContentResolver().query(
            RawContacts.CONTENT_URI
            , new String[] {RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME}
            , RawContacts._ID+"=?"
            , new String[] {String.valueOf(rawContactId)}
            , null);

    if(c.moveToFirst()) {
        if(!c.isAfterLast()) {
            accountType = c.getString(c.getColumnIndex(RawContacts.ACCOUNT_TYPE));
            accountName = c.getString(c.getColumnIndex(RawContacts.ACCOUNT_NAME));
        }
    }

    getContentResolver().delete(rawContactUri, null, null);

    c.close();
    c = null;

    preference.setString("contactAccountType", accountType);
    preference.setString("contactAccountName", accountName);
}
Beryllium
  • 12,808
  • 10
  • 56
  • 86
Brad Hong
  • 389
  • 2
  • 11
  • 2
    ahh i see. Adding a dummy contact as default and getting the type and name. Thanks. That will work out nicely. A good work around. =) – Creniale Jul 18 '11 at 07:17
  • 2
    hmm it seems like this doesn't work for Nexus S. It works for HTC hero which is on 2.1. On Nexus S, I got a null value when I tried to get the account name/type from the cursor. – Creniale Aug 12 '11 at 08:28
3

I made the same experiences as you did and can only suggest two workarounds:

  1. Let the user make the decision. For example show him a list of all raw contacts and then let him choose which one is a phonebook contact vs. a sim contact.

  2. My experience with three different devices is that the AccountManager is not aware of the account used to store those phonecontacts. For example when you fetch an account array from the AccountManager as you did (AccountManager.getAccounts()) the "com.htc.android.pcsc" is not in the list! But you can use exactly that fact to your advantage: Exclude all known account types/names and the list you get should be the list of all phonebookcontacts/simcontacts.

Hopefully those ideas helped you :) I would like to read your thoughts about those workarounds, eventually I missed something or there is a even better workaround.

Beryllium
  • 12,808
  • 10
  • 56
  • 86
Christoph Haefner
  • 1,093
  • 1
  • 9
  • 25
  • point number 2 of your workaround sounds good. But please do note that some contacts that are created on the phone might be under Google Account. Those contacts will not be synced to gmail/facebook but it will appear in the phonebook. Those contacts are under "com.google" which is under the list in AccountManager. – Creniale May 06 '11 at 07:37
  • This answer still helping the community :) thanks all – Sushant Somani Nov 02 '18 at 06:35
1

I solved this problem.

Account[] accountList = AccountManager.get(this).getAccounts();

String accountSelection = "";
for(int i = 0 ; i < accountList.length ; i++) {
  if(accountSelection.length() != 0)
    accountSelection = accountSelection + " AND ";
  accountSelection = accountSelection + ContactsContract.Groups.ACCOUNT_TYPE + " != '" +  accountList[i].type + "'";
}
Brad Hong
  • 389
  • 2
  • 11
  • you need "android.permission.GET_ACCOUNTS" permission – Brad Hong Apr 27 '11 at 07:32
  • Does this mean that SIM and PHONE account type are not in the list (getAccounts())? I will check and verify this, thanks for sharing. – Rahul Choudhary Apr 28 '11 at 06:36
  • This code only display contacts that are not under any accounts. The contacts which are being created by the user as Google Account will not be shown too. Note that a Google Account is not the same as Gmail contacts. – Creniale May 06 '11 at 07:28
  • I think this is the only way to get the contacts created on phone/device. @Creniale and Rahul Choudhary, please correct me in case I am wrong. – Tejas Sherdiwala Jun 13 '15 at 02:40
  • 1
    @BradHong, I was able to get it done with adding the permission to manifest. – Tejas Sherdiwala Jun 13 '15 at 02:41
  • just as a heads up: GET_ACCOUNTS permission will deprecate in N (GET_ACCOUNTS_PRIVILEGED replaces it). Google keeps making it harder and harder to have system Contacts app alternatives without root or embedded ROM apps. – leRobot Mar 21 '16 at 14:59
  • @leRobot The permission still works fine, even on Android O. You just have to request it. – android developer Aug 26 '17 at 15:40