Write to contacts on Xamarin.Forms

DeviOSDeviOS USMember ✭✭

Hi,
I'm trying to write contact information into their respective address books. I've seen examples on reading contacts (still haven't managed to get it to work, none of the examples compile, have to spend hours resolving bugs to get it to work!) but is there anything out there to write to contacts?
From the AddressbookSample (https://github.com/softsan/AddressbookSample) , Xamarin.Contacts does not work. Xamarin.Mobile does not compile.
Is there any way?

Best Answer

Answers

  • NMackayNMackay GBInsider, University mod
    edited February 2017

    @JamesMontemagno has a pluggin, not sure it's supported but may be you started down the right path. I think it only reads the address book but might give you some ideas on how to get to the API's to write back.

    Ported from Xamarin.Mobile to a cross platform API.

    https://github.com/jamesmontemagno/ContactsPlugin
    https://www.nuget.org/packages/Xam.Plugin.Contacts

    Remember to enable read & write contacts in your Android manifest.

  • VinayakGawasVinayakGawas USMember ✭✭✭

    @DeviOS For which platform do you want it??

  • DeviOSDeviOS USMember ✭✭

    @NMackay Thank you for your suggestions. I installed Plugin.Contacts and was able to read the contacts. Still working out on how to write to the addressbook..
    @VinayakGawas I want it for Android and iOS. Thank you.

  • DeviOSDeviOS USMember ✭✭

    Thank you @VinayakGawas! You saved my day(s). Its working like it should! Thank you very much again.

  • TVHTVH BEMember

    @VinayakGawas I tried a variant of this code to save a contact with multiple phone numbers and e-mail addresses, but my app crashes on iOS when trying to run this code. (Android works fine though, thanks for that!)

    Here's my method (phones and emails are both lists of strings containing the phone numbers and e-mail addresses):

            var store = new CNContactStore();
            var contact = new CNMutableContact();
            var phonesToSave = new List<CNLabeledValue<CNPhoneNumber>>();
            var mailsToSave = new List<CNLabeledValue<NSString>>();
            foreach(string number in phones)
            {
                phonesToSave.Add(new CNLabeledValue<CNPhoneNumber>("", new CNPhoneNumber(number)));
            }
            foreach(string mail in emails)
            {
                mailsToSave.Add(new CNLabeledValue<NSString>("", new NSString(mail)));
            }
            contact.PhoneNumbers = phonesToSave.ToArray();
            contact.GivenName = name;
            contact.EmailAddresses = mailsToSave.ToArray();
    
            var saveRequest = new CNSaveRequest();
            saveRequest.AddContact(contact, store.DefaultContainerIdentifier);
    
  • DeviOSDeviOS USMember ✭✭

    @TVH I'd suggest you step through the loops and see what's causing the crash. I'm not using a loop coz I save each contact once. But incase it helps, here's my complete iOS code.

    using System;
    using System.Threading;
    using AddressBook;
    using AddressBookUI;
    using Contacts;
    using ContactsUI;
    using DirList.iOS;
    using Foundation;
    using Plugin.Contacts;
    using Plugin.Contacts.Abstractions;
    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    [assembly: Xamarin.Forms.Dependency(typeof(ContactAdder_iOS))]
    
    namespace DirList.iOS
    {
        public class ContactAdder_iOS : UIViewController, IAddContact
        {
            public void AddContactMethod(string name, string phone, string email)
            {
                System.Diagnostics.Debug.WriteLine("Contact service in iOS");
    
                //Check for contact permissions
                var authStatus = CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts);
                if (authStatus == CNAuthorizationStatus.Denied || authStatus == CNAuthorizationStatus.Restricted)
                { 
                    System.Diagnostics.Debug.WriteLine("Contacts Denied or Restricted");
                    throwAlertMethod("Contacts Permission Required", "This app requires permission to access your contacts. " +
                                     "Please go to Settings>AppName and enable access.");
                    return;
                }
    
                //if user adds contact for 1st time
                if (authStatus == CNAuthorizationStatus.NotDetermined)
                {
                    System.Diagnostics.Debug.WriteLine("Contact permission not determined");
                    var store = new CNContactStore();
                    store.RequestAccess(CNEntityType.Contacts, (granted, error) =>
                    {
                        if (!granted)
                        {
                            throwAlertMethod("Contacts Permission Required", "This app requires permission to access your contacts, " +
                                             "please go to Settings>AppName and re-enable permissions.");
                            return;
                        }
                        else
                        {
                            saveContactToStoreMethod(name, phone, email);
                        }
                    });
                }
                else
                {
                    saveContactToStoreMethod(name, phone, email);
                }
            }
    
            void saveContactToStoreMethod(string name, string phone, string email)
            {
                var store = new CNContactStore();
                var contact = new CNMutableContact();
                var cellPhone = new CNLabeledValue<CNPhoneNumber>(new NSString("work"), new CNPhoneNumber(phone));
                var workEmail = new CNLabeledValue<NSString>(new NSString("work"), new NSString(email));
                var emailAdd = new[] { workEmail };
                var phoneNumber = new[] { cellPhone };
                contact.PhoneNumbers = phoneNumber;
                contact.EmailAddresses = emailAdd;
                contact.OrganizationName = "XXXX";
                contact.GivenName = name;
                var saveRequest = new CNSaveRequest();
                saveRequest.AddContact(contact, store.DefaultContainerIdentifier);
    
                NSError error;
                if (store.ExecuteSaveRequest(saveRequest, out error))
                {
                    Console.WriteLine("New contact saved");
                    throwToastMethod("Contact Saved");
                }
                else
                {
                    Console.WriteLine("save error {0}", error);
                    throwToastMethod("Error saving contact");
                }
            }
    
            void throwAlertMethod(string heading, string Body)
            { 
                var alertController = UIAlertController.Create(heading, Body, UIAlertControllerStyle.Alert);
                alertController.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
    
                UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alertController, true, null);
            }
    
            void throwToastMethod(string message)
            { 
                var toast = UIAlertController.Create(null, message, UIAlertControllerStyle.Alert);
                UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(toast, false, null);
    
                //Add Delay to dismiss the alert view without any user interaction
                new Timer((state) => InvokeOnMainThread(() => toast.DismissViewController(true, null)),
                                           null,
                                           600,
                                           Timeout.Infinite);
    
            }
        }
    }
    
  • TVHTVH BEMember

    Thanks @DeviOS. I think my app crashed previously because it didn't check permissions, so I added your code to do so. However, now the method still isn't working. Sometimes it goes through the method, but the contact isn't saved, sometimes the app crashes when asking for permission.

    For reference, here's my full class:

    public class UserContactService : IUserContactService
    {
        public async Task<bool> AddContact(string name, List<string> phones, List<string> emails)
        {
            bool hasPermission = CheckPermission();
    
            if (hasPermission == true)
            {
                var store = new CNContactStore();
                var contact = new CNMutableContact();
                var phonesToSave = new List<CNLabeledValue<CNPhoneNumber>>();
                var mailsToSave = new List<CNLabeledValue<NSString>>();
                foreach (string number in phones)
                {
                    phonesToSave.Add(new CNLabeledValue<CNPhoneNumber>("", new CNPhoneNumber(number)));
                }
                foreach (string mail in emails)
                {
                    mailsToSave.Add(new CNLabeledValue<NSString>("", new NSString(mail)));
                }
                contact.PhoneNumbers = phonesToSave.ToArray();
                contact.GivenName = name;
                contact.EmailAddresses = mailsToSave.ToArray();
    
                var saveRequest = new CNSaveRequest();
                saveRequest.AddContact(contact, store.DefaultContainerIdentifier);
    
                return true;
            }
            return false;
        }
    
        private bool CheckPermission()
        {
            var authStatus = CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts);
            if (authStatus == CNAuthorizationStatus.Denied || authStatus == CNAuthorizationStatus.Restricted)
            {
                System.Diagnostics.Debug.WriteLine("Contacts Denied or Restricted");
                throwAlertMethod("Contacts Permission Required", "This app requires permission to access your contacts. " +
                                                                 "Please go to Settings>FollowItUp and enable access.");
                return false;
            }
    
            //if user adds contact for 1st time
            bool check = false;
            if (authStatus == CNAuthorizationStatus.NotDetermined)
            {
                var store = new CNContactStore();
                store.RequestAccess(CNEntityType.Contacts, (granted, error) =>
                {
                    if (!granted)
                    {
                        throwAlertMethod("Contacts Permission Required", "This app requires permission to access your contacts, " +
                                                                         "please go to Settings>FollowItUp and re-enable permissions.");
                        //check = false;
                        return;
                    }
                    else
                    {
                        check = true;
                    }
                });
            }
            else
            {
                check = true;
            }
            return check;
        }
    
        void throwAlertMethod(string heading, string Body)
        {
            var alertController = UIAlertController.Create(heading, Body, UIAlertControllerStyle.Alert);
            alertController.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
    
            UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alertController, true, null);
        }
    
  • DeviOSDeviOS USMember ✭✭

    Hey @TVH , It was working fine for me without crashing, until one day. It started throwing a SIGABRT error when asking for permission. Same issue even on Debug and Release builds. However, it doesn't crash using a release build on a Device, only crashes in the simulator. Funny.

  • hi...
    now i am creating simple application in xamrin forms
    i have one doubt for me....please help me

    my task is , read contact details from phone to my app
    i have completed Read contact name and id
    but contact number cant able

  • andreacurtiandreacurti ITUniversity ✭✭

    Hi,
    I solved the SIGABRT issue, by adding "Privacy - Contacts usage description" entry in info.plist.
    now the code works till saveRequest.AddContact.
    I've no error, but the app do nothing, any contact or gui to add it.
    On Android it works fine.
    Any help?

  • andreacurtiandreacurti ITUniversity ✭✭

    Hi,
    I solved my issue, by adding this code after saveRequest.AddContact

    NSError error;
    if (store.ExecuteSaveRequest(saveRequest, out error))
    {
    Console.WriteLine("New contact saved");
    }
    else
    {
    Console.WriteLine("Save error: {0}", error);
    }

  • RUBENCARREONRUBENCARREON USMember ✭✭

    @VinayakGawas

    Do you have an example (for android and iOS) how to read a contact with the same approach?

    Regards
    rubenc

  • Gandhi_123Gandhi_123 Member ✭✭

    Hello @DeviOS and @VinayakGawas

    I have to implement add contact in Address book. so please help me which plugin I have to implement and how. As I am new in xamarin forms.

    Thanks you

  • Tracy320Tracy320 Member ✭✭

    @Gandhi_123
    Could you share the basic demo of adding contact in Address book?

  • Gandhi_123Gandhi_123 Member ✭✭

    Hello @Tracy320

    As of now I have implement read contact code which is given below:

    private async void Button_Clicked(object sender, EventArgs e)
    {
    switch (Device.RuntimePlatform)
    {

                case Device.Android:
                    var ContactList = await DependencyService.Get<IContacts>().GetDeviceContactsAsync();
                    listContact.ItemsSource = ContactList;
                    break;
                default:
                    break;
            }
        }
    

    But now I want to implement Write Contact code. and I don't understand how to start. Please help me.

    Thank You

  • Gandhi_123Gandhi_123 Member ✭✭
    edited October 2018

    Hello @DeviOS , @VinayakGawas

    Thanks for the best solution but I want to know that how to come back in our xamarin forms app after saving contact.

  • Gandhi_123Gandhi_123 Member ✭✭

    Hello @VinayakGawas , @DeviOS , @TVH

    This is the perfect solution for save contact in phone book. I have applied in android and its work perfectly but when i have applied in ios the contcat is not saved . So please help me for come out with this problem.

    Thanks in advance!!!!!!

  • Gandhi_123Gandhi_123 Member ✭✭

    @Gandhi_123 said:
    Hello @VinayakGawas , @DeviOS , @TVH

    This is the perfect solution for save contact in phone book. I have applied in android and its work perfectly but when i have applied in ios the contcat is not saved . So please help me for come out with this problem.

    Thanks in advance!!!!!!

Sign In or Register to comment.