In this Xamarin hackfest, Microsoft teamed up with Norsk Tid to hack an existing solution, tidBANK. We describe the process and the results here, including implementation of the following Xamarin application functionality:

  • Geolocation
  • Notification system
  • Widget

We also included the following practices for DevOps:

  • Continuous integration
  • Continuous deployment
  • Automated tests with Xamarin Test Cloud

tidBANK is flexible software for time tracking and time reporting used everywhere from small companies to large, multinational corporations.

Key technologies used

During the hackfest, we primarily used these technologies:

  • Visual Studio for development (on Mac and Windows)
  • Xamarin for Visual Studio
  • Xamarin Test Cloud
  • BitBucket
  • Visual Studio Team Services
  • Git for source control
  • HockeyApp
  • Azure Storage Explorer
  • Microsoft Azure for:
    • Notification Hubs
    • Queue storage
    • Web Apps feature of Azure App Service

Hackfest members

  • Øystein Gregers Lindbjør – Developer, Norsk Tid
  • Anton Shunkov – Technical Evangelist, Microsoft
  • Anders Gill – Technical Evangelist, Microsoft

Customer profile

Norsk Tid is a leading supplier of modern systems for time registration located in Oslo. Norsk Tid also delivers products for time allocation and budgeting. It helps hundreds of Norwegian companies and thousands of users to be more productive and keep track of time, vacation days, and hours worked on a project/budget.

Focus of the hackfest

Norsk Tid is developing a new Xamarin application (tidBANK) for both Android and iOS, and would like to expand the possibilities of the application by leveraging more functionality from the Xamarin API to provide a better product for the end users.

The focus of the hackfest is to:

  • Implement geolocation so that users, when tracking time, can provide their locations if they choose.
  • Implement a notification system into the app so company administrators can send notifications directly to users.
  • Create a widget for quickly being able to log hours worked without having to actually open the app itself.

Norsk Tid is also interested in implementing multiple DevOps practices into their workflow to have a better application deployment and development life cycle. This specifically involves:

  • Continuous integration
  • Continuous deployment
  • Automation testing in Xamarin Test Cloud

Deeply focused team

The team hacking

Problem statement

Norsk Tid is essentially facing two issues with the current application:

  • Acknowledging the location from where a user is registering hours.
  • A company’s inability to deliver on-the-fly messages to employees using the application to track hours.

At the time of this writing, the users are able to record their locations based on wherever they are at. There is no way to accurately check and verify the actual location of the user at the time of reporting. Moreover, a place name can be written in multiple ways and has the potential to clutter the database with low-quality data.

For the DevOps part, the main problem is that the deployment of the app to the beta tester is highly connected through a dependency between the developers and their knowledge. Before the hackfest, Norsk Tid did not have a proper distribution model for the beta apps. Implementing the DevOps practices will make it much easier for the developer to get the app to the beta testers (automation), which also makes it much easier to repeat, as well as decoupling the dependency. This allows the next developer on the project to continue on the application development life cycle.

Norsk Tid was very interested in implementing continuous integration (CI). CI would allow the developers to check in code directly to a shared repository where each check-in would then be verified by an automation build that in turn would detect problems early on before release.

For a deeper breakdown of the different capabilities of a proper build process, read more about Continuous Integration.

As a natural step after having implemented CI, we decided to implement continuous deployment (CD). CD is an approach where you can produce software in short cycles, which in turn allows for faster and more frequent releases. Norsk Tid was very intrigued by the capabilities CD would bring because this step adds transparency between the developer, software quality assurance (SQA), and the stakeholders.

Other measurable benefits from the DevOps implementation should be increased release velocity for the tidBANK app. The use of HockeyApp allowed us to distribute the beta version internally with ease. The developers behind tidBANK don’t have to be reluctant anymore to make changes that should effectively be put into release. The process is now fully continuous and automatic, and doesn’t contain manual steps that increase the overhead of the release.

Other benefits from the implementations include:

  • Reduced time to recover upon failure.
  • Reduced deployment failures and rollbacks.

Geolocation

By implementing geolocation, you can easily leverage the GPS to track whether an object is leaving a virtual perimeter (designated area), which could be the office where a worker is located during work hours, or simply use the current location when reporting hours.

Notifications

Another important aspect of the application is to allow the company administrators to provide whatever information they would like their employees to know about, on the fly, through a notification system inside the Xamarin app. For this, Azure Notification Hubs will be used in order to send personalized, scalable push-notifications to all target devices.

Widget

The tidBANK app widget will allow users of the app to more easily log hours worked since they no longer have to open up the full application, but can easily use the miniature application view (widget). The widget could also be used to show other relevant information from the app.

The process

We decided to prepare for the four-day hackfest with multiple calls beforehand to discuss architecture and the “need-to-have” functionality. This allowed us to get directly to work on the application when arriving and proved to be very valuable because we had a lot of functionality to implement and only four days of active work to do it in.

We discussed each member’s strengths in the team and thereafter decided to allocated work based on the specialities of the people involved.

Because there was a limited amount of time set for this hackfest, we decided to focus just on the Android version of the app and building stepping stones for Norsk Tid to add these capabilities to their production app.

Solution, steps, and delivery

Three separate tools were created for this hackfest as stepping stones that can be added to the production app:

  • Web application hosting the web API exposing JSON.
  • Windows Forms application to connect to the storage account in Azure and create a queue to visualize the messages on the queue.
  • Android app made in Xamarin that shows a notification when you have checked into a geofenced area.

Architecture

There are essentially two architectures for the tidBANK application. First, there is a prototype architecture that we developed during this hackfest. It consists of:

  • A web app hosted in Azure.
  • A notification hub hosted in Azure.
  • A storage queue hosted in Azure.
  • A Windows Forms application used for visualization.
  • The Android Xamarin app itself.

The web includes a custom-built API service that exposes the location data (longitude, latitude) for the different offices in JSON format. It also connects to the notification hub that allows us to send notifications to the Xamarin Android app.

The app also deserializes the JSON that the web API has exposed, and uses it for the geolocation part. The app then registers a message on the storage queue when a user has entered a geofenced area based on the geolocation data. When the user leaves the geofenced area, the Xamarin app deletes the message on the storage queue. The Windows Forms application connects to the storage queue and looks for messages on the queue. If there are messages on the queue, it shows a green image displaying that the user is inside the geofenced area. As soon as the user leaves, the Windows Forms application recognizes this and changes the image to red, displaying that the user has left the geofenced area.

The second architecture that we decided on for the tidBANK application looks like this:

The customer has the location data on-premises inside a database. Connected to this database, a tidBANK agent is installed that uses that location data for its location service. This tidBANK web application pings the Azure Function Version Service monthly for the latest version of the tidBANK agent software. Based on the versioning, the tidBANK agent application will update itself or stay idle because it already has the latest updates. The tidBANK agent will be connected to the Azure App Service Mobile App, which has a notifications system and will be used to push notifications out to its users. This service will be connected to Firebase Cloud Messaging for Android push notification. This is again connected to the Xamarin app, and the cycle is complete.

The web app (API)

The web app hosted in Microsoft Azure consists of the example location data that would be stored at the customer’s on-premises database. A web API with Swashbuckle Swagger is exposing the data as JSON format and allows other services to fetch this data and deserialize the JSON for their needs.

Image of web app

The code for the web API:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Swashbuckle.Swagger.Annotations;

namespace TidBankWebAppDemo.Controllers
{
    public class LocationsController : ApiController
    {

        [SwaggerOperation("GetLocations")]
        public IEnumerable<Location> Get()
        {
            return locations;
        }

        public class Location
        {
            public string ID { get; set; }
            public string Long { get; set; }
            public string Lat { get; set; }
            public string Name { get; set; }
        }

        static List<Location> locations = new List<Location>()
        {
            new Location() { ID = "1", Lat = "59.9238397", Long="10.7295549", Name = "Teknologihuset"},
            new Location() { ID = "2", Lat = "59.9250158", Long="10.7311643", Name = "Bislett stadion"},
            new Location() { ID = "3", Lat = "59.9245263", Long="10.7292303", Name = "Sonans"},
        };

    }
}

Download the full code from our GitHub repo.

The Windows Forms application (Queue visualization)

The Windows Forms application was created in order to easily pass messages to the storage queue, as well as display the messages on the queue to visualize if the user had entered the fenced perimeter or had left the perimeter.

The image on the left in the Windows Forms application visualizes the state of the storage queue.

Image of Windows Form application

The main code for the storage queue:

        private async void InitializeQueue(string connectionString, string queueName)            //<<< (async)   initializes queue, create new or use existing
        {
            CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(connectionString);  
                                                                                            // ^ creates an object from your storage account
            CloudQueueClient queueClient = cloudStorageAccount.CreateCloudQueueClient();    // < creates a client queue
            queue = queueClient.GetQueueReference(queueName);                                  

            try { await queue.CreateIfNotExistsAsync(); }                                   // < creates the queue if it doesn't exist
            catch (Exception ex)
            { Console.WriteLine("Could not initialize queue! Error: " + ex.Message); return; }

            groupBox.Enabled = true;

            InitTimer();                                                                  // < fetches elements from the queue through the timer method (uses the ReadFromQueue(); function)
        }

The code above initializes the queue and creates a queue from the name you entered in the UI if it doesn’t exist.

The following code fetches the attributes from the queue inside the ReadFromQueue() function.

            try { await queue.FetchAttributesAsync(); }                                     // < fetches items from queue(items)            
            catch (Exception ex)
            { Console.WriteLine("Could not read from queue! Error: " + ex.Message); return; }

Download the fully documented code from our GitHub repo.

Android App

At the beginning of the hackfest, Norsk Tid had already implemented a Xamarin Android app to simplify the experience for the end users. During the hackfest, Microsoft experts were brainstorming with Norsk Tid to envision how we could further streamline the user experience for customers, making it even easier and more convenient to track their working hours. We came up with three core directions of work for the hackfest:

  • Push notifications
  • Geofencing
  • Widget

The improvements listed above will help ensure that employees don’t miss a check-in by allowing the back-end system to send reminders to employees via push notifications, allowing automatic check-ins and check-outs based on their presence in the office, and allowing users to check in or out directly from the lockscreen. We were using a lot of the platform-specific things Android can offer to really make a great user experience.

Push notifications

For push notifications, we used Azure Notifications Hub.

This is the main code for the notification system:

private NotificationHub _notificationHub { get; set; }
_notificationHub = new NotificationHub(Constants.NotificationHubName, Constants.ListenConnectionString,
				context);
_notificationHub.Register(registrationId, tags.ToArray());

In addition, Norsk Tid wanted their customers to have the ability to check in directly from the “reminder notification,” so we decided to add the “Action” function to the notification as well:

var notificationBuilder = new Notification.Builder(this)
				.SetSmallIcon(Android.Resource.Drawable.IcDialogAlert)
				.SetContentTitle(title)
				.AddAction(new Notification.Action(Android.Resource.Drawable.SymContactCard, "Check in", PendingIntent.GetService(this, 0, checkinIntent, PendingIntentFlags.UpdateCurrent)))
				.SetAutoCancel(true)
				.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification));

Download the full code from our GitHub repo.

Geofencing

Geofencing combines awareness of the user’s current location with awareness of the user’s proximity to locations that may be of interest. To mark a location of interest, you specify its latitude and longitude. To adjust the proximity for the location, you add a radius. The latitude, longitude, and radius define a geofence, creating a circular area, or fence, around the location of interest.

Image of geofenced area

Image from Android Developers.

There is a Google Play service running in the background that we connect to in our Xamarin app. This service registers our geofences. When the user either leaves or enters a geofenced area, the service alerts us to this status change as well as which area it was, so that we can react accurately to the alert.

Here is the main code for the geofencing:

GeofencingRequest GetGeofencingRequest(IList<IGeofence> geofence)
		{
			var builder = new GeofencingRequest.Builder();
			builder.SetInitialTrigger(GeofencingRequest.InitialTriggerEnter);
			builder.AddGeofences(geofence);

			return builder.Build();
		}

Read the full documentation on Android Developers: Creating and Monitoring Geofences, which was immediately applicable to our application (besides the code that is written in Java).

Download the full code from our GitHub repo.

Widget

The implemented widget allows the users to “check in” and “check out” their current working hours without having to launch the tidBANK app itself. This makes the whole experience more fluid and fast. See how the widget functions below:

Here is the main code for the widget:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widgetLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="0dip"
    android:background="@android:color/transparent"
    android:orientation="horizontal"
    android:gravity="fill_horizontal">
    <Button
        android:text="Normal"
        android:layout_width="wrap_content"
        android:layout_height="48.0dp"
        android:id="@+id/selectCheckin" />
    <Button
        android:text="Check in"
        android:layout_width="wrap_content"
        android:layout_height="48.0dp"
        android:id="@+id/postCheckin" />
</LinearLayout>
public override void OnEnabled(Context context)
		{
			var remoteViews = new RemoteViews(context.PackageName, Resource.Layout.WidgetLayout);
			var widget = new ComponentName(context, Java.Lang.Class.FromType(typeof(TidBankWidget)).Name);
			remoteViews.SetOnClickPendingIntent(Resource.Id.selectCheckin, GetPendingSelfIntent(context, ChangeCheckinType));
			remoteViews.SetOnClickPendingIntent(Resource.Id.postCheckin, GetPendingSelfIntent(context, CheckIn));
			AppWidgetManager.GetInstance(context).UpdateAppWidget(widget, remoteViews);
		}

Download the full code from our GitHub repo.

DevOps

After finishing up with all the ideas we had regarding the Android application, we decided to enhance some areas that are highly important for Norsk Tid but rather hidden from the users: DevOps.

Norsk Tid was very interested in implementing continuous integration. CI would allow the developers to check in code directly to a shared repository where each check-in would then be verified by an automation build that in turn would detect problems early on before release. Visual Studio Team Services was up for discussion regarding where the source code would be hosted, but since Norsk Tid already had prior source code for other projects hosted in a BitBucket repository, the decision was to keep the consistency and continue to check in code to BitBucket. Since Bitbucket has good integration with Team Services (which we were aware of before making the decision), we didn’t experience any issues trying to connect both platforms.

After successfully setting up CI, we decided to continue on the good streak of valuable implementations. Norsk Tid already had made some attempts to implement continuous delivery but was facing some issues regarding automatic deployment to HockeyApp—the app wasn’t able to install due to a “parse error.” CD is an approach where you can produce software in short cycles, which in turn allows for faster and more frequent releases. Norsk Tid was very interested in the capabilities of CD and therefore we decided to pursue the challenge. We added a signing step to the pipeline as well as fixes for a couple of other issues (which both parties learned from).

During this endeavor, HockeyApp was picking up the wrong .apk due to excessive use of wildcards in the paths. It turned out there were still some additional unsigned .apk files even after the signing step renamed the main .apk to .unsigned.

After finishing up the continuous integration and the continuous delivery implementations, this is how the architecture for the whole DevOps pipeline looked.

Architectural image of the DevOps pipeline

Now it’s possible for Norsk Tid to go back in time based on the progressive health of the project and evaluate how metrics have changed and what trends occur during the whole development cycle. This includes the unit tests that we configured in the Team Services part. This provides a source of documentation for Norsk Tid and will give an overview of how the unit tests for tidBANK have been performing.

If you are able to rectify potential bugs at the development level before the issue flows to production, then you are actively keeping your costs lower because it would be significantly more cost-inefficient to fix those bugs in another environment. Therefore, Norsk Tid also saves potential work-hours for the time it took us to set up the fully fledged CI system. Not only that, but the quality assurance from having a proper CI process is very valuable because you escape potential failures and errors that might occur during a manual and repetitive process.

Xamarin Test Cloud

The tidBANK app will potentially be displayed on multiple types of screens with different aspect ratios and varying performance. This is almost certain, especially with the lenient rules of bring your own device (BYOD) that Norwegian companies allow. So being able to accurately test this before launch is crucial for the app development cycle. With Xamarin Test Cloud, we can identify potential bugs and test specific UX features before we make a release.

The following shows our setup for running the Xamarin Test Cloud through Team Services.

Image of the setup of test cloud in VSTS

The following shows Xamarin Test Cloud where we tested that we could successfully insert text into a textbox (an Entry in Xamarin), and that the text in the textbox accurately reflects what’s shown on the HTC Desire 510 and Huawei Nexus 6P phone running Android versions 4.4.3 and 6.0.1.

Image of the test in Xamarin Test Cloud of a text entry

Flow

The developer commits code to the BitBucket repo where Team Services compiles and runs the unit tests. Xamarin Test Cloud then checks whether the test has passed, and Team Services then continues the flow by proceeding to HockeyApp where in the end the beta testers will receive the app for testing.

Image of different stages of build and release

Image of the signing build definition

Image of the build definition

Image of the build after it has succeeded

Image of build complete

Screenshot of HockeyApp

Image of the Hockeyapp

Future plans, going forward

All in all, Norsk Tid is very pleased with what we managed to come up with during these four days of hacking. Norsk Tid looks forward to integrating the functionality that we developed during the hackfest into the application that is in production.

And that’s exactly what they will be doing during the next few weeks: using the capabilities we developed as the stepping stone for implementing the proper functionality to increase the value of the current app and deliver better solutions for end customers.

Norsk Tid also will further develop this app with more functionality based on customer feedback throughout the whole application life cycle, and might even implement Azure Active Directory for a single-sign-on experience as well as implementing even more DevOps practices to increase the efficiency of the application deployment cycle to further extend what we did.

Conclusion

What we learned

Many learnings were made during the hackfest. We learned that:

  • Working with the Azure Queue storage can be extremely useful for rapid development of projects with a high velocity of messages. Paying attention to the difference between Peek Messages and Get Messages is important for what you are trying to achieve. Not only is Azure Queue storage useful for projects with a high velocity of messages, but it can also be used in a wide variety of ways to fulfill the need for data transfer and temporary persistence. If you don’t want a limited time persistence, the natural recommendation would be to use the Service Bus Queue instead because it doesn’t delete the message on the queue after the seven-day window is over.
  • It is easy to customize Swashbuckle to handle common scenarios where you may need to alter the default behavior such as allowing for other response codes than just code 200. This documentation explains how to achieve this.
  • It should be one notification hub per mobile app, per environment. And when dealing with multitenant scenarios, each tenant should have its own separate hub. We also found it very useful to be able to send test notifications through the Azure portal itself if the devices have been registered, or even manage all the registrations in the integrated Visual Studio component that speeds up the testing phase and makes it more flexible.
  • It is easy to work with automatic deployment to HockeyApp as well as setting up continuous integration from BitBucket to Team Services with all the documentation that resides on the Internet. We learned that when working with continuous delivery, it is important to pay attention to which .apk file HockeyApp picks up in the path.

Going forward

With the hackfest complete, Norsk Tid is looking forward to further developing this application with more functionality that will please its customers.

By implementing geolocation into the app, customers are now able to pick the location where they are currently located based on the GPS information gathered through the app itself. This increased the usefulness of the app and creates a better experience for the user, as well as increasing the quality of the data that gets into the database behind the app.

If Norsk Tid ever wants to perform business intelligence on the data, the ETL (Extract Transform Load) process will be more efficient because the data residing in the database is already of better quality and doesn’t need much cleansing efforts.

The notification system that has been implemented allows the administrators of a company to send notifications to all of its users on the fly without the need for complex systems to handle this. With the ease of Azure Notifications Hub, the administrators can target all of their employees and make sure everyone using the app gets notified of the latest happenings via a push notification.

And now with the DevOps practices that have been implemented, Norsk Tid can increase the efficiency of its application deployment life cycle and make changes and fixes that can be put into production in minutes (through automation) rather than having to go through a manual undocumented process for occasional releases.

New functionality implemented:

  • Geolocation
  • Notification system
  • Widget
  • DevOps implementation

New functionality wanted in the future:

  • Azure Active Directory integration

Resources