0

My android app is supposed to load all contacts recorded in the device and display them in a list. I haven't been able to figure out why, but not all contacts are being loaded.

Here is the code I'm using to start the query with a CursorLoader:

public android.support.v4.content.Loader<Cursor> onCreateLoader(int id, Bundle args) {

        if (id == ContactsQuery.QUERY_ID) {
            Uri contentUri;


            if (mSearchTerm == null) {
                contentUri = ContactsQuery.CONTENT_URI;
            } else {
                contentUri =
              Uri.withAppendedPath(ContactsQuery.FILTER_URI, Uri.encode(mSearchTerm));
        }

        return new CursorLoader(getActivity(),
                contentUri,
                ContactsQuery.PROJECTION,
                ContactsQuery.SELECTION,
                null,
                ContactsQuery.SORT_ORDER);

ContactsQuery is defined as follows:

public interface ContactsQuery {

    final static int QUERY_ID = 1;

    final static Uri CONTENT_URI = Contacts.CONTENT_URI;

    final static Uri FILTER_URI = Contacts.CONTENT_FILTER_URI;

    @SuppressLint("InlinedApi")
    final static String SELECTION =
            (Utils.hasHoneycomb() ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME) +
            "<>''" + " AND " + Contacts.IN_VISIBLE_GROUP + "=1";

    @SuppressLint("InlinedApi")
    final static String SORT_ORDER =
            Utils.hasHoneycomb() ? Contacts.SORT_KEY_PRIMARY : Contacts.DISPLAY_NAME;

    @SuppressLint("InlinedApi")
    final static String[] PROJECTION = {

            // The contact's row id
            Contacts._ID,

            Contacts.LOOKUP_KEY,

            Utils.hasHoneycomb() ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME,

            Utils.hasHoneycomb() ? Contacts.PHOTO_THUMBNAIL_URI : Contacts._ID,

            SORT_ORDER,
    };

    final static int ID = 0;
    final static int LOOKUP_KEY = 1;
    final static int DISPLAY_NAME = 2;
    final static int PHOTO_THUMBNAIL_DATA = 3;
    final static int SORT_KEY = 4;
}

Why aren't all contacts being loaded when mSearchTerm is null?

Matt Samuel
  • 133
  • 10

2 Answers2

1

You are only pulling down contents of the phone's contacts - the contacts that are stored on the SIM may or may not be accessible due to the phone's settings (for example if the phone has disabled access to SIM contacts).

Here is a post that will show you how to read them separately.

You can potentially discern between the two using the following:

//for SIM Card 
ContentValues values = new ContentValues();
values.put(RawContacts.ACCOUNT_TYPE, "com.android.contacts.sim");
values.put(RawContacts.ACCOUNT_NAME, "SIM");
Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values);

//for everyone else
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
values.put(StructuredName.DISPLAY_NAME, "Name");
Community
  • 1
  • 1
Max Worg
  • 2,932
  • 2
  • 20
  • 35
  • So the SIM contacts table has completely different columns? – Matt Samuel Jan 25 '15 at 19:01
  • Yes - for a few reasons. First of all there is less storage space and less fields that you can use to store contact information on SIM cards and secondly they are stored in two different locations. You can still use a cursor to load them but they use different URIs and have different column names. But don't forget that different phones will act differently (some phones will give you both phone and sim card contacts in the way you are attempting to get them and others will not). It's just one of the joys of Android programming. – Max Worg Jan 25 '15 at 19:05
  • I don't suppose there's a good way to tell whether or not the SIM contacts were loaded the usual way? – Matt Samuel Jan 25 '15 at 19:24
  • Updated my answer with a potential solution to determine where they are coming from. It still requires two calls though. – Max Worg Jan 25 '15 at 19:56
  • Thanks. I'm thinking of having two query IDs and having the SIM load started after the usual load is finished. Seeing if that works. – Matt Samuel Jan 25 '15 at 19:57
  • This wasn't the problem, but I figured it out. – Matt Samuel Jan 25 '15 at 20:43
0

The problem was in the selection. The offending line is

final static String SELECTION =
        (Utils.hasHoneycomb() ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME) +
        "<>''" + " AND " + Contacts.IN_VISIBLE_GROUP + "=1";

The missing contacts had Contacts.IN_VISIBLE_GROUP <> 1. This behavior seems a bit pathological because it seems that perfectly valid contacts that are displayed in the contact list for the built in apps, such as my mother, are not in the visible group. I implemented a kludge:

final static String SELECTION =
            (Utils.hasHoneycomb() ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME) +
            "<>'' AND ("+Contacts.HAS_PHONE_NUMBER+"=1 OR "+Contacts.IN_VISIBLE_GROUP+" = 1)";

This is sufficient for my app.

Matt Samuel
  • 133
  • 10