iOS - James Montemagno https://staging.montemagno.com/tag/ios/ https://staging.montemagno.com/content/images/2017/08/MonogramIcon_Orange_NoBuffer.png iOS - James Montemagno https://staging.montemagno.com/tag/ios/ Hugo -- gohugo.io Tue, 13 Oct 2026 20:48:55 GMT 60 Long-running Operations on macOS and iOS with NSProcessInfo https://staging.montemagno.com/long-running-processes-ios-macos-nsprocessinfo/ 6117d5c0ba5764003b25bff5 Sat, 14 Aug 2021 15:04:35 GMT

One issue that sometimes comes up in app development is keeping your app alive and running during long running processes. In my case with My Stream Timer, when the user starts a timer, it needs to keep running no matter what. My first solution was to simply turn on Screen Saver mode.

var appDelegate = ((AppDelegate)NSApplication.SharedApplication.Delegate);

appDelegate.MainWindow.Level = NSWindowLevel.ScreenSaver;

This solution "works" but has the side effect that the app will always be on top all the time, no matter what.  As you could imagine this is not an ideal solution. Then out of nowhere Frank told me about starting and stopping Activities with NSProcessInfo. We then did a full podcast on it:

I of course ignored his advice until this morning when I wrote 40 lines of code that solved all of my problems.

What are Activities?

According to Apple:

"The system has heuristics to improve battery life, performance, and responsiveness of applications for the benefit of the user. You can use the following methods to manage activities that give hints to the system that your application has special requirements."

What this means when you Begin or Perform and Activity is that:

"the system disables some or all of the heuristics so your application can finish quickly while still providing responsive behavior if the user needs it."

This is pretty awesome! There are also two distinct categories of activities based on what you app is looking to do.

  • User-initiated activities are explicitly started by the user. Examples include exporting or downloading a user-specified file.
  • Background activities perform the normal operations of your application and aren’t explicitly started by the user. Examples include autosaving, indexing, and automatic downloading of files.

In my case I have a "User-initiated" activity where I want to keep the screen on, app alive, and the processor going. There are several different types of NSActivityOptions that you have fine grain control over to specify this:

In my case this is a NSActivityUserIntitated, which includes NSActivityIdleSystemSleepDisabled, but I also want NSActivityIdleDisplaySleepDisabled. I also have multiple activities running at the same time, so I created a small manager to handle this.

Start Activity

Dictionary<string, NSObject> Activities { get; } = new Dictionary<string, NSObject>();

public void StartActivity(string id)
{
    if (Activities.ContainsKey(id))
    return;

	try
	{
		var options = NSActivityOptions.UserInitiated | NSActivityOptions.IdleDisplaySleepDisabled;

		var activity = NSProcessInfo.ProcessInfo.BeginActivity(options, "User has inititiated a timer that is a long running process.");

	Activities.Add(id, activity);
	}
	catch (Exception ex)
	{
		Debug.WriteLine($"Unable to start activity: {ex}");
    }
}

Now, when the user starts a timer, I kick off an activity and I am good to go.

End Activity

Now, I need to stop it when the timer ends or the users stops or pauses the timer.

public void StopActivity(string id)
{
    if (!Activities.ContainsKey(id))
        return;
    try
    {
        var activity = Activities[id];
        NSProcessInfo.ProcessInfo.EndActivity(activity);
        Activities.Remove(id);
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Unable to start activity: {ex}");
    }
}

That is it! Easy peasy, and now the system will keep My Stream Timer will continue running without having to stay on top.

]]>
Introducing My Cadence for iOS & Android - a Simple Cadence Sensor Display https://staging.montemagno.com/introducing-my-cadence-for-ios-a-simple-cadence-sensor-display/ 5fe0dec86c10e100399f4e62 Tue, 22 Dec 2020 17:30:00 GMT

It has been nearly 3 weeks since I put together my DIY spin bike and I have now clocked in over 25 rides! Let's just say I am really enjoying have the bike at home now that it is chilly and more rainy outside. Last week I wrote a blog on my experience and did a full Apple Fitness+ review video, in which I mentioned one of the issues I had was the lack of Cadence sensor integration into the app. Knowing your cadence is really important during a ride because it is your RPM that you are spinning the pedals. A number is often called out during rides and you are set to match it. The Peloton digital app has the ability to connect to a sensor such as the Wahoo or moofit, but Apple Fitness+ does not. So like I always do I set out to fix this problem and build a mobile app! Today, I am proud to introduce My Cadence for iOS & Android available for free on the App Store and Google Play.

My Cadence for iOS

The application works by connecting to to any sensor that is broadcasting the Cadence & Speed Bluetooth service. This includes Wahoo, moofit, and other sensors that are popular for indoor cycling bikes. In addition the app fully supports light and dark mode, adjustable font sizes, and is completely free with no time restrictions at all. Here is a quick look at how the app works with me setting it up on my spin bike.

The app is completely free, but I also introduced a Pro mode for $2.99 that helps support independent development and unlocked custom theme colors :)

Selecting custom colors in the app

You can grab the app on the App Store and Google Play today. I will have another blog and video on my YouTube explaining how I built the app soon.

]]>
Investing Time in the Xamarin Linker for Smaller App Sizes https://staging.montemagno.com/investing-time-in-the-xamarin-linker-for-smaller-app-sizes/ 5dd314f084e2c7003870dfd4 Mon, 02 Dec 2019 19:00:00 GMT When developing an app, 99% of our time goes into writing the code, testing the functionality, and making small UI tweaks to please our end users. Most of this is done in debug mode which optimizes compilation and app size for speed, which makes sense. When we flip that flag to Release with the default settings, we often pay very little attention as to what is happening to our app. We get a nice APK or IPA and ship it up to the app store and we are done. However, if we just spent a little time fine tuning our settings, we could really reduce the overall app size. I recently sat down for 1 hour and reduced Hanselman.Forms by 4 MB on Android by optimizing the linker in Full Link mode. When I flipped on Startup Tracing for comparison the app size was reduced by 10MB!

App Before and After Optimizing the Linker

I have written many times about using & understanding the linker, however today I want to talk about how to debug the linker.

My recommendation is to flip on Link "Sdk & User Assemblies" and run your application. See if everything works or if your application crashes. Most likely, it will crash and you will see an error such as:

Getting: System.InvalidOperationException: 'A suitable constructor for type 'Shiny.Jobs.JobManager' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'

If you see this, it means it is time to debug through.

Debug the Linker

You should NEVER have the linker on when debugging an app.... unless you are debugging the linker settings! So, turn on that linker in debug and see what happens. Like I said above, you will probably see a crash with the linker stripping away too much. That is usually because of reflection or the main project not referencing items from your .NET Standard project. Hopefully library creators have optimized their libraries to handle the linker, however if they haven't you can easily setup assembly skipping in your csproj file. Here is what it looks like to completely skip over Xamarin.Forms:

// iOS
 <MtouchExtraArgs>--linkskip=Xamarin.Forms.Platform.iOS --linkskip=Xamarin.Forms.Platform --linkskip=Xamarin.Forms.Core --linkskip=Xamarin.Forms.Xaml --linkskip=Samples</MtouchExtraArgs>

// Android
<AndroidLinkSkip>Xamarin.Forms.Platform.Android;Xamarin.Forms.Platform;Xamarin.Forms.Core;Xamarin.Forms.Xaml;FormsViewGroup;</AndroidLinkSkip>

We can easily add assemblies into this list until the app runs. Here is what Hanselman.Forms looks like:

<AndroidLinkSkip>Xamarin.Forms.Platform.Android;Xamarin.Forms.Platform;Xamarin.Forms.Core;Xamarin.Forms.Xaml;FormsViewGroup;Shiny.Core;MediaManager;MediaManager.Forms;</AndroidLinkSkip>

Don't Skip, Inform the Linker

Have you ever wondered why you have all this those Init calls in your app's startup?

Forms.SetFlags("CarouselView_Experimental");
Forms.Init(this, bundle);
FormsMaterial.Init(this, bundle);
Xamarin.Essentials.Platform.Init(this, bundle);
CrossMediaManager.Current.Init(this);
ImageCircleRenderer.Init();
Android.Glide.Forms.Init(this);

This is to help the linker become aware that you are using this library, so don't remove it. If a library doesn't have an Init, you can easily inform the linker you are using a class that is getting linked out like this:

var pancake = typeof(PancakeView);
var circle = new CircleImage();

Depending on how complex the dependency is then you may want to link skip assemblies out since we don't have access to the source code.

Custom Preserve Flags

If you are getting exceptions in classes that are in your own code then you can add a special attribute to the class to tell the linker to preserve it.

In your shared code (usually .NET Standard) add a new file called PreserveAttribute:

public sealed class PreserveAttribute : System.Attribute
{
    public bool AllMembers;
    public bool Conditional;
}

Now, on any class that is getting stripped out add the following attribute:

[Preserve(AllMembers = true)]
public partial class Tweet
{
}

Keep doing this until your code is linker safe and everything is working as expected. In no time at all you will have your app ready to be fully linker optimized and the app size will be reduced :)

Cleanup Before Committing Code

When debugging linker issues, I like to have the same settings mirrored acrossed debug and release. However, leaving these settings on in debug will slow down your builds and will turn off XAML Hot Reload. So, NEVER turn on linking in debug unless you are doing this.

Read More

Now that you have an idea of how to debug and customize yoru code for the linker be sure to read the in-depth documentation for even more goodies. I would also read the following blogs on shrinking your app size, optimizing Android builds, and faster startup times with startup tracing.

]]>
Azure DevOps Settings for Xamarin iOS 13 and Android 10 Apps https://staging.montemagno.com/azure-devops-settings-for-xamarin-ios-13-and-android-10-apps/ 5dd43e2784e2c7003870dfe2 Wed, 20 Nov 2019 20:12:00 GMT

Settings up continuous integration can be tricky when there are new versions coming out. Recently Visual Studio 2019 updated to support Xcode 11, iOS 13, Android 10, .NET Core 3, and C# 8. What a whirlwind of new updates that CI servers got all around the same time! This means that as you were updating your apps your hosted machines also got updated and probably broke your builds :(. My good friend Jonathan Peppers wrote an amazing tool called Boots that allows you to manually install dependencies and previews of Xamarin and Mono.

Boots task in Azure DevOps installing Mono 6.4.0

This is great, but it also means that your build takes a little bit longer to manually install items. Did you know that Azure DevOps has all of the latest bits installed on their hosted agents and even have simple scripts enabling you to decide what version of Xamarin and Mono to run? Here is what you need to know to build your apps in Azure DevOps with C# 8, iOS 13, and Android 10.

Use macOS 10.14

Be sure that you select the latest version of macOS to build your iOS and Android apps on. You can simply specify macOS-latest or macOS-10.14 in your Pipeline settings.

macOS-version selection in Azure DevOps

You can find what software is installed here.

Install .NET Core

This may sound funny to install .NET Core for a Xamarin build, but the latest reference assemblies and build system require it. You can find what version of .NET Core is compatible with Visual Studio for Mac on the docs site.

You can add the Use .NET Core task to install .NET Core 2.2.x or 3.0.x. Either work just fine.

.NET-Core version task in Azure DevOps

Set Xamarin & Mono Version

This next task is very important as it will tell the build agent what version of Xamarin and Mono to use when compiling the app. I like to define a variable with the version number in the format Major_Minor_Revision. For the latest we will use 6_4_0:

Variable in Azure DevOps specifying Mono 6.4.0

Then we will add a task to run a bash script to set the version of Xamarin. This is done with the following inline script:

sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MonoVersion)

Bash script setting the version of Xamarin to use

That is it! Now you are good to go to build your apps with C# 8, iOS 13, and Android 10!

More DevOps!

Looking for more DevOps? Checkout my Channel 9 series on DevOps for Mobile Developers where I walk you through everything you need to know about DevOps with my friend Abel.

]]>
Is the MacBook Pro 16-inch the Ultimate Developer Laptop? https://staging.montemagno.com/is-the-macbook-pro-16-inch-the-ultimate-developer-machine/ 5dcddce884e2c7003870dfbc Sat, 16 Nov 2019 00:30:31 GMT

It seems as though Apple has finally fixed the keyboard on the latest MacBook 16-inch and as a bonus, brought back the escape key! This seems to be what everyone is talking about, but what is really important is the return to PRO for the MacBook Pro. What I mean by this is that finally we can fully spec out a MacBook Pro with as much RAM and SSD space that we could ever want and at a decent price. If you head over to the configuration page you will be able to spec out your MacBook Pro with up to 64GB of RAM and 8TB of SSD! That is right 8TB!!!!!!!!

This is a big deal for developers that need a super powerful laptop on the go, especially if you are doing mobile development for iOS and Android. More importantly, is that for the first time I think we have a MacBook Pro that can actually handle running macOS and Windows (in Parallels) without compromise! Yes, you will be sharing the GPU, but there are 8-cores built into this puppy! I actually don't think you need to fully spec out the machine either. Here is the build I would go for:

That is the upgraded 8-core i9, 64GB RAM, and 2TB SSD, all for just around $4,000! That does seem expensive, but it is basically 3 laptops in 1! I am very impressed with this offering and could feel very confident dedicating 32GB of RAM to Parallels, for that super butter smooth development experience between macOS and Windows!

Yes, $4,000 is very expensive and obviously you do not need to spend this much on a machine. However, if you are looking for a machine to last the next 6-8 years and do all of your heavy lifting on macOS and Windows 10 then it is a pretty solid option.

What do you think? Leave a comment below if you think this is genius or if I am crazy.

]]>
Opt-out of Dark Mode on iOS, Android, UWP, and macOS https://staging.montemagno.com/opt-out-of-dark-mode-on-ios-android-uwp-and-macos/ 5da372290980fc00385d9b78 Mon, 14 Oct 2019 19:17:00 GMT Everyone can't stop talking about dark mode now that iOS 13 and Android 10 are officially released. To my surprise I have actually really been enjoying dark mode on my desktop and mobile devices. I really want to go through all my apps and add proper dark mode support, however I just haven't had the time. When running apps on iOS 13 or macOS and flipping on dark mode can make your app look.... not so great:

image_from_ios

This can depend on the framework you are using, hard coded values, or a bunch of other things. You may be in this situation or perhaps you have a completely custom theme and you don't want the operating system to touch it. Well, you are in luck because you can opt-out!

iOS

You have two options here. The easiest is to update your Info.plist and add a new entry named UIUserInterfaceStyle. You can manually set this to Light or Dark to apply a theme to your entire app.

<key>UIUserInterfaceStyle</key>
<string>Light</string>

If your app is basically ready to go and just a few screens require a specific mode you can set the OverrideUserInterfaceStyle propety. This can be done on any UIView, UIViewController, or UIWindow.

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
        OverrideUserInterfaceStyle = UIUserInterfaceStyle.Light;
}

macOS

Similar to iOS you can add a very special key to your Info.plist called NSRequiresAquaSystemAppearance and set it to true:

<key>NSRequiresAquaSystemAppearance</key>
<true/>

Android

Android is actually really easy as you have to opt-in for the dark mode to apply to your application. Traditionally, you have always set a light or dark mode for your app in your app's styles. Every Xamarin app defaults to a light theme:

<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">

You have to opt in by setting the theme to DayNight:

<style name="MainTheme.Base" parent="Theme.AppCompat.DayNight.DarkActionBar">

This also works if you are using MaterialComponents theming:

<style name="MainTheme.Base" parent="Theme.MaterialComponents.DayNight">

UWP

UWP is also similar to Android as you have to opt-in for the system wide defaults. Traditionally in your App.xaml file you would set a requested theme:

<Application
    RequestedTheme="Light">

</Application>

This means your app will always use light theme no matter what. To opt-in you will need to remove this property completely.

Checking Requested Theme

It is actually pretty simple to check theme of the app. It has been blogged abotu a lot, and I have even submitted a pull request to Xamarin.Essentials that hightlights it, so take a look. There are also great docs for iOS, Android, and UWP to help guide you.

]]>
Add ASP.NET Core's Dependency Injection into Xamarin Apps with HostBuilder https://staging.montemagno.com/add-asp-net-cores-dependency-injection-into-xamarin-apps-with-hostbuilder/ 5cc7df16b2f3d500bff4c9d0 Tue, 18 Jun 2019 21:53:00 GMT

Dependency injection(DI) and inversion of control (IoC), have been a recurring theme in questions that I have received over the last six years. Sometimes it is around using constructor injection(), simple service containers, and often around full frameworks such as Prism or MVVM Light. I will be honest with you, I have never been a fan of DI/IoC when building mobile apps. My main reason is that there has never been any official pattern or recommendations from Google or Apple (or Microsoft/Xamarin) when building Android and iOS apps. Also, I have always been worried around startup performance in my apps and didn't want to introduce another dependency. However, it is 2019 and I think that my concerns have finally been resolved after talking with my friend Glenn Condron, and here is why:

  1. There is a new official library from Microsoft that handles everything for you.
  2. Using this model gives you other powerful features like logging, HTTPClientFactory, and more.
  3. These devices are crazy powerful and the frameworks we use such as Xamarin.Forms, have really matured.

So, what is this magical library? It is the Microsoft.Extensions framework, but specifically the Generic Host framework that lives inside of Microsoft.Extensions.Hosting. It is a platform independent implementation of ASP.NET Core's extensibility framework.

Microsoft.Extenions

The cool part about this library is that if you already have been building ASP.NET Core applications, then you already know exactly how to use the library. Additionally, it means that just about every other library that extends it works with your Xamarin apps like app configuration, logging, HTTPClientFactory, Polly, and more! Let's start with the basics and first setup a HostBuild, which is the base for the Extensions library and then setup some dependency injection with constructor injection.

Installation and Setup

The first thing to do is to install the v3 pre-release Micosoft.Extensions.Hosting NuGet into all of our projects. This will give our projects access to the base foundation and also includes the ability to use the built-in logging framework and application configuration via a json file.

With the library installed we will create two files in our shared code (also if you are building a single iOS/Android app this will also work):

Startup.cs

Will host all of our HostBuilder configuration and setup all of the dependencies in our application. Here is the base foundation for the file with all of the using statements we will need:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Xamarin.Essentials;

namespace MyApp
{
    public static class Startup
    {
        public static IServiceProvider ServiceProvider { get; set; }
        public static void Init()
        {

        }

        static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
        {

        }
    }
}

appsettings.json

This file will need to be set as an EmbeddedResource and will host configuration properties and settings. Here is a generic default appsettings file:

{
  "Hello": "World",
  "Environment": "Development",
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Host Builder setup

The extensions library has a few main concepts to understand:

  1. HostBuilder: Acts as a builder for adding services (logging, app config, etc.) onto the app.
  2. IServiceProvider: Handles all dependency injection & acts as a service locator and comes from the HostBuilder.

Our Init method must be called from either the main Xamarin.Forms or platform specific app startup. We will fill in the Init method by getting a stream to the app settings file so the HostBuilder can read it, configure services, and setup the built in logging service:

var a = Assembly.GetExecutingAssembly();
using var stream = a.GetManifestResourceStream("MyAssemblyName.appsettings.json");

var host = new HostBuilder()
            .ConfigureHostConfiguration(c =>
            {
                // Tell the host configuration where to file the file (this is required for Xamarin apps)
                c.AddCommandLine(new string[] { $"ContentRoot={FileSystem.AppDataDirectory}" });

                //read in the configuration file!
                c.AddJsonStream(stream);
            })
            .ConfigureServices((c, x) =>
            {
                // Configure our local services and access the host configuration
                ConfigureServices(c, x);
            })
            .ConfigureLogging(l => l.AddConsole(o =>
            {
                //setup a console logger and disable colors since they don't have any colors in VS
                o.DisableColors = true;
            }))
            .Build();

//Save our service provider so we can use it later.
ServiceProvider = host.Services;

Configure Dependencies

We have setup our HostBuilder and called ConfigureServices, but we haven't done anything yet. So let's do it!

Let's say we have the following code for a ViewModel and a service that it needs to use:

public interface IDataService
{
    void DoStuff();
}

public class MyDataService : IDataService
{
    // We need access to the ILogger from Microsoft.Extensions so pass it into the constructor
    ILogger<MyDataService> logger;
    public MyDataService(ILogger<MyDataService> logger)
    {
        this.logger = logger;
    }

    public void DoStuff()
    {
        logger.LogCritical("You just called DoStuff from MyDataService");
    }
}

public class MockDataService : IDataService
{
    // We need access to the ILogger from Microsoft.Extensions so pass it into the constructor
    ILogger<MyDataService> logger;
    public MockDataService(ILogger<MyDataService> logger)
    {
        this.logger = logger;
    }

    public void DoStuff()
    {
        logger.LogCritical("You just called DoStuff from MockDataService");
    }
}

public class MyViewModel
{
    IDataService dataService;
    public MyViewModel(IDataService dataService)
    {
        this.dataService = dataService;
    }

    public void DoIt()
    {
        dataService.DoStuff();
    }
}

Here we have a ViewModel that needs access to the IDataService and one of the implementations needs access to a ILogger. This is where the ServiceCollection comes in allowing us to configure all of our dependencies. Let's setup the ConfigureServices method in the Startup.cs again and configure these new classes.

static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
{
    // The HostingEnvironment comes from the appsetting.json and could be optionally used to configure the mock service
    if (ctx.HostingEnvironment.IsDevelopment())
    {
        // add as a singleton so only one ever will be created.
        services.AddSingleton<IDataService, MockDataService>();
    }
    else
    {
        services.AddSingleton<IDataService, MyDataService>();
    }

    // add the ViewModel, but as a Transient, which means it will create a new one each time.
    services.AddTransient<MyViewModel>();

    //Another thing we can do is access variables from that json file
     var world = ctx.Configuration["Hello"];
}

HostingEnvironment

Access Dependencies

With our HostBuilder and dependencies configured, we can now access them from anywhere. Since we only went up to the ViewModel level we will need to grab it from the ServiceProvider in the code behind from our page:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = Startup.ServiceProvider.GetService<MyViewModel>();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        ((MyViewModel)BindingContect).DoIt();
    }
}

When we call GetService the Microsoft.Extensions framework will handle creating and injecting any dependencies including our IDataService and the ILogger that came for free just by using the library. When we call DoIt in the OnAppering our app ill print out a message to the console using the logger that will have info of what data service it was using.

HTTPClientFactory In Your Xamarin App!

That's right, if you are using Microsoft.Extensions you can use the awesome HTTPClientFactory class that is essentially HTTPClient done right! It handles caching, retries, logging, and all other sorts of awesome! It is really easy to put into your app with just a few lines of code.

First, we will need to install the v3 prerelease Microsoft.Extensions.Http NuGet to get access to HTTPClientFactory. Then in the ConfigureServices method add the following line of code:

services.AddHttpClient();

With this single line of code in place it is now time to get access to the HTTPClientFactory from one of our classes. This is handled like our interface that was passed in as a parameter to the constructor. Microsoft.Extensions takes care of everything for you:

public class MyDataService : IDataService
{
    ILogger<MyDataService> logger;
    HttpClient client;
    public MyDataService(ILogger<MyDataService> logger, IHttpClientFactory httpClientFactory)
    {
        this.logger = logger;
        client = httpClientFactory.CreateClient();
    }

    public void DoStuff()
    {
        logger.LogCritical("You just called DoStuff from MyDataService");
    }
}

If you don't need access to the IHttpClientFactory at all this code can be simplified down to just passing in the HttpClient itself:

ILogger<MyDataService> logger;
HttpClient client;
public MyDataService(ILogger<MyDataService> logger, HttpClient client)
{
    this.logger = logger;
    this.client = client;
}

What is cool now is that when you make any calls with this HttpClient you will automatically get console logging, which is super helpful:

Response

To top it off you can even extend the HttpClient beyond just logging and introduce Polly into the mix with the Microsoft.Extenions.Http.Polly library that will enable you to automatically setup retries and other really cool features. You can find an example of this in my "First App Example" with ASP.NET Core + Xamarin

Platform Specific Dependencies

At this point you are probably like WOW, this is amazing, but what about platform specific implementations that I may need to get access to. Do not fear because it is totally possible and pretty easy to setup. Instead of calling the Init from your shared code, you can call it from your iOS/Android project and pass in a configuration Action like this:

First, let's modify the Init:

public static App Init(Action<HostBuilderContext, IServiceCollection> nativeConfigureServices)
{
    // Resource code

    var host = new HostBuilder()
                    //ConfigureHostConfiguration
                    .ConfigureServices((c, x) =>
                    {
                        //Add this line to call back into your native code
                        nativeConfigureServices(c, x);
                        ConfigureServices(c, x);
                    })
                    // Logging
                    .Build();
}

Then from inside of the Android project's MainActivity and iOS project's AppDelegate you can call this Init method:

Android Example

public class MainActivity : FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(savedInstanceState);

        //setup code

        Startup.Init(ConfigureServices);
        LoadApplication(new App());
    }

    void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
    {
        services.AddSingleton<INativeCalls, NativeCalls>();
    }
}

public class NativeCalls : INativeCalls
{
    public void OpenToast(string text)
    {
        Toast.MakeText(Application.Context, text, ToastLength.Long).Show();
    }
}

iOS Example

[Register("AppDelegate")]
public partial class AppDelegate : FormsApplicationDelegate
{
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        //Init Code:

        Startup.Init(ConfigureServices)

        LoadApplication(new App();

        return base.FinishedLaunching(app, options);
    }

    void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
    {
        services.AddSingleton<INativeCalls, NativeCalls>();
    }
}

public class NativeCalls : INativeCalls
{
    public void OpenToast(string text)
    {
        var vc = UIApplication.SharedApplication.KeyWindow.RootViewController;
        var okAlert = UIAlertController.Create(string.Empty, text, UIAlertControllerStyle.Alert);
        okAlert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
        vc.PresentViewController(okAlert, true, null);
    }
}

Inject The Entire App

As you can see this framework is extremely flexible and allows for optimal extensibility, but you can go even further. As I was trying out this API Glenn challenged me to see how far I could take this dependency/constructor injection madness... so I took it all the way up to the app level. That is right, I injected the entire app, pages, and view models.... because why not! Well maybe you shouldn't do this, but it is pretty cool.

Keeping the same dependencies and view models from above all we need to do is update our MainPage, App, and Init calls:

MainPage

public partial class MainPage : ContentPage
{
    //simply pass in the view model you desire!
    public MainPage(MyViewModel viewModel = null)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }
}

App

There are a few ways to do this. You could pass in the page that you desire into the App constructor or you could have some logic and grab it from the ServiceProvider:

public App()
{
    InitializeComponent();
    MainPage = ServiceProvider.GetService<MainPage>();
}

Update Init

This is where it gets pretty cool, we will create Transient and Singletons of all of the services, view models, pages, and the app itself and have the method return the App intead of being a void method.

public static App Init(Action<HostBuilderContext, IServiceCollection> nativeConfigureServices)
{
    //all of the same code from before
    return ServiceProvider.GetService<App>();
}

static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
{
    services.AddHttpClient();
    services.AddSingleton<IDataService, MyDataService>();
    services.AddTransient<MyViewModel>();
    services.AddTransient<MainPage>();
    services.AddSingleton<App>();
}

Then, call Init from the LoadApplication method instead of calling Init randomly in the iOS/Android project:

LoadApplication(Startup.Init(ConfigureServices));

Just like that we dependency injected our entire application and that is crazy! If you want to try it yourself, you can grab my sample project from GitHub that shows off just about everything in this blog post.

Required Versions of Xamarin/VS

As of today, you should be able to develop and debug iOS/Android apps with all these goodies using any version of Visual Studio 2019 or Visual Studio for Mac 2019. However, if you want to use ship your app and turn on the Linker you will need to have a newer version of mono, which ships with Visual Studio 2019 16.2 (preview 2) and Visual Studio for Mac 2019 8.2 (preview). If you are on Windows you can easily install VS 2019 Preview side by side the normal release.

Watch The Build Session

I had the honor of presenting how ASP.NET and Xamarin can come closer in app model with Glenn in a 20 minute theater session. It is available on the Xamarin Developers YouTube channel:

Learn More

This stuff is super fun and I really hope that it takes off and we can encorporate it into user testing, and perhaps one day into the official templates! Until then it is easy to setup and can lead to some really clean and powerful code. Be sure to read through all of the great docs for Generic Host and through any of the extensions documentation. Enjoy!

]]>
Enhanced Mobile App Versioning in Azure DevOps (VSTS) with Mobile Tasks https://staging.montemagno.com/enhanced-mobile-app-versioning-in-azure-devops-vsts-with-mobile-tasks/ 5c39652e58056200bf4c25d0 Tue, 15 Jan 2019 22:30:00 GMT A little over a year ago, I introduced my Mobile App Tasks Extensions for iOS and Android into the Azure DevOps (VSTS) marketplace. For iOS and Android developers it made the tasks of versioning and adjusting package names a breeze. They were written completely in TypeScript with VS Code and of course are open source on GitHub. Since the initial release I have received overall positive feedback and a few feature requests to add new features. Over the last year I teamed up with my good friend Andrew Hoefling to add small features and optimizations, but finally this week we released version 1.0 with tons of great new features!

New

PList Transform

The first feature you will see is a brand new PList Transform Task. Andrew sent down this pull request and it is super slick. Basically just set any property name and value you want to set in your iOS plist file and you are good to go!

Unix Timestamp

When versioning apps I always had the assumption that developers wanted to manually configure version numbers. However, sometimes you want an auto incrementing number such as a timestamp. When versioning iOS and Android apps you now have the ability to select a custom version number or auto numbering with the Unix time in seconds. This matches App Center functionality, which is super cool :)

format

Misc Updates of Joy

Beyond that we fixed a few other items such as adding the iOS Bundle Identifier to the package name task, fixed issues when comments were in the Android Manifest, handled escaped paths, and updated to the latest packages.

Grab the Extension

You can grab the latest update of the Mobile App Tasks from the Visual Studio Marketplace right now!

Watch Me & Donovan

Last year my good friend Donovan Brown asked me to come on Visual Studio Toolbox to show off the awesome extension and talk Mobile DevOps. Check it out as I walk through the extensions:

How It Was Developed

If you want to see more on how it was developed be sure to check me out on Twitch where I live code. I recently did a full live stream where I added the unix timestamp feature to iOS and Android build tasks. You can watch the full video on YouTube right now!

]]>
Unique Device & App Installation Identifiers for Mobile Apps https://staging.montemagno.com/unique-device-id-for-mobile-apps/ 5c0ec14158056200bf4c259f Fri, 14 Dec 2018 20:00:00 GMT One common query I get all the time from developers is how to get a unique device or application identifier for their mobile app. After deciding to not include an API for this in Xamarin.Essentials we heard a lot of different use cases for it including:

  • Client/Server Communication
  • Login Validation
  • In-App Purchase Verification
  • Licensing Purposes

The next obvious question that you may have is why didn't we include it in Xamarin.Essentials if everyone seemed to want it? The answer is actually pretty straight forward: There is truly no consistent API across every platform to deliver an identifier that is unique to the device or application. On top of that developers all wanted to use the API a bit differently and in some cases make it a core part of processing transactions and that is something we don't want to get in the middle of.

So what can you do if you need this identifier? I would first stop and ask yourself if you can use some sort of User Identifier based on login information as this will ensure uniqueness that you control. If not then there are a few options to go down then trying to implement this.

Platform APIs Available

Each platform offers up something a bit different:

iOS: IdentifierForDevice

This API is pretty interesting as it will give you an alphanumeric string that uniquely identifies a device to the app's vendor. Based on your Bundle ID that you set Apple will return back the same identifier. The issue that I always found is that this can be spoofed by someone else setting a similar Bundle ID, but it is in general a decent API:

public string Id => UIDevice.CurrentDevice.IdentifierForVendor.AsString();

Android: Serial, getSerial & AndroidId

What a mess Android is as there are now three APIs that do similar things and even Google's documentation is all over the place on which to use!

A recommended route would be to attempt to grab the Serial number when available. In the world of Xamarin we will automatically figure out whether to use the static property or the new getSerial() method introduced in Android 9.0 (which requires the READ_PHONE_STATE). The issue here is that this can be modified via rooted devices and sometimes is not available on all hardware. This means that you need to attempt to figure out something else to use, which would be the ANDROID_ID. This is a unique number that is randomly generated when the device is setup, unless you are on API 26+ which is a number that is unique for each combination of app-signing key, user, and device.... As you can see now we have like 4 different identifiers here that all mean different things. If you went this route then your code would look like this:

string id = string.Empty;
public string Id
{
    get
    {
        if (!string.IsNullOrWhiteSpace(id))
            return id;

        id = Android.OS.Build.Serial;
        if(string.IsNullOrWhiteSpace(id) || id == Build.Unknown || id == "0")
        {
            try
            {
                var context = Android.App.Application.Context;
                id = Secure.GetString(context.ContentResolver, Secure.AndroidId);
            }
            catch(Exception ex)
            {
                Android.Util.Log.Warn("DeviceInfo", "Unable to get id: " + ex.ToString());
            }
        }

        return id;
    }
}

Before going down this route think about the implications here of your code and what you are trying to accomplish.

UWP: GetPackageSpecificToken or GetSystemIdForPublisher

We are in a tricky place for UWP as well depending on what we are trying to do. GetSystemIdForPublisher is very similar to what iOS does, but it may not be available in all versions of Windows. The next level is trying to grab a unique hardware identifier for the specific app with GetPackageSpecificToken. So in this case your code may look like:

string id = null;
public string Id
{
    get
    {

        if (id != null)
            return id;

        try
        {
            if (ApiInformation.IsTypePresent("Windows.System.Profile.SystemIdentification"))
            {
                var systemId = SystemIdentification.GetSystemIdForPublisher();

                // Make sure this device can generate the IDs
                if (systemId.Source != SystemIdentificationSource.None)
                {
                    // The Id property has a buffer with the unique ID
                    var hardwareId = systemId.Id;
                    var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);

                    var bytes = new byte[hardwareId.Length];
                    dataReader.ReadBytes(bytes);

                    id = Convert.ToBase64String(bytes);
                }
            }

            if (id == null && ApiInformation.IsTypePresent("Windows.System.Profile.HardwareIdentification"))
            {
                var token = HardwareIdentification.GetPackageSpecificToken(null);
                var hardwareId = token.Id;
                var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);

                var bytes = new byte[hardwareId.Length];
                dataReader.ReadBytes(bytes);

                id = Convert.ToBase64String(bytes);
            }

            if(id == null)
            {
                id = "unsupported";
            }

        }
        catch (Exception)
        {
            id = "unsupported";
        }

        return id;
    }
}

Just like Android you may get different results based on what you are looking for.

A True Cross-Platform Identifier

Now that we have seen each of the platforms and how inconsistent they are, let's talk about a better way of doing this. What most developers are attempting to do is ensure that when an application is installed they can get some unique identifier for that installation. If the app is transfered to a new phone then the identifier is the same, but if it is un-installed then a new identifier is generated. This can easily be accomplished by using Xamarin.Essentials Preferences API to save a Guid when your app starts if it doesn't exist yet. The code is super simple:

var id = Preferences.Get("my_id", string.Empty);
if(string.IsNullOrWhitespace(id))
{
   id = System.Guid.NewGuid().ToString();
   Preferences.Set("my_id", id);
}

This will ensure a unique identifier for the installed application and it is actually the same mechanism that App Center uses for their SDK across each platform! You should of course be aware that this Guid will sync across the user in some instances based on their device and account setup, which is probably what you want to have happen.

There you have it a full break down of each platform with the complexity that each offer. However, my recommendation remains that you should just generate a Guid and go from there :)

]]>
Xamarin.Forms - Icons in Navigation Toolbar https://staging.montemagno.com/xamarin-forms-icons-in-navigation-toolbar/ 5b3e3da02a21a600bf2b04ef Fri, 06 Jul 2018 17:14:00 GMT A somewhat common scenario for mobile apps is to place an icon in the center of the Navigation Toolbar. While I am not sure if this is really best practice in 2018 there still seems to be a lot of demand to do this. What if I was to tell you that this is actually pretty easy to do and for iOS it is built directly into Xamarin.Forms with no need for a custom renderer?

Let's take the default "Master/Detail" template for Xamarin.Forms in Visual Studio. It has a few tabs and an about page that has the Xamarin logo in it. Let's say we want to put that logo into the Toolbar for some reason, let's do it!

Xamarin.Forms 3.2.0 Updates!

The release of Xamarin.Forms 3.2.0 brought some amazing new updates for the Navigation Toolbar including the new TitleView that allows you to set any custom content you would like! Here is the new fancy way of doing it:

<ContentPage>
    <NavigationPage.TitleView>
        <StackLayout Orientation="Horizontal" VerticalOptions="Center" Spacing="10">
            <Image Source="iconXamagon.png">
                <Image.GestureRecognizers>
                    <Image.TapGestureRecognizer
                        Tapped="HandleTapped" />
                </Image.GestureRecognizers>
            </Image>
            <Label Text="3.2.0" FontSize="16" TextColor="Black" VerticalTextAlignment="Center" />
        </StackLayout>
    </NavigationPage.TitleView>
    ...
</ContentPage>
Pretty!
Pretty!

On an older version of Xamarin.Forms? Here is the original post:

iOS Toolbar Icon

This is the easiest as it is built directly in to the API and applied on a Page by Page basis. That is right you can easily adjust the icon that is displayed by setting the TitleIcon static property on NavigationPage.

So if we want our icon to appear on the first tab, we can set the property:

<views:ItemsPage NavigationPage.TitleIcon="xamarin_logo.png"/>

This of course needs to be inside of a Navigation page, so here is the full XAML:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:views="clr-namespace:NavigationIcons.Views"
            x:Class="NavigationIcons.Views.MainPage">
    <TabbedPage.Children>
        <NavigationPage Title="Items">
            <NavigationPage.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                    <On Platform="iOS" Value="tab_feed.png"/>
                </OnPlatform>
            </NavigationPage.Icon>
            <x:Arguments>
                <!-- Set Title Icon Here-->
                <views:ItemsPage NavigationPage.TitleIcon="xamarin_logo.png"/>
            </x:Arguments>
        </NavigationPage>

        <!-- About Page-->
    </TabbedPage.Children>
</TabbedPage>

Just like that we have a beautiful (although not properly sized) logo in our navigation toolbar:

Icon on items page for iOS
Icon on items page for iOS

You can also set it in the code behind for the specific page inside of the constructor if you don't want to clutter up your XAML.

NavigationPage.SetTitleIcon(this, "xamarin_logo.png");

This will yield the same result. Ensure that this icon is inside of your iOS project's Resources and is marked as a BundleResource. You should also follow Apple's guidelines for the size of this icon.

Android Toolbar Icon

Unfortunately the TitleIcon property only works for iOS :(, but we do have the ability to set the icon in our toolbar on a global level for the application. Inside of the Android projects Resources/layout folder lives Toolbar.axml and this is what you set in the MainActivity, which Xamarin.Forms will use to inflate it. Double click to open up the Toolbar.axml and head over to the Source view. The toolbar can actually have anything inside of it, which is pretty nice. We could add a LinearLayout and stack multiple items or we can add an ImageView directly:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:popupTheme="@style/ThemeOverlay.AppCompat.Light">
	<ImageView
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:scaleType="fitCenter"
        android:src="@drawable/xamarin_logo"
        android:layout_gravity="center" />
</android.support.v7.widget.Toolbar>

This will result in any NavigationPage in your app to have a fancy icon on it. You can even add padding to adjust it.

Android App with Icon in Toolbar
Android App with Icon in Toolbar

Hopefully Xamarin.Forms adds an ability to just create a Toolbar for any page that we are on, so we can have this on a page by page basis on Android. The other option here would be to hide the actual Toolbar on Android and just create our own from scratch. This has some up sides as you have more control, but the toolbar won't react to dpi and rotation changes unless you implement more code to do so.

Learn More

The SetTitleIcon property is actually documented over on docs.microsoft.com.

]]>
Introducing Azure DevOps (VSTS) Mobile App Tasks Extension for iOS and Android https://staging.montemagno.com/introducing-vsts-mobile-build-tasks-extension/ 5a3816bb538da90021c4b262 Mon, 18 Dec 2017 19:43:13 GMT

This year I have made a big push towards making Visual Studio Team Services my new continuous everything for my mobile apps, libraries, and any other project that I work on. While Azure DevOps (VSTS) has a lot of built in tasks for mobile applications, there are still a few essential things missing that would really make it a joy to use. The top that stuck out was having the ability to easily bump the version/build numbers for iOS and Android. The other was to change the app's label and package name, which can be nifty when doing different build types for QA/Production. This is where my brand new and open source Azure DevOps (VSTS) Mobile App Tasks Extension comes in!

Mobile-Tasks

Simply install the extension and four brand new tasks are ready to take building mobile apps in Azure DevOps (VSTS) to the next level.

MobileTasks2

Here is a full breakdown of each task:

Android

Multiple tasks to update the AndroidManifest.xml file

Bump Version

Change app's version name and code at build time.

Inputs:

  • sourcePath: Path to android manifest
  • versionCode: code number that must be an integer
  • versionCodeOffset: a specific number to increment the version code
  • versionName: user visible name
  • printFile: output the file before and after changing variables

Package Identifiers

Change app's package name.

Inputs:

  • sourcePath: Path to android manifest
  • packageName: name to replace (com.company.app)
  • appLabel: application name to replace (App Name)
  • printFile: output the file before and after changing variables

iOS

Multiple tasks to update the info.plist file, must be run on macOS

Bump Version

Change app's version name and code at build time.

Inputs:

  • sourcePath: Path to info.plist
  • versionCode: code number that must be an integer
  • versionCodeOffset: a specific number to increment the version code
  • versionName: user visible name (short code)
  • printFile: output the file before and after changing variables

Bundle Identifiers

Change app's bundle name and identifier

Inputs:

  • sourcePath: Path to android manifest
  • bundleIdenifier: identiier to replace (com.company.app)
  • bundleName: name to replace (App Name)
  • printFile: output the file before and after changing variable

Open Source

I have to say that none of this would have been possible without the help of Andrew Hoefling who helped not only convert the bash scripts I had to powershell core, but then again to TypeScript!. He is awesome and really made this all possible. That being said, if you go over to project's GitHub page you will be able to find all the tasks written in Bash, PowerShell Core, and TypeScript. Have ideas for more great mobile specific tasks? Open up an issue on the GitHub page or send down a PR!

]]>
Building Xamarin.iOS Apps in Azure DevOps (VSTS) with Hosted macOS Agents! https://staging.montemagno.com/building-xamarin-ios-apps-in-team-services-vsts-with-hosted-macos-agents/ 5a204fd19f3eff0022eb6594 Thu, 30 Nov 2017 20:38:16 GMT

Azure DevOps (VSTS) is quickly becoming one of my favorite products that Microsoft creates for developers. It helps any developer writing apps in any language build, test, and deploy their applications. On top of that it has free unlimited private Git repos, work item tracking and kanban board, test, release management, and so much more! What is cool is you can use some of it or all of it, up to you. So if you have your code in GitHub, no problem, want to use Trello, no problem, because they all work great together.

IQsRzovW

Since I am a cross platform developer, Azure DevOps (VSTS) is awesome because I can build any of my iOS, Android, Windows, and ASP.NET backends all in one place. On top of that I can do complete release management straight to AppCenter Test/Distribute, Azure, or directly into the App Store. You can hear about my love and passion for Azure DevOps (VSTS) on Merge Conflict Episode 71.

Azure DevOps (VSTS) has always offered hosted Windows VMs for use and recently Linux VMs that could build apps in the "cloud", which is pretty awesome. This is nice becuase all of the tooling is installed and ready to go on demand. There was always one operating system missing, which was macOS... which is required for iOS and macOS development. This wasn't too bad because you can actually download the Azure DevOps (VSTS) build agent on your own macOS machine and point VSTS to it. This is what I normally like to do, but it is also conveinent to run stuff in the cloud, which is why I am excited that they are now offering a hosted macOS agent! It is super easy to use and has some nice scripts installed for Xamarin developers.

Setting up an iOS CI Build

It couldn't be easier to get started with Azure DevOps (VSTS) for Xamarin.iOS. In fact there is a pre-built template with everything setup that you need.

Xamarin-Templates

Hosted macOS Agent

Once the build is setup it is easy to use the hosted macOS agent. Under Process tap on the Agent and hosted macOS will show up!

HostedMacOS

Build with MSBuild (VS for Mac)

One little gotcha seems to be that if you are using new project structures or .NET Standard you will need to use MSBuild (this is the default now in VS for Mac anyways). So make sure you flip the switch under advanced:

BuildwithMSBuild

At this point you are ready to go, and just like that you are off to the races building your iOS apps inside of Azure DevOps (VSTS) on a hosted macOS agent!

]]>
Streamlined TestFlight Registration with fastlane https://staging.montemagno.com/streamlined-testflight-registration-with-fastlane/ 5a15df67f3f57f002151293b Wed, 22 Nov 2017 20:47:23 GMT I think we all can agree that attempting to do beta testing on iOS is pretty terrible. You can't side load apps easily, provisioning profiles are terrible, and manually adding people to TestFlight is no fun. All I want to do is get my app in users hands! Why do I have to go through so much stress? Well you don't, because fastlane comes in to save the day just like it simplifies provisioning in Visual Studio for Mac.

11098337

The issue with TestFlight

So TestFlight is a bit better now that we can add 10,000 people to an app and it will auto install without any provisioning madness. The issue though is that you need to manually add people or upload a CSV file! What? That is crazy! And I have been doing so for way too long.

Introducing fastlane boarding

I feel as though I should have found this a long time ago, but essentially the boarding tool from fastlane enables you to single click deploy an app to heroku (a free service, or optionally grab a docker image) and within a few seconds you have a full website setup ready to automatically add users to a group in TestFlight! Now that is absolutely amazing! Just configure you app, team id, and login credentials and fastlane boarding takes care of the rest. In fact you can test this out right now with the Xamarin Live Player iOS Fast Ring Signup!

FastRing

On top of that it totally works! All you need to do is ensure your account has App permissions in iTunes Connect! I hope this small post helps someone out there simplifier their onboarding with boarding!

Listen to Merge Conflict

Want to learn more about CI/CD and fastlane? Frank and I discuss it all on our podcast Merge Conflict:

]]>
Xamarin Live Player - VS 2017 version 15.4 & 15.5 Awesomeness https://staging.montemagno.com/xamarin-live-player-vs-2017-version-15-5-awesomeness/ 59e6960ed67162002ee82e38 Wed, 18 Oct 2017 16:41:30 GMT Last week Visual Studio 2017 version 15.4 and VS for Mac 7.2 were released into the stable channel. They include the very first release of the Xamarin Live Player capabilities in Visual Studios. This means you can simply update Visual Studio, turn on Xamarin Live Player (Preview), and get started visualizing your mobile apps with nothing more than VS and your iOS or Android device!

image8

Whenever there is a stable release a new preview release of Visual Studio is not far behind. That is right, VS 2017 version 15.5 preview is available right now! It runs side-by-side your existing VS 2017 install and has tons of awesome new features that Pierce blogged about last week. I wanted to take a quick minute to point out some of this new awesome.

Right Click Live Run!

Finally, it happened! You can now right click on any XAML or C# file and live run it! Additionally, you can use the keyboard shortcut: Shift+ALT+F5.

RightClick

Live Run Entire App

A new feature in 15.5 enables the Live Run mode to instantly swap between any XAML or C# file that you have open. No need to ever stop and start the Live Run mode, simply change the focused file:

Live-Player-Swap-2

Live Run Banner

To help better find the Live Run feature there is now a small banner when opening a Xamarin.Forms XAML page. Simply click on Live Run to instantly see it on your device:

image11

Better Feedback

A lot of work has gone into giving proper feedback when things are deploying or errors that may occure with the Live Player.

Errors!

If your code has errors then it will not be deployed, but will instead show up in the Error console as you would expect. How cool, it wasn't actually even compiled... because nothing is compiled, yet the errors are shown.

image16

Deploy Information

In 15.4 the Live Player will output it's deploy information to the output window as to what files were being synchronized. Now in 15.5 the state of connection, transfer, and running are shown in the Visual Studio status bar:

LivePlayerStatus

So Much More

There are tons of nice little teaks and opitmizations to the Xamarin Live Player that I know you are going to love. Go download the latest version of Visual Studio and be sure to get the "Fast Ring" version of the app for the latest and greatest in app features.

In Action

Writing about new featuers is fun, but actually seeing them in action is better. So, I made a short video highlighting how to get started in Visual Studio 2017 version 15.4 and some of the new features in 15.5:

]]>
iOS 11 Missing Marketing Icon https://staging.montemagno.com/ios-11-missing-marketing-icon/ 59d82f9dc76a42002225ace6 Sat, 07 Oct 2017 01:42:51 GMT It is update season for iOS and Android applications with new versions of the operating systems being released. Today, I was on my way to push out a new version of the Xamarin Live Player to Test Flight users and hit this nasty error:

Missing Marketing Icon. iOS Apps must include a 1024x1024px Marketing Icon in PNG format. Apps that do not include the Marketing Icon cannot be submitted for App Review or Beta App Review.

What is that?!?!? I swear I uploaded the icon to iTunes connect. Well... I did, but that wasn't the issue! It is this new silly icon that is in the assets library that you must include. Tha tis right, you need to now shove a 1024x1024px icon for not good reason into your app. It is a new one and is NOT the iTunes artwork of the past. So, let's head into the assets library and find this little hidden icon:

2017-10-06_1840

Just like that, we can now actually send out our app to testers and to the app store! Silly Apple :)

]]>