- How to get and use location data in your Android app
- Preparation
- Layout
- MainActivity
- Getting location updates
- LocationListener
- Android Developer Newsletter
- Conclusion
- Android Location API to track your current location
- Android Tutorial
- Android Location API
- LocationListener
- Android Location API Project Structure
- Android Location APICode
- Глубокое погружение в определение местоположения
- Покажи мне код!
- Что оно делает на самом деле?
- Теперь у вас есть код, давайте подробнее рассмотрим его
- Свежесть — значит никогда не ждать
- Используйте Intent’ы для получения обновлений местоположения
- Получение данных во время автономной работы
- Оптимизация времени работы аккумулятора: умные сервисы и использование состояния устройства для переключения ресиверов
- Мониторинг состояния аккумулятора для уменьшения функциональности и экономии энергии
How to get and use location data in your Android app
Using Location in your app has incredible potential in making your app seem intelligent to end users. With location data, your app can predict a user’s potential actions, recommend actions, or perform actions in the background without user interaction.
For this article, we shall discuss integrating location updates into an Android app, with a focus on fetching the latitude and longitude of a given Location only. It is worth pointing out that Location can (and does) contain much more than just latitude and longitude values. It can also have values for the bearing, altitude and velocity of the device.
Preparation
Before your app can receive any location data, you must request location permissions. There are two location permissions, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION. We use ACCESS_FINE_LOCATION to indicate that we want to receive as precise a location as possible. To request this permission, add the following to your app manifest:
We also need to select which of the location providers we want to use to get the location data. There are currently three providers:
- GPS_PROVIDER: The most accurate method, which uses the built-in GPS receiver of the device. GPS is a system of satellites in orbit, that provides location information from almost anywhere on earth. It can sometimes take a while to get a GPS location fix (generally faster when the device is outdoors).
- NETWORK_PROVIDER: This method determines a device’s location using data collected from the surrounding cell towers and WiFi access points. While it is not as accurate as the GPS method, it provides a quite adequate representation of the device’s location.
- PASSIVE_PROVIDER: This provider is special, in that it indicates that your app doesn’t want to actually initiate a location fix, but uses the location updates received by other applications/services. In other words, the passive provider will use location data provided by either the GPS or NETWORK providers. You can find out what provider your passive provider actually used with the returned Location’s getProvider() method. This provides the greatest battery savings.
Layout
For our app, we are going to fetch location data using the GPS provider, the NETWORK provider, and also by asking the device to decide which is the best available provider that meets a given set of criteria. Our layout has three identical segments, each of which contains:
- A title for the section, such as GPS LOCATION
- A Button to resume and pause location updates for the section/provider
- Longitude Value
- Latitude Value
The code snippet for the GPS section, from our layout/activity_main.xml file is shown below
MainActivity
It is possible that the user has their device Location settings turned off. Before requesting location information, we should check that Location services are enabled. Polling for location data with the settings turned off will return null. To check if Location is enabled, we implement a method, called isLocationEnabled(), shown below:
We simply ask the LocationManager if either the GPS_PROVIDER or the NETWORK_PROVIDER is available. In the case where the user has Location turned off, we want to help them get to the Location screen as easily and quickly as possible to turn it on and get back into our app. To do this, we implement the showAlert() method.
The most interesting line in the snippet above is within the setPositiveButton() method. We start an activity using the Settings.ACTION_LOCATION_SOURCE_SETTINGS intent, so that when the user clicks on the button, they are taken to the Location Settings screen.
Getting location updates
To get GPS and Network location updates, we use one of the LocationManager’s requestLocationUpdates() methods. Our preferred is requestLocationUpdates(String provider, int updateTime, int updateDistance, LocationListener listener). updateTime refers to the frequency with which we require updates, while updateDistance refers to the distance covered before we require an update. Note that updateTime simply specifies the minimum time period before we require a new update. This means that the actual time between two updates can be more than updateTime, but won’t be less.
A very important point to consider is that Location polling uses more battery power. If your app doesn’t require location updates when in the background, consider stopping updates using one of the removeUpdates() methods. In the code snippet below, we stop/start location updates in response to clicking on the relevant Button.
For both NETWORK_PROVIDER and PASSIVE_PROVIDER, simply replace GPS_PROVIDER above with your desired provider.
In the case where you just want to pick the best available provider, there is a LocationManager method, getBestProvider() that allows you do exactly that. You specify some Criteria to be used in selecting which provider is best, and the LocationManager provides you with whichever it determines is the best fit. Here is a sample code, and it’s what we use to select a provider:
Using the above code and Criteria, the best provider will be GPS_PROVIDER, where both GPS and NETWORK are available. However if the GPS is turned off, the NETWORK_PROVIDER will be chosen and returned as the best provider.
LocationListener
The LocationListener is an interface for receiving Location updates from the LocationManager. It has four methods
- onLocationChanged() – called whenever there is an update from the LocationManager.
- onStatusChanged() – called when the provider status changes, for example it becomes available after a period of inactivity
- onProviderDisabled() – called when the user disables the provider. You might want to alert the user in this case that your app functionality will be reduced
- onProviderEnabled() – called when the user enables the provider
We implement only the onLocationChanged() method for this sample, but in a production app, you will most likely want to perform an appropriate action for each situation.
Android Developer Newsletter
Conclusion
The complete source code is available on github, for use (or misuse) as you see fit. Just be mindful of the following:
- Integrating location tracking in your apps drains the battery.
- Google recommends apps request updates every 5 minutes (5 * 60 * 1000 milliseconds). You might need faster updates if your app is in the foreground (fitness/distance tracker).
- Users can have location turned off. You should have a plan for when location settings is turned off.
Have fun building Android apps, and watch out for our upcoming tutorial where we make use of Android device location data and web APIs to build something even more fun and challenging.
Источник
Android Location API to track your current location
Android Tutorial
Android Location API can be used to track your mobile current location and show in the app. In this tutorial, we’ll develop an application that fetches the user’s current location programmatically.
Android Location API
There are two ways to get a users location in our application:
- android.location.LocationListener : This is a part of the Android API.
- com.google.android.gms.location.LocationListener : This is present in the Google Play Services API. (We’ll look into this in the next tutorial)
Android Location Services is available since Android API 1.
Google officially recommends using Google Play Location Service APIs. Android Location Services API is still used to develop location-based apps for devices that don’t support Google Play Services.
LocationListener
The LocationListener interface, which is part of the Android Locations API is used for receiving notifications from the LocationManager when the location has changed. The LocationManager class provides access to the systems location services.
The LocationListener class needs to implement the following methods.
- onLocationChanged(Location location) : Called when the location has changed.
- onProviderDisabled(String provider) : Called when the provider is disabled by the user.
- onProviderEnabled(String provider) : Called when the provider is enabled by the user.
- onStatusChanged(String provider, int status, Bundle extras) : Called when the provider status changes.
The android.location has two means of acquiring location data:
- LocationManager.GPS_PROVIDER: Determines location using satellites. Depending on the conditions, this provider may take a while to return a location fix
- LocationManager.NETWORK_PROVIDER: Determines location based on the availability of nearby cell towers and WiFi access points. This is faster than GPS_PROVIDER
In this tutorial, we’ll create a Service that implements the LocationListener class to receive periodic location updates via GPS Providers or Network Providers.
Android Location API Project Structure
The project consists of a MainActivity.java class which displays a Get Location and a LocationTrack.java Service class.
Android Location APICode
The activity_main.xml layout is defined below.
The MainActivity.java class is defined below.
In the above code, we’re implementing runtime permissions that are used in Android 6.0+ devices.
We’ve added the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in the AndroidManifest.xml file.
Clicking the button invokes the LocationTrack.java service class. If the location returned is NULL in the case of GPS Provider, we call the showSettingsAlert() method from the LocationTrack.java class that we’ll be seeing shortly. When the activity is destroyed stopLocationTrack() method is called to turn off the location updates.
The LocationTrack.java class is defined below.
Few inferences drawn from the above code are:
- In the above code isProviderEnabled(String provider) is called upon the locationManager object and is used to check whether GPS/Network Provider is enabled or not.
- If the Providers aren’t enabled we’re calling the method showSettingsAlert() that shows a prompt to enable GPS.
- requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) method of the LocationManager class is used to register the current activity to be notified periodically by the named provider.
- onLocationChanged is invoked periodically based upon the minTime and minDistance, whichever comes first.
- Location class hosts the latitude and longitude.
To get the current location the following code snippet is used.
On the above Location object, getters are called to store the double values of latitude and longitude. These double values are then disabled as a Toast message on the screen.
The output of the above application in action on an emulator is:
Our emulators can’t fetch locations, hence it’s returning 0.0 for lat/lng. You can connect your smartphone and run the application in debug mode to check your current location.
To emulate GPS Locations in an emulator we can pass fixed Latitude and Longitude values from Android Studio. Besides the emulator window, you can see a list of options. The one at the bottom (which has three dots) is our Extended Controls options. Open that and send a dummy location. Your application should look like this:
This brings an end to this tutorial. We’ll be implementing Location API using Google Play Services in a later tutorial. You can download the Android GPSLocationTracking Project from the link below.
Источник
Глубокое погружение в определение местоположения
Этот пост является переводом топика из блога android-developers. Далее повествование ведется от Рето Майера, автора книги Professional Android 2 Application Development. Он пишет о том, как можно улучшить приложения, использующие местоположение, в смысле кэширования результатов, скорости работы и так далее.
Без разницы, ищете ли вы место, где бы поесть, или ближайшее место велосипедов Boris Bike, всегда есть задержка при получении данных местоположения от GPS и заполнении абстрактного списка результатов в вакууме. Когда вы находитесь в месте, где хотели бы получить контекстную информацию, то часто вы сталкиваетесь с отсутствием подключения к данным.
Вместо того, чтобы грозить кулаком в небо, я написал open-source приложение, которое включает в себя советы и рекомендации по сокращению времени между открытием приложения и просмотром актуальной информации о близлежащих местах, вкупе с разумным обеспечением offline режима работы. И всё это, сохраняя использование аккумулятора на возможном минимуме.
Покажи мне код!
Вы можете проверить мой проект Android Protips for Location. Не забудьте прочесть Readme.txt, чтобы успешно скомпилировать и запустить приложение.
Что оно делает на самом деле?
Оно использует Google Places API для реализации базовой функциональности приложений, которые которые используют местоположение для определения списка близлежащих достопримечательностей (точек на карте), позволяют просмотреть их детали, а также проверить или оценить.
Код реализует многие из лучших практик, о которых я подробно рассказал на своей сессии на Google I/O 2011, Android Protips: Advanced Topics for Expert Android Developers (видео). В том числе использование Intent’ов для получения обновлений о местоположении, используя Passive Location Provider, наблюдение за состоянием устройства для изменения частоты обновлений, переключение Receiver’ов во время исполнения приложения, и также используя Cursor Loader.
Приложение написано для Honeycomb, но также может работать и на версия 1.6 и выше.
Теперь у вас есть код, давайте подробнее рассмотрим его
Мой главный приоритет — свежесть: минимизация задержек между открытием приложения и возможностью проверить нужные места, и в то же время минимизировать использование аккумулятора.
Требования:
- Текущее местоположение должно находиться так быстро, как это возможно
- Список мест должен обновляться при изменение местоположения
- Список близлежащих мест должен быть доступен (в деталях) в автономном режиме
- Отметки также должны быть доступны в автономном режиме
- Данные о местоположении и другие данные пользователя должны быть правильно обработаны (см. более ранний пост с лучшими практиками )
Свежесть — значит никогда не ждать
Можно значительно сократить время ожидания получения первого приближения к местоположению, путём выбора последнего известного из Location Manager’a каждый раз, когда приложение переходит в активный режим.
В этом примере из GingerbreadLastLocationFinder, мы перебираем все провайдеры местоположения на устройстве, даже те, которые на данный момент недоступны, чтобы найти наиболее точное последнее местоположение.
Если есть координаты одного или более местоположений, то выбирается самое точное. Иначе, просто возвращается самый недавний результат.
Во втором случае (когда определено, что последнее обновление местоположения недостаточно недавнее), значение так или иначе возвращается, но мы запрашиваем одно обновление местоположения, используя самый быстрый провайдер.
К сожалению, мы не можем определить наибыстрейших провайдеров, но, на практике, понятно, что определение местоположения при помощи сети возвращает результаты быстрее.
Отметим также, что этот фрагмент кода показывает GingerbreadLastLocationFinder, который использует метод requestSingleUpdate для получения единоразового обновления местоположения. Эта функциональность не была доступна до Gingerbread — проверьте LegacyLastLocationFinder, посмотрите как я реализовал такую же функциональность для более ранних версий Android.
singleUpdateReceiver передает полученное обновление назад к вызывающему классу через слушателя Location Listener.
Используйте Intent’ы для получения обновлений местоположения
Получив наиболее точную/своевременную оценку текущей позиции, мы также хотим получать её обновления.
Класс PlacesConstants включает в себя набор значений, которые определяют частоту обновления местоположения. Настройте их, чтобы убедиться, что обновления приходят так часто, как это требуется.
Следующий шаг — запросить обновление местоположения от Location Manager. В следующем фрагменте кода, взятом из GingerbreadLocationUpdateRequester мы можем передать критерии, используемые для определения — какой Location Manager будет запрашивать обновления напрямую в вызове метода requestLocationUpdates.
Обратите внимание, что мы передаём Pending Intent, а не Location Listener.
Вообще, я предпочитаю использовать Location Listener’ов, потому что они предоставляют гибкость в регистрации приёмников в нескольких Activity или Сервисах, или напрямую в манифесте.
В этом приложении, новое местоположение означает обновленный список близлежащих мест. Это происходит через сервисы, которые отправляют запросы к серверу и обновляют Контент-провайдер, который заполняет список мест.
Так как изменение местоположения напрямую не обновляет UI, то имеет смысл создавать и регистрировать связанный LocationChangedReceiver в манифесте, а не в Activity.
LocationChangedReceiver извлекает местоположение из каждого обновления и запускает сервис PlaceUpdateService, чтобы обновить базу близлежащих мест.
Получение данных во время автономной работы
Чтобы добавить поддержку режима offline, мы начнём с кэширования результатов поиска по PlacesContentProvider и PlaceDetailsContentProvider.
Также, при определенный обстоятельствах нужно проводить выборку сведений о местоположении. Этот фрагмент кода из сервиса PlacesUpdateService демонстрирует, как предварительная выборка включается для ограниченного количества мест.
Обратите внимание на то, что предварительная выборка данных потенциально выключается при низком заряде аккумулятора.
Похожая техника используется для реализации offline отметок.
Оптимизация времени работы аккумулятора: умные сервисы и использование состояния устройства для переключения ресиверов
Нет смысла запускать сервис обновления, когда устройство находится в автономном режиме. Сервис PlaceUpdateService проверяет возможность соединения, прежде чем пытаться получить обновление.
Если соединения нет, то ActiveLocationChangedReceiver и PassiveLocationChangedReceiver выключаются, а ConnectivityChangedReceiver включается.
ConnectivityChangedReceiver прослушивает все изменения сетевого соединения. Когда производится новое подключение, то он просто выключает себя и включает слушателей местоположения.
Мониторинг состояния аккумулятора для уменьшения функциональности и экономии энергии
Когда телефон на последних 15%, то большинство приложений не работает, для того чтобы сохранить заряд. Мы можем зарегистрировать ресиверов в манифесте, чтобы выдавать предупреждение, когда устройство входит или выходит из состояния низкой батареи.
Этот фрагмент из PowerStateChangedReceiver выключает PassiveLocationChangedReceiver всякий раз, когда устройство переходит в состояние низкого аккумулятора и включает его, когда заряд в порядке.
Можно расширить эту логику, отключив все упреждающие выборки или уменьшив частоту обновления в условиях низкого заряда аккумулятора.
Источник