Compartilhar via


How to get the phone's current location for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

This topic shows you how to use the Windows Phone Location APIs to determine the phone’s current location. If your app only needs the user’s location at the current time, for example, to check in the user at a location, or to make a location-based search, this is the recommended method for obtaining the location. This method is much better for the phone’s battery life than using continuous tracking. If you do need continuous location updates, see How to continuously track the phone's location for Windows Phone 8.

Important Note:

You must include the ID_CAP_LOCATION capability in your app manifest file to use the Location API in your app. Failure to do this will result in your app throwing an exception when you deploy it during development, and your app will fail ingestion when you submit it to Windows Phone Store. For more information, see App capabilities and hardware requirements for Windows Phone 8.

Tip

The Windows Runtime location API is supported for both Windows Phone 8 and Windows Phone 8.1 apps. This topic is part of the Windows Phone 8 documentation. To view the Windows Phone 8.1 documentation for this feature, which includes information on developing for both phone and PC, see Detecting Geolocation.

Getting the phone’s current location

  1. In Visual Studio, create a new Windows Phone app.

  2. In Solution Explorer, expand the Properties folder, and then double-click WMAppManifest.xml.

  3. On the Capabilities tab of the manifest designer, select the check box next to ID_CAP_LOCATION.

  4. In MainPage.xaml, paste the following XAML code over the existing Grid element named ContentPanel. This code defines a button that will initiate the location API, and some text blocks to display latitude, longitude, and the app’s status.

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <StackPanel>
            <Button x:Name="OneShotLocationButton" Click="OneShotLocation_Click" Content="get one-shot location"/>
            <TextBlock x:Name="LatitudeTextBlock"/>
            <TextBlock x:Name="LongitudeTextBlock"/>
            <TextBlock x:Name="StatusTextBlock"/>
        </StackPanel>
    </Grid>
    
  5. In MainPage.xaml.cs, add the following using statements to the top of the file.

    using System.Threading.Tasks;
    using Windows.Devices.Geolocation;
    
  6. Add a consent prompt to allow the user to opt out of allowing your app to access their location. All apps should obtain user consent prior to using the location APIs. This example checks for user consent in the OnNavigatedTo(NavigationEventArgs) method of the MainPage class, which is called whenever the app is launched. The code first checks the ApplicationSettings dictionary for the “LocationConsent” key. If the key is found, it means the user has already opted in or out of location, so the method returns immediately. If the key is not found, then a MessageBox is shown asking for user consent. The result of the MessageBox operation is checked and a boolean value indicating the user consent status is stored in the “LocationConsent” key in ApplicationSettings. This key will be checked before the app attempts to access the user’s location.

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains("LocationConsent"))
        {
            // User has opted in or out of Location
            return;
        }
        else
        {
            MessageBoxResult result = 
                MessageBox.Show("This app accesses your phone's location. Is that ok?", 
                "Location",
                MessageBoxButton.OKCancel);
    
            if (result == MessageBoxResult.OK)
            {
                IsolatedStorageSettings.ApplicationSettings["LocationConsent"] = true;
            }else
            {
                IsolatedStorageSettings.ApplicationSettings["LocationConsent"] = false;
            }
    
            IsolatedStorageSettings.ApplicationSettings.Save();
        }
    }
    
  7. Paste the following handler into MainPage.xaml.cs for the button click event. This method first checks the status of the user consent in the ApplicationSettings dictionary. If the value is false, then the method exits immediately. Once user consent has been established, the method initializes the Geolocator object and sets the DesiredAccuracyInMeters property. Next, the GetGeopositionAsync method is called. This method attempts to obtain the phone’s current location. It does this asynchronously so that the UI thread is not blocked while the location is obtained. You can use the await operator to place code after the asynchronous call that will be executed after the call finishes. This requires this handler method to be declared async. Because calls made using await are guaranteed to return on the thread from which they were called, and this await call was made from the UI thread, the code is able to access and modify the UI directly when the call returns.

    The whole location operation is wrapped in a try block in case any exceptions are thrown. If an UnauthorizedAccessException exception is thrown while you are developing, it could mean that you haven’t included ID_CAP_LOCATION in your app manifest. If this happens after your app has been deployed, it may mean that the user has disabled location for this app in the phone Settings.

    private async void OneShotLocation_Click(object sender, RoutedEventArgs e)
    {
    
        if ((bool)IsolatedStorageSettings.ApplicationSettings["LocationConsent"] != true)
        {
            // The user has opted out of Location.
            return;
        }
    
        Geolocator geolocator = new Geolocator();
        geolocator.DesiredAccuracyInMeters = 50;
    
        try
        {
            Geoposition geoposition = await geolocator.GetGeopositionAsync(
                maximumAge: TimeSpan.FromMinutes(5),
                timeout: TimeSpan.FromSeconds(10)
                );
    
            LatitudeTextBlock.Text = geoposition.Coordinate.Latitude.ToString("0.00");
            LongitudeTextBlock.Text = geoposition.Coordinate.Longitude.ToString("0.00");
        }
        catch (Exception ex)
        {
            if ((uint)ex.HResult == 0x80004004)
            {
                // the application does not have the right capability or the location master switch is off
                StatusTextBlock.Text = "location  is disabled in phone settings.";
            }
            //else
            {
                // something else happened acquring the location
            }
        }
    }
    

Getting the phone’s current location using native code

  1. This walkthrough uses a IAsyncOperation to represent the asynchronous operation of getting the phone’s location. It is important that this object not fall out of scope while the location is being obtained, so it’s a good idea to declare a class member variable for it in the header.

        Windows::Foundation::IAsyncOperation<Windows::Devices::Geolocation::Geoposition^>^ m_getOperation;
    
  2. For this example, we also declare the method, GetOneShotLocation, in which the Location APIs will be used. The method takes 3 integers as arguments which represent the desired accuracy of the result in meters, the maximum number of seconds that the system should wait to get a location result before timing out, and the maximum age of the location result, in seconds.

        void GetOneShotLocation(int accuracyInMeters, int timeoutSeconds, int maxAgeSeconds);
    
  3. In the .cpp implementation file, a using statement is used to reference the Windows.Devices.Geolocation namespace.

    using namespace Windows::Devices::Geolocation;
    
  4. This step shows the definition of the example GetOneShotLocation method. First a Geolocator object is instantiated. The desired accuracy of the result is then set using the DesiredAccuracyInMeters()()() property. If a timeout or maximum age value are provided, GetGeopositionAsync()()() is called using those values, otherwise the version with that takes no parameters is called. This method returns an IAsyncOperation object that is stored in our class variable.

    Next, the Completed()()() event handler is defined. As soon as this event handler is hooked up, the system begins to asynchronously acquire the phone’s location. In this example, an inline anonymous delegate is used instead of a separate event handler. When the async operation completes, the inline code will run. When the delegate runs, it first checks the AsyncStatus parameter. If there is no error, GetResults()()() is called, which returns a Geoposition object that can be used to get the latitude, longitude, and accuracy of the location result, among other data. If an error occurred, check to see if the error code value is E_ABORT. If so, it means the user has disabled the location service for this app in the phone’s settings. If this is the case, you may choose to alert the user and then provide fallback app behavior that does not require location.

    void WPNativeLocationExample::GetOneShotLocation(int accuracyInMeters, int timeoutSeconds, int maxAgeSeconds)
    {
    
        Geolocator^ geolocator = ref new Geolocator();
    
        geolocator->DesiredAccuracyInMeters = (Platform::IBox<UINT>^)(PropertyValue::CreateUInt32(accuracyInMeters));
    
        m_getOperation = nullptr;
    
        if(timeoutSeconds > 0 || maxAgeSeconds > 0)
        {
            TimeSpan maxAge;
            maxAge.Duration = maxAgeSeconds * 10000;
    
            TimeSpan timeout;
            timeout.Duration = timeoutSeconds * 10000;
            m_getOperation = geolocator->GetGeopositionAsync(maxAge, timeout);
        }
        else
        {
             // Use the API with defaults
            m_getOperation = geolocator->GetGeopositionAsync();    
        }
    
        // Start location acquisition.
        // Setting the completion callback implicitly starts acquisition.
        m_getOperation->Completed = ref new AsyncOperationCompletedHandler<Geoposition^>(
            [=] (IAsyncOperation<Geoposition^>^ asyncOperation, AsyncStatus status) mutable
            {
                if(status != AsyncStatus::Error)
                {
                   Geoposition^ geoposition = asyncOperation->GetResults();
    
                   // use the location information
                   double latitude = geoposition->Coordinate->Latitude;
                   double longitude = geoposition->Coordinate->Longitude;
                   double accuracy = geoposition->Coordinate->Accuracy;
                   MyUseLocationFunction(latitude, longitude, accuracy);
                }
                else
                {
                    if(asyncOperation->ErrorCode.Value == E_ABORT)
                    {
                        // The user has disable location in the phone settings
                    }
                    else
                    {
                        // There was another error
                    }
                }
            });
    }