Xamarin.Tip – iOS Push Notification Device Token Extraction in iOS 13+

This weekend, I spent some time getting some apps updated with the latest Xamarin, iOS, Android, etc. A lot of these apps make use of push notifications across platforms. I was running some automated tests against them to do the following steps:

  • Register for push notifications on sign-in / startup
  • Send registration update details to API
  • API sends updates to Azure Notification Hub or Firebase (depends on the project)
  • Send push notification to all test users
  • Send push notification to specific test user

I noticed immediately that all my new iOS builds were failing to receive any push notifications after updating registrations.

Time to debug!

The Old Way

Here was my original method for kicking off the push notification registration:

AppDelegate.cs

//...
private void RegisterForPush()
{
    if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
    {
        UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
            (granted, error) =>
            {
                if (granted)
                    InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications);
            });
    }
    else if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
    {
        var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
                UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
                new NSSet());

        UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
        UIApplication.SharedApplication.RegisterForRemoteNotifications();
    }
    else
    {
        UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
        UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
    }
}
// ..

This processes kicks off the internal iOS process to start registration. It will check against your apps registered entitlements for push, check the environment it should be using between development and production, and then if all goes well, it will hit the RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) method in the AppDelegate. If there are any explicit errors it will instead hit FailedToRegisterForRemoteNotifications(UIApplication application, NSError error).

So what we need is the data within that deviceToken of the RegisteredForRemoteNotifications method to send to our API.

Here is what the ORIGINAL implementation looked like (with some of the abstractions removed for simplicity):

AppDelegate.cs

// non-user registration
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    // if using default registration with notification hub for non-user apps
    Hub = new SBNotificationHub("{CONN_STRING}", "{AZURE_HUB_NAME}");

    Hub.UnregisterAll(deviceToken, (error) =>
    {
        if (error != null)
        {
            System.Diagnostics.Debug.WriteLine("Error calling Unregister: {0}", error.ToString());
            return;
        }

        NSSet tags = null; // create tags if you want
        Hub.RegisterNativeAsync(deviceToken, tags);

    });
}

And for handling specific user registration, we need to send it to the API:

AppDelegate.cs

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    var token = deviceToken?.Description?.Trim('<', '>')?.Replace(" ", string.Empty);
    if (!string.IsNullOrEmpty(token))
    {
        // this sends the handle to the API to do all the registration
        var remoteRegistrar = new RemoteNotificationRegistrar();
        remoteRegistrar.RegisterForPushAsync("apns", token);
    }
}

Debugging showed me the issue was here:

var token = deviceToken?.Description?.Trim('<', '>')?.Replace(" ", string.Empty);

The token was no longer in the same format… Feeling like an idiot who has been out of the loop, I hit the internet to see what I missed and landed on some of these lovely articles and posts:

So lets do this update in Xamarin:

The New Way

So the old token structure looked like this:

And the new token looks like this:

{length = 32, bytes = 0x965b251c 6cb1926d e3cb366f dfb16ddd ... 5f857679 376eab7c }

So basically we need a clean version of that bytes property of the NSData object.

Azure notification hubs already do this behind the scenes, but we need the clean version for our own method to send to our API, so here’s the new version:

AppDelegate.cs

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    var token = ExtractToken(deviceToken);
    if (!string.IsNullOrEmpty(token))
    {
        // this sends the handle to the API to do all the registration
        var remoteRegistrar = new RemoteNotificationRegistrar();
        remoteRegistrar.RegisterForPushAsync("apns", token);
    }
}

private string ExtractToken(NSData deviceToken)
{
    if (deviceToken.Length == 0)
        return null;
    var result = new byte[deviceToken.Length];
    System.Runtime.InteropServices.Marshal.Copy(deviceToken.Bytes, result, 0, (int)deviceToken.Length);
    return BitConverter.ToString(result).Replace("-", "");
}

There are a few different ways to write this ExtractToken method, but this is what has worked for me!.

After making this change and running it on iOS 13, I started getting user notifications again!

Both Ways

This is great and all, but I still want to make sure folks who haven’t updated to iOS 13 can still use my apps, so I added some explicit version checks to decide which way to extract the token. Here’s what the final looks like all within that ExtractToken method:

private string ExtractToken(NSData deviceToken)
{
    if(UIDevice.CurrentDevice.CheckSystemVersion(13,0))
    {
        if(deviceToken.Length > 0)
        {
            var result = new byte[deviceToken.Length];
            Marshal.Copy(deviceToken.Bytes, result, 0, (int)deviceToken.Length);
            return BitConverter.ToString(result).Replace("-", string.Empty);
        }
    }
    else 
    {
        return deviceToken?.Description?.Trim('<', '>')?.Replace(" ", string.Empty);
    }

    return null;
}

And that’s it! Try this out if you’re having issues with the latest iOS 13 update and your push notification registration.

If you’re still having problems with push notification registration in general, leave a comment below! I’d love to put together an article about the common pitfalls of push notifications on both iOS and Android with a checklist of things to look at, fix, or build on top of what you have!


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile and AI developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.


Alexa.Tip – Build Better Responses in .NET With SSML

In this Alexa.Tip series, we explore some little bits of code that can make your life easier in developing Alexa Skills in many languages including C# + .NET, node.jS + TypeScript, Kotlin, etc. We look at concepts that developers might not be aware of, design patterns that and how they can be applied to voice application development, best practices, and more!

In this post, we are looking at a VERY simple, but useful tool when developing Alexa Skills – SSML or Speech Synthesis Markup Language.

If you’re new to voice application development, SSML is a common standard among all the big players – Alexa, Google, Cortana, etc. At its simplest form, it’s a simple set of XML elements that are used to tell the Voice Assistant (such as Alexa) how to speak your response in a particular way. The alternative to using SSML is to return simple text as a string and let the assistant respond with their normal speech. However, this commonly falls short on things like:

  • Abbreviations
  • Dates
  • Emphasis
  • Pauses
  • Tone
  • Pitch

This is especially true when the assistant is reading out a particularly long set of text. It becomes too… robotic. Ironically…

So let’s look at an example of a C# and .NET response using simple text:

Function.cs

public SkillResponse SimpleTextResponse()
{
    return ResponseBuilder.Tell(new PlainTextOutputSpeech
    {
        Text = "When one door of happiness closes, another opens; but often we look so long at the closed door that we do not see the one which has been opened for us."
    });
}

With a response like this, Alexa will likely read it too quickly which can really diminish the power behind such a great quote (by Helen Keller).

Now we can very easily update a response like this to give ourselves something more powerful:

Function.cs

public SkillResponse RichTextResponse()
{
    return ResponseBuilder.Tell(new SsmlOutputSpeech
    {
        Ssml = 
            @"<speak>
                When <emphasis level=""moderate"">one</emphasis> door of happiness closes, another opens;
                <break time=""1.5s""/>
                <s>but often we look so long at the <emphasis level=""strong"">closed</emphasis> door that we do not see the one which has been opened for us.</s>
            </speak>"
    });
}

Now with this, we can add emphasis of different levels on certain words, add breaks in the speech when we need to, and separate contextual sentences!

For a full list of SSML tags that Alexa supports check this out:
https://developer.amazon.com/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html

And be sure to check back for more intro to expert level tips on Alexa Skill development!
Or take a look at other posts in the Alexa.Tip series here!

Side note: I’m also working on a tool to make building SSML responses even better – especially for very large and dynamic pieces of conversations. The idea is to build a more Fluid Design approach for something like this:

// returns a string
return SsmlBuilder.Speak("When")
    .Emphasis("one", Emphasis.Moderate)
    .Speak("door of hapiness closes, another opens;)
    .Break(1.5)
    .Sentence("but often we look so long at the closed door that we do not see the one which has been opened for us.")
    .Build();

Or something like:

// returns a string - uses string searching
return SsmlBuilder.Speak("When one door of happiness closes, another opens; but often we look so long at the closed door that we do not see the one which has been opened for us.")
    .Emphasis("one", Emphasis.Moderate)
    .Break(";")
    .Sentence("but often we look so long at the closed door that we do not see the one which has been opened for us.")
    .Emphasis("closed", Emphasis.Strong)
    .Build();

Or:

// returns a string - uses indexes and lengths
return SsmlBuilder.Speak("When one door of happiness closes, another opens; but often we look so long at the closed door that we do not see the one which has been opened for us.")
    .Emphasis(4, 3, Emphasis.Moderate)
    .Break(47)
    .Sentence(49, 112)
    .Emphasis(59, 6, Emphasis.Strong)
    .Build();

Let me know what you think in the comments or on twitter @Suave_Pirate – Would you rather build SSML Responses like this or is writing the XML in a big fat string working alright for you?


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile and AI developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.


voicify_logo
I’m the Director and Principal Architect over at Voicify. Learn how you can use the Voice Experience Platform to bring your brand into the world of voice on Alexa, Google Assistant, Cortana, chat bots, and more: https://voicify.com/


Alexa.Tip – How to Host Alexa Skills in Azure

If you’re a .NET developer in the Azure cloud sphere and want to start dabbling in Alexa Skill Development, you don’t have to uproot your entire career and development process to go learn AWS, how Lambdas work, the serverless lifecycle, etc. In this post, we’ll go over just how easy it can be to build an Alexa Skill using C#, ASP.NET Core, and Azure!

The traditional setup for Alexa Skills is:
– AWS Lambda
– .NET Core Lambda project template

But we’re going to be using:
– Azure App Services
– ASP.NET Core API project template

NOTE: This is not an introduction into how Alexa skills work, or how to create your very first skill. This is meant to provide options for hosting your skills, and for how to build skills in general using .NET. If you’re BRAND new to Alexa Skill development, start by reading through their documentation (mostly using node.js, but focus on the structure of an interaction model, what intents and slots are, etc.)

For source of the entire project checkout: https://github.com/SuavePirate/Alexa.NET.WebApi

Step 1 – Create an Alexa Developer Account

If you haven’t already created an Alexa Developer account, you’ll need one in order to register and test your skill.

Simply follow, the Amazon documentation on how to do this – super simple: https://developer.amazon.com/alexa

Step 2 – Create a Skill in the Developer Console

With your Alexa developer account, create a new Skill.

Choose Custom Skill:

create_skill

Then choose the empty “Start from Scratch” template:

choose_template

Now you can manage your interaction model.

For this example, we are going to create a skill that let’s users ask for information about Animals. We’ll use a custom Intent for this, but use the built in AMAZON.Animal slot.

On the left side, go to JSON Editor and paste this interaction model. You can make adjustments as you see fit:

interactionModel.json

{
  "interactionModel": {
    "languageModel": {
      "invocationName": "animal facts",
      "intents": [
        {
          "name": "AMAZON.FallbackIntent",
          "samples": []
        },
        {
          "name": "AMAZON.CancelIntent",
          "samples": [
            "I'm all set"
          ]
        },
        {
          "name": "AMAZON.HelpIntent",
          "samples": []
        },
        {
          "name": "AMAZON.StopIntent",
          "samples": [
            "Quit",
            "Goodbye"
          ]
        },
        {
          "name": "AnimalFactIntent",
          "slots": [
            {
              "name": "Animal",
              "type": "AMAZON.Animal"
            }
          ],
          "samples": [
            "I'd like to know about {Animal}",
            "What is an {Animal}",
            "Give me information about the {Animal}",
            "Tell me about {Animal}"
          ]
        }
      ],
      "types": []
    }
  }
}

This allows our users to ask things such as “Tell me about Monkeys” and then use the animal they are asking for to send information back to them!

Step 3 – Create the ASP.NET Core API

In Visual Studio, create a new project and choose the ASP.NET Core Web Application:

aspnetcore

In the next dialog, select the API template, and be sure that HTTPS is enabled:

API_project_with_https

With your new web application, you’ll need to install the Alexa.NET Nuget Package from Tim Heuer
https://www.nuget.org/packages/Alexa.NET/1.5.5-pre

This nuget package has models for the JSON that Alexa sends to your API and a convenient fluid API design for building your responses that is similar to how the actual Alexa Java and JavaScript SDKs work.

Now that the Alexa models are available, let’s create a new API controller:

AlexaController.cs

[Route("api/[controller]")]
public class AlexaController : Controller
{
    /// <summary>
    /// This is the entry point for the Alexa skill
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public SkillResponse HandleResponse([FromBody]SkillRequest input)
    {
        var requestType = input.GetRequestType();

        // return a welcome message
        if(requestType == typeof(LaunchRequest))
        {
            return ResponseBuilder.Ask("Welcome to animal facts, ask me about information on an animal", null);
        }

        // return information from an intent
        else if (requestType == typeof(IntentRequest))
        {
            // do some intent-based stuff
            var intentRequest = input.Request as IntentRequest;

            // check the name to determine what you should do
            if (intentRequest.Intent.Name.Equals("AnimalFactIntent"))
            {
                // get the slots
                var animal = intentRequest.Intent.Slots["Animal"].Value;
                if(animal == null)
                    return ResponseBuilder.Ask("You forgot to ask about an animal! Please try again.", null);

                return ResponseBuilder.Tell($"I would normally tell you facts about ${animal} but I'm not a real skill yet.");
            }
        }

        return ResponseBuilder.Ask("I didn't understand that, please try again!", null);
    }
}

This controller contains a single HTTP POST endpoint that takes in an SkillRequest. It then breaks down the request in order to respond accordingly. So if the user opens the skill which initiates the LaunchRequest, we can give them a welcome message with hints on what they can ask about. Then if they ask for information about an animal, we can handle the IntentRequest with the intent name of “AnimalFactIntent” and use the Animal slot value!

That’s all there is too it! I’d normally suggest abstracting this out of using the controller so that it is more easily testable with unit tests, but for the sake of a simple example, it will work fine.

Step 4 – Publish to Azure App Service

Now that we have our ASP.NET Core project, we need to publish it to an Azure App Service. You can do this directly in Visual Studio or in the Azure portal. For the sake of this example, we’ll do it directly in Visual Studio – assuming you have a valid Azure license and account setup.

From the Solution Explorer – right click your project and Select “Publish”.

Select the “App Service” option and click “Create”.

Then fill out the form to create a new App Service:
AzurePublish

Once your publish is done, you’ll need to ensure that HTTPS / SSL is configured correctly for your app service.

In the Azure portal, go to your new App Service, then scroll to the SSL Settings section.

Be sure that you enforce SSL (Alexa requires endpoints to use HTTPS with trusted certificates. The default App Service SSL cert is signed with Microsoft’s trusted certificate which means that Amazon will accept it).

azure_ssl.PNG

Now make sure that you can hit your App service API endpoint. I usually prefer to enable Swagger for my API using Swashbuckle for this: https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-2.1&tabs=visual-studio%2Cvisual-studio-xml

Step 5 – Register Endpoint with Alexa Skill

Now that we have our App Service with HTTPS set up, we need to go back to the Alexa Developer Console and to the skill. In the left menu, scroll down to the “Endpoint” option.

In the main view, select “HTTPS” instead of “AWS Lambda ARN”. Then enter the URL for the endpoint in your app service and choose the subdomain ssl cert option:
azure_alexa_endpoint

Once this is done, you can save, and build your skill then proceed to test it!

Step 6 – Test

In the Alexa Developer Console, go to your skill and select the “Test” tab. Here you can type or say things like “Open Animal Facts” or “Ask Animal Facts to tell me about Monkeys”.

animal skill test

Here you can also view the JSON that Alexa is sending to your skill and use that to test against your skill directly using something like Swagger or Postman.

Here’s an example JSON input you could use to test:

{
    "version": "1.0",
    "session": {
        "new": false,
        "sessionId": "...",
        "application": {
            "applicationId": "..."
        },
        "user": {
            "userId": "..."
        }
    },
    "context": {
        "AudioPlayer": {
            "playerActivity": "IDLE"
        },
        "Display": {
            "token": ""
        },
        "System": {
            "application": {
                "applicationId": "..."
            },
            "user": {
                "userId": "..."
            },
            "device": {
                "deviceId": "...",
                "supportedInterfaces": {
                    "AudioPlayer": {},
                    "Display": {
                        "templateVersion": "1.0",
                        "markupVersion": "1.0"
                    }
                }
            },
            "apiEndpoint": "https://api.amazonalexa.com",
            "apiAccessToken": "..."
        }
    },
    "request": {
        "type": "IntentRequest",
        "requestId": "...",
        "timestamp": "2018-09-04T17:07:45Z",
        "locale": "en-US",
        "intent": {
            "name": "AnimalFactIntent",
            "confirmationStatus": "NONE",
            "slots": {
                "Animal": {
                    "name": "Animal",
                    "value": "monkeys",
                    "confirmationStatus": "NONE"
                }
            }
        }
    }
}

You can also test on a real Alexa device! Once you enabled testing, any device that is assigned to the same email address as your Alexa Developer Account will have it enabled.

And that’s it! Now get out there and build some Alexa Skills in .NET!


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile and AI developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.


voicify_logo
I’m the Director and Principal Architect over at Voicify. Learn how you can use the Voice Experience Platform to bring your brand into the world of voice on Alexa, Google Assistant, Cortana, chat bots, and more: https://voicify.com/


Xamarin.Meetup – Boston Meetup Today: DevOps for Mobile Apps with Dan Hermes

Join us at Microsoft’s NERD Center to learn about DevOps for Mobile Apps! Meet with some of the local Xamarin MVPs and employees while also enjoying some food.

https://www.meetup.com/bostonmobiledev/events/244933704/

How do we keep our iOS and Android builds organized, tested, and distributed to team members and users who need them, with the correct versions flowing into the app stores? This is DevOps for mobile apps.

Dan Hermes, Xamarin MVP and co-organizer of Boston Mobile C# Developers Group, will discuss the high points of his upcoming edX video course for Microsoft on how to do all of these things using Visual Studio Mobile Center (VSMC). He will talk about developing, deploying and managing mobile applications in DevOps environments. He’ll cover setup and management of VSMC and the testing and deployment of mobile apps. Mobile Center Build, Test, and Distribute are powered by Visual Studio Team System (VSTS), Xamarin Test Cloud, and HockeyApp.  Learn the VSMC workflows that tie all of these tools together.

This talk is for any and all native app developers, not just C#.  Many features of VSMC work for Objective-C and Java just as well as Xamarin.

About the Speaker

Dan Hermes is a Xamarin MVP,  Microsoft MVP, and founder of Lexicon Systems, an award-winning Xamarin consulting firm. Mr. Hermes helps developers create great mobile apps and helps businesses develop a winning mobile strategy. His firm’s Xamarin projects include B4UFLY, a drone app for the Federal Aviation Administration, and a cross-platform app for Thermo Fisher Scientific which won a W3, a Davey award, and was a finalist for a Xammy award. Mr. Hermes’ clientele includes dozens of software-building firms such as Fidelity Investments, EDS, and Computerworld Magazine. He has spoken recently at Microsoft Ignite, IBM InterConnect, Microsoft Azure Day, Xamarin DevDays, and mobile user groups nationwide . His mobile cross-platform dev blog is http://mobilecsharpcafe.com/. Connect with him on Twitter at @danhermes. Dan is a writer for MSDN Magazine, a video course instructor for Microsoft’s OpenEdX curriculum, and author of the best-selling Apress book Xamarin Mobile Application Development.

 

 

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Reality, Virtually, Hackathon This Weekend!

Reality, Virtually, Hackathon is this weekend October 6th – 9th at MIT’s Media Labs.

I’m excited to announce that I’ll be joining the Microsoft team to mentor participants at this year’s installment of the hackathon. If you’re working with Microsoft technologies such as using C# with Unity, Hololens, Acer VR, Xamarin with ARKit and ARCore, Xenko,  or using any of the Azure Cloud Services, then I’m here to help. I’m looking forward to working with some incredible teams with some of the latest technology to build some awe inspiring applications.

Check out some of the other mentors there as well!
http://www.realityvirtuallyhack.com/mentors/ 

Here’s the schedule:

Event Schedule


Friday


Saturday


Sunday


Monday

 


I’ll be there from Friday evening until Sunday evening, so keep an eye out for me if you’re around!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Meetup – Boston Meetup Today: Xamarin on Azure and Cognitive Services

Join us at Microsoft’s NERD Center to learn about using Azure Cognitive Services in your Xamarin apps! Meet with some of the local Xamarin MVPs and employees while also enjoying some food.

https://www.meetup.com/bostonmobiledev/events/242566795/

Xamarin on Azure and Cognitive Services

Mobile development and cloud technologies are very popular right now. If you are a C# developer and already created your first application with Xamarin, you might be interested in learning some more details about Xamarin and Xamarin Forms. You might also want to use all benefits of Azure in your application or jump right into advanced topics and select one (or a couple) Cognitive Services for your application to integrate with. You will be able to get a flavor of all those tools from this talk. Also final demo will add some visual understanding of the topic.

About the speaker

Veronika Kolesnikova is a web developer at UMass Medical School.

Passionate about backend web development, mainly with Microsoft technologies like C#, .NET, SQL, Azure. Loves to learn new development tools and languages and share the knowledge with the community. Recently started working with Xamarin and cannot wait to provide her insights.
Last year Veronika graduated with MS degree in Information Technology.
In her free time, she likes dancing, traveling and practicing aerial yoga.

 

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.