Running Android Device Tests for Xamarin.Essentials on Windows

As a developer working with Xamarin or Xamarin.Forms you should be aware of the Xamarin.Essentials package that Microsoft have been developing that “provides developers with cross-platform APIs for their mobile applications”. If you haven’t taken the time to look through the source code, it’s well worth cloning the repository and taking a look. Not only is this a great example of how to do multi-targeting, they’ve also taken the time to invest in device specific tests. In this post we’re going to look at how to run the device tests for Android in the same way that it’s run as part of the Azure Pipelines build script.

The first thing to do is of course clone a copy of the repository and then launch the solution in Visual Studio – before we try to run the device tests we’d better make sure everything is able to be built and run. Unless you’ve been using the same machine for a long time, you’re unlikely to have all the difference MonoAndroid SDKs installed. When you take a look at the Dependencies for Xamarin.Essentials in the Solution Explorer window it’s likely to look similar to what mine did.

The good news is that if you force a build, some of these are likely to go away. For example I actually did have 8.0 and 8.1 installed, so after the build they were resolved and the warning indicators disappeared. Unfortunately, the bad news is that I still had a couple of missing versions.

Luckily this is easily resolved using the Android SDK Manager (launch this from Tools > Android > Android SDK Manager from within Visual Studio), where you can install the missing SDK Platforms.

You’ll need to accept the license terms.

Installing the missing Android SDKs should resolve the Android dependencies. If you’re still seeing a warning for the UAP dependency, you need to verify that you’ve got the Windows SDK v 10.0.16299 installed.

The build process for Xamarin.Essentials is driven from the azure-pipeline.yml file in the root of the repository. This YAML file defines various jobs, one of which is the devicetests_android, which as the name suggests, runs the device tests. Actually this job invokes build.sh, specifying the test-android-emu target. The build.sh is actually just a proxy for running build.cake.

I wanted to run the device tests on Windows, so I’m going to be invoking build.ps1, which is the Powershell equivalent for invoking build.cake. The following command invokes Powershell, passes the build.ps1 as the Powershell script to invoke, and then I’ve included the other parameters that were specified in the azure-pipeline.yml.

powershell -f build.ps1 --target=test-android-emu --settings_skipverification=true --verbosity=diagnostic

Note: You need to invoke this command from the DeviceTests folder.

Unfortunately, simply running the Powershell script from a command prompt isn’t sufficient. There are a few steps you’ll need to jump through in order to get the script to run correctly. Without making any changes, if you run the Powershell script you’ll most likely see an error similar to the following image.

Whilst the error is highlighted in red, the actual cause of the error is in light grey font and indicates that JAVA_HOME hasn’t been defined. Easily fixed by using the set command (make sure the path to the JDK matches where it is on your computer).

set JAVA_HOME=C:\Program Files\Android\Jdk\microsoft_dist_openjdk_1.8.0.25

Also, whilst we’re setting environment variables, check that ANDROID_HOME and ANDROID_SDK_ROOT are set to the root folder of the Android SDK installation (typically C:\Program Files (x86)\Android\android-sdk on Windows if installed via Visual Studio installer)

Suggestion: You’ll find that invoking the Powershell script can be quite time consuming because Xamarin.Essentials has to be built (once for each supported platform) and then the emulator needs to be created and launched. To accelerate this process, after running the script the first time, you can temporarily disable the build by commenting out the “.IsDependentOn("Build-Android")” line in the build.cake file.

Now, when you run the Powershell script, you’re likely to see a different error. Again, it’s not the highlighted error that contains the useful information. Looking a few lines earlier you can see that there is an error relating the system image that the script attempts to use.

Again, fixing this issue is relatively easy. You just need to pick one of the existing system images (listed alongside the error) and use it to set the ANDROID_EMU_TARGET variable.

set ANDROID_EMU_TARGET=system-images;android-29;google_apis_playstore;x86

The next error you’ll see is at the point where the script attempts to launch the emulator. It will fail, indicating that it can’t find the file specified.

It would appear that the build script, build.cake, attempts to call “emulator.bat”. However, this file doesn’t exist. Instead, there is an emulator.exe – we just need to adjust the build.cake to use .exe instead of .bat when locating the emulator command.

Unfortunately there’s also an issue with the search logic, resulting in using a copy of emulator.exe that doesn’t work. After making the above change to .exe, you’ll see that it attempts to launch the emulator but comes up with an error “PANIC: Missing emulator engine program for ‘x86’ CPU”.

Again, this issue is easily fixed with a small change to build.exe to get it to search for the emulator.exe in the correct folder. In the following code, we’ve adjusted the search logic to look in only the emulator folder on Windows.

if (ANDROID_HOME != null) {
        var andHome = new DirectoryPath(ANDROID_HOME);
        if (DirectoryExists(andHome)) {
            if(IsRunningOnWindows()){
                emulatorPath = MakeAbsolute(andHome.Combine("emulator").CombineWithFilePath("emulator" + emulatorExt)).FullPath;
                if (!FileExists(emulatorPath))
                    emulatorPath = "emulator" + emulatorExt;
            }
            else{
                emulatorPath = MakeAbsolute(andHome.Combine("tools").CombineWithFilePath("emulator" + emulatorExt)).FullPath;
                if (!FileExists(emulatorPath))
                    emulatorPath = MakeAbsolute(andHome.Combine("emulator").CombineWithFilePath("emulator" + emulatorExt)).FullPath;
                if (!FileExists(emulatorPath))
                    emulatorPath = "emulator" + emulatorExt;
            }
        }
    }

Finally, when you run the script now, it will run through without error. However, you will see a Windows Security Alert requesting a rule be added to the firewall. You’ll need to click the Allow access button in order for the emulator to talk back to the build script – it uses a TCP listener to retrieve the results from the device tests.

After granting permissions, you should see the following output – if you want more details on the device test output, there’s an xml file that is returned which has the full details of the test execution.

One last comment: If you have the emulator running when you run the device test script, you’ll find that it generates an error at the end of running the script. When the script attempts to launch the emulator, emulator.exe will detect the running emulator and will exit immediately. At the end of the script it attempts to terminate the emulator.exe process – since this process has already ended, it throws and error. You can ignore this error as the device tests will still have executed correctly.

MVVM Navigation with Xamarin.Forms Shell – Part II

Following my previous post on Mvvm Navigation with Xmarin.Forms Shell there were a few things that I felt I hadn’t addressed adequately.

Loading Data on Appearing

The first thing is how to load data when navigating to a page, and perhaps to do something when the user navigates away from the page. Since it’s the responsibility of the viewmodel to provide the data (i.e. via data binding), we have to invoke a method on the corresponding viewmodel when arriving at a page. In Xamarin.Forms the navigation to/from a page invokes the OnAppearing and OnDisappearing methods, which we can use to request that the viewmodel loads data.

The simplest approach is that for each page that needs to load data, the developer can override the OnAppearing method and simply call a method, for example LoadData, on the corresponding viewmodel. Since most pages are likely to have to load some data, this will quickly become a bit of a drag and something we can easily optimise. We’ll introduce an interface, INavigationViewModel, that when implemented by a viewmodel will define methods OnAppearing and OnLeaving. Then in our BasePage (which we introduced in the previous post) we simply need to check to see whether a viewmodel implements the interface before invoking the appropriate method.

public class BasePage : ContentPage
{
    protected override void OnAppearing()
    {
        base.OnAppearing();

        var vm = this.BindingContext as BaseViewModel;
        if (vm!=null && AppShell.Maps.TryGetValue(vm.GetType(), out var maps))
        {
            foreach (var map in maps)
            {
                map.Wire(vm);
            }
        }

        (vm as INavigationViewModel)?.OnAppearing();
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        var vm = this.BindingContext as BaseViewModel;
        if (vm!=null && AppShell.Maps.TryGetValue(vm.GetType(), out var maps))
        {
            foreach (var map in maps)
            {
                map.Unwire(vm);
            }
        }

        (vm as INavigationViewModel)?.OnLeaving();
    }
}

Note: If you’re going to be adapting some of this code for your project, you might want to consider making OnAppearing/OnLeaving return a Task that can be awaited.

Passing Parameter

The next point that we need to cover is how to pass a parameter from one page to the next. In our example, we have a list of items and when the user taps on an item the app navigates to the ItemDetailPage to view the details of the item. This requires some information about the selected item to be passed to the ItemDetailPage.

I’ve seen all sorts of mechanisms for passing data between pages across various application platforms. Some platforms only allow a simple query string to be passed as part of navigating between pages, whilst others allow you to pass entire objects. In the case of Xamarin.Forms the default navigation pattern doesn’t provide for a mechanism to pass data. However, because you create the instance of the new page before navigating to it, there’s a perfect opportunity to pass data from the existing page to the new page.

The following code is adapted from the code in the previous post to illustrate wiring up navigation to the ItemDetailPage based on the SelectedItemChanged event on the ItemsViewModel. Note that the selected item, passed into the event handler as the variable args, is set on the Item property of the ItemDetailViewModel.

// When the SelectedItemChanged event is raised on the ItemsViewModel
// navigate to the ItemDetailPage, passing in a new ItemDetailViewModel
// with the selected item
Maps.For<ItemsViewModel>()
    .Do(new EventHandler<Item>(async (s, args) =>
    {
        if (args == null)
        {
            return;
        }
        var page = new ItemDetailPage();
        if (page.BindingContext is ItemDetailViewModel vm)
        {
            vm.Item = args;
        }
        await Navigation.PushAsync(page);
    }))
    .When((vm, a) => vm.SelectedItemChanged += a, (vm, a) => vm.SelectedItemChanged -= a);

Note: Setting a property on the viewmodel will occur before the OnAppearing method is invoked (see previous discussion regarding loading data) which means the viewmodel can make use of whatever data you pass in when loading data. In this case we could have simply passed in the Id of the item we want to display and have the viewmodel load the rest of the data related to that item.

Returning a Parameter

One thing I’ve seen in a number of MVVM frameworks is the ability to navigate to a new page with the expectation that the page will return data at some point in the future. Whilst there are cases where this is convenient (eg prompting the user for some data) this pattern introduces a very heavy dependency between the lifecycle of two pages and their corresponding viewmodels.

An alternative is to assume that each page/viewmodel is independent and that when you arrive at a page any data that is displayed on the page should be refreshed. Of course, if you’ve got a long list of items that the user has scrolled mid-way down and you reload the list, it’s going to return to the top of the list, making the user experience quite nasty. Furthermore, if the list of items is coming from a service, you don’t want to be reloading that data every time the user goes back and forth to a details page.

Most of the above issues can be handled with appropriate caching of data in a service or manager class. If the user navigates to an item, makes changes and saves that item, the cached data in the service would be updated (along with any call required to any backend services). When the user returns to the list of items, the service would simply return the latest cached data. This addresses the latency issue of having to fetch data from a backend service but how do we address the scroll position issue?

One way is to only update the items in the list that have changed (ie catering for add, edit, delete of items). However, having to write this code for every page is again tiresome. In the past, I investigated a possible workaround for this issue when I discussed immutable data – check out posts I, II and III on working with immutable data

Summary

Again, the disclaimer here is that this isn’t a library that you can just drop in and use in your application. However, feel free to take/leave what code you find useful.

Get the latest source code

XAML Control Templates for Windows (UWP) and Platform.Uno

Recently there has been a lot of discussion about using code to declare the user interface of an app. Such as a recent post I did following the announcement of SwiftUI by Apple. In the Xamarin.Forms world the hashtag CSharpForMarkup has become the latest distraction. CSharpForMarkup encourages developers to move away from XAML to defining their layouts using C#. Whilst I’m not against this, I do feel that we’re all discussing the wrong problem. Whether you use code or XAML to define your layouts, Xamarin.Forms suffers from being tied to the underlying platform controls. Renderers, Effects and Visual are all mechanisms to compensate for not having XAML control templates for every control (more on templates).

Enter Platform.Uno and their mission to take the XAML framework from Windows (UWP) and adapt it to other platforms. As an alternative for building apps for iOS and Android, Platform Uno was moderately interesting. With their push to support WebAssembly, Platform.Uno opens up a world of opportunities for building rich applications for the web. Their recent example of publishing the Windows calculator to the web (https://calculator.platform.uno) is just the the start for this technology.

In this post we’ll walk through how the XAML templating system works and how to go about defining a Control Template to customise the behaviour of controls.

Note: In this post I’ll be using XAML so that I can use Blend to assist with writing XAML. You can choose to use C# if you prefer defining your layouts in code. The point of this post is to highlight the templating capabilities of UWP and Platform.Uno.

Lookless or Templated Controls

One of the foundations of XAML was the notion of a templated, or lookless, control. In his post “What does it mean to be ‘lookless’?” Dave observes that a lookless control is one where the UI is declared in XAML and the behaviour or functionality of the control is defined in code. My view is that a lookless control is one where the functionality of the control isn’t tied to a specific design. By this I mean that each aspect of the control should be defined using a template, thus making it a templated control. A developer using the control should be able to adjust any of the templates without affecting the functionality of the control.

What is a Button?

Let’s look at what this means in practice by examining a Button. If I asked you what you thought a Button in UWP is, you’d probably answer by writing the following element:

<Button Content="Press Me!" />

All you’ve done is declared a Button with content that says “Press Me!” that uses the default Button styles. You haven’t actually answered the question. So let’s start with a simple definition of a button.

A Button is an element that responds to the user tapping or clicking by performing some action.

However, in the context of UWP where a Button is an actual control, this definition is a little too vague. For example, the following Border/TextBlock combination matches the definition

<Border Background="Gray" Tapped="PressMeTapped">
    <TextBlock Text="Press Me!"/>
</Border>

Tapping on the Border does invoke the PressMeTapped event handler but is that all we mean when we say a Button. I would argue that one of the significant aspects to a Button is that it gives some visual cues to the user. By this I mean that when the user hovers their mouse over a button they can the mouse pointer changes, or the Button adjusts how it looks. Similarly, when the user taps or clicks on the Button they should get some visual feedback confirming their action. This feedback is what separates a Button from just simply a tap or click event handler that can be attached to any element.

What we’ve just observed is that the Button has a number of different visual states. In the context of a UWP button these are the Normal, PointerOver and Pressed states. Using the default Button style in the Light theme, these states are shown in the following image.

States in the Control Template for the UWP Button
UWP Button States

As part of extending our definition of a Button I was careful not to define what feedback, or change to layout, should be used for each state of the Button. UWP ships with Dark and Light themes and a set of default control styles that combine to give you the states shown above. However, the important thing to remember is that the visual appearance isn’t what defines a Button. Perhaps an updated definition might be something like:

A Button is an element that responds to the user tapping or clicking by performing some action. It has Normal, PointerOver, Pressed and Disabled visual states that can provide feedback and guide the user on how to interact with the control.

Content v Text Properties

Xamarin.Forms deviates from most other XAML platforms when it comes to defining elements and attributes. For example, instead of using a StackPanel, Xamarin.Forms has a StackLayout. Not only are they named differently, they also exhibit different behaviour. Similarly, the Button control has a Text property instead of a Content property. Whilst this might seem like a decision to simplify the Button control it highlights the limitation of Xamarin.Forms due to the lack of templating.

Let’s back up for a second and take a look at the Content property. In a lot of cases you might simply set the Content attribute to a string, such as the earlier example where I set the Content to “Press Me!”. However, to override the styling of the text, or add other content to the Button, I can set the Content property explicitly.

<Button>
    <StackPanel>
        <TextBlock Style="{StaticResource HeaderTextBlockStyle}"
                   Text="Press Me!" />
        <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                   Text="or.... perhaps not" />
    </StackPanel>
</Button>

Note: As the Content property on the Button is annotated with the ContentPropertyAttribute, we don’t need to wrap the StackPanel in Button.Content tags.

Even though I’ve changed the content of the Button, I haven’t in anyway changed the way the Button functions. In fact, in this case I haven’t even changed how the Button changes appearance for the different states.

Using a Content Template

Before we get into customising the different Button states I just wanted to touch on the use of content templates. In the previous example I showed how the Content of the Button could be set to any arbitrary XAML. What happens if I want to reuse the content layout but just with different text? This is where the ContentTemplate property is useful.

The ContentTemplate property expects a DataTemplate which will be used to define the layout for the Content. At runtime the DataContext of the ContentTemplate will be set to the value of the Content property. Let’s see this in practice by moving the XAML from the Content property into the ContentTemplate.

<Button>
  <Button.Content>
    <local:ButtonData Heading="Press Me!" SubText="or.... perhaps not" />
  </Button.Content>
  <Button.ContentTemplate>
    <DataTemplate>
      <StackPanel>
        <TextBlock Style="{StaticResource HeaderTextBlockStyle}"
                   Text="{Binding Heading}" />
        <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                   Text="{Binding SubText}" />
      </StackPanel>
    </DataTemplate>
  </Button.ContentTemplate>
</Button>

In this code block you can see that the Content property has been set to a new instance of the ButtonData class. The two TextBlock elements are subsequently data bound to the Heading and SubText properties.

public class ButtonData
{
    public string Heading { get; set; }

    public string SubText { get; set; }
}

What this shows is that we’ve separated the data (i.e. the instance of the ButtonData class) from the presentation (i.e. the DataTemplate that is specified for the ContentTemplate property). Now if we wanted to reuse the DataTemplate across multiple elements we can extract it as a StaticResource. The following code illustrates extracting the DataTemplate to a StaticResource, as well as updating the data binding syntax. The x:Bind syntax gives us strongly typed data binding. Meaning we get intellisense and better runtime performance as there are no reflection calls. Button1 and Button2 are properties on the page that return instances of the ButtonData class.

<Page.Resources>
    <DataTemplate x:Key="MyButtonTemplate"
                  x:DataType="local:ButtonData">
        <StackPanel>
            <TextBlock Style="{StaticResource HeaderTextBlockStyle}"
                       Text="{x:Bind Heading}" />
            <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                       Text="{x:Bind SubText}" />
        </StackPanel>
    </DataTemplate>
</Page.Resources>
<Button Content="{x:Bind Button1}"
        ContentTemplate="{StaticResource MyButtonTemplate}" />
<Button Content="{x:Bind Button2}"
        ContentTemplate="{StaticResource MyButtonTemplate}" />

Custom Control Templates

So far we’ve seen how the Button control supports arbitrary Content and the use of ContentTemplates to reuse layouts across multiple controls. Neither of these can be used to adjust the visual appearance of the different Button states. In this section we’re going to start by looking at what properties you can adjust to tweak the existing states. We’ll then bust out Blend and start messing with the way a Button looks. All of this will be done without changing the functionality of the Button.

ThemeResources in the Control Template

In the previous section I added some arbitrary XAML to the Content of the Button. However, when I run the application I still see the default background gray. The background of the Button control is part of the default Template for the control. We’ll delve into this in a little more detail in the next sections. For the time being we’re going to adjust the colour of the background and round the corners on the border.

Adjusting the background of the Button when it’s in the Normal state can be done two ways. You can either specify the Background on the Button element itself, or you can override the ButtonBackground resource with the colour of your choosing.

<Page.Resources>
    <Color x:Key="ButtonBackground">DarkGreen</Color>
</Page.Resources>

<Button Content="{x:Bind Button1}"
        Background="Blue"
        ContentTemplate="{StaticResource MyButtonTemplate}" />
<Button Width="200"
        Height="200"
        HorizontalAlignment="Center"
        Content="{x:Bind Button2}"
        ContentTemplate="{StaticResource MyButtonTemplate}" />

At this point if you run the application up on UWP you’ll see that the initial colours for the two Button elements are blue and dark green respectivey. However, if you move the mouse over each of them you’ll see that they switch back to a grey background. This is because we’ve only adjusted the colour used to set the initial background colour. To adjust the colour for the PointerOver and Pressed states we need to adjust the appropriate resources, which are aptly called ButtonBackgroundPressed and ButtonBackgroundPressed. A full list of the overridable colours is available in the documentation for the Button control. Alternatively you can find the entire list of built in color resources in the ThemeResources.xaml file (more information here).

Button Colors in ThemeResources.xaml

In addition to changing the background colour, we also wanted to round the corners of the border that appears around the control when the user moves the mouse in closer. This can be done by simply setting the CornerRadius property to 10 on the Button element.

When we get to talking about visual states we’ll go through how properties on the Button control are modified with each visual state.

Changing the Control Template Layout

Sometimes it’s necessary to make changes that can’t be achieved by either setting the ContentTemplate or overriding the default colour resources. For example, say you wanted to add the Built to Roam logo as a watermark behind the content of the Button. To do this we need to override the Template for the Button. For this I’m going to use Blend as it’s particularly good at edit templates.

To begin editing the control template, locate the Button in the Objects and Timelines window. Right-click on the [Button] and select Edit Template, followed by Edit a Copy.

Editing a Copy of the Default Button Template

Next, you’ll be prompted to give the new template a name and specify where you want the template to be defined. When the new template is created it will include the default Button Template, thus allowing you to customise it. In this case the WatermarkButtonTemplate will be defined in the current document, limiting its availability to just the Button elements on the page.

Naming the New Control Template

Note: In this example we’re copying the default Button template. However, what gets copied into the XAML is actually the entire default Button style. This includes all the default property setters. The value of the Template property is set to a new instance of a ControlTemplate.

I’m not going to go through the changes to the template in detail but the summary is:

  • Wrap the ContentPresenter in a Grid called ContentFrame
  • Move Background, BackgroundSizing, BorderBrush, BorderThickness and CornerRadius from the ContentPresenter to ContentFrame
  • Adjust Visual States so that they reference ContentFrame for border and background properties. Leave any references to Foreground targetting the ContentPresenter element.
  • Add an Image inside the Grid with Source set to an image added to the Assets folder.
  • Set Opacity to 20% (0.2) and Stretch to Uniform on the Image.

Before:

<ControlTemplate TargetType="Button">
    <ContentPresenter
        x:Name="ContentPresenter"
        Padding="{TemplateBinding Padding}"
        HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
        AutomationProperties.AccessibilityView="Raw"
        Background="{TemplateBinding Background}"
        BackgroundSizing="{TemplateBinding BackgroundSizing}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}"
        Content="{TemplateBinding Content}"
        ContentTemplate="{TemplateBinding ContentTemplate}"
        ContentTransitions="{TemplateBinding ContentTransitions}"
        CornerRadius="{TemplateBinding CornerRadius}">
        <VisualStateManager.VisualStateGroups>                
        ...
        </VisualStateManager.VisualStateGroups>
    </ContentPresenter>
</ControlTemplate>

After:

<ControlTemplate TargetType="Button">
    <Grid
        x:Name="ContentFrame"
        Padding="{TemplateBinding Padding}"
        Background="{TemplateBinding Background}"
        BackgroundSizing="{TemplateBinding BackgroundSizing}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}"
        CornerRadius="{TemplateBinding CornerRadius}">
        <Image
            Opacity="0.2"
            Source="Assets/BuiltToRoamLogo.png"
            Stretch="Uniform" />
        <ContentPresenter
            x:Name="ContentPresenter"
            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
            AutomationProperties.AccessibilityView="Raw"
            Content="{TemplateBinding Content}"
            ContentTemplate="{TemplateBinding ContentTemplate}"
            ContentTransitions="{TemplateBinding ContentTransitions}"
            FontFamily="Segoe UI" />
        <VisualStateManager.VisualStateGroups>
        ...
        </VisualStateManager.VisualStateGroups>
    </Grid>
</ControlTemplate>

The net result is that the image is displayed on top of the background colour (which is set on the parent Grid) but beneath the content.

The important thing about defining this ControlTemplate is that it can be reused on any Button, irrespective of the Content that is being displayed. Again, these changes have affected the design of the Button but we still haven’t modified what happens when the user interacts with the Button.

Tweaking Control Template Visual States

The last set of changes we’re going to look at is how we modify the behaviour of the Button when the user does interact with it. In this case we’re going to look at the Pressed state. We’re going to change the default behaviour to slightly enlarge the Button when it’s in the Pressed state. To do this we need to modify the Pressed VisualState that is defined inside the ControlTemplate.

Using Blend we’ll step through adjusting the Pressed Visual State to expand the Button to 150% of it’s original size (i.e. a scale of 1.5 in both X and Y directions). To get started in the Objects and Timeline window, right click the Button element and select Edit Template, then Edit Current. This is similar to what we did previously but this time we already have a ControlTemplate in the XAML for the page.

Edit an Existing Control Template

Next, from the States window, select the Pressed state. If you click where the word Pressed is written you should see both the focus border around the Pressed state and a red dot appear alongside, indicating that Blend is in recording mode. You should also see a red border appear around the main design surface. If you look at the Button on the design surface it should appear like it’s been Pressed to illustrate what the Pressed state looks like.

Switching to the Pressed state

In the Properties window, locate the Transform section. Select the third icon in, which is for adjusting the Scale of the element. Set both X and Y values to 1.5. You should see a white square alongside each of the values indicating that you’ve explicitly set the value.

Adjusting the Scale Transform for X and Y

If you go back to the Objects and Timeline window you should see that under the ContentFrame there are entries for RenderTransform/ScaleX and RenderTransform/ScaleY to indicate that these properties have been modified for the currently selected visual state.

Visual State Properties

If you run the application now and click on the Button you should see that whilst the mouse button is depressed the Button moves to the Pressed state which shows the Button enlarged.

Enlarged Pressed State for Button

If you examine the change to the XAML, what you’ll see is that two Setters were added to the Pressed Visual State.

<VisualState x:Name="Pressed">
    <VisualState.Setters>
        <Setter Target="ContentFrame.(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Value="1.5" />
        <Setter Target="ContentFrame.(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Value="1.5" />
    </VisualState.Setters>
    <Storyboard>
        ... other existing animations ...
    </Storyboard>
</VisualState>

Animating Content Template State Transitions

The change we just made to the Control Template was to change the Scale X and Scale Y properties for the Pressed state. However, this is rather a jarring experience as there’s no transition or animation defined. The final step in this process is to add a transition both too and from the Pressed state.

In the States window, click the arrow with a plus sign and select the first item (i.e. *=>Pressed) to add a transition that will be invoked whenever the Button goes to the Pressed state, regardless of the initial state.

Adding Transition into Pressed State

If you look in the Objects and Timeline window you can now see a timeline that will define what animations are run during the transition.

Start of the Transition Timeline

Over in the Properties window, locate the Transform section and click on the empty square alongside the X property. Select Convert to Local Value, which will set the value to 1. The square will now appear as a sold white square. Repeat for Scale Y

Setting the Start of the Transition

Back in the Objects and Timeline window you should now see a keyframe marker appear at time 0. Drag the vertical orange line to 0.5 seconds.

End of Transition in Timeline

Now in the Properties window set the Scale X and Scale Y to 1.5, which is the end values for the transition. Thisshould match the values previously set for the Pressed state.

End Transition Values

Repeat this process for a transition for leaving the Pressed state. The transition should be the reverse with the Scale X and Y starting at 1.5 and ending at 1.

Transitions In and Out of Pressed State

And there you have it, an animated Pressed state.

Animated Pressed State in Control Template

The final XAML for the Transitions includes two Storyboards that defines the transition to and from the Pressed state.

<VisualStateGroup.Transitions>
    <VisualTransition GeneratedDuration="00:00:00"
                      To="Pressed">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentFrame"
                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)">
                <EasingDoubleKeyFrame KeyTime="00:00:00"
                                      Value="1" />
                <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
                                      Value="1.5" />
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentFrame"
                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)">
                <EasingDoubleKeyFrame KeyTime="00:00:00"
                                      Value="1" />
                <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
                                      Value="1.5" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </VisualTransition>
    <VisualTransition GeneratedDuration="00:00:00"
                      From="Pressed">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentFrame"
                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)">
                <EasingDoubleKeyFrame KeyTime="00:00:00"
                                      Value="1.5" />
                <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
                                      Value="1" />
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentFrame"
                                           Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)">
                <EasingDoubleKeyFrame KeyTime="00:00:00"
                                      Value="1.5" />
                <EasingDoubleKeyFrame KeyTime="00:00:00.5000000"
                                      Value="1" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </VisualTransition>
</VisualStateGroup.Transitions>

As you can see from this walkthrough, the XAML templating system is relatively sophisticated. It allows for multiple levels of configuration or tweaking in order to get it looking just right.

In coming posts I’ll be talking more about what differentiates XAML and why it’s still being used across Windows, Xamarin.Forms and of course Platform Uno. If you’re looking for cross platform solutions, please don’t hesitate to contact me or anyone on the team at Built to Roam.

Xamarin Developer Summit Schedule Breakdown

In just under a month some of the biggest names in the Xamarin community will be presenting alongside a prominent members of the Microsoft Xamarin and Xamarin.Forms teams at the Xamarin Developer Summit.

Xamarin Developer Summit – 11/12 July – Houston, Texas

Whilst I’m not going to be able to make it across to the summit I wanted to do a bit call out to all the great sessions that are in the schedule. The summit is a result of the massive effort that Dan Siegel has put in and the support from all the fantastic presenters.

If you scan the schedule you’ll no doubt be familiar with some of the names but with so many great sessions, how do you know where to start. I thought I’d take the opportunity to break the sessions into some groups to help you decide what’s of interest. These are of course just my groups based on what I can gather from the session description.

Getting Started / Overview

Workshops

Optimisation / Quality

Testing

Mvvm / Architecture

  • Xamarin.Forms made better with Prism – Hussain Abbasi
  • Streamline & Simplify Events with Reactive Extensions – Shane Neuville
  • Rapid Enterprise Architecture Delivery – Paul Schroeder
  • Reactive UI and Reactive Extensions for Xamarin.Forms – Michael Stonis
  • Mobile architecture with MvvmCross, are you doing it right? – Martijn van Dijk
  • Using Xamarin.Forms Shell to easily create a consistent, dynamic, customized, and feature filled UI – Shane Neuville

Security

  • Authentication and Authorization for Xamarin apps using ADB2C and MSAL – David Allen

Device

AI / ML

  • Cognitive Services in Xamarin Applications – Veronika Kolesnikova
  • Build Smarter Cross-Platform Applications Using Xamarin, Azure Cognitive Services, and ML.NET – Richard Taylor
  • How to build your modern ai app with Xamarin – Lo Kinfey

Azure

  • Crafting Real-Time Mobile Apps with SignalR – James Montemagno
  • Light up Xamarin Apps with ChatBots – Sam Basu
  • Build a mobile chatbot with Xamarin & Bot Framework – Luis Beltran
  • Build a Media Streaming App With Azure and Xamarin – Matt Soucoup
  • Create Mixed Reality Experiences with Azure Spatial Anchors and Xamarin – Sweekriti Satpathy

Data

Design

  • Let’s Make Crazy Beautiful UI With Xamarin.Forms – David Ortinau
  • Creating Consistent UI with Xamarin.Forms Visual – David Ortinau

General

DevOps

For more information on any of these topics then you should Register and bring all your learnings back to your company, community through user groups and other forums.

Apple Introduces SwiftUI; So What?

Shortly after Apple announced SwiftUI a twitter thread erupted discussing a hypothetical Sharp UI. It was positioned an alternative for declarative ui development, across Xamarin applications in C# or F#.

What’s interesting is that both Google, with Jetpack Compose, and now Apple, with SwiftUI, have joined the modern evolution of app development by introducing a declarative way to define user interfaces. Declarative UI development has been around for a long time. For example, take any of a number of XAML based frameworks that Microsoft has produced (something completely missed by Martin’s post on What SwiftUI Means for Flutter who incorrectly claims declarative ui development was invented in React by Facebook).

So why now? Why is it that Apple, Google and Microsoft have all recognised that declarative UI is the way forward?

XAML as a Declarative UI

The back history of XAML goes way back to the WinForms days. It was common for developers to fight the IDE in order to wrestle control of the window layout. XAML was supposed to fix everything. It is not designed for humans (much the same way storyboards weren’t designed to be manually coded). XAML id designed for developer tooling such as Blend.

A few XAML frameworks later and what we find ourselves in Xamarin.Forms. The XAML is non-standard version. It is similar, yet in ways dramatically different from every flavour of XAML that predates it. The industry has moved on from trying to get previewers, such as Blend, to work. The developer community favours hot reload and the ability to adjust layout within a running app.

I’m sure that Xamarin.Forms will get there with XAML but is it too much of a liability? Should we look for an alternative?

Declarative UI in Code aka #CSharpForMarkup

Following down the discussion on the SharpUI twitter thread we end up discussing an alternative to XAML, which is declaring UI in code. This sounds awfully familiar to what SwiftUI or Flutter is doing, except this is for Xamarin.Forms.

Normally I would be against using declarative ui development in code as I feel that it becomes harder to separate the UI logic from the application logic. However, having spent time reviewing CSharpForMarkup I feel that it is a viable alternative to XAML and perhaps even removes a layer or two of the cognitive load Adam talks about

Cross Platform is the Future

At Built to Roam we spend a lot of time discussing app strategy with our clients. We often talk about the spectrum of app development options ranging from native all the way through to web. Almost the first thing we do is to discount and remove from discussion both native and web. If the client wanted a web experience, they would have gone to a web development agency, instead of come to us. We’re not going to recommend building a native application, even in Xamarin, when we should be considering cross platform options.

If you’re following the announcements about SwiftUI, or Jetpack Compose, sure go ahead and read up on them. Then pack them into their single platform box and put them back on the shelf. Take our your cross platform tool of choice (React Native, Flutter, Xamarin.Forms etc) and get back to building high quality amazing apps for both iOS and Android.


Nick Randolph @thenickrandolph
If you have an app and want to go cross platform, or are just starting you app development journey, contact Built to Roam.


Fiddler Debugging Http/Https Traffic for Xamarin iOS, Android and Windows (UWP) Applications

Debugging Http/Https Traffic using Fiddler for Xamarin iOS, Android and Windows (UWP) Applications

One of the most frustrating things as a frontend developer is when you are receiving incorrect data. You don’t know whether the problem lies with your application, or the backend services. The easiest way to validate this is to pretend to be a hacker. You can stage a man-in-the-middle attack on your own application. Debugging using tools like Fiddler or Charles can be used to inspect the traffic from your application. Unfortunately, the same effort that goes into protecting apps from such attacks, also means that it is harder for developers to setup Fiddler debugging.

In this post I’ll walk through setting up Fiddler debugging for a Xamarin.Forms application. The same basic approach will work for a native or Xamarin iOS/Android application as well. For this post I’ve created an application using the Blank Xamarin.Forms template that comes with Visual Studio 2019. I’ve selected to target all three platforms.

In the OnAppearing method in the MainPage of the Xamarin.Forms application, I’ve added some basic code to retrieve a string for a Https endpoint. We’ll use a Https endpoint on the assumption that if we can intercept Https then we can also intercept Http traffic.

protected override async void OnAppearing()
{
     base.OnAppearing();
     var client = new HttpClient();
     var users = await client.GetStringAsync("https://reqres.in/api/users?page=0");
     Debug.WriteLine(users);
}

Setting Up Fiddler Debugging

Before we get started with the individual platforms, it’s worth checking your configuration for Fiddler:

  • You need to make sure you have setup Https traffic decryption. I’m not going to repeat the documentation, so check out how to Configure Fiddler to Decrypt HTTPS Traffic.
  • You’ll also need to setup Fiddler debugging for remote traffic. This can be done by opening the Options window. Under the Connections tab, make sure the “Allow remote computers to connect” checkbox is checked. If you’re running Skype, or some other communication tools, it may have jumped onto the default port configured in Fiddler. In this case you can adjust the “Fiddler listens on port”.
Fiddler Debugging Options Window
Enabling remote connection in Fiddler

Windows (UWP)

I’ll start with Windows, because it’s relatively straight forward to get setup. With Fiddler running, you can run the UWP project from within Visual Studio and Fiddler debugging will work. Fiddler will capture the Https traffic without any further configuration or setup.

Fiddler Debugging
Capturing network traffic in Fiddler

In some cases, you need to make sure your application is added to the exemption list, so that traffic can be routed to the local machine. For more information see the blog post Revisiting Fiddler and Win8+ Immersive applications. To check this, click the WinConfig button in the top left corner of the Fiddler interface.

WinConfig
Click WinConfig to adjust the exemption list for Windows 10 apps

Locate your application and confirm that there is a check in the box next to your application. If it’s not checked, check the box, and then click Save Changes

Exemption Utility
Locate your UWP application and check the box to add your application to exemption list

One other issue I’ve seen but can’t reproduce reliably, is that sometimes when you run your application from Visual Studio it unchecks the box in the WinConfig in Fiddler. If for some reason you no longer see traffic in Fiddler for your application, go back and double check the exemption list in Fiddler.

Diagnosing Issues with Fiddler on Windows

When configuring Https traffic decryption, you’ll be prompted to install and trust the Fiddler root certificate. If you don’t accept all the prompts, Fiddler debugging for Windows applications will not work. Windows traffic debugging works without any further configuration because the Fiddler root certificate is trusted on the machine running Fiddler.

If you’re attempting to run the Windows application on a different machine than the one running Fiddler, you’ll need to install and trust the Fiddler root certificate. This is in addition to setting the remote machine as a proxy, which is a topic for another post. Navigate to http://[ipaddress]:[port] where [ipaddress] is the ip address of the machine running Fiddler and the [port] is the port number that Fiddler is listening on. Do NOT use https as this site is http only. You should see a screen similar to the following image – if you don’t, make sure you check that Fiddler is running!!

Fiddler Debugging Echo Service
Click on the FiddlerRoot certificate to install the root certificate

Click on the FiddlerRoot Certificate and install as a Trusted Certificate Authority on the Local Machine. This should allow your Windows application to trust Fiddler.

iOS Fiddler Debugging

Next up is iOS and in this case we’re going to use the iOS simulator. The same process should work with any iOS device that’s on the same local network as the machine running Fiddler. There are two steps to setup iOS for traffic debugging:

  1. Trust the Fiddler root certificate, and
  2. Set the http proxy to use the machine running Fiddler.

To setup the simulator, first launch the iOS application from Visual Studio. If you’re on Windows, this will launch the remote viewer for the simulator. Once the simulator is running, stop debugging and we’ll setup the simulator for traffic debugging.

Trusting the Fiddler Certificate

Navigate to http:[ipaddress]:[port] (eg http://192.168.1.109:8888) to load the Fiddler echo page. Then click on the Fiddler Certificate link. Follow the prompts to download and install the certificate.

Fiddler Echo Service iPhone Download Certificate iPhone Download Profile iPhone

In addition to downloading the certificate you also need to install it. Go to Settings / General / Profile and click through on the FiddlerRoot profile in order to Install it.

image image image image image image image

The Fiddler root certificate needs to be trusted as a root certificate. Go to Settings / About / Certificate Trust Settings and toggle the switch next to the FiddlerRoot certificate. Fiddler generates a certificate for each site you go to that is derived from the root certificate, so the root certificate needs to be installed as a trusted certificate.

image image image image

The only difference between a real iOS device and the simulator is that on a real iOS device you can set a network proxy. There are online tutorials, such as this one, for instructions on setting a proxy. Unfortunately, setting up a proxy this isn’t configurable on the simulator. If you want to use a proxy in the simulator, you can set the proxy on the mac running the simulator but this would affect all traffic on the mac. Alternatively, when running on the simulator, we can adjust the HttpClient to use a WebProxy using the following code:

var handler = new HttpClientHandler();
handler.Proxy = new WebProxy("192.168.1.109", 8888);
var client = new HttpClient(handler);

Running the iOS application should show network traffic in Fiddler debugging window. You should still see the returned data printed out in the Output window (ie from the Debug.WriteLine statement).

Android Fiddler Debugging

For Android I’m going to use the Android Simulator. Real devices should behave similarly, assuming they’re connected to the same local network as the machine running Fiddler.

Unlike iOS, that will use any proxy configured for the device, for Android you need to explicitly opt in to use a proxy in your code. You’ll need to use code similar to the following on both emulator and real devices:

var handler = new HttpClientHandler();
handler.Proxy = new WebProxy("192.168.1.109", 8888);
var client = new HttpClient(handler);

What’s a little scary about this code is that it “just works”. You might be thinking that this is a good thing. However, it does raise the question of how much of the system security model does the Microsoft built HttpClientHandler respect. What I would have expected is an SSL fail exception because the Fiddler root certificate isn’t trusted by the emulator. Furthermore, the application is not configured to use any user certificates.

The other thing to point out here is that you should not be using the HttpClientHandler. I’ve discussed this in my previous post on working with the HttpClient. Let’s change our code by moving it into the OnCreate method of the Android head project. We’ll also change over to using the AndroidClientHandler.

protected override async void OnCreate(Bundle savedInstanceState)
{
     ...
     var handler = new AndroidClientHandler();
     handler.Proxy = new WebProxy("192.168.1.109", 8888);
     var client = new HttpClient(handler);
     var users = await client.GetStringAsync("https://reqres.in/api/users?page=0");
     System.Diagnostics.Debug.WriteLine(users);
}

When we run the application we see the very familiar SSL handshake exception being raised, which is what we should expect. To get things to work, we now need to install the Fiddler certificate and configure the application to use user certificates.

Install the Fiddler Root Certificate

To install the Fiddler root certificate, navigate to http:[ipaddress]:[port] (eg http://192.168.1.109:8888) to load the Fiddler echo page. Click on the Fiddler Certificate link in order to download the certificate. Follow the prompts to download and install the certificate

image image image image image  image

After installing the certificate go to Setting / Security and Location / Encryption & credentials / User credentials to inspect the certificate

image  image

With the certificate installed into the user store, you need to configure the Android project to allow the use of certificates from the user store. In my post Working with Self Signed Certificates (Certificate Pinning) in Android Applications with Xamarin.Forms, I covered this in detail. The quick summary is that you need to create a network_security_config.xml file which sets the trust-anchors property (set using the debug-overrides element) to include certificates from the user store. You then need to reference this xml file from the networkSecurityConfig attribute on the application element in the AndroidManifest.xml file.

After installing the certificate and adding the network security configuration to the Android application you should now see network requests from the application appear within Fiddler debugging window.

Self Signed Android Certificates and Certificate Pinning in Xamarin.Forms

Working with Self Signed Certificates (Certificate Pinning) in Android Applications with Xamarin.Forms

Next up is looking at working with self-signed certificates in an Android application. Previous posts in this sequence are:

In this post we’re going to briefly talk about non-secure services. Next, we’ll look at how to trust self signed certificates by adding them to the Android bundle. Then lastly we’ll look at intercepting the certificate validation process when making service calls.

One resource that is particularly useful is the network security documentation provided for Android developers. This lists the various elements of the network security configuration file that this post will reference.

Non-Secure (i.e. Http) Services

By default, Android, like iOS, doesn’t allow applications to connect to non-secure services. This means that connecting to http://192.168.1.107 or http://192.168.1.107.xip.io will not work out of the box. You’ll see an error similar to the following, if you attempt to connect to a non-secure service:

Java.IO.IOException: Cleartext HTTP traffic to 192.168.1.107 not permitted occurred

It’s important to note that this behaviour has changed between Android 8.1 and Android 9. Prior to Android 9 there were no default restrictions on calling non-secure, or plain text, services.

Adding Network Security Configuration

You can enable accessing Http/Plain text services by adjusting the network security configuration for the application. To do this we need to add an xml file to the Resources/xml folder which we’ve called network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
     <base-config cleartextTrafficPermitted="true" />
</network-security-config>

This adjusts the network security for the application both in debug and in production. If you want to access plain text services only during debugging, you should change the base-config open and close tags to debug-overrides (everything else remaining the same). The “Application (Debuggable = true/false)” assembly attribute controls whether or not the application runs in debugging mode.

#if DEBUG
[assembly: Application(Debuggable = true)]
#else
[assembly: Application(Debuggable = false)]
#endif

We also need to add a reference to the network_security_config.xml file. In the application manifest file (AndroidManifest.xml) add the networkSecurityConfig attribute.

<?xml version="1.0" encoding="utf-8"?>
< manifest http://schemas.android.com/apk/res/android%22">http://schemas.android.com/apk/res/android"
           android_versionCode="1"
           android_versionName="1.0"
           package="com.refitmvvmcross"
           android_installLocation="auto">
     <uses-sdk android_minSdkVersion="19"
               android_targetSdkVersion="28" />
     <application
         android_allowBackup="true"
         android_theme="@style/AppTheme"
         android_label="@string/app_name"
         android_icon="@mipmap/ic_launcher"
         android_roundIcon="@mipmap/ic_launcher_round"
         android:networkSecurityConfig="@xml/network_security_config"
         android_resizeableActivity="true">
         <meta-data
             android_name="android.max_aspect"
             android_value="2.1" />
     </application>
< /manifest>

You can change the filename of the network_security_config.xml file, so long as it matches the networkSecurityConfig attribute value in the AndroidManifest.xml file.

If you run the application it will connect to the Http/Plain text endpoint.

Plain-text on iOS

In addition to enabling/disabling Http/Plain text services across the entire application, it can also be controlled on a per-endpoint basis. See the documentation on the Network Security Configuration for more information.

Self Signed Certificate Endpoints

Switching the endpoint to a Https endpoint with a self signed certificate (eg https://192.168.1.107:5001) will raise the following error:

Javax.Net.Ssl.SSLHandshakeException: <Timeout exceeded getting exception details> occurred

Which of course is completely meaningless, except that we do know it’s related to establishing the SSL connection.

If we look to the Output window, we can find more information about the exception. Unfortunately when an Android app crashes it will spew a lot of mostly irrelevant data into the output window. I’m sure all that debug information is useful in a lot of cases. However, in this case it is a lot of irrelevant information that makes it hard to find the important information. The best way to find more information is to search for the error from the debug session (i.e. Javax.Net.Ssl.SSLHandshakeException). Once found, look at the next 10-15 lines of information. In this case we see

05-04 08:31:21.756 I/MonoDroid( 5948): UNHANDLED EXCEPTION:
05-04 08:31:21.768 I/MonoDroid( 5948): Javax.Net.Ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. ---> Java.Security.Cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. ---> Java.Security.Cert.CertPathValidatorException: Trust anchor for certification path not found.

This points to the fact that the application hasn’t been able to verify the certificate path for the certificate returned by the service. This result is not surprising because the service is using a self signed certificate and neither the Android device or the application trust the certificate.

Trusting Self Signed Android Certificates

In this section we’re going to use the public key from the self signed certificate. This will allow the application to connect to the secure endpoint, without having to write code to intercept the certificate validation. We’ll cover two different ways but they amount to the same thing. In both cases it’s necessary to have the public key of the certificate authority available to the application. The application will use the public key to verify the certificate path of the certificate returned by the service.

Installing to the Android Certificate Store

The first option is to install the public key of the certificate authority onto the Android device. Android maintains two different certificate stores: system and user. We’re going to be adding the certificate to the user store. Aadding to the System store requires root access and can be done using ADB as shown in various posts, such as this one.

The public key that we need to use is the public key of the certificate authority. As discussed in previous posts, we’ve used mkcert to generate our self signed certificate. The public key of the certificate authority used by mkcert is available at C:\Users\[username]\AppData\Local\mkcertrootCA.pem

The first challenge is to get the certificate onto the device, which I typically find easiest via a download link. I add the public key to dropbox and then open the link in Chrome on the Android device:

image image

Installing the Public Key

After downloading the pem file, clicking on the file in the Downloads list does nothing. You actually need to go to Settings / Security & location / Encryption & credentials / Install from SD card

image

The name of the items under settings may vary from device to device. For example Install from SD card might be Install from storage. The quickest way is to search for certificate and go to the item that says something like Install from SD card.

image

Clicking on the Install from SD card/storage settings item will display a file picker. From the burger menu you can select Downloads which will reveal the pem file you’ve just downloaded. However, this item will be disabled, presumably because of some security related to downloaded items. I initially thought that I’d downloaded the wrong certificate format. In actual fact, if you go back to the burger menu and browse the contents of the device (see third image above) and click on Download, you’ll see the same rootCA.pem file but this time it’s not dimmed out and you can click on it.

image

Saving the Root Certificate

If you have a PIN setup on the device, when you click on the rootCA.pem, you’ll need to enter your pin. After entering your PIN you’ll be asked to enter a Name for the certificate and what the certificate is to be used for.

The Name isn’t particularly useful since it doesn’t show up anywhere. It doesn’t appear in either the Trusted credentials screen (second image, showing the added certificate), nor the Security certificate popup that appears if you click on the certificate for more information.

Since we want the certificate to be used by the app we leave the default use, “VPN and apps”. At this point if you open the service endpoint in the browser you should see that the certificate is trusted.

image

Accessing the Android Certificate Store

Now that we’ve installed the certificate, there’s just one change we need to make to the Android application itself. By default Android applications will only use certificates in the system store. However, you can adjust the application to make use of the user certificate store. To do this we need to add a trust-anchors and certificates elements to the network_security_config.xml with the following contents:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
     <debug-overrides>
         <trust-anchors>
            <certificates src="user" />
         </trust-anchors>
     </debug-overrides>
</network-security-config>

In this case, the certificates element will only be used when the application is running in debug mode (ie by using the debug-overrides element). Running the application now will return data from the Https endpoint.

image

The issue with this approach is that the public key for the certificate authority has to be installed on the device. Since the public key appears in the user store, it means that at any point the user could remove it. Whilst it is unlikely that the user will delete the individual item, they may decides to clear all cached credentials.

Clearing cached credentials has the unfortunate side effect of clearing out the user store, thus preventing the application from running. If you’re only connecting to endpoints for the purpose of development or debugging, this option may be sufficient and would minimise the changes required to the application.

Adding to Application Package

The second option is to add the public key of the certificate authority to the application package itself. We’ll use the DER format for the public key which we generated from the mkcert public key file in the previous post. Add the kestrel.der file to the Resources / raw folder, with Build Action set to AndroidResource, and the Custom Tool to MSBuild:UpdateGeneratedFiles.

image

You need to link the public key to the network security configuration file. Add the trust-anchors and certificates elements to the network_security_config.xml file as follows:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
     <base-config>
         <trust-anchors>
             <certificates src="@raw/kestrel" />
         </trust-anchors>
    </base-config>
</network-security-config>

If you only want to use the certificates in debugging, exchange the base-config with debug-overrides.

That’s all you need to do to be able to access a service that uses a self-signed certificate.

Validating Server Certificates (i.e. Android Certificate Pinning)

The other alternative to working with self signed certificates is to override the certificate validation that is done as part of each service request. On Android you can override the ConfigureCustomSSLSocketFactory and GetSSLHostnameVerifier methods on the AndroidClientHandler. For example, here’s a CustomerAndroidClientHandler that inherits from the AndroidClientHandler and overrides these methods:

public class CustomAndroidClientHandler : AndroidClientHandler
{
     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
     {
         request.Version = new System.Version(2, 0);
         return await base.SendAsync(request, cancellationToken);
     }

    protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
     {
         return SSLCertificateSocketFactory.GetInsecure(0, null);
     }

    protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
     {
         return new BypassHostnameVerifier();
     }
}

internal class BypassHostnameVerifier : Java.Lang.Object, IHostnameVerifier
{
     public bool Verify(string hostname, ISSLSession session)
     {
         return true;
    }
}

We’ve also included the class BypassHostnameVerifier, which is a basic implementation of the IHostnameVerifier that needs to be returned from the GetSSLHostnameVerifier method. In the ConfigureCustomSSLSocketFactory method we’re returning a factory generated by the GetInsecure method. According to the method documentation the GetInsecure method “Returns a new instance of a socket factory with all SSL security checks disabled”. The documentation goes on to provide a warning “Warning: Sockets created using this factory are vulnerable to man-in-the-middle attacks!”.

I would like at this point to reiterate this warning. By providing your own handling of the SSL checks, you are effectively taking ownership and responsibility of making sure your application isn’t being hacked. As such, I would recommend only overriding these methods when you need to connect to a service that uses a self signed certificate. Make sure that in the Verify method you validate the service response to ensure only responses with self signed certificates that you trust are processed (ie check for man-in-the-middle attacks).

If you’re just interested in certificate pinning (i.e. ensuring that your application is connecting to a server that is returning a known certificate) you can simply override the GetSSLHostnameVerifier method. This will leave the default SSL verification/security in place but give you the opportunity to validate that the certificate being returned is what you expect.

Http2 Handling on Android

The bad news is that Http2 combined with self signed certificates doesn’t currently play nicely with the out of the box AndroidClientHandler. The AndroidClientHandler is the default and preferred handler on Android. When you attempt to connect to a service that is Http2 only and it uses a self signed certificate, you’ll probably see an error similar to the following:

Javax.Net.Ssl.SSLHandshakeException: Connection closed by peer occurred

Unfortunately there’s no simple solution without importing another library. Luckily, the ModerHttpClient library has the code necessary to do this and is updated slightly in the modernhttpclient-updated nuget package.

Please do not include the nuget package in your application as neither the original or the updated package are being actively maintained. Instead, copy the source code that you need (in this case the NativeClientHandler) and take ownership of maintaining it within your application logic.

To round this out, here’s an example that overrides the NativeMessageHandler to set the Http version to 2.

public class CustomNativeClientHandler : NativeMessageHandler
{
     protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
     {
         request.Version = new System.Version(2, 0);
         return await base.SendAsync(request, cancellationToken);
     }
}

And when an instance of the CustomNativeClientHandler is created, the EnableUntrustedCertificates property is set to true. This effectively disables any of the SSL checking, so again opens up the risk of man-in-the-middle attacks.

Mvx.IoCProvider.LazyConstructAndRegisterSingleton<HttpMessageHandler, IServiceOptions>(options =>
{
     return new CustomNativeClientHandler
     {
         AutomaticDecompression = options.Compression,
         EnableUntrustedCertificates = true
     };
});

And when we run this, we can see that the Http protocol used is Http/2.

image

In this post we’ve touched on using both self signed certificates, as well as certificate pinning. This is not an easy topic but important for application developers to be across. If you come across issues with your application security, feel free to reach out on twitter or via Built to Roam’s contact page.


Nick Randolph @thenickrandolph

Built to Roam on building cross-platform applications


Self Signed iOS Certifcates and Certificate Pinning in a Xamarin.Forms application

Working with Self Signed Certificates (Certificate Pinning) in iOS Application with Xamarin.Forms

The next post in the app security series looks at working with self-signed certificates in an iOS application. Previous posts in this sequence are:

In this post we’re going to cover:

1) accessing non-secure services

2) trusting a self-signed certificate and

3) handling certificate validation.

This gives you all the options you should need when accessing which security option to use during development. It will also cover how to implement certificate pinning in the production version of your app.

Non-Secure (i.e. Http) Services

iOS is secure by default, which means that, by default, an iOS application can only connect to services over Https. The certificate will be verified against one of the well known certificate authorities. Most production services will use a certificate that has been issued by a well know certificate authority. For example, when you deploy a service to Azure App Service, the generated endpoint (eg myservices.azurewebsites.net) already has a Https endpoint with a certificate that is trusted.

In some cases being able to connect to plain-text services may useful. For example,when you’re running the services locally, or you’re attempting to connect to a service in an environment, where there is no https endpoint. In these cases, you can adjust the behaviour of the iOS application so that it can connect to a non-secure (ie http) endpoint.

Accessing Non-Secure Services

Let’s see this in action by changing our the endpoint of our service request to http://192.168.1.107:5000. The endpoint is configured for both https on port 5001 and http on port 5000. If you are trying on a new ASP.NET Core 3 project, don’t forget that the template comes with the line UseHttpRedirection in startup.cs so. If you want to expose an http endpoint you’ll need to remove that line.

image

In the iOS application if you simply change the endpoint to http://192.168.1.107:5000, the application will operate correctly. This is despite all the concern that http connections aren’t supported. This is because there’s a clear set of exceptions to the Https rule on iOS:

image

If you want to use http but instead of using an IP address (ie the exclusion we just saw) you have a domain name. Let’s try this by changing the endpoint to http://192.168.1.107.xip.io:5000. BIG shout out to the xip.io service which is super cool. You can enter any ip address before the xip.io and the returned ip address from doing a DNS lookup will be the same ip address.

image

When we run the iOS application and it attempts to make the service call we get the following exception raised within Visual Studio:

Unhandled Exception:
System.Net.WebException: <Timeout exceeded getting exception details> occurred

This isn’t very meaningful. However, in the Output window there’s much more information:T

Unhandled Exception:
System.Net.WebException: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection. ---> Foundation.NSErrorException: Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection., NSErrorFailingURLStringKey=http://192.168.1.107.xip.io:5000/api/values

Allowing Insecure Connections

This exception we can combat by including an exception in the Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
   <key>NSExceptionDomains</key>
   <dict>
     <key>192.168.1.107.xip.io</key>
     <dict>
       <key>NSExceptionAllowsInsecureHTTPLoads</key>
       <true />
     </dict>
   </dict>
</dict>

Adding this to the plist will exclude the listed domain from the App Transport Security policy. Another alternative is to use the NSAllowArbitraryLoads attribute.  You should avoid using this attribute as it effectively disables the security policy for any endpoint that the app connects to.

<key>NSAppTransportSecurity</key>
<dict>
   <key>NSAllowsArbitraryLoads</key>
   <true />
</dict>

So that’s it for accessing non-secure, or Http, endpoints. Simply add the endpoint to the NSExceptionDomains element in the Info.plist file and you’re good to go.

Trusting Self-Signed Certificates

Now let’s go back to connecting to a secure endpoint. This time we’re going to keep with using a xip.io address to ensure any security policies are enforced. The secure endpoint would be https://192.168.1.107.xip.io:5001. I’ve reissued the certificate used by the ASP.NET Core application to include 192.168.1.107.xip.io in the alternative names section:

image

You would expect this to work since the endpoint domain is already listed in the Info.plist file (see earlier on doing this using the NSExceptionDomains). Unfortunately there is still an error similar to the following.

System.Net.WebException: The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.1.107.xip.io” which could put your confidential information at risk.

The information in this error is only partially correct. The certificate for the server is actually valid, it’s just that the app/device isn’t able to verify the integrity of the certificate.

Working with Public Keys

We need to find a way for the device to trust the certificate being returned by the server. By far the easiest way to get the certificate to be trust by applications running on an iOS device, is to install the public key for the certificate onto the device. To do this we need the public key, which we can extract from the pfx file used by the ASP.NET Core service, using the following openssl command (This site is very useful for Openssl commands):

openssl pkcs12 -in kestrel.pfx -out kestrel.pem -nodes

This extracts the public key in pem format. iOS needs der format. Luckily there’s again an openssl command for converting the files.

openssl x509 -outform der -in kestrel.pem -out kestrel.der

To get the public key to the device you can either share a hyperlink (ie upload the der file and share a link) or email the file to your self and open it on the device. My preference is just to add the file to my dropbox and then open the corresponding link using Safari on the device. Select the Direct Download option and the file downloads, extracts and attempts to installs the certificate

image

After clicking on Direct download you should see a prompt from the OS about installing a profile that has been installed from a website. We understand the risk so click on Allow. You will then see a confirmation prompt, indicating the Profile has been Downloaded.

imageimage

Installing iOS Root Certificate

It’s important to read the second prompt closely because what it’s saying is that you still need to go to Settings in order to complete the installation of the profile (which in this case is just a certificate). Open Settings / General / Profile and then select the profile for 192.168.1.107.xip.io you’ll see information about the certificate and the ability to Install (top right corner) the certificate.

image

After clicking Install and following the prompts you’ll be returned to this screen. The link to Install will change to Done. However, the certificate will be marked as Not Verified. This is because the root certificate, which in this case is the root certificate used by mkcert, is not trusted by the device.

image

Unfortunately since the certificate isn’t trusted, the application will still fail to connect to this endpoint. For the moment we’ll remove this certificate as it’s not helpful.

Trusting the Root iOS Certificate

Let’s repeat the process of installing the certificate but this time let’s install the root certificate used by mkcert. The public key can be found at C:Users[username]AppDataLocalmkcertrootCA.pem and when you attempt to install it on the device you should see something similar to

image image

Note the difference after the certificate has been installed – it is clearly marked as Verified in green.

To prevent profiles being accidentally downloaded and installed by users and for them to have full access to the device, it is necessary to manually trust certificates. The certificate settings can be found under Settings / General / About / Certificate Trust Settings. On this screen you can control which profiles (ie certificates) are fully trusted.

image

After toggling the full trust setting we’re good to try our application. We’ve not had to make any changes to the application itself. After installing the correct certificate onto the device, we’re able to connect to the secured services. Marking the root certificate as trusted on this device, also removes the need for the NSExceptionDomains section in the Info.plist file.

Validating Server Certificates (i.e. Certificate Pinning)

In this last section we’re going to look at how you can specify a certificate within the application itself. This will to allow requests to be made to the service with the self-signed certificate. Before proceeding you should removed any certificates that were previously installed.

Currently (at the time of writing) there is no way to override the certificate validation process for the out of the box NSUrlSessionHandler. There’s been work done in the past to provide a better alternative, such as the ModernHttpClient. However, most do not seem to work with self-signed certificates. They may have worked well with self-signed certificates back when the library was created but as it’s no longer maintained it appears to not support self-signed certificates.

Using the NSUrlSessionHandler

Even the sample project put together by Jonathan Peppers on SSLPinning doesn’t appear to work. Luckily with a minor tweak it’s possible to use the revised NSUrlSessionHandler to permit access to the self-signed service. Using the source code in the SSLPinning repository as the starting point, I’ve collated all the pieces of the alternative NSUrlSessionHAndler into a single file (Full source code). The main changes are:

- The addition of an UntrustedCertificate property which will accept the raw data from the .der public key

public NSData UntrustedCertificate { get; set; }


- Modification to the processing included in the DidReceiveChallenge method. This essentially installs the root certificate so that it can be trusted by the application.

if (sessionHandler.UntrustedCertificate != null)
{
   var trust = challenge.ProtectionSpace.ServerSecTrust;
    var rootCaData = sessionHandler.UntrustedCertificate;
    var x = new SecCertificate(rootCaData);

    trust.SetAnchorCertificates(new[] { x });
     trust.SetAnchorCertificatesOnly(false);
    completionHandler(NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential);
}
else
{
    completionHandler(NSUrlSessionAuthChallengeDisposition.CancelAuthenticationChallenge, null);
}

In order to take advantage of the updated NSUrlSessionHandler we need to modify the setup.cs

Mvx.IoCProvider.LazyConstructAndRegisterSingleton<HttpMessageHandler, IServiceOptions>(options =>
{
     var handler = new Xamarin.SSLPinning.iOS.NSUrlSessionHandler
     {
         UntrustedCertificate = NSData.FromFile("kestrel.der")
     };
     return handler;
});

And of course we need to make sure we include the kestrel.der file in the Resources folder. Make sure the Build Action set to BundleResource.

image

Running this up and we get the response back from the service.

image

The big difference with this option is that there’s nothing outside of the application is modified. All the setting up of the trust is done within the application, making it much easier to deploy to any device without having to worry about configuring the device.

Summary of iOS Certificates

Note that we didn’t strictly do certificate pinning – we just allowed the application to connect to a self-signed endpoint. To carry out certificate pinning you can make changes to the DidReceiveChallenge method and determine whether the certificate should be trusted. The ModernHttpClient does have an implementation of a callback that the application can register for in order to determine whether the certificate, and thus the endpoind, should be trusted.

Working with Self Signed Certificates (Certificate Pinning) in Windows (UWP) Application with Xamarin.Forms

Working with Self Signed Certificates (Certificate Pinning) in Windows (UWP) Application with Xamarin.Forms

I’ve been doing a bit of progression talking about building and debugging ASP.NET Core services over https and http/2, coupled with using platform specific handlers to improve the way the HttpClient works on each platform. The following links provide a bit of a background on what we’ve covered so far.

Accessing ASP.NET Core API hosted on Kestrel over Https from iOS Simulator, Android Emulator and UWP Applications.
Publishing ASP.NET Core 3 Web API to Azure App Service with Http/2
Xamarin and the HttpClient For iOS, Android and Windows

In this post we’re going to pick up from the end of the previous post to discuss using self-signed certificates in a Windows (ie UWP) application. Previously we managed to get the ASP.NET Core API hosting setup in such a way that the services were exposed using the IP address of the host computer, meaning that it can be accessed from an app running on an iOS simulator, the Android emulator, or even a UWP app running locally on the computer. As we’ll see there’s still a bit of work to be done within the app on each platform to allow the app to connect to the API.

Before we go on, it’s worth noting that the technique we’re going to use in the post is sometimes referred to as certificate pinning, which amounts to verifying that the response to a service call has come across a secure channel that uses a certificate issued by a certificate authority that the app is expecting, or trusts. There are a variety of reasons for using this technique but the main one is to help eliminate man in the middle attack by preventing some third party from impersonating the service responding to the requests for an app. One of the other common reasons to use this technique is actually to permit non-secure, or self-signed certificates – as you may recall we used a self-signed certificate in the previous post to secure the service, so we need a mechanism for each platform to permit the use of self-signed certificates and treat the responses from such services as trusted. This will be done over a three part series of posts, starting with a Universal Windows Application (UWP) application in this post.

To get started, let’s take a quick look at what happens if we simply run up both the UWP application we had previously setup to use the WinHttpHandler. The only change I’m going to make to the UWP application initially is to change the BaseUrl for the service to https://192.168.1.107 (ie the IP address of the development machine) – note that it’s a https endpoint. Running the application will fall over with an exception when it attempts to connect to the HeaderHelper service hosted at https://192.168.1.107/api/value.

image

The extracted error message is as follow:

System.Net.Http.HttpRequestException
   HResult=0x80072F8F
   Message=An error occurred while sending the request.
   Source=System.Private.CoreLib
Inner Exception 1:
WinHttpException: Error 12175 calling WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, ‘A security error occurred’.

Now if you search for this error information, you’re likely to see a bunch of documents talking about the 0x80072F8F error code as it seems to come up in relation to Windows activation issues. However if you google the 12175 error (ie the internal exception) you’ll see a number of articles (eg http://pygmysoftware.com/how-to-fix-windows-system-error-12175-solved/) that point at there being an SSL related error. In this case it’s because we accessing a service that uses a certificate that isn’t trusted and can’t be validated.

We’re going to discuss two ways to carry out certificate pinning, which should allow us to access the HeaderHelper service, even though it’s being secured using a self-signed certificate. In the previous post where we setup the ASP.NET Core service to use a new certificate when hosting on Kestrel, we generated a .PFX certificate that included both the public and private components using mkcert. In both of the methods described here, you’ll need the public key component, which is easy to grab using openssl thanks to this post. For example:

openssl pkcs12 -in kestrel.pfx -nocerts -out kestrel.pem -nodes

Look Dad, No Code

The first way to configure the UWP application to connect to the service with a self-signed certificate is to add the public key for the certificate into the UWP application and declare the certificate in the Package.appxmanifest.

– Open the Package Manifest designer by double-clicking the package.appmanifest

– Once opened, select the Declarations tab, and then from the Available Declarations, select Certificates and click Add.
image

– Click the Add New button at the bottom of the Properties section
image

– Set the Store name to TrustedPeople and click the … button to select the public key file generated earlier

image

If you’re interested as to what has been changed when you selected the public key in the manifest editor:

– The public key file (in this case kestrel.pem) was added to the root of the UWP project with Build Action set to Content so that the pem file gets deployed with the application

– The package.manifest file was updated to include an Extensions section, specifically a Certificate element that defines both the store and the certificate file name.

<Extensions>
   <Extension Category=”windows.certificates”>
     <Certificates>
       <Certificate StoreName=”TrustedPeople” Content=”kestrel.pem”/>
     </Certificates>
   </Extension>
</Extensions>

And that’s it – you can successfully run the application and all calls to the service secured using the generated self-signed certificate will be successful.

With Code Comes Great Responsibility

The second way to prevent man in the middle style attacks is to do some validation of the connection in code of the certificate returned as part of the initial all to the services.

If you read some of the documentation/blogs/posts online they sometimes reference handling the ServerCertificateValidationCallback on the ServicePointManager class. For example the following code will simply accept all validation requests, thereby accepting all response data, on the assumption that the caller is in some way validating the response.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

Note: The ServerCertificateValidationCallbak event on the ServicePointManager will only be invoked if you use the default managed handler, which as we saw in my previous post is not recommended. I would discourage the use of this method for handling certificate validation challenges.

So, if ServicePointManager isn’t the correct place to intercept request, what is?

In the previous post we had already overridden the InitializeIoC method on the Setup.cs class, so it makes sense to route the NBN cabling through the roof cavity.

– A new method, CertificateCallacbk, has been set to handle the ServerCertificateValidatationCallback on the WinHttpHandler (not to be confused with the ServicePointManager callback).

protected override void InitializeIoC()
{
     base.InitializeIoC();


    Mvx.IoCProvider.LazyConstructAndRegisterSingleton<HttpMessageHandler, IServiceOptions>(options =>
     {
         return new WinHttpHandler()
         {
             ServerCertificateValidationCallback = CertificateValidationCallback,
         };
     });
}
private bool CertificateValidationCallback(HttpRequestMessage arg1, X509Certificate2 arg2, X509Chain arg3, SslPolicyErrors arg4)
{
     return true;
}

– Of course simply returning true to all certificate validation challenges, isn’t very secure, and it’s highly recommended that your certificate checking is much more comprehensive.

And that’s it; you can now ignore certificates that are self-signed, or that aren’t signed by a trusted certificate authority. Whilst the methods presented in this post are for UWP, they are equally applicable for a UWP application that’s been written using Xamarin.Forms.

Xamarin and the HttpClient For iOS, Android and Windows

Xamarin and the HttpClient For iOS, Android and Windows

In an earlier post that talked about using dependency injection and registering interfaces for working with Refit across both Prism and MvvmCross I had code that registered an instance of the CustomHttpMessageHandler class which internally used a HttpClientHandler for its InnerHandler. For developers who have spent a bit of time optimising their iOS, Android or Windows application, you’ll have noted that using the HttpClientHandler is generally not deemed to be best practice.  As I’m a big fan of trying to demonstrate best practices, I figured I’d expand on this a little into a post talking about the HttpClient and some of the options you have.

Firstly, a couple of bits of side reading:

What you should gather from these articles is that Microsoft is doing their best to set you up for success but not wanting to take any documentation for granted, let’s see what happens when we create a brand new Xamarin.Forms project and spin up an instance of the HttpClient. When creating the project I just picked the Blank Xamarin.Forms template and made sure that all three platforms were included. The code for creating the HttpClient just uses the zero-parameter constructor:

var client = new HttpClient();

Let’s run each platform and see what the HttpClient gives us (and at this point I haven’t updated any NuGet packages, framework versions or anything. This is just what VS2019 gives me when I create a new XF project).

UWP

image

Here we get the managed HttpClientHandler, rather than the newer (and arguably better) WinHttpHandler. Actually I didn’t find a definitive guide on which is better for UWP, although this stackoverflow post does seem to imply the WinHttpHandler would be the preferred choice, particularly if you want to leverage Http/2.

Android

image

Android is using the AndroidClientHandler which is what should give us the most up to date http experience.

iOS

image

iOS is using the NSUrlSessionHandler which is what should give us the most up to date http experience.

This all seems good (albeit that you might want to use the WinHttpHandler on UWP) so for a lot of developers they might never run into any issues. If you did want to adjust which handler is used on iOS and Android (again assuming you’re just using the HttpClient with the default constructor) you can do so via the properties dialog for the corresponding platform:

image

However, where things come unstuck is if you want to customise some of the http behaviour. In my previous post I demonstrated setting the compression flag but it could have equally been adding an additional header or changing the credentials that are sent as part of each request. In this case, it’s easy enough to use the overload of the HttpClient constructor that takes a HttpMessageHandler and use the managed HttpClientHandler implementation (as I demonstrated). As you’d have seen from the linked articles above, this isn’t ideal as the managed implementation doesn’t leverage the platform specific optimisations.

The better approach is for my application to register the platform specific handler, which in MvvmCross can be done via the Setup class (which is created by default when using MvxScaffolding):

UWP

public class Setup : MvxFormsWindowsSetup<Core.App, UI.App>
{
     protected override void InitializeIoC()
     {
         base.InitializeIoC();
        Mvx.IoCProvider.LazyConstructAndRegisterSingleton<HttpMessageHandler, IServiceOptions>(options =>
         {
return new WinHttpHandler()
             {
                AutomaticDecompression = options.Compression
             };
         });
     }
}

Android

public class Setup : MvxFormsAndroidSetup<Core.App, UI.App>
{
     protected override void InitializeIoC()
     {
         base.InitializeIoC();

 

        Mvx.IoCProvider.LazyConstructAndRegisterSingleton<HttpMessageHandler, IServiceOptions>(options =>
         {
             return new AndroidClientHandler
             {
                 AutomaticDecompression = options.Compression
             };
         });
     }
}

iOS

public class Setup : MvxFormsIosSetup<Core.App, UI.App>
{
     protected override void InitializeIoC()
     {
         base.InitializeIoC();

 

        Mvx.IoCProvider.LazyConstructAndRegisterSingleton<HttpMessageHandler, IServiceOptions>(options =>
         {
             var nsoptions = NSUrlSessionConfiguration.DefaultSessionConfiguration;
             if (options.Compression == System.Net.DecompressionMethods.None)
             {
                 nsoptions.HttpAdditionalHeaders = new NSDictionary("Accept-Encoding", "identity", new object[] { });
             }
             var handler = new NSUrlSessionHandler(nsoptions);
             return handler;
         });
     }
}

Note: for iOS the NSUrlSessionHandler enabled compression by default, so the code here illustrates how you could disable compression if you wanted by sending the identity Accept-Encoding header.

In this post I’ve shown you how you can register each of the native platform handlers to optimise the requests made when using the HttpClient. This post should be read in conjunction with my earlier post that registered the other classes necessary to create the HttpClient based on the registered handler. The only other change is that the HttpService constructor should accept an HttpMessageHandler instead of an ICustomHttpMessageHandler.

public class HttpService : IHttpService
{
     public HttpService(HttpMessageHandler httpMessageHandler, IServiceOptions options)
     {
         HttpClient = new HttpClient(httpMessageHandler as HttpMessageHandler)
         {
             BaseAddress = new Uri(options.BaseUrl)
         };
     }

 

    public HttpClient HttpClient { get; }
}

Update: It’s worth noting that the WinHttpHandler used in the UWP example isn’t part of the core framework. Instead it is accessible via the System.Net.Http.WinHttpHandler NuGet package. Visual Studio provides a handy way to find and install this package – selecting the WinHttpHandler reference (where there is a build error) and looking at the intellisense options, there is an option to Install the System.Net.Http.WinHttpHandler package.

image

Design Time Data for Xamarin.Forms

Design Time Data for Xamarin.Forms

In my previous post I showed how to switch between Visual States using the tooling that comes with the BuildIt.Forms library. One of the other features of the tooling is the ability to load mock data that can assist with visualising how a page might look like with certain data. Rather than try to guess at what data your page might require, the tooling simply allows you to define a series of design actions. Each design action will appear within the BuildIt.Forms flyout, allowing you to invoke the action.

Let’s demonstrate this with an example. I’m going to change the layout of my page slightly so that in the DataLoaded state a ListView is displayed that takes up the entire screen. The XAML for the ListView is as follows:

<ListView x_Name=”DataList” IsVisible=”false”>
     <ListView.ItemTemplate>
         <DataTemplate>
             <ViewCell>
                 <Label Text=”{Binding Name}” />
             </ViewCell>
         </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

As I don’t have any actual data at the moment, when I run up the application and click the Load Data button I see the following for the DataLoaded state:

image

This isn’t great as I’ve got no idea what my ListView is going to look like. So let’s fix this by adding a design action. I do this by calling the AddDesignAction method (it’s an extension method which is why I can access it on the MainPage) and providing a name, “Mock Data”, and the action to perform when the design action is run.

public MainPage()
{
     InitializeComponent();


    var groups = VisualStateManager.GetVisualStateGroups(this);

#if DEBUG
     this.AddDesignAction(“Mock Data”,
         () =>
         {
             var data = from i in new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
                        select new { Name = $”Item {i}” };
             DataList.ItemsSource = data;
         });
#endif
}

In this case I’m creating an IEnumerable of an anonymous type that has a property Name, which aligns with the data binding in the ListView XAML shown earlier. I’m assigning this directly to the ItemsSource of the ListView – at this stage I’m just creating the layout of the pages of my application so I might not even have View Models, which is why I’m assigning directly to the ItemSource property in place of data binding it.

Now when I run the application I see:

imageimage

imageimage

The final image shows the list of items being displayed in the ListView – clearly this layout could do with some work!

Page State with the Visual States Manager for Xamarin.Forms

Page State with the Visual States Manager for Xamarin.Forms

One of the current limitations of the Xamarin.Forms implementation of the Visual State Manager (VSM) is that it only works for setting properties on an individual control. Whilst this is great for control state management (think button states like disabled, pressed etc), its incredibly limiting and makes it unsuitable for some typical visual state scenarios. The one that often comes up in a mobile application is for pages that load data. In this scenario you typically have a least three states: Loading, DataLoaded, DataFailedToLoad. In some cases you might even extend this to have states such as Refreshing or LoadingMoreData. For these states you probably want to show/hide different elements on the screen, which is why the current Xamarin.Forms implementation of the VSM isn’t a great option.

Luckily there’s an alternative, which is the Visual State Manager that’s part of the BuildIt.Forms library. Here’s a quick example of it in action:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<ContentPage
             
             
              x_Class=”App14.MainPage”>
     <vsm:VisualStateManager.VisualStateGroups>
         <vsm:VisualStateGroups>
             <vsm:VisualStateGroup Name=”LoadingStates”>
                 <vsm:VisualState Name=”Loading”>
                     <vsm:VisualState.Setters>
                         <vsm:Setter Value=”True” Element=”{x:Reference LoadingLabel}” Property=”IsVisible” />
                     </vsm:VisualState.Setters>
                 </vsm:VisualState>
                 <vsm:VisualState Name=”DataLoaded”>
                     <vsm:VisualState.Setters>
                         <vsm:Setter Value=”True” Element=”{x:Reference LoadedLabel}” Property=”IsVisible” />
                     </vsm:VisualState.Setters>
                 </vsm:VisualState>
                 <vsm:VisualState Name=”DataFailedToLoad”>
                     <vsm:VisualState.Setters>
                         <vsm:Setter Value=”True” Element=”{x:Reference FailedLabel}” Property=”IsVisible” />
                     </vsm:VisualState.Setters>
                 </vsm:VisualState>
             </vsm:VisualStateGroup>
         </vsm:VisualStateGroups>
     </vsm:VisualStateManager.VisualStateGroups>

     <StackLayout VerticalOptions=”Center”>
         <Label Text=”Loading…” x_Name=”LoadingLabel” HorizontalOptions=”Center”  IsVisible=”False” />
         <Label Text=”Success: Data Loaded!!” x_Name=”LoadedLabel” HorizontalOptions=”Center” IsVisible=”False” />
         <Label Text=”Failure :-(” x_Name=”FailedLabel” HorizontalOptions=”Center” IsVisible=”False” />
         <Button Text=”Load Data” Clicked=”LoadClicked” />
     </StackLayout>
</ContentPage>

In this case we’ve defined three Visual States that correspond to showing the LoadingLabel, LoadedLabel and FailedLabel respectively. The code behind for the LoadClicked method illustrates how easily you can switch between the states:

private readonly Random rnd = new Random();


private async void LoadClicked(object sender, EventArgs e)
{
     var success = rnd.Next(0, 1000) % 2 == 0;
     await VisualStateManager.GoToState(this, “Loading”);
     await Task.Delay(2000);
     await VisualStateManager.GoToState(this, success ? “DataLoaded” : “DataFailedToLoad”);
}

Ok, so one last thing we can add in is a bit of animation to make the transition between states a little smoother. Let’s fade our labels in and out:

<vsm:VisualState Name=”Loading”>
     <vsm:VisualState.ArrivingAnimations>
         <animations:AnimationGroup>
             <animations:AnimationGroup.PostAnimations>
                 <animations:FadeAnimation Opacity=”1″
                                           Duration=”500″
                                           Element=”{x:Reference LoadingLabel}” />
             </animations:AnimationGroup.PostAnimations>
         </animations:AnimationGroup>
     </vsm:VisualState.ArrivingAnimations>
     <vsm:VisualState.LeavingAnimations>
         <animations:AnimationGroup>
             <animations:AnimationGroup.PreAnimations>
                 <animations:FadeAnimation Opacity=”0″
                                           Duration=”500″
                                           Element=”{x:Reference LoadingLabel}” />
             </animations:AnimationGroup.PreAnimations>
         </animations:AnimationGroup>
     </vsm:VisualState.LeavingAnimations>

     <vsm:VisualState.Setters>
         <vsm:Setter Value=”True” Element=”{x:Reference LoadingLabel}” Property=”IsVisible” />
     </vsm:VisualState.Setters>
</vsm:VisualState>

The XAML adds a fade in after the state transition has occurred (Post animation) when transitioning to (Arriving at) the the Loading state, and a fade out before the state transition has occurred (Pre animation) when transitioning from (Leaving) the Loading state. As you can see the XAML gets fairly verbose but it’s structured this way to allow for complex combinations and sequences of animations:

<animations:AnimationGroup.PostAnimations>
     <animations:SequenceAnimation>
         <animations:ParallelAnimation>
             <animations:FadeAnimation Opacity=”1″ Duration=”500″ Element=”{x:Reference LoadingLabel}” />
             <animations:ScaleAnimation Scale=”5″ Duration=”500″ Element=”{x:Reference LoadingLabel}” />
             <animations:SequenceAnimation>
                 <animations:RotateAnimation Rotation=”10″ Duration=”250″ Target=”LoadingLabel” />
                 <animations:RotateAnimation Rotation=”0″ Duration=”250″ Target=”LoadingLabel” />
                 <animations:RotateAnimation Rotation=”-10″ Duration=”250″ Target=”LoadingLabel” />
                 <animations:RotateAnimation Rotation=”0″ Duration=”250″ Target=”LoadingLabel” />
             </animations:SequenceAnimation>
         </animations:ParallelAnimation>
         <animations:ScaleAnimation Scale=”1″ Duration=”500″ Element=”{x:Reference LoadingLabel}” />
     </animations:SequenceAnimation>
</animations:AnimationGroup.PostAnimations>

And let’s see this in action:

App14UWP20190317022241

Hopefully you can see from this short post how you can leverage the BuildIt.Forms Visual State Manager to do complex page state management as well as animations. We’ve just released a new beta package compatible with the latest Xamarin.Forms v3.6 and would love feedback (https://www.nuget.org/packages/BuildIt.Forms/2.0.0.27-beta).

Android Emulator Exception after updating to Visual Studio 15.9 preview 3

Android Emulator Exception after updating to Visual Studio 15.9 preview 3

I noticed earlier this evening that there was an update available for Visual Studio 15.9. Normally I wait a few days to update as I’m not in any particular hurry but I noticed in the blog post and release notes that work had been done on the Android build and execution. I also remembered that I hadn’t updated Visual Studio or my emulator images since updating my Surface Book 2 to the latest Windows update – it contains a fix for the awful performance of the Android emulator running on Windows hypervisor. Anyhow, the upshot is that I updated Visual Studio to the latest preview….

I decided to drop my existing emulator images and create new ones. Unfortunately this was a bad idea as I was then unable to start the new emulator images. When I attempted to start the emulator I would get an error stating “The requested operation requires elevation. (Exception from HRESULT: 0x800702E4)”.

image

Turns out I’m not the only person seeing this, as someone had already reported this issue.

It also turns out that there’s a simple solution…. close the Android Device Manager and just hit Run from within Visual Studio. Turns out that this causes the emulator image to boot, deploy and run the application. And all the updates seem to do the trick, debugging is back to an acceptable speed.

MVX=1: TipCalc – a second example – adding IoC and the Xamarin Android Designer (MVX+1 days of MvvmCross)

MVX=1: TipCalc – a second example – adding IoC and the Xamarin Android Designer (MVX+1 days of MvvmCross)

Following on from the first post in the MVX+1 series, in this post we’ll create a basic Tip Calculator (mirroring the original post from the N+1 series). However, in this case the first section is a more detailed set of instructions on how to get the basics of all three platforms setup with MvvmCross. Going forward we’ll use this as a starting point so that we don’t need to cover over this in each subsequent post.

Source code: https://github.com/nickrandolph/MvxPlus1DaysOfMvvmCross/tree/master/Mvx-01-TipCalc

Getting Started Instructions (Native Apps)

Note: In this case the name of the application is TipCalc but these instructions can be followed to get any new project started by simply replacing TipCalc with the name of your project.

  1. Create a the new solution by creating a new Class Library (.NET Standard) with the project name set to TipCalc.Core and the solution name to just TipCalc.
  2. Add a new project based on the Blank App (Universal Windows) project template called TipCalc.Uwp (make sure that the Minimum and Target versions are set to at least the Fall Creators Update)
  3. Add a new project based on the Android App (Xamarin) project template called TipCalc.Droid (use the Blank app template)
  4. Add a new project based on the iOS App (Xamarin) project template called TipCalc.iOS (use the Blank app template)
  5. Add a reference to MvvmCross NuGet package (v6.0.0 at time of writing to all four projects)
  6. TipCalc.Uwp: Update NuGet package Microsoft.NETCore.UniversalWindowsPlatform to the latest stable version (6.0.8 at time of writing)
  7. TipCalc.Droid: Update the Android version to Use Latest Platform (Project Properties –> Application –> Target Framework)
  8. TipCalc.Droid: Update Xamarin.Android.Support.Design to latest stable version (27.0.2 at time of writing)
  9. TipCalc.Droid: Add a reference to MvvmCross.Droid.Support.V7.AppCompat package
  10. TipCalc.iOS: Unload project; delete packages.config; edit TipCalc.iOS.csproj and add the following ItemGroup
    <ItemGroup>
       <PackageReference Include=”MvvmCross” Version=”6.0.0″ />
    </ItemGroup>

  11. Add a reference to TipCalc.Core to each of the three head projects (ie TipCalc.Uwp, TipCalc.Droid and TipCalc.iOS)
  12. TipCalc.Core: Rename the default Class1.cs to App.cs, and allow Visual Studio to rename class to App
  13. TipCalc.Core: Change the App class to inherit from MvxApplication
  14. TipCalc.Core: Add a folder, ViewModels, and add a class called FirstViewModel.
  15. TipCalc.Core: Change FirstViewModel to inherit from MvxViewModel
  16. TipCalc.Core: Override Initialize method in App to register services and set startup view model to FirstViewModel
    public override void Initialize()
    {
         CreatableTypes()
                 .EndingWith(“Service”)
                 .AsInterfaces()
                 .RegisterAsLazySingleton();
         RegisterAppStart<FirstViewModel>();
    }

  17. TipCalc.Uwp: Add a help class ProxyMvxApplication

    public abstract class ProxyMvxApplication: MvxApplication<MvxWindowsSetup<Core.App>, Core.App> { }
  18. TipCalc.Uwp: Change App.xaml and App.xaml.cs to inherit from ProxyMvxApplication
  19. TipCalc.Uwp: Remove all code in App.xaml.cs other than the constructor which should contain a single call to InitializeComponent
  20. TipCalc.Uwp: Delete MainPage.xaml and MainPage.xaml.cs
  21. TipCalc.Uwp: Add a Views folder, and  add a FirstView based on the Blank Page template
  22. TipCalc.Uwp: Change FirstView.xaml and FirstView.xaml.cs to inherit from MvxWindowsPage
  23. TipCalc.Droid: Add a new class, MainApplication, that inherits from MvxAppCompatApplication
  24. [Application]
    public class MainApplication : MvxAppCompatApplication<MvxAppCompatSetup<App>, App>
    {
         public MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
         {
         }
    }

  25. TipCalc.Droid: Rename MainActivity.cs to SplashScreen.cs and let Visual Studio rename the class
  26. TipCalc.Droid: Rename activity_main.axml to SplashScreen.axml, and adjust layout to indicate application loading
  27. TipCalc.Droid: Adjust SplashScreen class to inherit from MvxSplashScreenAppCompatActivity and set NoHistory to true (since we don’t want the user to be able to press the back button and go back to the splash screen)

    [Activity(Label = “@string/app_name”, Theme = “@style/AppTheme”, MainLauncher = true, NoHistory = true)]
    public class SplashScreen : MvxSplashScreenAppCompatActivity

  28. TipCalc.Droid: Add a folder, Views, and add a new Activity, FirstView.c
  29. [Activity(Label = “FirstView”)]
    public class FirstView : MvxAppCompatActivity<FirstViewModel>
    {
         protected override void OnCreate(Bundle bundle)
         {
             base.OnCreate(bundle);


            SetContentView(Resource.Layout.FirstView);
         }
    }

  30. TipCalc.Droid: Add a new Android Layout to the Resources/Layout folder, FirstView.axml
  31. TipCalc.Droid: You may run into an error: “error XA4210: You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute.” If you do, you just need to Add Reference to Mono.Android.Export (search in the Add Reference dialog).
  32. TipCalc.iOS: Update AppDelegate class to inherit from MvxApplicationDelegate, and remove the default code.
    [Register(“AppDelegate”)]
    public class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
    {
    }
  33. TipCalc.iOS: Add an Empty Storyboard, called Main.storyboard, to the root of the project
  34. TipCalc.iOS: Add a ViewController to the Main.storyboard using the designer and set the Class and Storyboard ID to FirstView (also make sure the “User Storyboard ID” checkbox is set to true)
  35. TipCalc.iOS: Move the generated FirstView.cs and FirstView.designer.cs files (from the previous step) into a new folder called Views, and adjust the namespace of the FirstView class to FirstView.iOS.Views
  36. TipCalc.iOS: Update the FirstView class to inherit from MvxViewController
    [MvxFromStoryboard(“Main”)]
    public partial class FirstView : MvxViewController<FirstViewModel>

Now to actually build out the Tip Calculator. Rather than embed the calculation logic into our view model, we’re going to abstract it out into a service. To do this we’ll make use of the IoC container made available by MvvmCross. We’ll register a CalculationService which will be injected into our view model constructor.

Let’s continue our development of the Tip Calculator in TipCalc.Core:

  1. Add a folder called Services
  2. Add an interface ICalculationService into the Services folder
    public interface ICalculationService
    {
         double Tip(double subTotal, double generosity);
    }
  3. Add a class, CalculationService, which implements ICalculationService, again into the Services folder
    public class CalculationService : ICalculationService
    {
         public double Tip(double subTotal, double generosity)
         {
             return subTotal * generosity / 100.0;
         }
    }
  4. Add a constructor to the FirstViewModel which accepts an ICalculationService parameter
  5. private readonly ICalculationService _calculationService;
    public FirstViewModel(ICalculationService calculationService)
    {
         _calculationService = calculationService;
    }

  6. Add properties for SubTotal, Generosity, Tip and Total. Each property should take the following form where SetProperty is called within the setter
    private double _subTotal;
    public double SubTotal
    {
         get { return _subTotal; }
         set { SetProperty(ref _subTotal, value); }
    }
  7. Add a Recalc method which will invoke the Tip method on the ICalculationService
    private void Recalc()
    {
         Tip = _calculationService.Tip(SubTotal, Generosity);
         Total = SubTotal + Tip;
    }
  8. Add a call to Recalc into the setter for both SubTotal and Generosity
  9. Set some initial values for the SubTotal and Generosity (if you use the property setters, rather than setting the fields, the Recalc method will be invoked)

That’s it for the core logic for the application. Now we just need to wire up the UI for each platform.

One thing that’s worth noting is that in step 16 of the original setup where the Initialize method is overridden, there is logic in the Initialize method to interrogate the current assembly looking for all classes that end in Service and register them, based on their interface, with the MvvmCross IoC container – this is how MvvmCross knows about the implementation of the ICalculationService which is used when instantiating the FirstViewModel.

Let’s built out the UWP interface in TipCalc.Uwp:

  1. Add the following XAML inside the existing Grid element:
    <StackPanel>
         <TextBlock Text=”SubTotal”/>
         <TextBox Text=”{Binding SubTotal, Mode=TwoWay}”/>
         <TextBlock Text=”How generous?”/>
         <Slider Value=”{Binding Generosity, Mode=TwoWay}”
                 Minimum=”0″
                 Maximum=”100″/>
         <TextBlock Text=”Tip:”/>
         <TextBlock Text=”{Binding Tip}”/>
         <TextBlock Text=”SubTotal:”/>
         <TextBlock Text=”{Binding Total}”/>
    </StackPanel>

That’s the UWP interface done – four elements (with TextBlock headings): TextBox and Slider for inputting SubTotal and Generosity using two-way data binding, and two TextBlock for outputting the Tip and Total amounts.

Now let’s do Android:

  1. Add the following namespace declaration to FirstView.axml
  2. Add the following xml to FirstView.axml
    <TextView
         android_text=”SubTotal”
         android_textAppearance=”?android:attr/textAppearanceMedium”
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         android_id=”@+id/textView1″ />
    <EditText
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         android_id=”@+id/editText1″
         local:MvxBind=”Text SubTotal” />
    <TextView
         android_text=”Generosity”
         android_textAppearance=”?android:attr/textAppearanceMedium”
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         android_id=”@+id/textView2″ />
    <SeekBar
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         local:MvxBind=”Progress Generosity”
         android_id=”@+id/seekBar1″ />
    <TextView
         android_text=”Tip”
         android_textAppearance=”?android:attr/textAppearanceMedium”
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         android_id=”@+id/textView3″ />
    <TextView
         android_textAppearance=”?android:attr/textAppearanceMedium”
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         local:MvxBind=”Text Tip”
         android_id=”@+id/textView4″ />
    <TextView
         android_text=”Total”
         android_textAppearance=”?android:attr/textAppearanceMedium”
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         android_id=”@+id/textView5″ />
    <TextView
         android_textAppearance=”?android:attr/textAppearanceMedium”
         android_layout_width=”fill_parent”
         android_layout_height=”wrap_content”
         local:MvxBind=”Text Total”
         android_id=”@+id/textView6″ />

In this case we’re leveraging the xml extensions offered by MvvmCross in order to do the data binding using the MvxBind syntax.

Finally, let’s do iOS:

  1. Add the following code to the FirstView.cs
    public override void ViewDidLoad()
    {
         base.ViewDidLoad();

  2.     // Perform any additional setup after loading the view
         var label = new UILabel(new RectangleF(10, 0, 300, 40));
         label.Text = “SubTotal”;
         Add(label);


        var subTotalTextField = new UITextField(new RectangleF(10, 40, 300, 40));
         Add(subTotalTextField);


        var label2 = new UILabel(new RectangleF(10, 80, 300, 40));
         label2.Text = “Generosity?”;
         Add(label2);


        var slider = new UISlider(new RectangleF(10, 120, 300, 40));
         slider.MinValue = 0;
         slider.MaxValue = 100;
         Add(slider);


        var label3 = new UILabel(new RectangleF(10, 160, 300, 40));
         label3.Text = “Tip”;
         Add(label3);


        var tipLabel = new UILabel(new RectangleF(10, 200, 300, 40));
         Add(tipLabel);


        var label4 = new UILabel(new RectangleF(10, 240, 300, 40));
         label4.Text = “Total”;
         Add(label4);


        var totalLabel = new UILabel(new RectangleF(10, 280, 300, 40));
         Add(totalLabel);


       var set = this.CreateBindingSet<FirstView, FirstViewModel>();
         set.Bind(subTotalTextField).To(vm => vm.SubTotal);
         set.Bind(slider).To(vm => vm.Generosity);
         set.Bind(tipLabel).To(vm => vm.Tip);
         set.Bind(totalLabel).To(vm => vm.Total);
         set.Apply();

    }

In this case for iOS we again make use of the data binding support provided by MvvmCross by using the CreateBindingSet method, followed by a call to Bind for each element property we want to bind, and then finally a call to Apply to complete the setup of data binding.

And that’s it – a Tip Calculator for all three platforms.

MVX=0 : A first MvvmCross Application (MVX+1 days of MvvmCross)

MVX=0 : A first MvvmCross Application (MVX+1 days of MvvmCross)

[Repost: Apologies for those who have already read this but there were some issues with the link generated for the previous post, so I’ve reposted it]

Updated 16/4/2018: Reference to MvvmCross have been updated to v6.0.0

Yes, this is going to be a sequence of posts reworking the infamous N+1 series that Stuart Lodge did starting almost exactly 5 years ago. As we approach the 5 year anniversary of these posts I thought it only fitting to cover this series again as a way of introducing MvvmCross v6 which will be released very shortly has just been released. Unlike the original series that were YouTube videos accompanied by blog posts, this series will only contain the posts, mainly because I find generating videos to be time consuming. Anyhow, here goes:

We’ll start by creating a Blank Solution.

image_thumb4_thumb

Into the solution we’ll add a Core Library that will contain an App class and our first ViewModel:

  1. Add a Class Library (.NET Standard) called FirstDemo.Core
    image_thumb3_thumb
  2. Add a reference to MvvmCross NuGet package (v6.0.0-beta.8 v6.0.0 at time of writing)
  3. Rename the default Class1.cs to App.cs, and allow Visual Studio to rename class to App
  4. Change App to inherit from MvxApplication
  5. Add a folder, ViewModels, and add a class called FirstViewModel.
  6. Change FirstViewModel to inherit from MvxViewModel
  7. Add logic to FirstViewModel to include FirstName, LastName and a calculated FullName
  8. Override Initialize method in App to call RegisterAppStart, specifying FirstViewModel as the startup ViewModel

Let’s start with a Universal Windows Platform UI:

  1. Add a Blank App (Universal Windows) called FirstDemo.Uwp
    image_thumb6_thumb
  2. Make sure Minimum and Target versions are set to at least the Fall Creators Update so that it supports .NET Standard 2.0
    image_thumb8_thumb
  3. Update NuGet package Microsoft.NETCore.UniversalWindowsPlatform to the latest stable version (6.0.8 at time of writing)
  4. Add a reference to MvvmCross NuGet package
  5. Add reference to FirstDemo.Core project
  6. Add a help class ProxyMvxApplication to the FirstDemo.Uwp project – this is a proxy class to compensate for the lack of generics support in XAML
  7. public abstract class ProxyMvxApplication: MvxApplication<MvxWindowsSetup<Core.App>, Core.App> { }

  8. Change App.xaml and App.xaml.cs to inherit from ProxyMvxApplication
  9. Remove all code in App.xaml.cs other than the constructor which should contain a single call to InitializeComponent
  10. Delete MainPage.xaml and MainPage.xaml.cs
  11. Add a Views folder, and  add a FirstView based on the Blank XAML page template
  12. Change FirstView.xaml and FirstView.xaml.cs to inherit from MvxWindowsPage
  13. Add some TextBoxes and a TextBlock to the FirstView, complete with databinding
  14. Hit F5 and run the application (you may have to set the FirstDemo.Uwp project as the startup project and make sure it’s set to build and deploy using the Configuration Manager)

Next let’s add the Android UI:

  1. Add a Android App (Xamarin) called FirstDemo.Droid
    image_thumb10_thumb
  2. Select the Blank App template, and the minimum Android version
  3. Update the Xamarin.Android.Support.Design NuGet package (at time of writing the latest is 27.0.2)
  4. Update the Android version to Use Latest Platform
    image_thumb12_thumb
  5. Add a reference to MvvmCross NuGet package
  6. Add a reference to MvvmCross.Droid.Support.V7.AppCompat package
  7. Add reference to FirstDemo.Core project
  8. Add a new class, MainApplication, that inherits from MvxAppCompatApplication
    public class MainApplication : MvxAppCompatApplication<MvxAppCompatSetup<App>, App>
  9. Rename MainActivity.cs to SplashScreen.cs and let Visual Studio rename the class
  10. Rename activity_main.axml to SplashScreen.axml, and adjust layout to indicate application loading
  11. Adjust SplashScreen class to inherit from MvxSplashScreenAppCompatActivity and set NoHistory to true (since we don’t want the user to be able to press the back button and go back to the splash screen)
  12. [Activity(Label = “@string/app_name”, Theme = “@style/AppTheme”, MainLauncher = true, NoHistory = true)]
    public class SplashScreen : MvxSplashScreenAppCompatActivity

  13. Add a folder, Views, and add a new Activity, FirstView.cs
    1. Add a new Android Layout to the Resources/Layout folder, FirstView.axml, with a couple of EditText and a TextView, all data bound using MvxBind
    2. You may run into an error: “error XA4210: You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute.” If you do, you just need to Add Reference to Mono.Android.Export (search in the Add Reference dialog).
    3. Set the startup project to be FirstDemo.Droid and press F5 to run the application

    Lastly, let’s add the iOS UI:

    1. Add an iOS App (Xamarin) called FirstDemo.iOS
      image_thumb2_thumb
    2. Select the Blank App template, Universal devices support and Minimum iOS Version of 11.2
      1. Add a reference to MvvmCross NuGet package
        1. Add reference to FirstDemo.Core project
        2. Update AppDelegate class to inherit from MvxApplicationDelegate
          public class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
        3. Add an Empty Storyboard, called Main.storyboard, to the root of the project
        4. Add a ViewController to the Main.storyboard using the designer and set the Class and Storyboard ID to FirstView (also make sure the “User Storyboard ID” checkbox is set to true)
        5. Move the generated FirstView.cs and FirstView.designer.cs files (from the previous step) into a new folder called Views, and adjust the namespace of the FirstView class to FirstView.iOS.Views
        6. Add two UITextField and a UILabel to the FirstView ViewController using the Main.storyboard designer (make sure each element has a Name set so it can be referenced from code)
        7. Update the FirstView class to inherit from MvxViewController
          [MvxFromStoryboard(“Main”)]
          public partial class FirstView : MvxViewController<FirstViewModel>
        8. Add logic to FirstView to enable databinding using the CreateBindingSet extension method
        9. Set the startup project to be FirstDemo.Droid and press F5 to run the application
          Update 16/4/2018: For some reason the iOS App (Xamarin) project template still uses a package.config. During the update to the stable v6.0.0 package the package.config file in FirstDemo.iOS was removed, the reference in FirstDemo.iOS.csproj to MvvmCross was manually removed and the following ItemGroup added:
          <ItemGroup>
             <PackageReference Include=”MvvmCross” Version=”6.0.0″ />
          </ItemGroup>

        The final code is available at https://github.com/nickrandolph/MvxPlus1DaysOfMvvmCross/tree/master/Mvx-00-FirstDemo

        To get this to work I would suggest running the latest Visual Studio for Mac or PC. Hit me up on Twitter or Slack if you have any issues following the steps or running the samples.

        Slack, Teams and the Failings of the Universal Windows Platform (UWP)

        Slack, Teams and the Failings of the Universal Windows Platform (UWP)

        This is going to start of as a bit of a rant…. because it is – I’ve been building desktop and mobile applications using .NET since the first version of the .NET framework shipped many moons ago. In that time we’ve seen the rise and fall of various frameworks, patterns and technologies, all of which were supposed to make our lives as developers, designers and hopefully users better. Whilst the web seems to be this slowly devolving of JavaScript rot, you’d have thought that the .NET Framework after so many years would be everything that a developer needs in order to build amazing apps. Unfortunately, no, some idiot decided it would be great to run all that web-junk inside a native application.

        This brings me to the heart of my rant: Depending on our customers and suppliers, we toggle between Microsoft Teams, Slack, Skype, Skype for Business (now mostly deprecated in favour of Teams), HipChat, Hangouts and even Messenger. Whilst we all love to complain about how bad Skype is, the reality is that newer tools such as Teams and Slack are even worse. Both Slack and Teams are built using Electron and as far as desktop applications go, they are both as nasty as each other. They’re both slow; the user interface on both is painful and in no way takes advantage of the fact that I’m running on Windows. The operative word being Windows <<<—it has an S. I have to switch between multiple Slack channels and multiple Teams on a daily basis – they’re all in the same window; switching between them is slow (10-20secs); and it’s hard to keep track of conversations because notifications either don’t work, or are buried behind a single dot (not even a count as to how many unread messages).

        So why is it that things are so bad….. well it’s because the other options are no better. Take for instance the Universal Windows Platform – which is now only really Universal to desktop and Xbox because realistically they’re the only targets that you’ll consider (save some end cases for IoT and Hub). What a missed opportunity for Microsoft – they could have nuked the failed Xamarin Forms experiment in favour of extending UWP to really be the Universal Application Platform (UAP – oh wait, that’s the internal target framework for UWP already!!!); instead they’re sinking continued development effort into Xamarin Forms in the hope that it’ll one day be a viable alternative to Electron, Flutter, React Native….

        Talking of Xamarin Forms, is this such a bad platform? Well no, I actually quite like Xamarin Forms and I’ve personally invested a lot of time recently trying to help MvvmCross get to a stable v6 so that it can better support Xamarin Forms development. However, I would say that if you’re building for Xamarin Forms and you’re not using a third party Mvvm framework, you really need to – Microsoft’s continual assertion that Xamarin Forms has everything you need is just plain misleading and just leads to poorly architected applications.

        So, what is bad about Xamarin Forms? Well it’s hamstrung between at least three platforms (iOS, Android, Windows… Tizen, WPF….) in that they made a decision to rely on the native controls for each platform. React Native has a similar issue, since they decided on a similar approach. Flutter on the other hand has platform independent rendering and for that it’s getting a lot of attention. The design guidance from years ago that you should build for the platform UI is just plain wrong – you’ll end up with an application that just looks bad (lipstick on a pig!). You need to build applications that work for your brand – don’t design it multiple times, build it to suit your brand and your needs. You may decide to adopt some platform UX but the reality is that you want a button in your app to look the same on all platforms.

        Anyhow, enough of a rant about the failings of desktop apps…. until next time, enjoy losing hours of your day to responding to messages on Teams, Slack etc

        PWA Follow Up

        PWA Follow Up

        It’s clear that talking about Progressive Web Applications (PWAs) is all the rage. I noticed today that fellow Microsoft MVP, Adam Pedley who runs the Xamarin Help website and blog, posted about where PWAs and Xamarin.Forms fit. Whilst I’m not sure I agree with his opening statement about PWAs being started by Google (there is a long legacy of different browsers providing pseudo-offline features which pre-date the term PWA, so the concept itself isn’t new), I will definitely agree that it has been Google that has been championing the cause, with Microsoft adding some behind the curtain support (eg PWABuilder.com). One of the most interesting points that’s worth highlighting is the disconnect between the device features/capabilities that the web and client applications (native, Xamarin or Xamarin Forms) can take advantage of. Whilst the difference is being progressively eroded, there are still plenty of areas where a client application is the way to go. Shout out to https://whatwebcando.today/

        image

        Cross-platform applications – PhoneGap/Cordova, Xamarin, PWAs and now Flutter

        Cross-platform applications – PhoneGap/Cordova, Xamarin, PWAs and now Flutter

        At Built to Roam we build applications that target a wide array of different platforms, using a wide variety of technologies depending on the project requirements. One of the most challenging things faced by organisation looking to build any form of software is often not what should I build, it’s often what technology should I use to build it. Unfortunately this is also where the most cycles are wasted and the poorest decisions are made.

        Nirvana would be building the software once, and for it to be available on every platform and device type, able to be instantly updatable and have a rich and engaging user interface (and I’m sure there’s more things that needed to be bolted onto this list of “ideals”). However, the reality is that there are different device types and sizes; there are different technologies with differing capabilities; and different developer and deployment workflows. Rather than being able to make an absolute decision on the best strategy, companies are limited by their own field of influence. Too often this includes Gartner reports, media hype and both internal and contractors with whom the decision makers have a relationship with.

        In addition to the number of options that are available, the optimum strategy also evolves over time. For example, five years ago in Australia it made sense for organisations to start their investment in mobile apps with a fairly basic iPhone application. Today the market expectation is that a mobile strategy encompasses at least Android and iOS, phone and tablet, and with a comprehensive set of features. In fact some applications, don’t even have a web presence, finding that their mobile apps were sufficient for their business model.

        So the question is really whether it is possible to define the optimum strategy for a business and is it possible to future proof it?

        To investigate this a bit further, let’s take a look at the progression of native application development. What’s quite interesting is that businesses have woken up to the fact that maintaining multiple applications written in the preferred technology for each platform is not sustainable. This has led to the emergency of a host of cross platform tools that generate native applications. There are tools such as Xamarin/Xamarin Forms which compile C# so that it can be run on the target platform; There has also been an explosion in Javascript based solutions, such as React Native where it generates the native components for each platform based on HTML mark-up (+CSS, JavaScript etc); More recently again there is Flutter, which aims to provide a user experience that has been drawn from the ground up to be platform agnostic. How do you make a decision between these technologies?

        More importantly is – are you making the decision about the right thing? It would seem that making a decision about which native application toolset to use would be right but actually the web and some of the hybrid solutions solve so many challenges that native application developers face, it would be foolish to ignore them. Take for example the recent hype around Progressive Web Applications. There are some who believe this is just another round of hype about the newest buzzword to arrive on the scene but in actual fact whilst the name is new, the concept is not. Back even in the days of Windows Vista, there were desktop gadgets that essentially allowed parts of the web to run in a container in an offline capacity. PWAs are just the latest name to be given to this concept.

        Where PWAs are set to make a difference is that they are being widely backed (eg Google: https://developers.google.com/web/progressive-web-apps/ and Microsoft: https://pwabuilder.com) and they also arrive at a point in time where devices have browsers and rendering engines that are capable of delivering a high-performance web experience whether in-browser, or in a hosted web application.

        Do you think the market is ready for PWAs? or are native applications going to rule for the foreseeable future?

        New BuildIt Release for NetStandard 2.0 (General, States and Forms)

        New BuildIt Release for NetStandard 2.0 (General, States and Forms)

        A new release of the following libraries is available via NuGet (v1.1.0.134):

        BuildIt.General

        BuildIt.States

        BuildIt.Forms

        Whilst not much has changed in terms of features, behind the scenes there was quite a significant change as we adjusted the solution/project structure, and thus the nuget package structure. We took advantage of the ability to multi-target which meant we no longer have to have separate projects/libraries in order to support platform specific features. BuildIt.General, which used to have a UWP specific library, is now a single libary. Same goes for BuildIt.States. BuildIt.Forms has two libraries, down from the 5 that it used to have.

        Additionally we also added direct support for netstandard 2.0. As part of the build process, each library is compiled for netstandard 1.0, netstandard 2.0 and then any platforms that have additional features.

        In this release we’ve released multiple packages with the same version number, even though there is an interdependency between them (Forms –> States –> General).

        Please reach out and let me know if you see any issues in this release with any of these libraries. We’ll be working to release updates to the other BuildIt libraries over the coming weeks.

        Building Applications for Platform X

        Building Applications for Platform X

        As we get started with a new year it’s time to pause and think about how the app development ecosystem has evolved, what technologies continue or are emerging, and look at the decision matrix that will define what technology your next application is developed in. I’m going to treat this post as a bit of an intro to some of the technologies that I think are worth further investigation.

        I think the easiest way to do this is to walk the spectrum from web apps through to native platform apps:

        Web Apps

        When we talk about web apps, there is a natural assumption that these will be responsive web sites that will work across a wide range of devices and browsers. However, they can be divided further into what I would consider traditional web sites and single page applications. Whilst this division can be blurred, for example when you host an Angular application within a .NET core application, the point is that there is a difference in the mindset of the developers building the web app.

        Of course, this section includes the obvious ASP.NET Core, React and Angular. Whilst ASP.NET is still a valid choice, I specifically left it out of the list as I think most new projects will favour ASP.NET Core unless there is an impediment that requires full ASP.NET.

        Progressive Web Applications allow web developers to extend their applications to leverage more device capabilities. This is a particularly hot area of development for most platforms as this is seen as one of the best long term solution for minimising mobile development fatigue.

        Hybrid

        Next in the progression are hybrid applications which combine web technologies with a platform specific deployment package – this sounds a bit cryptic but that’s because there are a couple of different models for this.

        Firstly there’s the Cordova/PhoneGap model where the application is defined using html, css, javascript, and wrapped in a native platform deployment package. The deployment step is required in order for most stores to accept applications. The important thing here is that the layout and logic for the application is packaged with the application and that the platform web rendering engine is used to display the application.

        The second model is much more interesting and is one that’s being used by React Native and Native Script where the logic and layout is defined in javascript, css and a form of HTML. The HTML actually defines native elements that will be rendered in the correct location.

        Cross Platform

        Before we get to native platform tools and technologies, we’ll stop in on a long time friend, Xamarin. As with the previous sections there are again two options with Xamarin: traditional Xamarin, and Xamarin Forms. With the traditional Xamarin approach the developer is much closer to the metal and has a higher degree of control. However, the Xamarin Forms option allows for user interfaces to be rapidly developed once, and then feedback/issues are resolved on a platform by platform basis.

        Native Platform

        Lastly, we have the Native platform options for developers:

        Android

        Java, C++ with Eclipse, Android Studio

        iOS

        Objective C, Switft, Interface Builder (now part of XCode)

        UWP

        C#, XAML, Visual Studio (or Visual Studio for Mac)

        As this is hopefully one in a sequence of posts on the topic of framework selection, I’d love some feedback on what technology you think will be important to you and those you work with – comments are off but hit me up on twitter @thenickrandolph if you have thoughts on this.