Damian Mehers' Blog Xamarin from Geneva, Switzerland.

17Sep/170

Using Siri to control your Alexa Smart Home devices

I have many Smart Home devices that can be controlled from my Amazon Echo, however none of those devices can be controlled from Siri on my Apple Watch or iPhone. None are HomeKit compatible.

What I've done lets me control my Alexa Smart Home devices via Siri on my Apple Watch or iPhone. This solution is not elegant (it involves a Raspberry PI, HomeBridge and a speaker) but it does work...

Code here. Demo here:

11Jun/170

Live coding a Xamarin Forms Custom Circle Control using SkiaSharp

Supports segments of varying colors, radius and degrees, and supports data binding.

Resulting code in GitHub

Filed under: Xamarin No Comments
5Jun/170

Live coding an Alexa Smart Home skill from scratch in C#

Resulting code is here

Filed under: Uncategorized No Comments
5Jun/170

Recording of iOS and Android and C# and Xamarin: These are a few of my favorite things

Filed under: Xamarin No Comments
20Mar/174

Using Google Sign-in for iOS in Xamarin Forms to access Google APIs

This is another of those posts where I am essentially writing a message to my future self to remind myself how to do something, and in the process perhaps help out someone else.

I wanted to use the Google Sign-in for iOS Xamarin Component from Xamarin Forms to let a user sign-in to Google, and then use the resulting access token to invoke one of the Google APIs, in my case the Google Tasks API.

There are several hurdles to overcome:

  • How to use the Google Sign-in for iOS Xamarin Component from Xamarin Forms, since the examples are for iOS apps;
  • How to use that component to request access to the Google Tasks API;
  • How to use the resulting access token to actually invoke the API.

Google Sign-in for iOS Xamarin Component from Xamarin Forms

The Getting Started Guide for the Google Sign-in for iOS Xamarin Component explains how to set up the component for a native Xamarin iOS app.

I followed its instructions with regards to registering on the Google API Console, downloading the GoogleService-Info.plist file, and setting up my AppDelegate:

    public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
    {
      return Google.SignIn.SignIn.SharedInstance.HandleUrl(url, sourceApplication, annotation);
    }

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {

      NSError configureError;
      Google.Core.Context.SharedInstance.Configure(out configureError);
      if (configureError != null)
      {
        // If something went wrong, assign the clientID manually
        Debug.WriteLine("Error configuring the Google context: {0}", configureError);
        Google.SignIn.SignIn.SharedInstance.ClientID = "....apps.googleusercontent.com";
      }

          ...

The instructions with regards to Signing In were trickier though, since they assume access to iOS View Controller.

Xamarin Forms hides such platform-specifics, however this post on Using Custom UIViewControllers in Xamarin.Forms on iOS by Xamarin's Mike Bluestein explains how to get hold of the ViewController by creating a custom renderer for a page.

Assuming your Xamarin Forms main page is called "MainPage" (inspired, I know), I followed Mike's instructions and ended up with a renderer like this:

using System.Diagnostics;
using System.Threading.Tasks;
using Foundation;
using Google.SignIn;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(enfiler.Views.MainPage), typeof(enfiler.iOS.IOSMainPage))]
namespace enfiler.iOS
{
  public class IOSMainPage : PageRenderer, ISignInUIDelegate, ISignInDelegate
  {
    TaskCompletionSource<string> _taskCompletionSource;

    public override void ViewDidLoad()
    {
      Services.GoogleTasks.Instance.GetAccessToken = GetAccessToken;
      base.ViewDidLoad();
    }


    public Task<string> GetAccessToken()
    {
      _taskCompletionSource = new TaskCompletionSource<string>();
      SignIn.SharedInstance.UIDelegate = this;
      SignIn.SharedInstance.Delegate = this;
      SignIn.SharedInstance.Scopes = new string[] { Google.Apis.Tasks.v1.TasksService.Scope.Tasks };
      SignIn.SharedInstance.SignInUser();
      return _taskCompletionSource.Task;
    }

    public void DidSignIn(SignIn signIn, GoogleUser user, NSError error)
    {
      if (error != null)
      {
        _taskCompletionSource.SetException(new NSErrorException(error));
      }
      else
      {
        _taskCompletionSource.SetResult(user.Authentication.AccessToken);
      }
    }
  }
}

When the Xamarin Forms page called MainPage loads, this renderer gets invoked to actually render it on iOS. Since it derives from the builtin PageRender class, it doesn't have to do any of the heavy lifting of rendering, but instead simply registers itself in the Services.GoogleTasks.Instance class in my Xamarin Forms PCL, which we will see later.

Notice how the GetAccessToken does the Sign In work described in the Getting Started guide. It provides for asynchronous invocation and thus uses the TaskCompletionSource class since the sign-in completes via the DidSignIn callback.

One difference from the Getting Started guide is that I'm specifying the Google Tasks OAuth Scope in GetAccessToken. In order to do this I needed to add the Google APIs Client Library nuget package. I also needed to activate the Google Tasks API for my app in the Google API Console.

Notice also that in the DidSignIn I'm completing the task returned from GetAccessToken either with an exception, or with the OAUTH access token resulting from logging in.

Invoking the Google Tasks API with the token returned from the Google Sign-In component

This is the GoogleTasks class with which the IOSMainPage class registered itself by setting the GetAccessToken callback:

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Google.Apis.Tasks.v1;

namespace enfiler.Services
{
  public class GoogleTasks
  {

    public static GoogleTasks Instance { get; } = new GoogleTasks();
    public async Task<Google.Apis.Tasks.v1.Data.Task> CreateTask(string title, string notes)
    {
      var taskService = new TasksService();
      var task = new Google.Apis.Tasks.v1.Data.Task
      {
        Title = title,
        Notes = notes
      };
      var request = taskService.Tasks.Insert(task, "@default");
      request.OauthToken = await GetAccessToken.Invoke();
      return await request.ExecuteAsync();
    }

    public Func<Task<string>> GetAccessToken { get; set; }
  }
}

I defined this in the Xamarin Forms PCL for my project, and added the Google APIs Client Library nuget package to my PCL too.

The key thing here is the assigning of the OauthToken on the request.

Inside my Xamarin Forms app whenever I want to create a new Google Task I await the invocation of CreateTask which calls back into the custom renderer:

      var googleTask = await Services.GoogleTasks.Instance.CreateTask("Hello To", "Jason Isaacs")

Summary

Google have deprecated the use of Web Views to authenticate with their services and are instead requiring the use of their own libraries, such as the Google Sign-In for iOS library.

By combining the use of the Google Sign-In for iOS Xamarin Component with a custom page renderer, and requesting a custom OAUTH scope I was able to request access to a user's Google Tasks, and then create a task.

I've not yet explored the same thing on Android, but I'd hope to be able to register a callback from my Android code just as on iOS to do the OAUTH dance.

24Jan/170

A more friendly Xamarin Forms DatePicker

This is a small, simple thing, to make a Xamarin Forms DatePicker more friendly. Instead of showing the date for yesterday, today and tomorrow, as it normally does, it instead shows "yesterday", "today", and, you guessed it, "tomorrow":

iOS: Android:

The view is totally straight-forward, except that instead of just binding the Date in the DatePicker, I also bind the Format:

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:local="clr-namespace:FriendlyDatePicker" 
    x:Class="FriendlyDatePicker.FriendlyDatePickerPage"
    BindingContext="{x:Static local:ViewModel.Instance}">
    <DatePicker Date="{Binding TheDate}" Format="{Binding DateFormat}"/>
</ContentPage>

The View Model's Format property looks at the date, and returns the appropriate (escaped) string:

namespace FriendlyDatePicker {
  public class ViewModel : INotifyPropertyChanged {
    public static ViewModel Instance { get; } = new ViewModel();
    public event PropertyChangedEventHandler PropertyChanged;
    DateTime theDate = DateTime.Now;

    public DateTime TheDate {
      get {
        return theDate;
      }

      set {
        theDate = value;
        OnPropertyChanged();
        OnPropertyChanged(nameof(DateFormat));
      }
    }

    public string DateFormat {
      get {
        var date = DateTime.Now.Date;
        if (theDate.Date == date) {
          return Escape("Today");
        }
        if (theDate.Date == date.AddDays(1)) {
          return Escape("Tomorrow");
        }
        return theDate.Date == date.AddDays(-1) ? Escape("Yesterday") : "d";
      }
    }

    private string Escape(string s) {
      var result = new StringBuilder();
      foreach (var c in s) {
        result.Append('\\');
        result.Append(c);
      }
      return result.ToString();
    }

    void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

I've noticed that this doesn't work in UWP apps because the DatePicker renders as a native component, and ignores the Format.

It is trivial, but does make for a nicer UX.

That's all folks, nothing more to see, move along now.

Filed under: Xamarin No Comments
3Dec/161

Using the Apple Thunderbolt display with the Dell XPS 13

After many years of buying Mac laptops, I've bought a Dell XPS 13.

One question was how much of my old Apple hardware I could reuse. By buying an Apple USB C charger, I can re-use all the power adapter plugs and extensions I've bought over the years.

The big question for me, however was my Apple Thunderbolt display. One option, which I've not tried, is to buy the Thunderbolt 3 to Thunderbolt 2 adapter, and plug it in directly. I've not found anyone saying that works, and it also consumes the one and only, and thus very precious USB-C/Thunderbolt 3 port.

The solution I've found, which is not for everyone, is to plug the Apple Thunderbolt display into a Mac Mini running Windows 10. Then I enable the "Projecting to this PC" capability on the Mac Mini.

untitled

On my XPS 13 I project to the Mac Mini and extend the displays (yes, the Thunderbolt display has a lower resolution than my XPS 13):

untitled2

Performance isn't enough for gaming, but its good enough for software development.

Filed under: Uncategorized 1 Comment
30Nov/1616

“Alexa, enable the My Notebook skill”

I just released my first Amazon Echo Skill, called "My Notebook".

You can use it to create notes in Evernote or OneNote using your Amazon Echo:

2016-11-30-18-37-54

To try it out, say "Alexa, enable the My Notebook skill".

It was rejected twice (for good reasons) during the review process, and I learned a lot as a result, especially around keeping the conversation going, responding to help requests etc.

For the technical, as well as using the Alexa Skills Kit, I used the Amazon API Gateway, an AWS Lambda (written in Python, since C# isn't yet available), and Amazon DynamoDB.

I'm caught between hoping it takes off, and people use it, but also hoping it isn't too popular, since it is free and I'm not keen on maxing out my credit card!

Filed under: Uncategorized 16 Comments
27Sep/160

Using Styles and Data Triggers to disable Xamarin forms while waiting

It's a common scenario: You are sending data to a service, or waiting for something to happen, and you don't want the user to interact with your form while that is happening.

untitled-1

The naive approach is to bind the IsEnabled property on your containing Layout to a boolean property in your View Model, but you'll soon find that IsEnabled is not inherited. Setting it on a StackLayout doesn't set it on all the controls embedded within that layout.

Here is a solution which binds the IsRunning property of an ActivityIndicator to a View Model property, and then uses a Style and a DataTrigger to react to the ActivityIndicator's running by setting the IsEnabled properties on the Layouts contained controls:

First I overlay an ActivityIndicator over my form using an AbsoluteLayout:

  <AbsoluteLayout>
    <ActivityIndicator
        IsRunning="{Binding Loading}" HorizontalOptions="Center" VerticalOptions="Center"
        IsVisible="{Binding Loading}" AbsoluteLayout.LayoutBounds="0,0,1,1"
        AbsoluteLayout.LayoutFlags="All" x:Name="ActivityIndicator" />
    <StackLayout Orientation="Vertical"
                 AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All">

Next in my StackLayout I define an explicit Style with a DataTrigger which disables the targeted control and sets its Opacity to 30% when the ActivityIndicator is running:

      <StackLayout.Resources>
        <ResourceDictionary>
          <Style TargetType="View" x:Key="MyBase">
            <!-- Disable controls when the activity indicator is running -->
            <Style.Triggers>
              <DataTrigger
                  TargetType="View"
                  Binding="{Binding Source={x:Reference ActivityIndicator}, Path=IsRunning}"
                  Value="True">
                <Setter Property="Opacity" Value="0.3" />
                <Setter Property="IsEnabled" Value="False" />
              </DataTrigger>
            </Style.Triggers>
          </Style>

You might hope that using an implicit style instead of an explicit style above would affect all views contained within the StackLayout, but it doesn't work like that. There is also the tantalizing and undocumented ApplyToDerivedTypes Style property, but that has no impact that I am aware of.

So instead I create implicit styles for each specific type of control I use inside my StackPanel:

          <!-- Define implicit styles for each control we use. -->
          <Style TargetType="Label" BasedOn="{StaticResource MyBase}" />
          <Style TargetType="Entry" BasedOn="{StaticResource MyBase}" />
          <Style TargetType="Button" BasedOn="{StaticResource MyBase}" />
        </ResourceDictionary>
      </StackLayout.Resources>

At least I'm able to reuse my base style. So here is my final complete view (but I'm not quite done yet):

<?xml version="1.0" encoding="utf-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:shared="clr-namespace:LoadingDemo.Shared;assembly=LoadingDemo.Shared"
             BindingContext="{x:Static shared:Locator.MyViewModel}"
             x:Class="LoadingDemo.MainPage">

  <!-- Use an absolute layout to overlay one control over another -->
  <AbsoluteLayout>
    <ActivityIndicator
        IsRunning="{Binding Loading}" HorizontalOptions="Center" VerticalOptions="Center"
        IsVisible="{Binding Loading}" AbsoluteLayout.LayoutBounds="0,0,1,1"
        AbsoluteLayout.LayoutFlags="All" x:Name="ActivityIndicator" />

    <StackLayout Orientation="Vertical"
                 AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All">

      <StackLayout.Resources>
        <ResourceDictionary>
          <Style TargetType="View" x:Key="MyBase">
            <!-- Disable controls when the activity indicator is running -->
            <Style.Triggers>
              <DataTrigger
                  TargetType="View"
                  Binding="{Binding Source={x:Reference ActivityIndicator}, Path=IsRunning}"
                  Value="True">
                <Setter Property="Opacity" Value="0.3" />
                <Setter Property="IsEnabled" Value="False" />
              </DataTrigger>
            </Style.Triggers>
          </Style>

          <!-- Define implicit styles for each control we use. -->
          <Style TargetType="Label" BasedOn="{StaticResource MyBase}" />
          <Style TargetType="Entry" BasedOn="{StaticResource MyBase}" />
          <Style TargetType="Button" BasedOn="{StaticResource MyBase}" />
        </ResourceDictionary>
      </StackLayout.Resources>

      <Label Text="My Label" HorizontalOptions="Center" />
      <Entry Placeholder="Enter text here" />
      <Entry Placeholder="Enter text here" />
      <Entry Placeholder="Enter text here" />
      <Button Text="Click Me" Command="{Binding StartCommand}" HorizontalOptions="Center" />
    </StackLayout>
  </AbsoluteLayout>
</ContentPage>

This is my View Model:

  public class ViewModel : INotifyPropertyChanged {
    private bool _loading;

    public ViewModel() {
      StartCommand = new Command(Start);
    }

    private async void Start() {
      Loading = true;
      await Task.Delay(TimeSpan.FromSeconds(5));
      Loading = false;
    }

    public bool Loading {
      get {
        return _loading;
      }
      private set {
        _loading = value;
        OnPropertyChanged();
      }
    }

    public ICommand StartCommand { get; }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }

When I test the above code in an app I created, everything works swimmingly except for the Button. It doesn't become disabled when I click it.

The reason is that I am using the Command property to execute code in my View Model, and the ICommand interface to which it is bound has its very own CanExecute mechanism to decide when the Button can be clicked.

The solution is in the View Model, and involves raising the CanExecuteChanged event:

    public ViewModel() {
      // When you click the button run the Start method.  The command is available
      // when not loading
      StartCommand = new Command(Start, canExecute: () => !Loading);
    }
...
public bool Loading {
      get { ... }
      private set {
        _loading = value;
        OnPropertyChanged();
        StartCommand.ChangeCanExecute();
      }
    }

Here is the final View Model:

  public class ViewModel : INotifyPropertyChanged {
    private bool _loading;

    public ViewModel() {
      // When you click the button run the Start method.  The command is available
      // when not loading
      StartCommand = new Command(Start, () => !Loading);
    }

    private async void Start() {
      Loading = true;
      await Task.Delay(TimeSpan.FromSeconds(5));
      Loading = false;
    }

    public bool Loading {
      get {
        Debug.WriteLine($"Returning {_loading}");
        return _loading;
      }
      private set {
        _loading = value;
        OnPropertyChanged();
        StartCommand.ChangeCanExecute();
      }
    }

    public Command StartCommand { get; }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }

I like to put my View Models in a separate class library, which has no dependencies on Xamarin Forms, but the Command class comes from Xamarin Forms. Fortunately Xamarin Forms is now open source, so I can "borrow" the Command class' source and embed it within my class library and thus remove the Xamarin Forms dependency.

The complete solution is here in GitHub.

4Sep/163

UWP OAuth in Xamarin Forms using Xamarin.Auth

tl;dr: Complete standalone example here.

I recently wanted to authenticate to Evernote via OAuth in a Xamarin Forms app I'm creating.

There is an excellent Xamarin plugin, called Xamarin.Auth which lets you do the OAuth dance for iOS and Android Xamarin Forms apps, but even in the latest branch, I couldn't get it working on the Universal Windows Platform (UWP) app.

Comments pointed to using a the WebAuthenticationBroker from Microsoft. There are plenty of examples here, unfortunately none for Evernote.

I created and published an Evernote UWP OAuth example using WebAuthenticationBroker based on the Twitter example, which was similar, but not similar enough to be able to just copy/paste.

Once I had this working I was back to Xamarin Forms,and put together a complete standalone example using Google, to log you in to Google and then display your email address and photo. Here it is running in UWP:

uwp 04

I published that example on GitHub.

In order to make Xamarin.Auth work, you create a platform specific page renderer which does the OAuth. I'd already done this for iOS and Android. For Windows I implemented it like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using Windows.Security.Authentication.Web;
using Windows.Web.Http;
using Newtonsoft.Json;
using Xamarin.Auth;
using Xamarin.Forms.Platform.UWP;
using XamFormsUWPOAuth;
using XamFormsUWPOAuth.Shared;
using XamFormsUWPOAuth.UWP;

[assembly: ExportRenderer(typeof(AuthenticationPage), typeof(AuthenticationPageRenderer))]

namespace XamFormsUWPOAuth.UWP {
  class AuthenticationPageRenderer : PageRenderer {
    private bool _isShown;

    protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) {
      base.OnElementPropertyChanged(sender, e);
      if (_isShown) return;
      _isShown = true;

      var code = await AuthenticateUsingWebAuthenticationBroker();
      var account = await ConvertCodeToAccount(code);
      await AuthenticationHelper.FetchGoogleEmailAndPicture(account);
    }


    private async Task<string> AuthenticateUsingWebAuthenticationBroker() {
      var googleUrl = Constants.AuthorizeUrl + "?client_id=" +
                      Uri.EscapeDataString(Constants.GoogleClientId);
      googleUrl += "&redirect_uri=" + Uri.EscapeDataString(Constants.GoogleCallbackUrl);
      googleUrl += "&response_type=code";
      googleUrl += "&scope=" + Uri.EscapeDataString(Constants.Scope);

      var startUri = new Uri(googleUrl);

      var webAuthenticationResult =
        await
          WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, startUri,
            new Uri(Constants.GoogleCallbackUrl));
      return webAuthenticationResult.ResponseStatus != WebAuthenticationStatus.Success ? null : webAuthenticationResult.ResponseData.Substring(webAuthenticationResult.ResponseData.IndexOf('=') + 1);
    }


    private static async Task<Account> ConvertCodeToAccount(string code) {
      var httpClient = new HttpClient();
      IHttpContent content = new HttpFormUrlEncodedContent(new Dictionary<string, string> {
        {"code", code},
        {"client_id", Constants.GoogleClientId},
        {"client_secret", Constants.GoogleClientSecret},
        {"redirect_uri", Constants.GoogleCallbackUrl},
        {"grant_type", "authorization_code"},
      });
      var accessTokenResponse = await httpClient.PostAsync(new Uri(Constants.AccessTokenUrl), content);
      var responseDict =
        JsonConvert.DeserializeObject<Dictionary<string, string>>(accessTokenResponse.Content.ToString());

      return new Account(null, responseDict);
    }
  }
}

You could use one of the other Microsoft OAuth examples, or your own, in order to do the OAuth.

The AccountStore stuff is a little different. I wanted to reuse the AccountStore goodness that comes with Xamarin.Auth, but I needed a UWP AccountStore implementation. I also needed to ensure my shared code, in my shared project, picked up my UWP AccountStore. I did this by creating a simple container class in the shared project:

using System;
using Xamarin.Auth;

namespace XamFormsUWPOAuth.Shared {
public static class AccountStoreFactory {
    public static Func<AccountStore> Create { get; set; } = () => AccountStore.Create();
  }
}

I use this in order to get at the shared AccountStore throughout my code, rather than using AccountStore.Create() which you'd normally do. In my UWP startup code, I overwrite the default AccountStore (which doesn't exist on UWP anyway) in my App.xaml.cs :

    protected override void OnLaunched(LaunchActivatedEventArgs e) {
      AccountStoreFactory.Create = () => new UWPAccountStore();
      Frame rootFrame = Window.Current.Content as Frame;
              ...

My UWP specific AccountStore implementation was based on this one in the portable-bait-and-switch branch)

It makes use of the Igor Kulman's DataProtectionExtension implementation here.

uwp 01

uwp 03

uwp 04

Check out the full standalone example that works with iOS, Android and of course UWP in my GitHub repository.

Filed under: Xamarin 3 Comments