Search code examples
androidxamarinxamarin.androidcontactsphone-number

How to add a contact with multiple phone numbers in android via xamarin c#?


I am trying to add a contact with multiple phone numbers in android via xamarin c# . Here is a button on whose click I want to add contacts.

I tried everything from passing an array to trying to indivually adding the second number but the latter solution simply overwrites the first number before actually saving it (as suspected).

I read somewhere (probably on xamarin forums) that in Xamarin.ios we can add all the phone numbers as an array in one go.

        private void test_Click(object sender, EventArgs e)
    {
        List<ContentProviderOperation> ops = new List<ContentProviderOperation>();

        ContentProviderOperation.Builder builder =
            ContentProviderOperation.NewInsert(RawContacts.ContentUri);
        builder.WithValue(RawContacts.InterfaceConsts.AccountType, null);
        builder.WithValue(RawContacts.InterfaceConsts.AccountName, null);
        ops.Add(builder.Build());

        //Name
        builder = ContentProviderOperation.NewInsert(Data.ContentUri);
        builder.WithValueBackReference(Data.InterfaceConsts.RawContactId, 0);
        builder.WithValue(Data.InterfaceConsts.Mimetype,
                          StructuredName.ContentItemType);
        builder.WithValue(StructuredName.FamilyName, "Added fname");
        builder.WithValue(StructuredName.GivenName, "firstName");
        ops.Add(builder.Build());

        List<string> a = new List<string>();
        a.Add("89892302398");
        a.Add("93823239232");
        //Number
        builder = ContentProviderOperation.NewInsert(Data.ContentUri);
        builder.WithValueBackReference(Data.InterfaceConsts.RawContactId, 0);
        builder.WithValue(Data.InterfaceConsts.Mimetype,
                          cont.ContentItemType);
        builder.WithValue(cont.Number,"83293982" ); //tried to pass array here a.ToArray()

        builder.WithValue(cont.InterfaceConsts.Type,
                          cont.InterfaceConsts.TypeCustom);
        builder.WithValue(cont.InterfaceConsts.Label, "Work");

        builder.WithValue(cont.InterfaceConsts.Number, "808004038");
        builder.WithValue(cont.InterfaceConsts.Type,
                          cont.InterfaceConsts.TypeCustom);
        builder.WithValue(cont.InterfaceConsts.Label, "Home");

        ops.Add(builder.Build());

        //Add the new contact
        ContentProviderResult[] res;
        try
        {
            res = ContentResolver.ApplyBatch(Authority, ops);

            Toast.MakeText(this, "contact saved !", ToastLength.Short).Show();
        }
        catch
        {
            Toast.MakeText(this, "contact not saved_message !", ToastLength.Long).Show();
        }

    }

In my project I am trying to restore contacts from a csv file which I previously created but the only problem is that I can't save a contact with multiple numbers. I should look like :

How I want the contact to look like after it's added

UPDATE : this is how my full function looks like :

        //Restore Contacts
        private void CreateCon_Click(object sender, EventArgs e)
    {
        try
        {
            Toast.MakeText(this, "Create Contact Clicked", ToastLength.Short).Show();
            //  TextView txtv = FindViewById<TextView>(Resource.Id.txt);

            List<Contact> contacts = new List<Contact>();
            List<Contact> ex_cons = new List<Contact>();
            List<Contact> new_cons = new List<Contact>();

            CursorLoader loader;
            PUMservice.Service1 s = new PUMservice.Service1();

            double loop;
            Boolean boo;

            s.GetLoopTimes("contacts", PhoneNumbers[0], out loop, out boo);
            Toast.MakeText(this, "loops : " + loop, ToastLength.Short).Show();

            for (int ij = 0; ij < loop; ij++)
            {
                ex_cons = ex_cons.Union(s.GetContacts(PhoneNumbers[0])).ToList();
            }

            Android.Net.Uri uri = contact.ContentUri;
            Android.Net.Uri uri2 = cont.ContentUri;

            string[] projection =
                        {
            contact.InterfaceConsts.Id,
            contact.InterfaceConsts.DisplayName,
            contact.InterfaceConsts.ContactLastUpdatedTimestamp
        };

            string[] projection2 =
            {
            cont.InterfaceConsts.ContactId,
            cont.Number,
            cont.InterfaceConsts.Type,
        };

            loader = new CursorLoader(this, uri, projection, null, null, "contact_last_updated_timestamp Asc");

            var cursor = (ICursor)loader.LoadInBackground();

            if (cursor.MoveToFirst())
            {
                do
                {
                    //Add call Logs
                    string id = cursor.GetLong(cursor.GetColumnIndex(projection[0])).ToString();
                    string name = cursor.GetString(cursor.GetColumnIndex(projection[1]));
                    string date = cursor.GetString(cursor.GetColumnIndex(projection[2]));

                    PUMservice.Contact c_temp = new PUMservice.Contact
                    {
                        Id = id,
                        Name = name,

                    };

                    var l2 = new CursorLoader(this, uri2, projection2, cont.InterfaceConsts.ContactId + " = ?", new string[] { id }, null);

                    var cursor2 = (ICursor)l2.LoadInBackground();
                    if (cursor2.MoveToFirst())
                    {
                        List<string> temp_no = new List<string>();
                        List<string> temp_type_list = new List<string>();
                        List<string> temp_numbers_list = new List<string>();

                        do
                        {
                            string number = cursor2.GetString(cursor2.GetColumnIndex(projection2[1]));
                            //string numb = number; // used so that original spaces and all for unique contacts can be maintained...just replace numb with number if you don't want it. for eg. 95-9223-5321 can be stored as it is 
                            int typ = cursor2.GetInt(cursor2.GetColumnIndex(projection2[2]));
                            string temp_type = typ.ToString();

                            number = (number.Replace("-", "")).Replace(" ", "");
                            if (!(temp_no.Contains(number)))
                            {           
                                temp_type_list.Add(temp_type);
                                temp_numbers_list.Add(number);
                                temp_no.Add(number);
                            }
                        } while (cursor2.MoveToNext());
                            c_temp.Type = temp_type_list.ToArray();
                            c_temp.Number = temp_numbers_list.ToArray();
                    }
                                              contacts.Add(c_temp);
                } while (cursor.MoveToNext());
            }
            int i = 1;
            foreach(var single_con in ex_cons)
            {
                if(!(contacts.Exists(c=> c.Name == single_con.Name && c.Number.SequenceEqual(single_con.Number) && c.Type.SequenceEqual(single_con.Type))))
                {
                    i++;
                    //add the contact
                    // new_cons.Add(single_con);
                    List<ContentProviderOperation> ops = new List<ContentProviderOperation>();

                    ContentProviderOperation.Builder builder =
                    ContentProviderOperation.NewInsert(RawContacts.ContentUri);
                    builder.WithValue(RawContacts.InterfaceConsts.AccountType, null);
                    builder.WithValue(RawContacts.InterfaceConsts.AccountName, null);
                    ops.Add(builder.Build());

                    //Name
                    builder = ContentProviderOperation.NewInsert(Data.ContentUri);
                    builder.WithValueBackReference(Data.InterfaceConsts.RawContactId, Convert.ToInt32(single_con.Id));
                    builder.WithValue(Data.InterfaceConsts.Mimetype,
                                      StructuredName.ContentItemType);
                    builder.WithValue(StructuredName.DisplayName, "Added "+single_con.Name);
                    ops.Add(builder.Build());

                    //Number
                    for( int ix=0;i<single_con.Type.Length;i++)
                    {
                        builder = ContentProviderOperation.NewInsert(Data.ContentUri);
                        builder.WithValueBackReference(Data.InterfaceConsts.RawContactId, Convert.ToInt32(single_con.Id));
                        builder.WithValue(Data.InterfaceConsts.Mimetype,
                                          cont.ContentItemType);
                        builder.WithValue(cont.Number, single_con.Number[ix]);
                        builder.WithValue(cont.InterfaceConsts.Type,single_con.Type[ix]);
                        ops.Add(builder.Build());
                    }

                    //Add the new contact
                    ContentProviderResult[] res;
                    try
                    {
                        res = ContentResolver.ApplyBatch(Authority, ops);

                        Toast.MakeText(this, "Hahaahahaha contact saved ! "+i, ToastLength.Short).Show();
                    }
                    catch
                    {
                        Toast.MakeText(this, "contact not saved_message ! " + i, ToastLength.Long).Show();
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Toast.MakeText(this, ex.Message, ToastLength.Short).Show();
        }
    }

Solution

  • How to add a contact with multiple phone numbers in android via xamarin c#?

    Modify your NewContact code like this :

    public void NewContact(ref List<ContentProviderOperation> ops, string displayName, string Number1, string Number2, string Number3, string Number4)
        {
            ContentProviderOperation.Builder builder =
                ContentProviderOperation.NewInsert(ContactsContract.RawContacts.ContentUri);
            builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountType, null);
            builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountName, null);
            ops.Add(builder.Build());
    
            //Name  
            builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
            builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
            builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                              ContactsContract.CommonDataKinds.StructuredName.ContentItemType);
            builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.DisplayName, displayName);
            //builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.GivenName, firstName);  
            ops.Add(builder.Build());
    
            //Number1  
            builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
            builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
            builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                              ContactsContract.CommonDataKinds.Phone.ContentItemType);
            builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number1);
            builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                              ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
            builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
    
            ops.Add(builder.Build());
            //Number2  
            if (!string.IsNullOrEmpty(Number2))
            {
                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                                  ContactsContract.CommonDataKinds.Phone.ContentItemType);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number2);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                                  ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
                ops.Add(builder.Build());
            }
    
            if (!string.IsNullOrEmpty(Number3))
            {
                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                                  ContactsContract.CommonDataKinds.Phone.ContentItemType);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number3);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                                  ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
                ops.Add(builder.Build());
            }
    
            if (!string.IsNullOrEmpty(Number4))
            {
                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                                  ContactsContract.CommonDataKinds.Phone.ContentItemType);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number4);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                                  ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
                ops.Add(builder.Build());
            }
        }
    

    Then when you use this method add contact :

    new_Contact_Button.Click += (sender, args) =>
    {
    
        List<ContentProviderOperation> ops = new List<ContentProviderOperation>();
        NewContact(ref ops, "lizi", "1234" , "2234", "3234", "4234");
    
        //Add the new contact
        ContentProviderResult[] res;
        try
        {
            res = ContentResolver.ApplyBatch(Authority, ops);
            ops.Clear();//Add this line   
            Toast.MakeText(this, "contact saved !", ToastLength.Short).Show();
        }
        catch
        {
            Toast.MakeText(this, "contact not saved_message !", ToastLength.Long).Show();
        }
    }
    

    Effect in my Mi 5s, in my Huawei Nexus 6P.

    Update :

    Add ops.Clear() when you save a contact.

    public void SaveContacts(string filename)  
    {  
        var documentsPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);  
        var filePath = Path.Combine(documentsPath.AbsolutePath, filename);  
        var fileContent = File.ReadAllLines(filePath);  
    
        List<ContentProviderOperation> ops = new List<ContentProviderOperation>();  
    
        foreach (var strLine in fileContent)  
        {  
            if (string.IsNullOrEmpty(strLine))  
                continue;  
            var array = strLine.Split(new string[] { "\t", ":" }, StringSplitOptions.RemoveEmptyEntries);  
    
            NewContact(...);  
    
            //Add the new contact  
            ContentProviderResult[] res;  
            res = ContentResolver.ApplyBatch(ContactsContract.Authority, ops);  
            ops.Clear();   
        }  
    }