Get Current Device Location

PDF for offline use
Sample Code:
Related Articles:
Related SDKs:

Let us know how you feel about this

Translation Quality


0/250

last updated: 2016-12

This recipe shows how to get the location of a device using Android.Location.LocationManager.

This recipe will show how to get the location of the device. When a button on the activity is clicked by the user, then a street address that is close to the location will also be displayed.

🚫

This recipe is deprecated but is retained to support those devices that do not have Google Play Services installed. Android applications should use the Fused Location Provider that is available through Google Play Services.

Recipe

  1. Create a new Xamarin.Android application named GetLocation.

  2. Edit AssemblyInfo.cs, and declare the permissions necessary to use the LocationServices:

    [assembly: UsesPermission(Manifest.Permission.AccessFineLocation)]
    [assembly: UsesPermission(Manifest.Permission.AccessCoarseLocation)]
  3. Declare the permissions necessary to use the Geocoder class. This is not strictly necessary for obtaining the GPS coordinates of the device, but this example will attempt to provide a street address for the current location:

    [assembly: UsesPermission(Manifest.Permission.Internet)]
  4. Edit Main.axml so that it contains two TextViews and a Button:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingTop="20dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp">
        <TextView
            android:layout_width="fill_parent"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_height="wrap_content"
            android:text="Location (when available)"
            android:id="@+id/location_text"
            android:layout_marginBottom="15dp" />
        <Button
            android:layout_width="fill_parent"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_height="wrap_content"
            android:id="@+id/get_address_button"
            android:text="Get Address" />
        <TextView
            android:layout_width="fill_parent"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_height="wrap_content"
            android:text="Address (when available)"
            android:id="@+id/address_text"
            android:layout_marginTop="10dp" />
    </LinearLayout>
  1. Add some instance variables to Activity1.cs:
static readonly string TAG = "X:" + typeof (Activity1).Name;
TextView _addressText;
Location _currentLocation;
LocationManager _locationManager;

string _locationProvider;
TextView _locationText;
  1. Change OnCreate:
protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);

    _addressText = FindViewById<TextView>(Resource.Id.address_text);
    _locationText = FindViewById<TextView>(Resource.Id.location_text);
    FindViewById<TextView>(Resource.Id.get_address_button).Click += AddressButton_OnClick;

    InitializeLocationManager();
}

The handler for button click will be covered below. The logic for initializing the LocationManager is placed in its own method for clarity.

  1. Add a method called InitializeLocationManager to Activity1:
void InitializeLocationManager()
{
    _locationManager = (LocationManager) GetSystemService(LocationService);
    Criteria criteriaForLocationService = new Criteria
                                          {
                                              Accuracy = Accuracy.Fine
                                          };
    IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);

    if (acceptableLocationProviders.Any())
    {
        _locationProvider = acceptableLocationProviders.First();
    }
    else
    {
        _locationProvider = string.Empty;
    }
    Log.Debug(TAG, "Using " + _locationProvider + ".");
}

The LocationManager class will listen for GPS updates from the device and notify the application by way of events. In this example we ask Android for the best location provider that matches a given set of Criteria and provide that provider to LocationManager.

  1. Edit Activity1.cs and have it implement the interface ILocationListener and add in the methods required by that interface:
[Activity(Label = "Get Location", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity, ILocationListener
{
    // removed code for clarity

    public void OnLocationChanged(Location location) {}

    public void OnProviderDisabled(string provider) {}

    public void OnProviderEnabled(string provider) {}

    public void OnStatusChanged(string provider, Availability status, Bundle extras) {}
}
  1. Override OnResume so that Activity1 will begin listening to the LocationManager when the activity comes into the foreground:
protected override void OnResume()
{
    base.OnResume();
    _locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
  1. Override OnPause and unsubscribe Activity1 from the LocationManager when the activity goes into the background:
protected override void OnPause()
{
    base.OnPause();
    _locationManager.RemoveUpdates(this);
}

We reduce the demands on the battery by unsubscribing from the LocationManager when the activity goes into the background.

  1. Add an event handler called AddressButton_OnClick to Activity1. This button allows the user to try and get the address from the latitude and longitude. The snippet below contains the code for AddressButton_OnClick:
async void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
    if (_currentLocation == null)
    {
        _addressText.Text = "Can't determine the current address. Try again in a few minutes.";
        return;
    }

    Address address = await ReverseGeocodeCurrentLocation();
    DisplayAddress(address);
}

async Task<Address> ReverseGeocodeCurrentLocation()
{
    Geocoder geocoder = new Geocoder(this);
    IList<Address> addressList =
        await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10);

    Address address = addressList.FirstOrDefault();
    return address;
}

void DisplayAddress(Address address)
{
    if (address != null)
    {
        StringBuilder deviceAddress = new StringBuilder();
        for (int i = 0; i < address.MaxAddressLineIndex; i++)
        {
            deviceAddress.AppendLine(address.GetAddressLine(i));
        }
        // Remove the last comma from the end of the address.
        _addressText.Text = deviceAddress.ToString();
    }
    else
    {
        _addressText.Text = "Unable to determine the address. Try again in a few minutes.";
    }
}

The ReverseGeocodeCurrentLocation method will asynchronously lookup a collection of Address objects for the currrent location. Depending on factors such as the location and network availability, none, one, or multiple addresses will be returned. The first address (if possible) will be passed to the method DisplayAddress which will display the address in the Activity.

  1. Update the method OnLocationChanged to display the latitude and longitude when GPS updates are received and update the address:
public async void OnLocationChanged(Location location)
{
    _currentLocation = location;
    if (_currentLocation == null)
    {
        _locationText.Text = "Unable to determine your location. Try again in a short while.";
    }
    else
    {
        _locationText.Text = string.Format("{0:f6},{1:f6}", _currentLocation.Latitude, _currentLocation.Longitude);
        Address address = await ReverseGeocodeCurrentLocation();
        DisplayAddress(address);
    }
}

You will need to add the System.Xml.Linq assembly, this can be done by Right clicking on Resources > Edit Resources and selecting the correct assembly.

  1. Run the application. After a short while, the location of the GPS should be displayed. Be patient it can take a little while to display the co-ordinates:

  1. Click the button Get Address, and then the location should be translated into a street address:

Additional Information

The LocationManager provides access to the system location services, while the Geocoder class is used to retrieve an address associated with the given latitude and longitude. The Geocoder class makes a network call to Google's server to lookup the address, so because of this the call should be performed asynchronously.

Xamarin Workbook

If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.