Windows 8.1: Contacts API

One of the things that I’d really wanted to try out on the 8.1 Preview was the Contacts API which was talked about in the Build 2013 session below;

But I don’t think that it worked in the preview and I’ve a vague memory of the Build session perhaps even mentioning that – I watched it live back in June so could be wrong but I do remember trying the API but I don’t remember having any success with it.

Regardless, I’m onto the Windows 8.1 RTM version and I wanted to try out the new capabilities.

I started on the doc pages up at;

http://msdn.microsoft.com/en-us/library/windows/apps/windows.applicationmodel.contacts.aspx

and it starts with a note that seemed pretty confusing to me;

Note  Don't use API in this namespace that is new starting with Windows 8.1 with API in this namespace that may not be available for releases after Windows 8.1. If you mix these APIs in your app, it will fail.”

but I managed to work my way around that had a flick through that doc page where it feels like;

  • There’s a bunch of new classes here.
  • There’s a bunch of old classes that are might go away at some point in the future (“after Windows 8.1” is what the page says).

It’s not easy from the page to identify which classes are new in 8.1 so I visited all the hyperlinks and came up with what’s below (it’s just a bitmap) where the yellow highlights are meant to be for new 8.1 classes, the black crosses are against classes that say they might disappear post 8.1 and the untouched classes are meant to be neither (i.e. in 8.0 and don’t say they are going away);

image

image

A number of those classes (e.g. ContactWebsite, ContactSignificantOther, ContactJobInfo, ContactEmail etc) are essentially sub-sets of the data that might be available about a contact and the Contact class itself has slots to store entries of these types. For example, Contact.Emails gets you a number of ContactEmail instances which seems simple enough.

Beyond that, there is the ContactPicker class which was already present in Windows 8.0 and there’s the new ContactManager class which arrives in Windows 8.1.

The ContactPicker has changed its form. Looking at the public methods/properties there you can see that it’s been under the knife a little bit;

image

it’s worth also saying that this page mentions;

“Note  Apps that were compiled for Windows 8 but running on Windows 8.1 may encounter runtime errors without compile-time errors.”

which sounds like something that you’d want to test for.

In terms of picking a contact, it doesn’t feel like the ground has shifted too much here in that I can run code like;

      ContactPicker p = new ContactPicker();
      p.CommitButtonText = "Choose";
      p.SelectionMode = ContactSelectionMode.Fields;
      p.DesiredFieldsWithContactFieldType.Add(ContactFieldType.Email);

      Contact c = await p.PickContactAsync();
      
      // Debugger isn't so friendly in showing me all the WinRT bits here
      Debug.WriteLineIf(
        (c.Emails != null) && (c.Emails.Count > 0), "Got Emails");

      if ((c.Emails != null) && (c.Emails.Count > 0))
      {
        var email = c.Emails.First();
        Debug.WriteLine(email.Address);
      }

      Debug.WriteLineIf(
        (c.Phones != null) && (c.Phones.Count > 0), "Got Phones");

      if ((c.Phones != null) && (c.Phones.Count > 0))
      {
        var phone = c.Phones.First();
        Debug.WriteLine(phone.Number);
      }

      Debug.WriteLineIf(
        (c.Addresses != null) && (c.Addresses.Count > 0), "Got Addresses");

      if ((c.Addresses != null) && (c.Addresses.Count > 0))
      {
        var address = c.Addresses.First();
        Debug.WriteLine(address.StreetAddress);
      }

      Debug.WriteLineIf(
        (c.Websites != null) && (c.Websites.Count > 0), "Got Websites");

      if ((c.Websites != null) && (c.Websites.Count > 0))
      {
        var website = c.Websites.First();
        Debug.WriteLine(website.Uri);
      }

and that seems to do much what I’d expect in that it raises the contact picking UI (which on my current machine only includes contacts from the People app but could include others as they plug in to the system);

image

and then when I select a contact, I see my debug code giving me their details in terms of email, phone, address and website.

What surprised me a little was that I found that if I requested a specific field (like email) above and set the SelectionMode to Fields then I still seemed to get the phone, address, website fields populated regardless so whether this is an optimisation that can apply but isn’t perhaps being applied in this case I’m not sure. If I set the SelectionMode to Contacts then I didn’t notice any particular difference for the code above.

Regardless, I can fairly easily grab a contact’s information into my app. What else can I do with it apart from crunch on all the information that’s contained within?

The other bits of functionality here seem to live with the ContactManager which was demo’d in the BUILD video above starting at about the 15 minute mark.

There’s an official sample for the ContactManager up on the web.

In order to use this functionality, I think you have to start by knowing something about the contact in question and the most specific thing you might know about a Contact is its Id as in the code below;

    async void OnButtonClick(object sender, RoutedEventArgs e)
    {
      // This is my contact id for my colleage, Mike Ormond.
      string contactId = "26000365";
      Button button = (Button)sender;

      GeneralTransform transform = button.TransformToVisual(this);

      Rect transformedRect = transform.TransformBounds(
        new Rect(0, 0, button.ActualWidth, button.ActualHeight));

      Contact searchContact = new Contact()
      {
        Id = contactId
      };

      ContactManager.ShowContactCard(searchContact, transformedRect);        
    }

when I tap on the button in question I first see;

image

then I quickly see the contact card pop up;

image

I did a bit of “redacting” on the contact details there. I found it interesting to tap on the email option which pops up a choice of mail apps to use;

image

and if I choose the built-in Windows 8.1 mail app then the system pops that open taking up 50% of the screen;

image

whereas if I choose to phone/text then the system opens up Skype in a smaller view (below is the text message option);

image

and if I tap on the “more details” option then the People app opens up side-by-side;

image

which is very nice – looks very professional I think.

Not every app is going to have a nice contact id all set up and ready (or previously stored) in order to invoke the ContactManager API and so the app doesn’t have to know the contact’s ID up front but it does have to know something about the contact – either the id, email addresses or phone numbers.

I thought I’d try that out – I found that it seems that I have to get an exact match on the phone number string including bracket placement and so on;

    async void OnButtonClick(object sender, RoutedEventArgs e)
    {
      Button button = (Button)sender;

      GeneralTransform transform = button.TransformToVisual(this);

      Rect transformedRect = transform.TransformBounds(
        new Rect(0, 0, button.ActualWidth, button.ActualHeight));

      Contact searchContact = new Contact();
      searchContact.Phones.Add(
        new ContactPhone()
        {
          Number = mikesExactMobileNumberString,
          Kind = ContactPhoneKind.Mobile
        }
      );

      ContactManager.ShowContactCard(searchContact, transformedRect);        
    }

but if I got a match then it worked out ok and, similarly, filling in an email address worked out for me as well;

      Contact searchContact = new Contact();
      searchContact.Emails.Add(
          new ContactEmail()
          {
            Address = mikesEmailAddress
          }
        );

      ContactManager.ShowContactCard(searchContact, transformedRect);        

and I didn’t seem to have to tell the system what Kind of email address (work, home, etc) I was trying to look for.

In terms of the actions that are presented on the contact card, I think the system is in control of them (see Build session above at about 36 minutes in) with the list of options being available on MSDN here.

When an app is invoked via the user clicking one of these actions, it gets a new kind of activation (ActivationKind.Contact) taken from here and I wanted to see what that looked like so I thought I’d try and build a new app which registered itself for the tel: scheme so I just made a blank app, made its background colour red and then changed its manifest to specify what I thought was the minimum to say that the app handles the tel: scheme;

image

and then I overrode the App.OnActivated member and set a breakpoint to see if using the “Call” verb from the contact card would activate my breakpoint;

    protected override void OnActivated(IActivatedEventArgs args)
    {
      if (args.Kind == ActivationKind.Contact)
      {
        var contactArgs = args as ContactCallActivatedEventArgs;

        if (contactArgs != null)
        {
          
        }
      }
    }

The answer is “no” Smile What I found is that my app would be listed as a possible handler for the tel: scheme when I tapped on the “Call” verb on the contact card but the app was then activated for ActivationKind.Protocol rather than ActivationKind.Contact.

There’s a good help page up on MSDN that explains why this would be happening – I need to further alter the app manifest to add an extension to it. I unloaded the manifest from Visual Studio and edited it manually to try and add the right section (as an aside, I understand that Visual Studio might not include graphical editing for every aspect of the manifest but it would be nice if it maybe had a list of some of the missing sections that you’re going to have to edit manually);

   <m2:Extension Category="windows.contact">
          <m2:Contact>
            <m2:ContactLaunchActions>
              <m2:LaunchAction Verb="call" DesiredView="useMinimum">
                <m2:ServiceId>telephone</m2:ServiceId>
              </m2:LaunchAction>
            </m2:ContactLaunchActions>
          </m2:Contact>
        </m2:Extension>

Note that the m2 XML namespace declaration was already present in my manifest file so I didn’t add it.

With that in place, when my first app now activates my second app from the “Call” verb on the contact card, I now see (visually);

image

followed by my “red” protocol handling app showing up in a “minimal” view;

image

and if I set my breakpoint in the debugger;

image

and so, while I haven’t implemented it properly I can see how this second app can get activated from a contact card raised by the first app and can then pick up the details of the activation and go and do something with those details (in this case perhaps launching a telephone call).

All in all, this seems like one of those “simple but powerful” additions to the platform that lets apps work in a more connected way without actually building any dependencies between them or (as it talked about in the video above) taking away the user’s consent or opening them to a bunch of potential “leaks” of their contact information. It’ll be interesting to see how developers make use of this new capability.