android – Insert a new contact intent-ThrowExceptions

Exception or error:

For one of my apps, I need the user to select one of his existing contacts or to create a new one.
Picking one is clearly easy to do with the following code:

i = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(i, PICK_CONTACT_REQUEST );

Now I want to create a new contact. I tried to use that code but it doesn’t trigger the activity result:

i = new Intent(Intent.ACTION_INSERT);
i.setType(Contacts.CONTENT_TYPE);
startActivityForResult(i, PICK_CONTACT_REQUEST);

The above code will start the contact adding form. Then when I validate it, it just asks me to open the contact list and the onActivityResult method is never triggered.

Could you help me to make it working ?

I read on some boards that this wasn’t possible, and I had to create my own contact adding form. Could you confirm that ?

EDIT: Problem solved. Check my answer.

How to solve:

You can choose whether you want to add the contact automatically, or open the add contact activity with pre-filled data:

/**
 * Open the add-contact screen with pre-filled info
 * 
 * @param context
 *            Activity context
 * @param person
 *            {@link Person} to add to contacts list
 */
public static void addAsContactConfirmed(final Context context, final Person person) {

    Intent intent = new Intent(Intent.ACTION_INSERT);
    intent.setType(ContactsContract.Contacts.CONTENT_TYPE);

    intent.putExtra(ContactsContract.Intents.Insert.NAME, person.name);
    intent.putExtra(ContactsContract.Intents.Insert.PHONE, person.mobile);
    intent.putExtra(ContactsContract.Intents.Insert.EMAIL, person.email);

    context.startActivity(intent);

}

/**
 * Automatically add a contact into someone's contacts list
 * 
 * @param context
 *            Activity context
 * @param person
 *            {@link Person} to add to contacts list
 */
public static void addAsContactAutomatic(final Context context, final Person person) {
    String displayName = person.name;
    String mobileNumber = person.mobile;
    String email = person.email;

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

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

    // Names
    if (displayName != null) {
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
                        displayName).build());
    }

    // Mobile Number
    if (mobileNumber != null) {
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, mobileNumber)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
                        ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE).build());
    }

    // Email
    if (email != null) {
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
                .withValue(ContactsContract.CommonDataKinds.Email.TYPE,
                        ContactsContract.CommonDataKinds.Email.TYPE_WORK).build());
    }

    // Asking the Contact provider to create a new contact
    try {
        context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
    } catch (Exception e) {
        e.printStackTrace();
    }

    Toast.makeText(context, "Contact " + displayName + " added.", Toast.LENGTH_SHORT)
            .show();
}

###

Finally found a solution, I’m sharing it with you.
That’s only a fix for Android version above 4.0.3 and sup. It doesn’t work on 4.0 to 4.0.2.

i = new Intent(Intent.ACTION_INSERT);
i.setType(Contacts.CONTENT_TYPE);
if (Integer.valueOf(Build.VERSION.SDK) > 14)
    i.putExtra("finishActivityOnSaveCompleted", true); // Fix for 4.0.3 +
startActivityForResult(i, PICK_CONTACT_REQUEST);

###

Intent intent = new Intent(
        ContactsContract.Intents.SHOW_OR_CREATE_CONTACT,
        Uri.parse("tel:" + phoneNumber));
    intent.putExtra(ContactsContract.Intents.EXTRA_FORCE_CREATE, true);
    startActivity(intent);

this code might help you.

###

 // Creates a new Intent to insert a contact

Intent intent = new Intent(Intents.Insert.ACTION);
 // Sets the MIME type to match the Contacts Provider

intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

If you already have details for the contact, such as a phone number or email address, you can insert them into the intent as extended data. For a key value, use the appropriate constant from Intents.Insert. The contacts app displays the data in its insert screen, allowing users to make further edits and additions.

private EditText mEmailAddress = (EditText) findViewById(R.id.email);
private EditText mPhoneNumber = (EditText) findViewById(R.id.phone);

/*
 * Inserts new data into the Intent. This data is passed to the
 * contacts app's Insert screen
 */
 // Inserts an email address

 intent.putExtra(Intents.Insert.EMAIL, mEmailAddress.getText())
 /*
  * In this example, sets the email type to be a work email.
  * You can set other email types as necessary.
  */
  .putExtra(Intents.Insert.EMAIL_TYPE, CommonDataKinds.Email.TYPE_WORK)
 // Inserts a phone number
  .putExtra(Intents.Insert.PHONE, mPhoneNumber.getText())
 /*
  * In this example, sets the phone type to be a work phone.
  * You can set other phone types as necessary.
  */
  .putExtra(Intents.Insert.PHONE_TYPE, Phone.TYPE_WORK);

Once you’ve created the Intent, send it by calling startActivity().

/* Sends the Intent
 */
startActivity(intent);

Note : import “intents” of “ContactsContract”

###

Try if you use Kotlin

fun Fragment.saveContact(name: String?, phone: String?) {
    if (name != null && phone != null) {
        val addContactIntent = Intent(Intent.ACTION_INSERT)
        addContactIntent.type = ContactsContract.Contacts.CONTENT_TYPE
        addContactIntent.putExtra(ContactsContract.Intents.Insert.NAME, name)
        addContactIntent.putExtra(ContactsContract.Intents.Insert.PHONE, phone)
        startActivity(addContactIntent)
    }
}

###

Used the first part from accepted answer:

        Intent i = new Intent(Intent.ACTION_INSERT);
        i.setType(ContactsContract.Contacts.CONTENT_TYPE);
        if (Build.VERSION.SDK_INT > 14)
            i.putExtra("finishActivityOnSaveCompleted", true); // Fix for 4.0.3 +
        startActivityForResult(i, 1);

now on your result you can get phone number and also name,Since it’s a been tricky and you should query two different tables which are connected by same ids.I’ll post this part so it’s easier for everybody:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
            assert data != null;
            ContentResolver cr = getContentResolver();
            Cursor cursor = cr.query(Objects.requireNonNull(data.getData()), null, null, null, null);
            if (cursor != null && cursor.moveToFirst()) {
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
                if (cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {//Has phoneNumber
                    Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);
                    while (pCur != null && pCur.moveToNext()) {
                        String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                        Log.v("SteveMoretz", "NAME : " + name + " phoneNo : " + phoneNo);
                    }
                    if (pCur != null) {
                        pCur.close();
                    }
                }
            } else {
                Toast.makeText(getApplicationContext(), "User canceled adding contacts", Toast.LENGTH_SHORT).show();
            }
            if (cursor != null) {
                cursor.close();
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

Hope this will help somebody.

###

I’ve gathered all kinds of Intents that I’ve found for adding a contact. Here’s the result in a single function:

@JvmStatic
fun prepareCreateContactIntent(context: Context, contactName: String? = null, phoneNumber: String? = null): Intent? {
    var intent = Intent(Intents.Insert.ACTION)
    intent.type = ContactsContract.RawContacts.CONTENT_TYPE
    val packageManager = context.packageManager
    var resolveActivity: ResolveInfo? = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY or PackageManager.GET_RESOLVED_FILTER)
    if (resolveActivity == null) {
        intent = Intent(Intent.ACTION_INSERT).setType(ContactsContract.Contacts.CONTENT_TYPE)
        resolveActivity = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY or PackageManager.GET_RESOLVED_FILTER)
    }
    if (resolveActivity == null) {
        intent = Intent(Intents.SHOW_OR_CREATE_CONTACT, if (phoneNumber == null) Uri.parse("tel:") else Uri.parse("tel:$phoneNumber"))
        intent.putExtra(Intents.Insert.NAME, contactName)
        resolveActivity = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY or PackageManager.GET_RESOLVED_FILTER)
    }
    intent.putExtra(Intents.Insert.NAME, contactName)
    intent.putExtra(Intents.Insert.PHONE, phoneNumber)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
    return if (resolveActivity == null) null else intent
}

If it returns null, it means there is no app that can handle it, and so you should add it yourself, or show something to the user.

###

 int INSERT_CONTACT_REQUEST=2;
 i = new Intent(Intent.ACTION_INSERT,Contacts.CONTENT_URI);
 startActivityForResult(i, INSERT_CONTACT_REQUEST);

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{
// TODO Auto-generated method stub
 if(requestCode == INSERT_CONTACT_REQUEST)
   {
        if (resultCode == RESULT_OK)
            {                                  
             Toast.makeText().show(getApplicationContext(),"Added_Succesfully",Toast.LENGTH_SHORT);
            }else if(resultCode == RESULT_CANCELED)
                   {
                 Toast.makeText().show(getApplicationContext(),"Contacts Adding Error",Toast.LENGTH_SHORT);     
                    }

    }
}

###

In Xamarin.forms and Xamarin.Android c#.

Android.Content.Intent intent = new  
Android.Content.Intent(Android.Content.Intent.ActionInsert);
intent.SetType(Android.Provider.ContactsContract.Contacts.ContentType);
intent.PutExtra(Android.Provider.ContactsContract.Intents.ExtraForceCreate, 
true);
StartActivity(intent);

Leave a Reply

Your email address will not be published. Required fields are marked *