Android/Xamarin GPS Location Tracking

This short post is about the easiest way to get GPS Location Tracking with your Android Phone,  Xamarin and C#.

Imagine you have a navigation/tracking application and you need to get the GPS position of the device with real-time accuracy (and not periodically, each 5-15 minutes, like Google Location History does).

In this case you may find useful the following class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Locations;

namespace LocationTrackerTest
{
    /// <summary>
    /// Class provides GPS location.
    /// Note: Requires permission ACCESS_FINE_LOCATION.
    /// Usage: 
    ///   1. Create the class instance. 
    ///   2. Call InitializeLocationManager(). 
    ///   3. Check "CurrentLocation" when you wish or 
    ///      subscribe to "LocationChanged" event to be notified.
    ///   4. When you do not need it any more - call Dispose().
    /// </summary>
    public class GPSLocationTracker : Java.Lang.Object, ILocationListener, IDisposable
    {
        /// <summary>
        /// Current location
        /// </summary>
        public Location CurrentLocation { get; set; }

        /// <summary>
        /// Current location (if available) or status message if not available
        /// </summary>
        public string CurrentLocationString { get; set; }

        public Availability CurrentGPSProviderStatus = Availability.Available;

        /// <summary>
        /// Tracker Status - true if ok, false if no GPS location
        /// </summary>
        public bool IsGettingLocation { get; set; }

        /// <summary>
        /// True if GPS provider is enabled in settings, otherwise false
        /// </summary>
        public bool IsGPSProviderEnabled { get; set; }

        // Event handlers
        public event EventHandler<Location> LocationChanged;
        public event EventHandler GPSProviderDisabled;
        public event EventHandler GPSProviderEnabled;
        public event EventHandler<Availability> GPSStatusChanged;

        public LocationManager _locationManager = null;
        Context _context;
        bool _isGiveToastsOnStatusChanges;
        bool _isFirstLocationReported = false;

        // The minimum distance to change Updates in meters
        long _minDistanceChangeForUpdatesMeters = 10; // 10 meters

        // The minimum time between updates in milliseconds
        long _minTimeBetweenUpdatesMs = 1000 * 30; // 30 seconds

        public GPSLocationTracker(Context context, bool giveToastsOnStatusChanges = true, long minDistanceChangeForUpdatesMeters = 10, long minTimeBetweenUpdatesMs = 30000)
        {
            this._context = context;
            this._isGiveToastsOnStatusChanges = giveToastsOnStatusChanges;
            _minDistanceChangeForUpdatesMeters = minDistanceChangeForUpdatesMeters;
            _minTimeBetweenUpdatesMs = minTimeBetweenUpdatesMs;
            IsGettingLocation = false;
            IsGPSProviderEnabled = false;
        }

        /// <summary>
        /// Initialize location services and request getting location updates and events.
        /// Run this methid after construction of the class instance.
        /// Run it in the UI thread if you wish the GPS settings alert to be automatically displayed.
        /// </summary>
        public void InitializeLocationManager(bool isShowGPSSettingsAlert = true)
        {
            // Get location manager
            _locationManager = (LocationManager)_context.GetSystemService(Context.LocationService);

            // Check if GPS is enabled, If not - display alert with shortcut to GPS settings
            IsGPSProviderEnabled = _locationManager.IsProviderEnabled(LocationManager.GpsProvider);
            if (IsGPSProviderEnabled)
                CurrentGPSProviderStatus = Availability.Available;
            else
                CurrentGPSProviderStatus = Availability.OutOfService;
            if (!IsGPSProviderEnabled && isShowGPSSettingsAlert)
                ShowGPSSettingsAlert();

            // Subscibe to getting location updates with the desired treshold
            _locationManager.RequestLocationUpdates(LocationManager.GpsProvider, _minTimeBetweenUpdatesMs, _minDistanceChangeForUpdatesMeters, this);
            CurrentLocation = _locationManager.GetLastKnownLocation(LocationManager.GpsProvider);
        }

        /// <summary>
        /// Display GPS disabled alert with shortcut to GPS settings
        /// </summary>
        public void ShowGPSSettingsAlert()
        {
            // See http://stacktips.com/tutorials/xamarin/alertdialog-and-dialogfragment-example-in-xamarin-android

            AlertDialog.Builder alertDialog = new AlertDialog.Builder(_context);

            // Setting Dialog Title
            alertDialog.SetTitle("GPS settings");

            // Setting Dialog Message
            alertDialog.SetMessage("GPS is not enabled. Do you want to go to settings menu?");

            // On pressing Settings button
            alertDialog.SetPositiveButton("Settings", (senderAlert, args) => {
                Intent intent = new Intent(Android.Provider.Settings.ActionLocationSourceSettings);
                _context.StartActivity(intent);
            });

            // On pressing cancel button
            alertDialog.SetNegativeButton("Cancel", (senderAlert, args) => { });

            // Showing Alert Message (note - do it only on UI thread, or use Activity.RunOnUiThread method)
            Dialog dialog = alertDialog.Create();
            dialog.Show();
        }


        /// <summary>
        /// LocationListener will call this method when updates come from LocationManager
        /// </summary>
        /// <param name="location"></param>
        public void OnLocationChanged(Location location)
        {
            if (location == null)
            {
                CurrentLocationString = "No location";
                _isFirstLocationReported = false;
                IsGettingLocation = false;
                if (_isFirstLocationReported && _isGiveToastsOnStatusChanges)
                {   // if after we had location, we lost it and got null
                    Toast.MakeText(_context, String.Format("Location update: null", CurrentLocation.Latitude, CurrentLocation.Longitude), ToastLength.Short).Show();
                }
            }
            else
            {
                CurrentLocation = location;
                IsGettingLocation = true;
                CurrentLocationString = String.Format("{0}:{1}", CurrentLocation.Latitude, CurrentLocation.Longitude);
                if (!_isFirstLocationReported && _isGiveToastsOnStatusChanges)
                {
                    Toast.MakeText(_context, String.Format("Location update: {0}:{1}", CurrentLocation.Latitude, CurrentLocation.Longitude), ToastLength.Short).Show();
                    _isFirstLocationReported = true;
                }
            }
            // Fire event
            if (LocationChanged != null)
                LocationChanged(this, location);
        }

        public void OnProviderDisabled(string provider)
        {
            if (provider == LocationManager.GpsProvider)
            {
                if (_isGiveToastsOnStatusChanges)
                    Toast.MakeText(_context, "GPS provider disabled.", ToastLength.Short).Show();
                CurrentLocationString = "GPS provider disabled.";
                IsGettingLocation = false;
                _isFirstLocationReported = false;
                IsGPSProviderEnabled = false;
                // Fire event
                if (GPSProviderDisabled != null)
                    GPSProviderDisabled(this, null);
            }
        }

        public void OnProviderEnabled(string provider)
        {
            if (provider == LocationManager.GpsProvider)
            {
                if (_isGiveToastsOnStatusChanges)
                    Toast.MakeText(_context, "GPS provider enabled", ToastLength.Short).Show();
                CurrentLocationString = "GPS provider enabled.";
                _isFirstLocationReported = false;
                IsGPSProviderEnabled = false;
                // Fire event
                if (GPSProviderEnabled != null)
                    GPSProviderEnabled(this, null);
            }
        }

        public void OnStatusChanged(string provider, Availability status, Bundle extras)
        {
            if (provider == LocationManager.GpsProvider)
            {
                if (CurrentGPSProviderStatus != status)
                {
                    if (_isGiveToastsOnStatusChanges)
                        Toast.MakeText(_context, "GPS Status changed: " + status.ToString(), ToastLength.Short).Show();
                    CurrentLocationString = "GPS Status " + status.ToString();
                    CurrentGPSProviderStatus = status;
                    if (status != Availability.Available)
                    {
                        IsGettingLocation = false;
                        _isFirstLocationReported = false;
                    }
                    // Fire event
                    if (GPSStatusChanged != null)
                        GPSStatusChanged(this, status);
                }
            }
        }


        /// <summary>
        /// Stop location services and unsubscribe from getting events
        /// </summary>
        public void StopLocationManager()
        {
            if (_locationManager != null)
            {
                _locationManager.RemoveUpdates(this);
            }
        }

        public void Dispose()
        {
            StopLocationManager();
        }
    }
}

This class initializes the LocationManager, Checks if the GPS data provider is enabled (if not, it optionally displays a message box with shortcut to GPS settings), and starts listening to location updates with given threshold in meters and timeout.

To illustrate the usage of this class, I’ve created a sample and simple application which displays the GPS position from GPSLocationTracker class on the screen:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace LocationTrackerTest
{
    [Activity(Label = "LocationTrackerTest", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        GPSLocationTracker gpsLocationTracker = null;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Create and initialize the GPSLocationTracker,
            // subscribe to location changed event
            gpsLocationTracker = new GPSLocationTracker(this, true);
            gpsLocationTracker.InitializeLocationManager(true);
            gpsLocationTracker.LocationChanged += GpsLocationTracker_LocationChanged;
        }

        /// <summary>
        /// gpsLocationTracker.LocationChanged event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GpsLocationTracker_LocationChanged(object sender, Android.Locations.Location e)
        {
            // Just show current location in a text field
            TextView tv = FindViewById<TextView>(Resource.Id.txtLocation);
            tv.Text = gpsLocationTracker.CurrentLocationString;
        }
    }
}

There are just 3 lines of code required to initialize this class and subscribe to LocationChanged event. Then you need to create your LocationChanged handler and there perform all the actions you need – like update the position on the map, send the device location update to the server etc.

Note that you should add ACCESS_FINE_LOCATION permission to your application manifest:

androidmanifest

LinQ to Objects Performance Test

I had a discussion with my friend and colleague on LinQ to Objects and its usability and performance. Clearly in case of some simple conditions, the LinQ (especially its method syntax) may simplify your code. But what about performance – is it faster?

I’ll create a couple of tests to figure it out. I’ll query a collection of objects. Collection will contain 10,000,000 “Employee” class objects which will be generated automatically. Below is the code for the Employee class and collection generation method:

Continue reading

Run Processes Reliably (Process Watchdog Service)

Introduction

There are cases where you have one or multiple processes running on the computer and you need to ensure that these processes are running all the time and that they are restarted if they crash. And we are talking specifically about Windows OS.

Usually the scenario is that you have an application server which runs proxy server, mail server, self-hosted web services, web crawler – whatever application providing some API without GUI. And you need these applications to run all the time since the server startup.

The second scenario example is PC running in “kiosk” mode or presentation mode running GUI applications which should be executed on startup after automatic login and kept running, and restarted immediately when crashed.

Imagine also that your applications are developed as stand-alone EXE applications, and you do not wish or can’t convert them to Windows services.

So, the requirements for some tool which will help us in this situation are:

  • In scenario of server running applications without GUI, It must be able to start one or multiple applications with specified paths and command line arguments immediately after computer startup, without user interaction and user login (this way, in case of restart or power interruption, the server will reboot and your applications will be restarted).
  • In another scenario of “kiosk” mode or presentation mode PC running GUI applications, it must be able to run on startup after automatic login.
  • In both scenarios, it must monitor all the started applications and restart each one of them if it exits unexpectedly as soon as possible.

Continue reading

Handling Corrupted State Exceptions (e.g. StackOverflow or AccessViolation) in C#

Application exceptions are handled by your code, usually according to the Exception handling best practices – MSDN – which means that you catch the exception at some level of your application, gracefully finish failed tasks, write to log, give message to the user and continue running.

It is good practice also to create an application-level unhandled exception handler, for example AppDomain.UnhandledExceptionHandler which will catch all exceptions you may miss on other levels of your application.

Let’s see an example (console application, C#):

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            Console.WriteLine("Now we will simulate regular exception.");
            try
            {
                int i = 1;
                i--;
                int j = 1 / i;
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception occured: "+ex.Message);
            }
            Console.WriteLine("The execution continues.");
            Console.ReadKey();
        }
    } 

catch1

We see that the try/catch block successfully caught an exception in managed code.

But if our .NET code performs some unmanaged resources handling, marshaling or PInvoke to unmanaged code, we may get another type of exceptions like StackOverflowException or AccessViolationException (called Corrupted State Exceptions, Article, CSE ) which are not handled by default by regular .NET exception handlers.

Continue reading

C# UDP Multicast on Android Mobile

In the previous post I wrote about C# UDP Multicast. But what if we need to do the same on Android mobile? For example, imagine that you have multiple mobile devices which should exchange messages or send some information to the server without prior information about each other IP addresses. Again, multicast may help us here, and we may use the same C# MulticastUdpClient class explained in the previous post.

Note that mobile multicast will work only inside the local network over WiFi.

First of all, I will use Xamarin framework and Visual Studio 2015, this way I will reuse my C# code.

I will create small tester application, like I did for Windows. The application will have one activity which will provide an input fields to enter multicast IP and port, and 2 buttons to start UDP client and to send sample message.

The project will also contain the MulticastUdpClient class from previous post.

Continue reading

C#, Mono and Unit Testing

Recently I had to run some application which was developed for Windows using C# on Linux. It may be done with the help of Mono framework, and in this post I am sharing my experience of working with Mono.

Introduction

Mono is free and open-source cross-platform .NET Framework and C# compiler, which allows to run C# code in multiple platforms – Android, Linux, BSD, OS X, Solaris, some game consoles etc.

Mono is not a full implementation of .NET Framework – no support for WPF and Workflow Foundation, limited support for WCF and WinForms, some API in other namespaces like System.Management are not implemented. P/Invoke calls to Win32 API will not work on other platforms. But in general it covers almost all the framework which allows most of your C# code which works on Windows to work on other platforms.

Installation

Mono for Windows installation package may be found here: http://www.mono-project.com/docs/getting-started/install/windows/

Download and install it.

Continue reading

WCF Bootcamp #2

Here I will continue the overview of working with NetTcpBinding WCF services which I started in the previous post. Here we will review and answer a couple of additional questions you may meet while working with WCF services.

WCF Client: Keep channel open or not

MSDN best practices and examples of WCF services contain code where the WCF client opens channel to the service, performs a request and closes the channel. But what if your client needs to be connected for a long time and perform periodic requests? Should you open and close channel for each request, or should you hold the channel open? As usual, the answer is “it depends”. It depends on the frequency and amount of your requests to the service. Here are the choices:

  1. Hold the channel open:
    1. Pros: no performance overhead for opening/closing the channel
    2. Cons: channel may be closed/faulted between requests, so on a failed request you should try to reconnect and call the service again.
  2. Open/close for each request:
    1. Pros: connectivity problems between calls does not affect you because you connect each time when you need the service
    2. Cons: performance overhead of opening the service.

So, to be able to take an educated decision, it would be good to know how large this performance overhead is for opening the channel each time we call the service.

To measure this overhead, I’ve created a test application which calls some service in a loop. Here is the client-side code:

Continue reading

Consuming Web API (Xml, JSon) in C#

There are cases when you need to consume the Web API (or just any kind of API which returns you JSON or XML) in C#. Here is a great article by Anthony Baker which describes a quick and convenient way to build to that, generating C# classes exactly matching the schema of JSON or XML returned by some service: How to Consume a JSON REST API in .NET.

The general idea is to get a sample XML/JSON from the API, use one of the services like json2csharp.com or xmltocsharp.azurewebsites.net to generate C# classes, embed these classes into your C# project, call Web API using System.Net.WebClient and use XMLSerializer or DataContractJsonSerializer to convert the received data into C# objects.

There are also additional free services available for consuming Web API in other environments – for example JSON to TypeScript: http://json2ts.com/.

 

 

Microsoft Training Day

For my colleagues who missed the Microsoft Training Day – here are some highlights of things which were stated on the Microsoft presentations with some links to read.

Innovations

  Hololens

https://www.microsoft.com/microsoft-hololens/en-us

  • Virtual/augmented reality head display with cameras and sensors.
  • May project multiple flat displays to different surfaces and react to head movement and guestures.
  • May remove a need in monitors for control centers and more.
  • Microsoft is also working on 2 more head devices, style of Google Glass.

  Microsoft Band 2

https://www.microsoft.com/microsoft-band/en-gb

Windows 10

http://windows.microsoft.com/en-us/windows-10/getstarted-whatsnew-cortana

Continue reading

WCF NetTcpBinding Bootcamp

Introduction

WCF technology is a good and not complicated thing in general, especially the services with basic HTTP binding. But every time I need to develop TCP-binding (NetTcpBinding) services each couple of years, it is painful. All these configuration issues, strange exceptions with exception message without any relation to real reason of the problem, hitting different quotas and limitations – all this I forget from time to time and then I fight it again. So here I will write down my current experience so that the next time I need to create a service I will not step on the same rakes.

My assumptions and conditions are:

  1. I have two parts of my own application/system which run in different processes and possibly on different machines (two servers, or server and clients etc).
  2. I need the best performance and do not need inter-operability with other systems which are not mine – so I will use the NetTcp binding.
  3. Both the service publisher and consumer are parts of my own application, so consumer/client may “know” the service interface and all the data transfer objects used in the service. So, no need to create service reference, which I do not like because:
    1. We should update it every time the service interface is updated
    2. It generates another interface with another DataContract objects – but on my client side I may wish to reuse the server-side code working with my own classes and not with their generated versions; I may also wish to instantiate the service class locally for some circumstances.
    3. It involves metadata publishing overhead I wish to avoid, if not required.

These assumptions and conditions are not suitable for everyone, but I think it is suitable for the majority of the cases where WCF is used to connect between parts/tiers/components of the same application.

In this article I will review creation of a simple service, ways to configure it to avoid common pitfalls, ways to keep the connection online and reconnect on failure, ways to call the service asynchronously and a couple of additional issues.

Simple service

So I will create a solution with 3 projects:

WCFDemoProjectsStructure

The first is common interfaces and data objects – it contains service interface and data object class which will be used in the service:

Continue reading