How to make Google Maps work in .NET MAUI!

MAUI is still in Preview. That means it has a relatively small feature set and some of it doesn’t work as you’d expect. The fun part is figuring out how to make it work.

We wanted to implement an interactive map in a portion of our app. Seems like MAUI doesn’t support a solution for it yet. Whoops. Xamarin.Forms, the predecessor of MAUI, does support it but it hasn’t been ported to MAUI yet. So what do you do?

Here’s what we did:

  • Create a React project
  • Implement a React Component that shows Google Maps
  • Pass in location data to create pins
  • Host the app as a separate web app on a website (https://sosmap.vercel.app)
  • Show that React app as a “WebView” inside the MAUI app
    • A webview is a webpage hosted inside your app

Suddenly you have an interactive map in your application.

This isn’t the way MAUI is supposed to work, but a hack while it is in preview!


Also, the React app is hosted with CI/CD for a proper agile workflow.

Middle-Age Mutable Ninja Tuples has evolved!

A lot of improvements have been added to our solution, described in detail below. As different parts start to connect, we can see the potential value provided by our solution. Not just in crime fighting, but also as a competitor to food delivery apps like Foodora or Wolt, or transport apps like Uber or Lyft. Our now fully integrated solution includes apps for employees, the back-office and end users, and is easily applied to areas like those described above.

.NET MAUI app

https://streamable.com/fof2sw
Video of our app running on MacOS. Note: Some features are disabled when this video was recorded

We’ve just updated some design elements of our Ninja Turtle SOS App. It has a modern minimalist design. Because when you’re in an emergency you don’t want to have a confusing patterned background or 20 menus to click through. We are still improving on it but it’s feeling more modern already.

Our app is truly cross-platform. It works on iOS, Android, MacOS and Windows. The MAUI framework makes sure our app runs natively and uses device-specific buttons and UI. 

Two-way communication

The MAUI app now properly communicates with the gRPC service, giving it the ability to post SOS alerts to Dynamics and receive SOS status updates back, using a custom Dynamics API client. The status updates are streamed to the app from the server via gRPC.

The gRPC service is automatically deployed to an Azure App Service when we commit to master, using a GitHub Action. 

gRPC isn’t properly supported in Azure App Services yet, because of how new it is. Hopefully we can demonstrate the gRPC service working from Azure tomorrow – in the meantime it’s working fine running locally.

New feature: Google Maps!

When you need help from a Ninja Turtle it’s very useful to know where they are in relation to you. So we have now added Google Maps support to the .NET MAUI app. When a Turtle has been assigned to your distress call you will see a map of your area and live updates of your Ninja Turtles location. 

It’s a beautiful and easy to use feature that shows you where your Ninja Turtle and you are at any time. A small glance at the app and you know if they are close and you can continue to run towards your savior.

The Google Maps integration into MAUI was a challenge. We solved it by creating a React app that the MAUI app accesses using a WebView, basically rendering a website inside the app. The React app uses a Google Maps react library and is hosted as a separate web app (https://sosmap.vercel.app). We use CI/CD to update new features into our React app, so the users will always get the newest map features.

App for registering Turtles

We have added a web app for accepting new applicants for Ninja Turtles. This app allows for fast onboarding and expansion of the workforce in a gig economy style. Thus, Middle-aged Mutable Ninja Tuples can quickly become the biggest provider of Personal Safety as a Service, benefiting from the accompanying network effects.

The Blazor app is automatically deployed to an Azure App Service when committing to main, using a GitHub Action. It’s available here: https://mamntservice.azurewebsites.net/ 

After registering, the user should quickly be able to log in to the Dynamics mobile app. In order to make this possible, a lot of things need to happen behind the scenes.

The first step is automatic creation of an Azure AD user, and assigning of a Dynamics license. We created a custom Azure API client for this, which is called from the backend of the Blazor app. After that, the only thing missing is a Dynamics license. But first, the user must be synced to Dynamics from Azure AD, which can take up to an hour.

Because of this delay, we aren’t available to programmatically add a Dynamics license right away, so we created a Dynamics plug-in which automatically adds the license when a user is created. After it has run, the user should be able to log in to the Dynamics mobile app:

Note: it’s possible to force the user sync to happen right away using PowerShell, we’ll look into that as a possible improvement.

Feel The Heat

Dispatchers have a new tool at their disposal; a Power BI report that visualizes reported distress calls in a heatmap. This is achieved by pulling data using Azure Synapse Link to Dynamics 365, which is then used as a dataset for the Power BI report. For MaMNT, both Synapse and Power BI were uncharted waters before development began, and have proven to be just the tools we needed to bring some extra oomph to the user interface.The heatmap itself is a prebuilt feature by AppSource user Weiwei Cui that takes our latitude and longitude parameters as input and allows us to customize the clustering, values and the look and feel of the map. 

The heatmap dots warp in shape as you zoom on the map, in order to scale the dots and heat signatures, which produces an awesome-looking effect when the dots are split and merged. Going forward, the heatmap will be limited to a set number of the most recent calls, and we may add a timelapse effect to show patterns and development in crimes committed in the city.

For dispatchers, we also added a filtering feature to the right-hand side where the different types of distress calls can be selected to filter the map instantly. This will enable the turtles to move towards proactively fighting and predicting crime instead of reacting to distress calls. This has great utility not just for improving our services for individual users, but also for providing business facing services to third party security entities (i.e. Police).

Automatic test data generation

When developing a tool to fight crime and respond to distress calls, it is imperative to be able to simulate different loads on the systems and dispatchers to build the best possible solution that fits real-life scenarios. MaMNT set up an Azure Data Factory to produce the desired effect of simulated, continuous distress calls being sent from all over the city of Oslo. The Data Factory job randomizes a caller name, a crime type and x-values of coordinates within the range of 59.9xxxx, 10.xxxxx. New distress calls pop up all over the city at set intervals, and you can see the heatmap updating with a new batch of distress calls every 15 minutes. 

Middle-age Mutable Ninja Tuples is plugged in

Users who register as Turtles (those who want to help people in need) in our Blazor web app are automatically created as Azure AD Users and automatically assigned a Dynamics license, using MS Graph API. The only thing missing for Turtles to be able to log in to the Dynamics mobile app is getting a security role in Dynamics.

We would have programatically assigned a Dynamics security role right away, but there’s a problem: users aren’t immediately synced from Azure AD to Dynamics – it can take several minutes.

As a workaround, a Dynamics plug-in listens to user creations and automatically adds the correct security role when new users are added to Dynamics.

When the plugin has done its work, users will be able to log in to the Dynamics app for phones.

Helping out the community!

Yesterday another team were stuck trying to boot their Raspberry Pi from a micro-sd card. They didn’t have a card reader compatible with micro-sd cards and couldn’t format and burn the Raspberry Pi OS image onto it.

We stepped in and used some of our precious time to fully setup a brand spanking new image of Raspberry Pi OS on their micro sd card so they could continue their work! ☺️

Middle-age Mutable Ninja Tuples is integrating with all the things!

The backend for the end-user mobile app (.NET MAUI) is integrating with Dynamics 365 via MS Dynamics Web API, to create SOS alerts and get status updates.

The backend for the Turtle back-office (Blazor web app) is communicating with Azure via MS Graph API to programatically create Azure AD users.

Both backends are retrieving access tokens for MS APIs using MS OAuth API.

The Turtle code-base (GitHub) is configured to automatically post events to Discord, such as commits and releases.

Test – data

We needed testdata to develop the functions, so we made a simple ADF pipeline that inserts “actions” every x sec (if we want to).. We also need a lot of data, since we are planning to run reports and AI, with this test-data function we can start develop.

The ADF-pipeline takes a few params so we can controll how many runs we get.

Source data:

  • SQL server
    • Table with first Names
    • Table with last names
    • Table with IncidentTypes
    • View generating random:
      • name: mixing firstname and lastname
      • incident types (as we make more incident types)
      • longitude: Random – 59.9000 – 59.9999
      • latitude: Random – 10.1000 – 10.9999

Assaults

Planned Work

TBC

Completed Work

TBC

The ALIAS from hell

.NET MAUI is in Preview. Visual Studio is in Preview. If you try to do it on a Mac it feels like every single line of code is in Preview. It isn’t even the real Visual Studio, it’s “Visual Studio for Mac”.

Developing a .NET MAUI project on a MacBook is pain. The project will suddenly stop building and you will not know why. We spent hours debugging to get it working on a Mac again, but even then it is inconsistent.

To get a consistent build I created an ALIAS to run the app.

alias fuck="cd ~/git/all-the-code/Sos.ClientApp && rm -rf obj bin && dotnet restore && dotnet restore && dotnet build -t:Run -f net6.0-maccatalyst"

This command navigates to the project, removes any generated files, restores not once but twice (trust me, I have to) and then builds the project.

It’s way slower than just building normally, but it works. Now I can go back to being happy and creating awesomeness 😄

Stealing with pride

MaMNT have travelled around the internets and found clever, ready-for-use third party solutions to aid them in the development process. The list below shows all the third party solutions they have proudly stole from other hard-working individuals and companies to lighten their own load.

  • gRPC (Google): two-way communication between the mobile app and backend
  • Discord: collaboration and integration with GitHub: events are posted to the MaMNT Discord server
  • XrmToolbox: managing plugins
  • Level up for Dynamics 365: Debugging and configuration

Badges claimed: