Get contacts with email id

2019-02-19 10:48发布

问题:

I need to get contacts information(cursor) with email. They must be distinct. There must be one entry per contact if he has got an email. How to do it? I am targetting new contacts API comes with 2.0.

1)I tried to do it using CursorJoiner, but a strange thing happens. Here is my code :

MatrixCursor matCur = new MatrixCursor(
            new String[]{
            Contacts._ID,
                Contacts.DISPLAY_NAME,
                "photo_id",
                "starred"
            }
        );

Cursor newContactCursor = managedQuery(
        ContactsContract.Contacts.CONTENT_URI,
            new String[]{
                Contacts._ID,
                Contacts.DISPLAY_NAME,
                "photo_id",
                "starred"
            },
            null,
            null,
            null//Contacts._ID 
        );

newContactCursor.moveToFirst();

Cursor emailCur = managedQuery(
        ContactsContract.CommonDataKinds.Email.CONTENT_URI,
            new String[] {  
                Email.CONTACT_ID,
                Email.DATA1
            },
            null,
            null,
            Email.CONTACT_ID
        );

            emailCur.moveToFirst();

CursorJoiner joiner = new CursorJoiner(
        newContactCursor, 
            new String[]{Contacts._ID}, 
            emailCur, 
            new String[] {Email.CONTACT_ID}
        );

for (CursorJoiner.Result joinerResult : joiner) {
        switch (joinerResult) {

        case LEFT:
        // handle case where a row in cursorA is unique
        //Log.i(TAG,"L|"+
        //newContactCursor.getString(newContactCursor.getColumnIndex("_id")) );

        break;

        case RIGHT:
        // handle case where a row in cursorB is unique
        //Log.i(TAG,
        //"R|"+
        //emailCur.getString(emailCur.getColumnIndex("contact_id")) );

        break;

        case BOTH:

        //Log.i(TAG,
        //"L|"+
        //newContactCursor.getString(newContactCursor.getColumnIndex("_id"))+
        //"|R|"+
        //emailCur.getString(emailCur.getColumnIndex("contact_id")) );

                Log.i(TAG,                                           newContactCursor.getString(newContactCursor.getColumnIndex("_id"))+"|"+
                            newContactCursor.getString(newContactCursor.getColumnIndex("display_name"))+"|"+
                            emailCur.getString(emailCur.getColumnIndex(Email.DATA1)));

                    String[] columnValues = 
                    {newContactCursor.getString(newContactCursor.getColumnIndex("_id")),
                            newContactCursor.getString(newContactCursor.getColumnIndex("display_name")),
                            newContactCursor.getString(newContactCursor.getColumnIndex("photo_id")),
                            newContactCursor.getString(newContactCursor.getColumnIndex("starred"))
                    };

                    matCur.addRow(columnValues);

                    break;
                }
            }

now what my problem is i got output like this : in this log its _id | display_name | email id i have replaced them due to privacy issue

1|[contact name]|[email id] 
4|[contact name]|[email id] 
5|[contact name]|[email id] 
6|[contact name]|[email id]
7|
8| 
9| 
90| 
91| 
92|
93| 
94| 
95| 
96| 
97| 
98| 
99|

But you can see that it directly jumps from 9 to 90 then all 9 9 9, what is this?

2) Can we do this using distinct keyword? Is it possible with contact providers like ContactsContract?

回答1:

I just ran into the same problem. I know this thread is pretty old, but maybe this answer will help somebody else in the future.

You must filter by MIME type to get rid of duplicates. This is how I did it:

Uri contacts = ContactsContract.Data.CONTENT_URI;

String[] projection = new String[] {
        ContactsContract.Contacts._ID,
        ContactsContract.Contacts.LOOKUP_KEY,
        ContactsContract.Contacts.DISPLAY_NAME
};

String selection =
        ContactsContract.Contacts.IN_VISIBLE_GROUP + " = ? AND " + 
        ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?"  + " AND " +
        ContactsContract.Data.MIMETYPE + "='" +
        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'";

String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

mContactCursor = managedQuery(
        contacts,
        projection,
        selection,
        new String[] {"1", constraint.toString() + '%'},
        sortOrder);


回答2:

Try using this snippet: Showing Contact name and Email on the same row in list view.

 /**
 * Populate the contact list based on account.
 */
private void populateContactList() {
    // Build adapter with contact entries

    Cursor cursorEmail = getContactsEmail();//get all emails

    String[] fields = new String[] //fields of data to take
    {       ContactsContract.Contacts._ID,
            ContactsContract.Data.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Email.DATA
    };
    SimpleCursorAdapter adapter = 
            new SimpleCursorAdapter(this, R.layout.contact_entry, cursorEmail ,
            fields, new int[] 
                         {R.id.UID,R.id.contactEntryText,R.id.contactEmail});
    mContactList.setAdapter(adapter);
}

/**
 * Obtains the contact list for the currently selected account.
 *
 * @return A cursor for for accessing the contact list.
 */
private Cursor getContactsEmail()
{
    // Run query
    Uri uri = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
    String[] projection = new String[] {
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Email.DATA
    };
    String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP +"='1'";
    //showing only visible contacts  
    String[] selectionArgs = null;
    String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
  return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
}


回答3:

just do it in simple way first of all find contact_id, on basis of it we will search all email_ids related for that contact. on any button click event write this code

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
startActivityForResult(intent, 2);

now on activity result,

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{
    System.out.println("Request Code--"+requestCode);
    super.onActivityResult(requestCode, resultCode, data);
    if (data != null && requestCode == 2) 
     {
            fromCurrent = true;
            Uri uri = data.getData();
            //fromCurrent=true;
            if (uri != null) {
                Cursor c = null;
                try {
                    c = getContentResolver().query(uri, new String[]{ 
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
                                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                                ContactsContract.CommonDataKinds.Email.DATA ,
                                ContactsContract.CommonDataKinds.Email.TYPE },
                            null, null, null);

                    if (c != null && c.moveToFirst()) {
                        String id = c.getString(0);
                        String name = c.getString(1);

                        System.out.println("id  "+id+" name:"+name);

                        ContactID = id;
                        retriveEmail();


                        if(arrEmail.size() == 0)
                        {
                            showToast("No Email Address found for the selected contact!");
                        }
                        else
                        {
                        ListFile = arrEmail.toArray(new String[arrEmail.size()]);

                          builder1 = new AlertDialog.Builder(ShareTheHeart_Activity.this);

                          builder1.setTitle("Select an email address :");

                          builder1.setSingleChoiceItems(ListFile,-1,new DialogInterface.OnClickListener() {     //@Override
                         public void onClick(DialogInterface dialog, int which) 
                         {
                            txtEmail.setText(ListFile[which]);
                            alert.cancel();
                          }
                         });

                          alert = builder1.create();
                          alert.show();      

                        }
                    }
                } finally {
                    if (c != null) {
                        c.close();
                    }
                }
            }
        }
}

where retriveEmail is created method, write it in your code this way,

  private void retriveEmail()
{
    try { 
        arrEmail = new ArrayList<String>();
    String id = ContactID;

     // query for everything email  
   cursor = getContentResolver().query(Email.CONTENT_URI,  
            null, Email.CONTACT_ID + "=?", new String[] { id },  
            null);  

    int emailIdx = cursor.getColumnIndex(Email.DATA);  

    // let's just get the first email  
   if (cursor.moveToFirst())
   {
   do{  
        email = cursor.getString(emailIdx);  
        arrEmail.add(email);
        Log.v("ABC", "Got email: " + email);  
    } while(cursor.moveToNext());
    } else {  
        Log.w("ABC", "No results");  
    }  

} catch (Exception e) {  
    Log.e("ABC", "Failed to get email data", e);  
} finally {  
    if (cursor != null) {  
        cursor.close();  
    }   
    }
}

that's it.

please understand the code, don't just copy and paste!