Xamarin.Forms get user location when it change

This project you can find at: https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange

When you need to update the user’s location when it change you can make it in Xamarin.Forms too via DependencyService or using Xamarin.Essentials and create a Timer and get the actual Location per seconds (don’t do that :D).

Before coding, we have to satisfy the users permissons.

Andorid: (https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange/blob/master/Xamarin.Forms.DetectUserLocationCange/Xamarin.Forms.DetectUserLocationCange.Android/Properties/AndroidManifest.xml)

Turn ACCESS_COARSE_LOCATION on.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.Xamarin.Forms.DetectUserLocationCange" android:installLocation="auto">
	<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<application android:label="Xamarin.Forms.DetectUserLocationCange.Android"></application>
</manifest>

iOS: (https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange/blob/master/Xamarin.Forms.DetectUserLocationCange/Xamarin.Forms.DetectUserLocationCange.iOS/Info.plist)

    <key>NSLocationAlwaysUsageDescription</key>
    <string>Can we use your location at all times?</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Can we use your location when your app is being used?</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Can we use your location at all times?</string>

ATTENTION: if you will publish on the App Store, you have to pay attention for the privacy. You have to ask the user every time before you will get her/his location. So best way to do that, create a user’s settings, where the user can turn in or off, that you get her/his location. If turned off, you have to show a popup with some text: Can we use your location? and then subcribe to the event. If turned on, you don’t have to show popup.

We have to create an interface in the StandardLibrary. (https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange/blob/master/Xamarin.Forms.DetectUserLocationCange/Xamarin.Forms.DetectUserLocationCange/Services/ILocationUpdateService.cs)

using System;

namespace Xamarin.Forms.DetectUserLocationCange.Services
{
    public interface ILocationUpdateService
    {
        void GetUserLocation();
        event EventHandler<ILocationEventArgs> LocationChanged;
    }

    public interface ILocationEventArgs
    {
        double Latitude { get; set; }
        double Longitude { get; set; }
    }
}

We have to implement this interface in the platforms.

Android: (https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange/blob/master/Xamarin.Forms.DetectUserLocationCange/Xamarin.Forms.DetectUserLocationCange.Android/Services/LocationUpdateService.cs)

using System;
using Android.Content;
using Android.Locations;
using Android.OS;
using Android.Runtime;
using Xamarin.Forms;
using Xamarin.Forms.DetectUserLocationCange.Droid.Services;
using Xamarin.Forms.DetectUserLocationCange.Services;

[assembly: Dependency(typeof(LocationUpdateService))]
namespace Xamarin.Forms.DetectUserLocationCange.Droid.Services
{
    public class LocationEventArgs : EventArgs, ILocationEventArgs
    {
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    public class LocationUpdateService : Java.Lang.Object, ILocationUpdateService, ILocationListener
    {
        LocationManager locationManager;

        public void GetUserLocation()
        {
#pragma warning disable CS0618 // Type or member is obsolete
            locationManager = (LocationManager)Forms.Context.GetSystemService(Context.LocationService);
#pragma warning restore CS0618 // Type or member is obsolete
            locationManager.RequestLocationUpdates(
                provider: LocationManager.NetworkProvider,
                minTime: 0,//millisec
                minDistance: 0,//metres
                listener: this);
        }

        ~LocationUpdateService()
        {
            locationManager.RemoveUpdates(this);
        }

        public void OnLocationChanged(Location location)
        {
            if (location != null)
            {
                LocationEventArgs args = new LocationEventArgs
                {
                    Latitude = location.Latitude,
                    Longitude = location.Longitude
                };
                LocationChanged(this, args);
            };
        }

        public event EventHandler<ILocationEventArgs> LocationChanged;
        
        event EventHandler<ILocationEventArgs>
            ILocationUpdateService.LocationChanged
        {
            add
            {
                LocationChanged += value;
            }
            remove
            {
                LocationChanged -= value;
            }
        }

        public void OnProviderDisabled(string provider) { }

        public void OnProviderEnabled(string provider) { }

        public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras) { }
    }
}

iOS: (https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange/blob/master/Xamarin.Forms.DetectUserLocationCange/Xamarin.Forms.DetectUserLocationCange.iOS/Services/LocationUpdateService.cs)

using System;
using CoreLocation;
using Xamarin.Forms.DetectUserLocationCange.iOS.Services;
using Xamarin.Forms.DetectUserLocationCange.Services;

[assembly: Xamarin.Forms.Dependency(typeof(LocationUpdateService))]
namespace Xamarin.Forms.DetectUserLocationCange.iOS.Services
{
    public class LocationEventArgs : EventArgs, ILocationEventArgs
    {
        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    public class LocationUpdateService : ILocationUpdateService
    {
        CLLocationManager locationManager;

        public event EventHandler<ILocationEventArgs> LocationChanged;

        event EventHandler<ILocationEventArgs> ILocationUpdateService.LocationChanged
        {
            add
            {
                LocationChanged += value;
            }
            remove
            {
                LocationChanged -= value;
            }
        }

        public void GetUserLocation()
        {
            locationManager = new CLLocationManager
            {
                DesiredAccuracy = CLLocation.AccuracyBest,
                DistanceFilter = CLLocationDistance.FilterNone
            };

            locationManager.LocationsUpdated +=
                (object sender, CLLocationsUpdatedEventArgs e) =>
                {
                    var locations = e.Locations;
                    var strLocation =locations[locations.Length - 1].Coordinate.Latitude.ToString();

                    strLocation = strLocation + "," + locations[locations.Length - 1].Coordinate.Longitude.ToString();

                    LocationEventArgs args = new LocationEventArgs();
                    args.Latitude = locations[locations.Length - 1].Coordinate.Latitude;
                    args.Longitude = locations[locations.Length - 1].Coordinate.Longitude;

                    LocationChanged(this, args);
                };

            locationManager.AuthorizationChanged += (object sender, CLAuthorizationChangedEventArgs e) =>
            {
                if (e.Status ==
                    CLAuthorizationStatus.AuthorizedWhenInUse)
                {
                    locationManager.StartUpdatingLocation();
                }
            };

            locationManager.RequestWhenInUseAuthorization();
        }

        ~LocationUpdateService()
        {
            locationManager.StopUpdatingLocation();
        }
    }
}

Use theese implementations via DependencyService: (https://github.com/officialdoniald/Xamarin.Forms.DetectUserLocationCange/blob/master/Xamarin.Forms.DetectUserLocationCange/Xamarin.Forms.DetectUserLocationCange/App.xaml.cs)

using System;
using Xamarin.Forms;
using Xamarin.Forms.DetectUserLocationCange.Services;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Xamarin.Forms.DetectUserLocationCange
{
    public partial class App : Application
    {
        public static ILocationUpdateService LocationUpdateService;

        public App()
        {
            InitializeComponent();

            MainPage = new MainPage();

            LocationUpdateService.LocationChanged += LocationUpdateService_LocationChanged; ;
        }

        private void LocationUpdateService_LocationChanged(object sender, ILocationEventArgs e)
        {
            //Here you can get the user's location from "e" -> new Location(e.Latitude, e.Longitude);
            //new Location is from Xamarin.Essentials Location object.
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

5 thoughts on “Xamarin.Forms get user location when it change”

  1. It’s perfect time to make some plans for the future
    and it’s time to be happy. I have read this post and if I could
    I wish to suggest you few interesting things or suggestions.
    Maybe you could write next articles referring to this article.
    I want to read more things about it!

  2. It’s a shame you don’t have a donate button! I’d without a doubt donate to this superb blog!
    I guess for now i’ll settle for bookmarking and adding your RSS feed to my Google account.

    I look forward to new updates and will share this blog with my Facebook group.
    Chat soon!

  3. I think this is among the most significant info for
    me. And i am glad reading your article. But want to
    remark on few general things, The website style is wonderful,
    the articles is really excellent : D. Good job, cheers

Leave a Reply

Your email address will not be published. Required fields are marked *