0

I've worked hard on the following code, but unfortunately, the entry is assigned to the wrong contact. I don't know why. Tested for hours days but can't find the mistake. Can you help me?

I would like to use the code in order to select a person from the contact list (using the contact picker) and then adding an event entry (date of birth) for this person to the contacts table.

Step 1:

I've already set the permission in the manifest file:

<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>

Step 2:

The contact picker's ID is defined:

private static final int CONTACT_PICKER_ID = 123;

Step 3:

The contact picker is called:

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(contactPickerIntent, CONTACT_PICKER_ID);

Step 4:

Another method listens for the contact picker's result and tries to add an event for the selected user:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {  
        switch (requestCode) {  
            case CONTACT_PICKER_ID:
                Uri selectedPerson = data.getData();
                String contactId = selectedPerson.getLastPathSegment();
                // ADD A NEW EVENT FOR THE SELECTED CONTACT --- BEGIN
                ContentValues values = new ContentValues();
                values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
                values.put(ContactsContract.Data.RAW_CONTACT_ID, contactId);
                values.put(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY);
                values.put(ContactsContract.CommonDataKinds.Event.RAW_CONTACT_ID, contactId);
                values.put(ContactsContract.CommonDataKinds.Event.LABEL, "");
                values.put(ContactsContract.CommonDataKinds.Event.START_DATE, "2010-01-28"); // hard-coded date of birth
                Uri created = null;
                try {
                    created = getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                }
                catch (Exception e) {
                }
                if (created == null) {
                    Toast.makeText(this.getApplicationContext(), "Failed inserting the event!", Toast.LENGTH_SHORT).show();
                }
                else {
                    Toast.makeText(this.getApplicationContext(), "Successfully inserted the event!", Toast.LENGTH_SHORT).show();
                }
                // ADD A NEW EVENT FOR THE SELECTED CONTACT --- END
            break;
        }
    }
}

The event is successfully inserted to the database and also shown in the Google contacts - but unfortunately it's assigned to the wrong contact. Why is this so? Is my contactId wrong that I get from the contact picker?

caw
  • 30,999
  • 61
  • 181
  • 291
  • I'm not an android expert by any means, but do you need the ability to read the contacts to select one as well as the write capability? – Jared Jan 29 '12 at 01:18
  • per http://developer.android.com/reference/android/Manifest.permission.html the WRITE_CONTACTS doesn't have the ability to read them. again I don't know the answer this is just something that looked off to me. – Jared Jan 29 '12 at 01:20
  • Sorry, the permission READ_CONTACTS is set as well. But the reading process is not the problem, anyway. It's the writing which doesn't work. – caw Jan 29 '12 at 01:28
  • 1
    Just checking like I said I'm not an android person, but enjoy reading code and that just looked like something that 'might' cause a problem. – Jared Jan 29 '12 at 01:30
  • Yes, thank you for the comment! I do appreciate it, really :) I'm glad someone pays attention to this question. And with every try, there's the chance to find the mistake :) – caw Jan 29 '12 at 01:42
  • Did the solution below get you anywhere? – Jared Jan 29 '12 at 05:10
  • No, it didn't get me anywhere else, unfortunately :( – caw Jan 29 '12 at 12:37

3 Answers3

2

The activity result that you get back from the contact picker is the full path to the contact. Something like:

content://com.android.contacts/contacts/lookup/0r7-2C46324E483C324A3A484634/7

This is what's in your:

Uri selectedPerson = data.getData();

This contains both the Contact's LOOKUP_KEY AND the Contact's _ID. However, you need to be using the RawContacts _ID when inserting into the Data table. What you need to do is grab the RawContact's _ID:

long rawContactId = -1;
Cursor c = getContentResolver().query(RawContacts.CONTENT_URI,
      new String[]{RawContacts._ID},
      RawContacts.CONTACT_ID + "=?",
      new String[]{String.valueOf(contactId)}, null);
try {
    if (c.moveToFirst()) {
        rawContactId = c.getLong(0);
    }
} finally {
    c.close();
}

And then use the rawContactId:

values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);

However, it should be noted that there can be multiple RawContacts per one Contact. You may want to adjust your code so that it adds an event for each RawContact.

smoak
  • 14,554
  • 6
  • 33
  • 33
1

One entry is wrong in your content values. The Uri which you get in your onActivityResult data variable is not the raw_contact_id but the contact id. The difference between both is that one contact can contain multiple raw contacts. A raw contact is associated with a single account like Google or Facebook. But a contact can contain multiple raw_contacts.

            Uri selectedPerson = data.getData();
            String contactId = selectedPerson.getLastPathSegment();
            // ADD A NEW EVENT FOR THE SELECTED CONTACT --- BEGIN
            ContentValues values = new ContentValues();
            values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
            ***values.put(ContactsContract.Data.CONTACT_ID, contactId);***
            values.put(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY);
            values.put(ContactsContract.CommonDataKinds.Event.RAW_CONTACT_ID, contactId);
            values.put(ContactsContract.CommonDataKinds.Event.LABEL, "");
            values.put(ContactsContract.CommonDataKinds.Event.START_DATE, "2010-01-28"); // hard-coded date of birth
Ankur Kumar
  • 972
  • 7
  • 12
  • Thanks for this suggestion, but it doesn't work, actually :( With your code the insert() returns "null" again. So the toast "Failed ..." is shown. When I comment out your new line "values.put(ContactsContract.Data.CONTACT_ID, contactId)" then insert() returns a valid URI. – caw Jan 30 '12 at 15:29
0

try switching...

Uri created = null;
try {
     created = getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}catch (Exception e) {
}
            if (created == null) {
                Toast.makeText(this.getApplicationContext(), "Failed inserting the event!", Toast.LENGTH_SHORT).show();
            }
            else {
                Toast.makeText(this.getApplicationContext(), "Successfully inserted the event!", Toast.LENGTH_SHORT).show();
            }

to...

try{
    Uri created = getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
    if (created == null) {
         Toast.makeText(this.getApplicationContext(), "Failed inserting the event!", Toast.LENGTH_SHORT).show();
    }else{
         Toast.makeText(this.getApplicationContext(), "Successfully inserted the event!", Toast.LENGTH_SHORT).show();
    }
}catch (Exception e) {}
Jared
  • 5,840
  • 5
  • 49
  • 83
  • Thank you! Unfortunately, this doesn't change anything. Why should it, actually? The exception is thrown in the getContentResolver().insert() line - so it is now still thrown bad "catched"/caught a few steps later. The problem is that insert() throws this exception. Maybe the content that is inserted is wrong (wrong URI, wrong pairs of key-value). – caw Jan 29 '12 at 12:38
  • @MarcoW. I tried to look at that and for whatever reason I saw something that I thought might cause this to change something. I can't for the life of me remember what it was. I would have put it in a comment, but SO doesn't have good support for that amount of code in a comment. – Jared Jan 30 '12 at 06:49
  • :D It's okay. Thank you again for your will to help :) – caw Jan 30 '12 at 15:31