GeoLocation with VB and Windows 8 /8.1

Introduction

This has to be my favorite feature in Windows 8.x. OK, I’ve probably said that many a time. With so many developers wondering why exactly there were five-thousand plus new APIs introduced in Windows 8.x, it is hard to resist the temptation of looking into them. The Geolocation API allows us to find our current geographical location. With this article I will demonstrate how easy it is to implement Geolocation into your apps.

Geolocation

As mentioned earlier, geolocation refers to getting the geographical location of a certain device. This device could be anywhere. The geographical location can be found through the internet, which can be traced through IP address location, satellite, the Wi-Fi positioning system or a GPS. The results are usually shown in latitude and longitude.

To get this information, Visual Studio 2013 and Windows 8.x provides the Geolocation API. This is what we will use in our little sample project.

Our Project

Our project’s purpose is to display the latitude and longitude of the internet connected device.

Design

Open Visual Studio 2013 and create a new VB.NET Windows Store application. Give it a descriptive name, and design it to resemble Figure 1.

Our Design
Figure 1 – Our Design

The accompanying XAML code follows:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="GeoLocation VB Example" VerticalAlignment="Top" Margin="45,70,0,0" FontSize="72"/>
        <Button x_Name="btGetLocation" Content="Get Location" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="78,181,0,0"/>
        <TextBlock x_Name="tbAccuracy" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Accuracy Will Be Displayed Here" VerticalAlignment="Top" Margin="81,373,0,0" FontSize="16"/>
        <TextBlock x_Name="tbLongitude" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Longitude Will Be Displayed Here" VerticalAlignment="Top" Margin="81,273,0,0" FontSize="16"/>
        <TextBlock x_Name="tbLatitude" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Latitude Will Be Displayed Here" VerticalAlignment="Top" Margin="81,242,0,0" FontSize="16"/>
        <TextBlock x_Name="tbStatus" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Status Will Be Displayed Here" VerticalAlignment="Top" Margin="81,739,0,0" FontSize="16"/>
        <Button x_Name="btStop" Content="Stop" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="239,181,0,0"/>
        <Button x_Name="btSetAccuracy" Content="Set Accuracy" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="582,316,0,0"/>
        <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Enter Desired Accuracy In Metres" VerticalAlignment="Top" Margin="81,326,0,0" FontSize="16"/>
        <TextBox x_Name="tbEnterAccuracy" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="336,319,0,0" Width="204"/>
        <TextBlock x_Name="tbSource" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Source Will Be Displayed Here" VerticalAlignment="Top" Margin="81,427,0,0" FontSize="16"/>
    </Grid>

By having a quick glance at the picture above, you will get an idea of what we will accomplish today. Let us get started with the code.

Package Manifest

Before coding, let us just add a couple of Capabilities to our program. Add the selected Capabilities (in Figure 2) to your project.

Figure 2 - Manifest Capabilities
Figure 2 – Manifest Capabilities

Code

Do I really have to tell you what I always start with? OK, if you’re a first time reader of any of my articles, welcome! I always start with the namespaces and today is no exception. Add the following Namespaces above your Form declaration:

Imports Windows.Devices.Geolocation 'Geolocation Namespace
Imports System.Threading 'Threading Namespace
Imports System.Threading.Tasks 'Tasks Namespace

We need all these namespaces for our little project today. The first namespace assists in obtaining the Geolcation of the specified device. The other two NameSpaces deal with threading. We will spawn a different thread to get the geolocation, otherwise our program will freeze a bit until we have received some sort of result from the Geolocation functions.

Add the next modular variables:

    Private WithEvents glGeo As New Geolocator 'Create New Geolocator Object With Its Associated Events
    Private ctsCancel As CancellationTokenSource 'Cancel The Spawned Thread

We create a Geolocator object, and a Cancellation Token source. We will use the glGeo object’s methods to obtain the current location, and we will use ctsCancel to cancel the operation when the need arises or in the event of an error.

Add the following code segment behind the Set Accuracy button:

    'Accuracy Button Click
    Private Sub btSetAccuracy_Click(sender As Object, e As RoutedEventArgs) Handles btSetAccuracy.Click

        'Get & Convert Entered Info
        Dim uintWantedAccuracy As UInt32 = UInt32.Parse(tbEnterAccuracy.Text)

        'Set Accuracy For Geolocation Object
        glGeo.DesiredAccuracyInMeters = uintWantedAccuracy

        'Display Entered Info
        tbAccuracy.Text = glGeo.DesiredAccuracyInMeters.ToString()

    End Sub

Once users click this button, it will take the entered value and try to get you as close as possible to that location. We need to ensure that users enter the correctly formatted info into tbAccuracy. Let us add the next code segment:

    'Entering Of Text In tbEnterAccuracy
    Private Sub tbEnterAccuracy_TextChanged(sender As Object, e As TextChangedEventArgs) Handles tbEnterAccuracy.TextChanged

        Try

            'If Correct Info Entered, Use It
            Dim val As UInt32 = UInt32.Parse(tbEnterAccuracy.Text)

            btSetAccuracy.IsEnabled = True

            'Nothing Entered
        Catch ea As ArgumentNullException

            btSetAccuracy.IsEnabled = False

            'Unwanted Chars
        Catch ef As FormatException

            btSetAccuracy.IsEnabled = False

            'Too Many Numbers
        Catch eo As OverflowException

            btSetAccuracy.IsEnabled = False

        End Try

    End Sub

I have used a Try and catch block to test for valid input. Obviously we want a number, but not a decimal number or an infinite number. Instead of building the logic that will allow for valid input, a Try and Catch block comes in very, no, extremely handy. We attempt to cast the entered value into an Unsigned Int. There are three Catch blocks. the first Catch block determines whether or not a value was entered or not. The second Catch block determines if there was unwanted characters inside, such as alphabetical characters. The last catch block determines if a too large number has been entered.

Let us add the code behind the Get Location button:

    'Obtain Location
    Private Async Sub btGetLocation_Click(sender As Object, e As RoutedEventArgs) Handles btGetLocation.Click

        Try

            ' Create And Get Cancellation Token
            ctsCancel = New CancellationTokenSource()
            Dim canToken As CancellationToken = ctsCancel.Token

            ' Find Position
            Dim gpPos As Geoposition = Await glGeo.GetGeopositionAsync().AsTask(canToken)


            tbEnterAccuracy.IsEnabled = True 'Disabled

            'Display Coordinates
            tbLatitude.Text = gpPos.Coordinate.Point.Position.Latitude.ToString()
            tbLongitude.Text = gpPos.Coordinate.Point.Position.Longitude.ToString()

            'Display Accuracy
            tbAccuracy.Text = gpPos.Coordinate.Accuracy.ToString()

            'Display Location Finding Source
            tbSource.Text = gpPos.Coordinate.PositionSource.ToString()

            'Unauthorized
        Catch eu As System.UnauthorizedAccessException

            tbLatitude.Text = "No data"
            tbLongitude.Text = "No data"
            tbAccuracy.Text = "No data"

            'Cancelled
        Catch et As TaskCanceledException

            tbStatus.Text = "Canceled"

            'Any Other Error,  Such As Not Being Connected
        Catch err As Exception

            tbStatus.Text = "UNKNOWN"

        Finally

            'Clean Up
            ctsCancel = Nothing

        End Try

    End Sub

We set up a Cancelation token, just in case something goes wrong in obtaining the current position. We then use the GetPositionAsync method to obtain our current position. We then display the results accordingly. Add the last code segment for the Stop button:

    'Stop Clicked
    Private Sub btStop_Click(sender As Object, e As RoutedEventArgs) Handles btStop.Click

        'If Cancellation Token Exists
        If ctsCancel IsNot Nothing Then

            ctsCancel.Cancel() 'Cancel

            ctsCancel = Nothing 'Clean

        End If

    End Sub

This simply stops the process of getting the location.

If you were to run your application now, your screen would resemble Figure 3.

Location is displayed
Figure 3 – My Location is displayed. Oops, now you can find me….

Included in this article is a working sample.

Conclusion

I hope you have enjoyed today’s lesson, and hope to see you again soon! Until then, cheers!

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read