Reputation: 4582
I'm new to Xamarin
and tried some beginner tutorials so far.
Now I wanted to build some custom stuff and need to request the current location.
For this I installed Xamarin.GooglePlayServices.Location
in order to have access to the FusedLocationProviderClient
class.
In MainActivity
I retrieve the FusedLocationProviderClient
:
public class MainActivity : FormsAppCompatActivity, ILocationProvider
{
private FusedLocationProviderClient FusedLocationClient { get; set; }
protected override void OnCreate(Bundle savedInstanceState)
{
// snip
FusedLocationClient = LocationServices.GetFusedLocationProviderClient(this);
}
}
The ILocationProvider
needs the method TaskCompletionSource<Model.Location> GetPosition()
to be implemented:
public TaskCompletionSource<Model.Location> GetPosition()
{
// snip
if (CheckSelfPermission(Manifest.Permission_group.Location) == Permission.Granted)
{
FusedLocationClient.LastLocation.AddOnCompleteListener(new OnLocationRequestCompleteListener(this, tcs));
}
// snip
}
The UI has a button to request the current location.
Whenever the user clicks the button I get the ILocationProvider
via DependencyService
and execute the GetPosition
method:
private void GetPositionClicked(object sender, EventArgs e)
{
var provider = DependencyService.Get<ILocationProvider>();
if(provider != null)
{
var tcs = provider.GetPosition();
// snip
}
}
The problem now is that the application crashes as soon as I try to execute the CheckSelfPermission
method in GetPosition()
.
I set a breakpoint in GetPosition()
and noticed that FusedLocationClient
is null
although it clearly wasn't null
after OnCreate
was called.
I then inspected this
in OnCreate
and GetPosition
and noticed that they weren't the same instances which leads me to the conclusion that something is clearly wrong here.
To solve this for now I did the following:
public class MainActivity : FormsAppCompatActivity, ILocationProvider
{
internal static MainActivity Instance { get; private set; }
private FusedLocationProviderClient FusedLocationClient { get; set; }
protected override void OnCreate(Bundle savedInstanceState)
{
// snip
Instance = this
// snip
}
// snip
public TaskCompletionSource<Model.Location> GetPosition()
{
if (this != Instance)
{
return Instance.GetPosition();
}
// snip
}
}
At least this works for now but I can't imagine that this is the way to go.
What I learned so far is that DependencyService
seems to not get already created instances but create one instead (at least once).
What would be the correct way to call methods in MainActivity
from the shared .NET Standard
library?
Upvotes: 1
Views: 178
Reputation: 74144
Move those methods out of your Activity class into a standalone class (within your Xamarin.Android application (or a Xamarin.Android library project).
public interface ILocationProvider
{
Task<Tuple<double, double>> GetPosition();
}
public class Location_Android: Java.Lang.Object, ILocationProvider
{
private FusedLocationProviderClient FusedLocationClient { get; set; }
public Location_Android()
{
FusedLocationClient = new FusedLocationProviderClient(Application.Context);
}
public async Task<Tuple<double, double>> GetPosition()
{
var loc = await FusedLocationClient?.GetLastLocationAsync();
return new Tuple<double, double>(loc.Latitude, loc.Longitude);
}
}
Upvotes: 1