При запуске приложения Android, важной частью которого является определение местоположения устройства, можно столкнуться с некоторыми трудностями. Классический способ получения местоположения подразумевает использование основных API-интерфейсов Android.
Однако, эти интерфейсы появились сравнительно давно, поэтому с ними подчас бывает непросто разобраться. Чтобы упростить этот процесс, мы разработали плагин Geolocator, который позволяет получать местоположения при совместном использовании кода на iOS, Android и Windows из одного API-интерфейса. Однако, бывает время, когда требуется полный контроль над API-интерфейсом, и тогда новые API от сервисов Google Play, предназначенные для определения местоположения, приходятся как нельзя кстати. Эти API-интерфейсы упрощают определение местоположения пользователя при помощи различных датчиков на устройстве. Это означает, что при использовании этих новых API запрос на обновление местоположения выполняется быстрее и точнее, а с последним обновлением (11.0.4) это стало делаться и того проще.
Начало работы
Теперь следует убедиться в том, что наш проект ориентирован на Android 7.0 и установить последние версии библиотек поддержки Android.
Интерфейсы API, которые мы будем использовать, являются частью новой версии пакета NuGet — Google Play services Location 11.0.4 NuGet, который в настоящее время находится на стадии предварительного релиза. Просто удостоверьтесь в том, что у Вас включен показ предварительных версий NuGet, затем найдите пакет Xamarin.GooglePlayServices.Location и установите его в приложение Android:
Кроме того, нам следует убедиться и в том, что у нас есть права на получение данных местоположения в AndroidManifest.
Получение данных местоположения
Разработчикам ранее требовалось создать клиент Google API, указать, какие API они хотели бы использовать, подключиться к службе, и только затем осуществлять вызовы API, которые им были нужны. Это все изменилось в 11 версии Location APIs, которые могут запросить текущий FusedLocationProviderClient и затем начать выполнять вызовы. Для запуска этого клиента требуются два параметра:
- LocationRequest: Установки для обновления местоположения
- LocationCallback: Класс, который будет получать обратный вызов при обновлении местоположения
Создание обратного вызова местоположения
Внутри нашей MainActivity мы можем создать реализацию LocationCallback и событие, на которое можно подписаться, когда появится результат определения местоположения:
1 2 3 4 5 6 7 8 9 | class MyLocationCallback : LocationCallback { public EventHandler<Location> LocationUpdated; public override void OnLocationResult(LocationResult result) { base.OnLocationResult(result); LocationUpdated?.Invoke(this, result.LastLocation); } } |
Мы также можем создать обработчик событий внутри MainActivity, и когда нам потребуется получить события, мы сможем, соответственно, подписаться на него, равно как и отписаться:
1 2 3 4 5 | void OnLocationResult(object sender, Location location) { //location.Latitude; //location.Longitude; } |
Запрос местоположения
Теперь когда наш обратный вызов местоположения на месте, настало время получить текущий FusedLocationClient и создать запрос:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | MyLocationCallback locationCallback; FusedLocationProviderClient client; async Task StartLocationUpdatesAsync() { // Create a callback that will get the location updates if(locationCallback == null) { locationCallback = new MyLocationCallback(); locationCallback.LocationUpdated += OnLocationResult; } // Get the current client if(client== null) client = LocationServices.GetFusedLocationProviderClient(this); try { //Create request and set intervals: //Interval: Desired interval for active location updates, it is inexact and you may not receive upates at all if no location servers are available //Fastest: Interval is exact and app will never receive updates faster than this value var locationRequest = new LocationRequest() .SetInterval(10000) .SetFastestInterval(5000) .SetPriority(LocationRequest.PriorityHighAccuracy); await client.RequestLocationUpdatesAsync(locationRequest, locationCallback); } catch(Exception ex) { //Handle exception here if failed to register } } |
Ну вот! С помощью этих нескольких строк кода обновления местоположения будут производиться непрерывно, пока пользователь будет держать приложение открытым.
Подробнее
Не стоит также забывать о некоторых других немаловажных вопросах, возникающих при использовании служб местоположения, таких как обработка ситуаций при отключении пользователем определения местоположения, при входе в фоновое состояние и, конечно, при отключении обновлений местоположения, когда это не требуется. Вы можете найти полный сэмпл, посвященный всем этим факторам, включая обработку прав на моем GitHub.
Источник: Официальный блог Xamarin
Спасибо за перевод поста!
Хотелось бы добавить, что данный способ является оптимальным и самым простым.
Существует так же возможность взаимодействия с location api, используя GoogleApiClient, но данный способ я бы не рекомендовал, так как Linker при сборке Release делает его не работоспособным, а устранение неполадки занимает время.