Essentials: Device Contacts

Created on 20 Jun 2018  路  45Comments  路  Source: xamarin/Essentials

Hi Team, thanks for the great library, will save a huge amount of time.

Is it possible to add access to the contacts list into the API? Perhaps it can return a List or something similar?

VS bug #735685

feature-request needs-more-discussion proposal up-for-grabs

Most helpful comment

Long-lived issue and PR. Hopefully, this gets added to a release schedule or something. @pictos created a nice new PR at https://github.com/xamarin/Essentials/pull/1040 and addressed feedback from @jamesmontemagno.

All 45 comments

This is a pretty loaded API and extremely complicated. What I think most developers actually may want is a "Contact Picker" so you launch and pick a contact.

Can you give more use case on how you (and other developers please chime in) how you would use this API.

@jamesmontemagno thanks for the feedback. I my use case I need access to the list of contacts in code to populate a custom UI element as well format a message structure. For the most part I only need to read the list and obtain mobile number and/or email when working with the data itself and the UI element would be a picker type control, so I would be building the datasource for the picker.

The current app is Xamarin.IOS and not forms. #ContraintLayout

Hi there,
As I am working on same thing in my current project, I could add this functionality to this project.
A method to get list of device contacts including name, phone, email, ... and also may be function to update them.
Is it possible to participate in this project? is there any rule or limitation?
Thanks,
Amir

I think we could consider a really slimmed down API for this.

The first step I think is to figure out how each platform deals with this, and what is the minimum amount of information we'd want to provide for a 'contact' that would be returned from this API?

The first pass would be a read only API to get a list of contacts and some basic fields for them. I do seem to remember Android being particularly bad between API levels and vendors in terms of different field names were used to store the same information.

Before we go ahead with this I'd like to see some prototyping done on Android to see how feasible this really is.

I would love to see this feature added. Even a read only list of contacts would be helpful.

I definitely see myself using this once available. Here are my thoughts on this from experience working on various cross platform frameworks.

This API needs to support streaming/paging result sets.The device API's can take long to return 1000's of contacts. Also, the fetch operation needs to happen on a background thread.

Thanks for the note about paging results. This is something that may have been easily overlooked. Definitely this should be done off the UI thread with some async calls, but it sounds like it might make sense to have some sort of paging result that allows for a continuation after each callback.

What info do we want to return? Just phone numbers and name or email too?
In iOS and UWP we can get all info about contacts very easily, but in Android is a little a more complicated.

I think we want to return whatever the biggest subset of useful data is that's easy to figure out on all the platforms....

  • Email(s)
  • Phone(s)
  • Address(es)
  • Name
  • Birthday

Are those all easily identifiable and easy enough to capture on all platforms (looking at you android)? Again I seem to remember Android having different field names/mappings for the same data across vendors and api levels.

For now i can get, in all 3 plataforms :

  • Email(s)
  • Phone(s)
  • Name
  • Birthday

How i said, on Android is more verbose to get this informations, because we need to made a query for each item.

How you think about the pagination? I tried use the ManualResetEvent to handle with this.

So, addresses are not trivial to get from all platforms?

I think for paging, it depends how each platform works, but I think there are a couple of approaches and allowing both of them might make sense:

  1. Allow specifying how many to return, and which number to start at (so take and skip)
  2. Return some sort of continuation delegate which can be called to get the _next_ set from the query (which probably uses take and skip somehow).

About the address, i will investigate better, and i propose a spec for API. Sorry for the delay, I'm traveling and I do not always have internet.

I got the address on Android too, so here's my spec ...

first a structure to expose contact information:

public readonly struct PhoneContact : IEquatable<PhoneContact>
    {
        public string Name { get; }
        public List<string> Numbers { get; }
        public List<string> Emails { get; }       
        public string BirthDay { get; }
//another infos
}

I think we should use the Task to make a callback easier. And because in UWP this execution is asynchronous.
public static Task GetContacts(int pageSize) => PlataformGetContacts(pageSize);

For the callback, we can use an EventHandler and use the EventArgs to expose the trigger to get more contacts and the result, like this:

 public static event EventHandler<CallBackArgs> CallBack;

public class CallBackArgs : EventArgs
    {
        public ManualResetEvent Mre { get; }

        public IEnumerable<PhoneContact> Phones { get; }

        public CallBackArgs(ManualResetEvent mre, IEnumerable<PhoneContact> phones)
        {
            Mre = mre;
            Phones = phones;
        }
    }

and its use is thus:
```csharp
if (i % pageSize == 0)
{
Manualreset.Reset();
OnChanged(new CallBackArgs(Manualreset, phoneContacts));
}

I am thinking about this, and there is nothing to require anything special other than a simple IEnumerable<Contact>. Sure, that is not good for the main thread, but this API might just be fine for saying that it needs to be run on a background thread.

I whipped up a psudo-sample that people can talk about:
https://gist.github.com/mattleibow/4d7581fd2d13a31eeef25ddd0884e7f5

I have no idea how this translates to platform code, or if this is something we want, but this is what the user will write:

var contacts = Contacts.GetContacts();
foreach (var contact in contacts) {
    // process
}

Under the hood, the enumeration will block the calling thread as it hits the DB, so it has to be used in the background. Although, if you are in the background already, you would want it to block:

Task.Run(() => {
    var contacts = Contacts.GetContacts();
    foreach (var contact in contacts) {
        Console.WriteLine($"=> {contact.Name}");
    }
});

So, I think there are two api's here to consider...

1.) Getting contacts/adding contacts/removing contacts
2.) Contact Picker

I opt for option 2 first as this is a good way to get our feed in the door for what a contact is and is easier to implement and solves a good use case.

We can also split 1) into 2 parts:

1) managing contacts
1a. retrieve a read-only list of contacts / launch the contacts app for editing
1b. actually write code to edit phone contacts
2) contacts picker

1a) and 2) are different in that 1a) just launches the contacts app - just like the maps/browser - but 2) is a picker.

@jamesmontemagno , @mattleibow,

for now I implement the

1a. retrieve a read-only list of contacts .

I return a list with the contact information for dev. I think it's easier to talk about this if I show the code, so you can access my Spec repo here

For editing the contact it's better call the Native Contact, I think.

is this API going to be in which session of Xamarin.Essentials?

I made some tests, using the above suggestions, and until now here's what and so far, here's what I got:

Contact Picker

Access the contact picker in all plataforms and get PhoneContacts(struct with the properties required by @Redth ). In Android we can't select/get multiple contacts natively.

Get contacts list

Get a readonly list of all contacts save in device.

Add Contact

In my researchs only UWP allows the app save a contact, the others open the contact app. So I suggest we do this in UWP.

Removing

Open the specificy contact card and let the native contacts application handle it.

I suggest creating a folder to implement this API

Awesome! Do you have a branch or PR that we can follow along with?

not yet, as soon as I create I put the link here :)

@mattleibow I use this repo to implement the API. Feel free to ping me anytime

Would it be possible to get the type of the phone number -- work, home, etc.?

@markbrents I need to confirm this.

@markbrents it's possible, so I think we do this for all possible fields.

@mattleibow what do you think, about this struct:

 public struct PhoneContact : IEquatable<PhoneContact>
    {
        public string Name { get; }

        public Dictionary<string, string> Numbers { get; }

        public Dictionary<string, string> Emails { get; }

        public string BirthDay { get; }

        public string PersonalAddress { get; }

        internal PhoneContact(string name, Dictionary<string, string> numbers, Dictionary<string, string> emails, string bd, string address)
        {
            Name = name;
            BirthDay = bd;
            Numbers = new Dictionary<string, string>(numbers);
            Emails = new Dictionary<string, string>(emails);
            PersonalAddress = address;
        }
}

That might be a bit too minimal. Are you able to get a list of what the common fields so that we can sort of vote on eligibility for inclusion?

Maybe names (first, middle, last, mr/mrs), numbers (home, mobile), emails (personal, work), birthday, addresses (home, postal). Things like that. Also, it may be better to create a new type for the name (that way we can maybe start with fewer fields)

That might be a bit too minimal. Are you able to get a list of what the common fields so that we can sort of vote on eligibility for inclusion?

Yes, we can, I'll investigate this better, because in UWP is enumand Android is int.. iOS I don't know yet.

For name I think return the full name.

@mattleibow ,
Into iOS we have 2 types of contact, personaland organization. Into UWP we have 8. And android more than 8. So I was thinking, it's a good idea map this based on iOS

@mattleibow , Can I submit a PR draft of this feature? For now I implement Contact Picker and add new contact, and before implementing more things I would like you to review the code.

ezgif com-optimize

How about the contact photo? Notes? Address?

will it be able to create Labels? for example in URL field in iPhone you have Work url and home url? but you can add custom labels, e.g. Blog url.. so will it will also provide this feature?

Contact Picker just like @pictos demoe'd above looks perfect and I am sure is a common need. Would be really nice to have it ready to go as part of Essentials.

wait... @jamesmontemagno didn't you already do this? https://github.com/jamesmontemagno/ContactsPlugin

@mzhukovs the code is already completed. Fell free to do a code review and propose enhancements (:

A Count would be very useful to allow developer to show progress, a Count of total contacts as well as each element, e.g. Emails, Phones, etc

Will I be greedy if I ask for:

  • Feature to read and update contact Photo
  • Contact Listener to determine if a new contact was added or a contact was deleted or edited.
  • A field to read Created Date and Last Updated Date for every contact

@mzhukovs the code is already completed. Fell free to do a code review and propose enhancements (:

Shouldn't it also include other fields, e.g. Website, Address, Notes, etc...

Hi
Personal opinion is this pr has been sitting idle for a while.we don't want more stuff added now. We want it released and then more stuff added otherwise another 6-8 months will pass and no release

@jrahma sorry for the late reply. As Device Contacts are a complicated API (mainly for Android) I preferred to implement just two features. Grab one contact and Save one contact per time. After this API pass in the code review, by the Xamarin Team, I'll work on more features.

@pictos do you have any idea when this Will Go live?

@developer9969 I have no idea :/

Long-lived issue and PR. Hopefully, this gets added to a release schedule or something. @pictos created a nice new PR at https://github.com/xamarin/Essentials/pull/1040 and addressed feedback from @jamesmontemagno.

I could really use this right about now

This is really a cool addition not sure why is not being merged in. Will it ever be merged in? I need it right now too

looking forward to this update

This has been added to 1.6.

Was this page helpful?
0 / 5 - 0 ratings