Xamarin Android 使用 MvvmCross 获取位置
Xamarin Android get location with MvvmCross
我想在我的 Xamarin Android 应用程序中实施定位服务。这是代码:
public class LocationService : ILocationService
{
private readonly object _lock = new object();
private static readonly TimeSpan _timeOut = TimeSpan.FromSeconds(20);
private TaskCompletionSource<MvxCoordinates> _taskSource;
private readonly IMvxLocationWatcher _locationWatcher;
private readonly IMvxMainThreadDispatcher _dispatcher;
public Task<MvxCoordinates> GetCurrentLocation()
{
Task<MvxCoordinates> task;
bool startWatcher = false;
lock (_lock)
{
if (_taskSource == null)
{
_taskSource = new TaskCompletionSource<MvxCoordinates>();
startWatcher = true;
}
task = _taskSource.Task;
}
if (startWatcher)
{
StartWatcher();
}
return task;
}
public MvxCoordinates GetLastSeenLocation()
{
var location = _locationWatcher.LastSeenLocation;
if (location == null)
{
return new MvxCoordinates();
}
return new MvxCoordinates()
{
Latitude = location.Coordinates.Latitude,
Longitude = location.Coordinates.Longitude
};
}
public LocationService(IMvxLocationWatcher locationWatcher, IMvxMainThreadDispatcher dispatcher)
{
this._locationWatcher = locationWatcher;
this._dispatcher = dispatcher;
this._locationWatcher.OnPermissionChanged += PermissionChanged;
}
private void StartWatcher()
{
Console.WriteLine("StartWatcher");
_dispatcher.RequestMainThreadAction(() =>
{
if (_locationWatcher.Started)
{
Console.WriteLine("Watcher already started!");
return;
}
_locationWatcher.Start(new MvxLocationOptions() { Accuracy = MvxLocationAccuracy.Coarse },
location =>
{
_locationWatcher.Stop();
OnSuccess(new MvxCoordinates()
{
Latitude = location.Coordinates.Latitude,
Longitude = location.Coordinates.Longitude
});
},
error =>
{
_locationWatcher.Stop();
Console.WriteLine(error.Code);
OnError(new Exception(error.Code.ToString()));
});
Task.Delay(_timeOut).ContinueWith(_ => OnTimeout());
});
}
private void OnTimeout()
{
Console.WriteLine("Timeout");
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetException(new Exception(MvxLocationErrorCode.Timeout.ToString()));
if (_locationWatcher.Started)
{
_locationWatcher.Stop();
}
}
private void OnSuccess(MvxCoordinates coordinates)
{
Console.WriteLine("Updated: {0}, {1}", coordinates.Longitude.ToString(), coordinates.Latitude.ToString());
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetResult(coordinates);
}
private void OnError(Exception error)
{
Console.WriteLine("Error: {0}", error.Message);
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetException(error);
}
private void PermissionChanged(object sender, MvxValueEventArgs<MvxLocationPermission> e)
{
Console.WriteLine("Permission changed: " + e.Value.ToString());
if (e.Value != MvxLocationPermission.Denied)
{
return;
}
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetException(new Exception(MvxLocationErrorCode.PermissionDenied.ToString()));
}
}
但我有这个输出:
[0:] mvx:Warning: 41.12 Location Service Provider unavailable - returned null
03-05 12:52:08.449 I/mvx ( 4065): 41.12 Location Service Provider unavailable - returned null
ServiceUnavailable
03-05 12:52:08.457 I/mono-stdout( 4065): ServiceUnavailable
我在模拟器和真实设备上都有这个。怎么了?
我找到了解决方案。
Android Manifest
中没有检查 ACCESS_FINE_LOCATION
我想在我的 Xamarin Android 应用程序中实施定位服务。这是代码:
public class LocationService : ILocationService
{
private readonly object _lock = new object();
private static readonly TimeSpan _timeOut = TimeSpan.FromSeconds(20);
private TaskCompletionSource<MvxCoordinates> _taskSource;
private readonly IMvxLocationWatcher _locationWatcher;
private readonly IMvxMainThreadDispatcher _dispatcher;
public Task<MvxCoordinates> GetCurrentLocation()
{
Task<MvxCoordinates> task;
bool startWatcher = false;
lock (_lock)
{
if (_taskSource == null)
{
_taskSource = new TaskCompletionSource<MvxCoordinates>();
startWatcher = true;
}
task = _taskSource.Task;
}
if (startWatcher)
{
StartWatcher();
}
return task;
}
public MvxCoordinates GetLastSeenLocation()
{
var location = _locationWatcher.LastSeenLocation;
if (location == null)
{
return new MvxCoordinates();
}
return new MvxCoordinates()
{
Latitude = location.Coordinates.Latitude,
Longitude = location.Coordinates.Longitude
};
}
public LocationService(IMvxLocationWatcher locationWatcher, IMvxMainThreadDispatcher dispatcher)
{
this._locationWatcher = locationWatcher;
this._dispatcher = dispatcher;
this._locationWatcher.OnPermissionChanged += PermissionChanged;
}
private void StartWatcher()
{
Console.WriteLine("StartWatcher");
_dispatcher.RequestMainThreadAction(() =>
{
if (_locationWatcher.Started)
{
Console.WriteLine("Watcher already started!");
return;
}
_locationWatcher.Start(new MvxLocationOptions() { Accuracy = MvxLocationAccuracy.Coarse },
location =>
{
_locationWatcher.Stop();
OnSuccess(new MvxCoordinates()
{
Latitude = location.Coordinates.Latitude,
Longitude = location.Coordinates.Longitude
});
},
error =>
{
_locationWatcher.Stop();
Console.WriteLine(error.Code);
OnError(new Exception(error.Code.ToString()));
});
Task.Delay(_timeOut).ContinueWith(_ => OnTimeout());
});
}
private void OnTimeout()
{
Console.WriteLine("Timeout");
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetException(new Exception(MvxLocationErrorCode.Timeout.ToString()));
if (_locationWatcher.Started)
{
_locationWatcher.Stop();
}
}
private void OnSuccess(MvxCoordinates coordinates)
{
Console.WriteLine("Updated: {0}, {1}", coordinates.Longitude.ToString(), coordinates.Latitude.ToString());
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetResult(coordinates);
}
private void OnError(Exception error)
{
Console.WriteLine("Error: {0}", error.Message);
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetException(error);
}
private void PermissionChanged(object sender, MvxValueEventArgs<MvxLocationPermission> e)
{
Console.WriteLine("Permission changed: " + e.Value.ToString());
if (e.Value != MvxLocationPermission.Denied)
{
return;
}
TaskCompletionSource<MvxCoordinates> source;
lock (_lock)
{
source = _taskSource;
_taskSource = null;
}
source?.SetException(new Exception(MvxLocationErrorCode.PermissionDenied.ToString()));
}
}
但我有这个输出:
[0:] mvx:Warning: 41.12 Location Service Provider unavailable - returned null 03-05 12:52:08.449 I/mvx ( 4065): 41.12 Location Service Provider unavailable - returned null ServiceUnavailable 03-05 12:52:08.457 I/mono-stdout( 4065): ServiceUnavailable
我在模拟器和真实设备上都有这个。怎么了?
我找到了解决方案。
Android Manifest
中没有检查 ACCESS_FINE_LOCATION