Подробное Изучение Определения Местоположения

Этот пост является переводом темы блога Android-разработчики .

Следующее рассказывает Рето Майер, автор книги.

Профессиональная разработка приложений для Android 2 .

Он пишет о том, как можно улучшить геолокационные приложения с точки зрения результатов кэширования, скорости и так далее.

Неважно, ищете ли вы место, где можно поесть, или ближайшее место для велосипедов.

Борис Байк , всегда существует задержка при получении данных о местоположении от GPS и заполнении абстрактного списка результатов в вакууме.

Когда вы находитесь в месте, где вам хотелось бы получить контекстную информацию, вы часто сталкиваетесь с отсутствием возможности подключения к данным.

Вместо того, чтобы грозить кулаком небу, я написал приложение с открытым исходным кодом, включающее в себя советы и рекомендации по сокращению времени между открытием приложения и просмотром актуальной информации о близлежащих местах вкупе с разумным обеспечением автономной работы.

И все это при минимально возможном расходе заряда батареи.



Покажи мне код!

Вы можете проверить мой проект Android-советы по определению местоположения .

Не забудьте прочитать Readme.txt для успешной компиляции и запуска приложения.



Что это на самом деле делает?

Оно использует API Google Адресов для реализации базовых функций приложений, которые используют местоположение для определения списка близлежащих точек интереса (точек на карте), позволяют просматривать их детали, а также проверять или оценивать их.

В коде реализованы многие из лучших практик, которые я подробно описал на своей сессии на Google I/O 2011. Советы по Android: дополнительные темы для опытных разработчиков Android ( видео ).

Это включает в себя использование намерений для получения обновлений местоположения с помощью пассивного поставщика местоположений, мониторинг состояния устройства для изменения частоты обновлений, переключение приемников во время выполнения приложения, а также использование загрузчика курсоров.

Приложение написано для Honeycomb, но может работать и на версии 1.6 и выше.



Теперь у вас есть код, давайте взглянем на него поближе.

Мой главный приоритет — свежесть: минимизировать задержку между открытием приложения и возможностью проверить нужные мне места, одновременно минимизируя расход заряда батареи.

Требования: Текущее местоположение должно быть обнаружено как можно быстрее.

Список мест должен обновляться при изменении местоположения.

Список близлежащих мест должен быть доступен (подробно) офлайн.

Регистрация также должна быть доступна оффлайн.

Данные о местоположении и другие пользовательские данные должны обрабатываться корректно (см.

подробнее ранний пост с лучшими практиками )

Свежесть означает отсутствие ожидания

Вы можете значительно сократить время ожидания получения первого приближения к местоположению, выбирая последнее известное из Менеджера местоположений каждый раз, когда приложение переходит в активный режим.

В этом примере из ПряникLastLocationFinder , мы перебираем всех поставщиков местоположения на устройстве, даже тех, которые в данный момент недоступны, чтобы найти наиболее точное последнее местоположение.

  
  
  
  
  
  
  
  
  
  
  
  
   

List<String> matchingProviders = locationManager.getAllProviders(); for (String provider: matchingProviders) { Location location = locationManager.getLastKnownLocation(provider); if (location != null) { float accuracy = location.getAccuracy(); long time = location.getTime(); if ((time > minTime && accuracy < bestAccuracy)) { bestResult = location; bestAccuracy = accuracy; bestTime = time; } else if (time < minTime && bestAccuracy == Float.MAX_VALUE && time > bestTime){ bestResult = location; bestTime = time; } } }

Если есть координаты одной или нескольких локаций, выбирается наиболее точная.

В противном случае просто возвращается самый последний результат. Во втором случае (когда определено, что последнее обновление местоположения произошло недостаточно недавно) значение все равно возвращается, но мы запрашиваем одно обновление местоположения, используя самого быстрого провайдера.



if (locationListener != null && (bestTime < maxTime || bestAccuracy > maxDistance)) { IntentFilter locIntentFilter = new IntentFilter(SINGLE_LOCATION_UPDATE_ACTION); context.registerReceiver(singleUpdateReceiver, locIntentFilter); locationManager.requestSingleUpdate(criteria, singleUpatePI); }

К сожалению, мы не можем определить самых быстрых провайдеров, но на практике видно, что определение местоположения с помощью сети дает результаты быстрее.

Обратите также внимание, что этот фрагмент кода показывает ПряникLastLocationFinder который использует метод запроссинглобновление чтобы получить единовременное обновление местоположения.

Эта функция не была доступна до Gingerbread — проверьте LegacyLastLocationFinder , посмотрите, как я реализовал ту же функциональность для более ранних версий Android. одиночныйUpdateReceiver передает полученное обновление обратно вызывающему классу через прослушиватель Прослушиватель местоположения .



protected BroadcastReceiver singleUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { context.unregisterReceiver(singleUpdateReceiver); String key = LocationManager.KEY_LOCATION_CHANGED; Location location = (Location)intent.getExtras().

get(key); if (locationListener != null && location != null) locationListener.onLocationChanged(location); locationManager.removeUpdates(singleUpatePI); } };



Используйте намерения для получения обновлений местоположения

Как только мы получим наиболее точную/своевременную оценку текущей позиции, мы также хотим получать ее обновления.

Сорт МестаКонстанты включает набор значений, определяющих частоту обновления местоположения.

Настройте их так, чтобы обновления приходили так часто, как это необходимо.



// The default search radius when searching for places nearby. public static int DEFAULT_RADIUS = 150; // The maximum distance the user should travel between location updates. public static int MAX_DISTANCE = DEFAULT_RADIUS/2; // The maximum time that should pass before the user gets a location update. public static long MAX_TIME = AlarmManager.INTERVAL_FIFTEEN_MINUTES;

Следующим шагом будет запрос обновления местоположения у Менеджера местоположений.

В следующем фрагменте кода, взятом из ПряникLocationUpdateRequester мы можем передать критерии, используемые для определения того, какой менеджер местоположений будет запрашивать обновления, непосредственно при вызове метода.

запрослокацииобновления .



public void requestLocationUpdates(long minTime, long minDistance, Criteria criteria, PendingIntent pendingIntent) { locationManager.requestLocationUpdates(minTime, minDistance, criteria, pendingIntent); }

Обратите внимание, что мы передаем ожидающее намерение, а не прослушиватель местоположения.



Intent activeIntent = new Intent(this, LocationChangedReceiver.class); locationListenerPendingIntent = PendingIntent.getBroadcast(this, 0, activeIntent, PendingIntent.FLAG_UPDATE_CURRENT);

В общем, я предпочитаю использовать прослушиватели местоположения, поскольку они обеспечивают гибкость для регистрации прослушивателей в нескольких действиях или службах или непосредственно в манифесте.

В этом приложении новое местоположение означает обновленный список мест поблизости.

Это происходит через службы, которые отправляют запросы на сервер и обновляют контент-провайдера, который заполняет список локаций.

Поскольку изменение местоположения не приводит к непосредственному обновлению пользовательского интерфейса, имеет смысл создать и зарегистрировать связанный МестоположениеИзмененоПолучатель в манифесте, а не в действии.



<receiver android:name=".

receivers.LocationChangedReceiver"/>

МестоположениеИзмененоПолучатель извлекает местоположение из каждого обновления и запускает службу PlaceUpdateService чтобы обновить базу данных близлежащих мест.

if (intent.hasExtra(locationKey)) { Location location = (Location)intent.getExtras().

get(locationKey); Log.d(TAG, "Actively Updating place list"); Intent updateServiceIntent = new Intent(context, PlacesConstants.SUPPORTS_ECLAIR ? EclairPlacesUpdateService.class : PlacesUpdateService.class); updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_LOCATION, location); updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_RADIUS, PlacesConstants.DEFAULT_RADIUS); updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_FORCEREFRESH, true); context.startService(updateServiceIntent); }



Получайте данные в автономном режиме

Чтобы добавить поддержку автономного режима, мы начнем с кэширования результатов поиска с помощью МестаContentProvider И PlaceDetailsContentProvider .

Кроме того, при определенных обстоятельствах необходимо получить информацию о местоположении.

Этот фрагмент кода взят из сервиса PlacesUpdateService демонстрирует, как включена предварительная выборка для ограниченного числа местоположений.

Обратите внимание, что предварительная выборка данных может быть отключена при низком заряде батареи.



if ((prefetchCount < PlacesConstants.PREFETCH_LIMIT) && (!PlacesConstants.PREFETCH_ON_WIFI_ONLY || !mobileData) && (!PlacesConstants.DISABLE_PREFETCH_ON_LOW_BATTERY || !lowBattery)) { prefetchCount++; // Start the PlaceDetailsUpdateService to prefetch the details for this place. }

Аналогичный метод используется для реализации автономной маркировки.



Оптимизация срока службы батареи: интеллектуальные сервисы и использование состояния устройства для переключения приемников

Нет смысла запускать службу обновлений, когда устройство находится в автономном режиме.

Услуга PlaceUpdateService проверяет подключение перед попыткой получения обновления.



NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

Если соединения нет, ActiveLocationChangedReceiver и PassiveLocationChangedReceiver отключаются, и СвязьChangedReceiver включается.



ComponentName connectivityReceiver = new ComponentName(this, ConnectivityChangedReceiver.class); ComponentName locationReceiver = new ComponentName(this, LocationChangedReceiver.class); ComponentName passiveLocationReceiver = new ComponentName(this, PassiveLocationChangedReceiver.class); pm.setComponentEnabledSetting(connectivityReceiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); pm.setComponentEnabledSetting(locationReceiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); pm.setComponentEnabledSetting(passiveLocationReceiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

СвязьChangedReceiver прослушивает все изменения сетевого подключения.

Когда устанавливается новое соединение, оно просто отключается и включает прослушиватели местоположения.



Мониторинг состояния аккумулятора для снижения функциональности и экономии энергии

Когда на телефоне последние 15%, большинство приложений не работают в целях экономии заряда.

Мы можем зарегистрировать получатели в манифесте, чтобы выдавать оповещения, когда устройство входит в состояние низкого заряда батареи или выходит из него.



<receiver android:name=".

receivers.PowerStateChangedReceiver"> <intent-filter> <action android:name="android.intent.action.ACTION_BATTERY_LOW"/> <action android:name="android.intent.action.ACTION_BATTERY_OKAY"/> </intent-filter> </receiver>

Этот фрагмент из PowerStateChangedReceiver выключает ПассивныйLocationChangedReceiver всякий раз, когда устройство переходит в состояние низкого заряда батареи и включает его, когда заряд в порядке.



boolean batteryLow = intent.getAction().

equals(Intent.ACTION_BATTERY_LOW); pm.setComponentEnabledSetting(passiveLocationReceiver, batteryLow ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);

Вы можете расширить эту логику, отключив все предварительные выборки или уменьшив частоту обновления в условиях низкого заряда батареи.



Что дальше?

Этот пост уже длинный, поэтому я остановлюсь здесь.

Продолжить чтение в моем блоге Радиоактивный Як Теги: #Android #Android #location #API Google Places #geo-приложения #Разработка для Android

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.