2

I want to get my gps coordinates on a Xamarin CrossPlatform app, but I have a problem.

I have this code:

public MapPage()
    {
        SearchPosition();
        map = new Map
        {
            IsShowingUser = true,
            HeightRequest = 100,
            WidthRequest = 960,
            VerticalOptions = LayoutOptions.FillAndExpand
        };

        map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromMiles(0.3)));
        ...
        ...
    }

    private async void SearchPosition()
    {
       position = await getPosition();
    }

    async Task<Plugin.Geolocator.Abstractions.Position> getPosition()
    {
        var locator = CrossGeolocator.Current;
        locator.DesiredAccuracy = 50;

        Plugin.Geolocator.Abstractions.Position position = await locator.GetPositionAsync(TimeSpan.FromSeconds(5));

        return position;
    }

All I want is to wait for the gps coordinates, but it continues and goes to "MoveToRegien" before I have the gps coordinates. I don't understand why, can anyone help me? Thanks!

Imrik
  • 676
  • 2
  • 11
  • 32
  • 4
    An async void is like a fire and forget. Like this you are not waiting for the SearchPosition method to finish. – bkardol Jan 05 '18 at 10:20
  • And how I can wait for it? – Imrik Jan 05 '18 at 10:21
  • Possible duplicate of [Call asynchronous method in constructor?](https://stackoverflow.com/questions/23048285/call-asynchronous-method-in-constructor) – mnemonic Jan 05 '18 at 10:32
  • @mnemonic i see the post and it don't solve the problem. Any ideas? – Imrik Jan 05 '18 at 10:37
  • @Imrik if you want/need some examples of usages of async/await, you can also have a look at this answer of mine : https://stackoverflow.com/a/48127799/2814072 – AdricoM Jan 11 '18 at 15:39

2 Answers2

3

Is there any special reason for returning a void instead of a Task within your SearchPosition method?

This might be your problem, so change it to:

async Task SearchPosition()

I would change it actually to return a position:

async Task<Plugin.Geolocator.Abstractions.Position> SearchPosition() => await GetPosition();

Another problem is, do you actually need to wrap GetPosition() method by SearchPosition() method that just does nothing except calling the first method? Seems like a mess.

Your code is very hard to look at, you are not following naming conventions and half of your code looks like Java and the other like C#. Please, when you write code, respect the language and yourself, get familiar with the naming conventions and follow them.

EDIT:
I think I see your real problem now. You are trying to get a position inside your constructor, therefor you are not awaiting asynchronous SearchPosition() method.

I would suggest to move your GPS related logic to OnAppearing method if your MainPage actually derives from a ContentPage for example. Here is an example:

public class MainPage : ContentPage
{
    ...
    public MainPage()
    {
        map = new Map
        {
            IsShowingUser = true,
            HeightRequest = 100,
            WidthRequest = 960,
            VerticalOptions = LayoutOptions.FillAndExpand
        };
    }

    protected async override void OnAppearing()
    {
        position = await GetPosition();

        map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromMiles(0.3)));
    }

    async Task<Plugin.Geolocator.Abstractions.Position> GetPosition()
    {
        var locator = CrossGeolocator.Current;
        locator.DesiredAccuracy = 50;

        Plugin.Geolocator.Abstractions.Position position = await locator.GetPositionAsync(TimeSpan.FromSeconds(5));

        return position;
    }
}
EvZ
  • 10,710
  • 4
  • 35
  • 69
  • Thanks for the advice. It doesn't work, it still has null values at position variable. – Imrik Jan 05 '18 at 10:58
  • Updated my answer. – EvZ Jan 05 '18 at 11:05
  • I updated the code and I put breakpoints at OnAppearing method and it doesn't stop at any codeline. It still has null values at position variables. Any more ideas? Thanks a lot! :) – Imrik Jan 05 '18 at 11:09
  • Oh, I fix it, my fault. But know I have this exception: Unhandled Exception: Java.Lang.ClassNotFoundException: Didn't find class "md57251f317a80041e1a60080af127573bd.GeolocationSingleListener" on path: DexPathList[[zip file "/data/app/com.companyname.PruebaMapas-1/base.apk"],nativeLibraryDirectories=[/data/app/com.companyname.PruebaMapas-1/lib/x86, /system/fake-libs, /data/app/com.companyname.PruebaMapas-1/base.apk!/lib/x86, /system/lib, /vendor/lib]] I search on google but it doesn't find anything. Any ideas? – Imrik Jan 05 '18 at 11:12
  • Thats a different issue, and should be asked separately if you cannot find the answer in existing threads on stackoverflow or in WEB in general. – EvZ Jan 05 '18 at 11:15
2

You misunderstood the meaning of "await" (which seems to be the case for a lot of developers). Using "await" causes the compiler to return to the caller of that async method (in your case MapPage()) and sign up the rest of work do be done in that method (what you are waiting for) as a so-called "continuation". As soon as that completes the async method resumes execution where it left off. So, what you're complaining about is ultimately exactly what the system is meant to do. :-)

If you definitely don't want the system to go on you could make SearchPosition() return a Task and then call .Wait() on it (see msdn page).

You also might want to simply get rid of async pattern and call SearchPosition() synchronously if I understand you correctly ("All I want is to wait for the gps coordinates, but it continues...").

Grimm
  • 544
  • 5
  • 15