Programming, Visual Studio

Android Basic App using Xamarin with Visual Studio 2013 for getting User Location on GPS

Xamarin has become one of the essence for .NET developers like us to build applications in C# which can be shared on iOS, Android, Windows, Mac, etc. Nowadays it has become one of the best tool to develop cross platform applications with C# which does not limit us to write apps in Objective-C, Java in order to support other platforms than Windows. I do have a keen interest on developing cross platform applications and started to learn few of the technologies that are involved in developing this. Hence my first touch goes for Xamarin since it can be integrated to Visual Studio 2013 once you install this platform. You can download Xamarin from the following link http://xamarin.com/

While going through some of the code snippets I tried my first attempt to create an Android application in Visual Studio 2013 using Xamarin features. Let me go over how we can create the application. Once you install Xamarin, you can find Android and iOS templates available in Visual Studio 2013. Remember to install Windows version of Xamarin and not MAC version.

I am selecting the Blank App template of Android that I got listed in New Project Window of Visual Studio 2013

image

Once you select an android template prepare the solution, you can see few changes in Visual Studio IDE.

image

This is how your project structure looks like

image

Before I dive deep down on coding the functionality, as in above screenshot I would like to provide a brief of why this Activity class is pretty important. Activity class defines a single, focused thing that the user can perform. This class will typically launch the Android screen. The user will interact with *.xaml file but the actions will be defined in the Activity class. Let’s look at our Activity class and see what’s there.

[Activity(Label = "Xamarin.AndriodApp.Location.demo", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
int count = 1;

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

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

// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.MyButton);

button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); };
}
}

SetContentView() function that you see in the above code actually sets the layout. The layout name is passed as Resource.Layout.Main right. You might be wondering from where the value is coming. Well the value is coming from Resource.Designer.cs file. Lets see what’s there in the designer class which is deriving the value.

public partial class Layout
{

// aapt resource value: 0x7f030000
public const int Main = 2130903040;

static Layout()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}

private Layout()
{
}
}

So when you create the layout and add the UI elements like buttons, textboxes, etc in the views, mapping to the individual ID’s you define for these elements will be generated in this resource file. Whenever you delete these elements from the views, the resource file will automatically get updated.

There are some other components like Fragment class and Intent Class but I am not going to cover them as of now. Android Manifest is one of the main file without which the Xamarin.Android application will fail. It is similar to a Web.Config file in a typical web application. It has name and components of the application, permission level and most important minimum Android API level.  You can right click the project file and view the Manifest information

image

Let’s open the Layout page Main.axml and design the layout.

image

You can get more themes when you click the default theme on the top of the designer window and select more themes

image

While opening the Main.axml file you might encountered some issues with Visual Studio 2013 where the stack trace tells “Xamarin.Android An unhandled exception of type ‘System.InvalidOperationException’ occurred in WindowsBase.dll”. Try to see if you can open the same application in Xamarin Studio. Even if you succeed in opening the file in Xamarin Studio, you might see an error message in the designer window which states “disconnected from layout renderer please close the file and try again”. I searched in many forums and one of them from StackOverflow states to download some files from the following link http://dl-ssl.google.com/android/repository/tools_r23.0.2-windows.zip.  Well I did the same but never knowing what next to be done, I upgraded my Xamarin to latest version of 5.5.3 (build 6). Then the issue got resolved.

Now when I open the axml file either in Visual Studio 2013 or Xamarin Studio, I don’t see any error and the layout is displayed properly.

Now let’s go ahead with our development. Delete the default Button first from the view.

image

Let’s open the Android Manifest window by right-clicking the Project and selecting properties and declare the permissions to use the LocationService and Geocoder class. You need to give permissions for ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION and INTERNET.

image

Now let’s go back to the designer and add two TextView and one Button in the layout. You can add these elements from the Toolbox of Visual Studio IDE.

image

Provide the ID property of these TextViews and Button. Let’s say the first textview ID is location_text, button ID is get_address_button and the other textview ID next to the button is address_text. The IDs should be provided in this format as shown below.

image

Update the MainActivity.cs file with the following code

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


using Android.Locations;
using System.Text;
using System.Linq;
using System.Threading;
using System.Collections.Generic;

namespace Xamarin.AndriodApp.Location.demo
{
[Activity(Label = "Xamarin.AndriodApp.Location.demo", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity, ILocationListener
{

Android.Locations.Location _currentLocation;
Android.Locations.LocationManager _locationManager;
TextView _locationText;
TextView _addressText;
String _locationProvider;

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

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

// Get our button from the layout resource,
// and attach an event to it
_addressText = FindViewById<TextView>(Resource.Id.address_text);
_locationText = FindViewById<TextView>(Resource.Id.location_text);
Button button = FindViewById<Button>(Resource.Id.get_address_button);

button.Click += AddressButton_OnClick;

InitializeLocationManager();
}
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
public void OnLocationChanged(Android.Locations.Location location)
{
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location.";
}
else
{
_locationText.Text = String.Format("{0},{1}", _currentLocation.Latitude, _currentLocation.Longitude);
}
}

public void OnProviderDisabled(string provider)
{
throw new NotImplementedException();
}

public void OnProviderEnabled(string provider)
{
throw new NotImplementedException();
}

public void OnStatusChanged(string provider, Availability status, Bundle extras)
{
throw new NotImplementedException();
}

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;
}
}
async void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
_addressText.Text = "Can't determine the current address.";
return;
}

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

Address address = addressList.FirstOrDefault();
if (address != null)
{
StringBuilder deviceAddress = new StringBuilder();
for (int i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceAddress.Append(address.GetAddressLine(i))
.AppendLine(",");
}
_addressText.Text = deviceAddress.ToString();
}
else
{
_addressText.Text = "Unable to determine the address.";
}
}
}
}

You might encounter some issues with code for referring Location, LocationManager. You need to add Android.Locations.Location and Android.Locations.LocationManager in order to resolve the assembly reference issue. Also you might encounter an issue with IList not have any method ‘Any’ like ‘system.collections.generic.ilist does not contain a definition for ‘any’’. You need to add reference System.Linq and the issue will get resolved. I have modified the code accordingly so that you don’t get any compile and build errors.

Now run the application and you will see the following output.

image

Wait for sometime till the application get deployed native and the Android emulator device is initiated.

image

Click on the Menu button and then you can see the following layout which we have designed.

image

If you are connected to GPS or WiFi which can detect your current location, then on clicking of Get Location button, the co-ordinates will be displayed.

That’s all. Do some more testing on this.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s