Я пытаюсь получить местоположение (lat/lon), используя Fused Location Api в andriod. Мой код отлично работает, когда включены WiFi и gps. Если я отключу gps, то я не получаю никакого обновления местоположения.
Я использую BALANCED_POWER_ACCURACY для запроса местоположения. Я добавил Access_FINE_Location разрешения в манифесте и с помощью игровых сервисов версии 9.2.1 в файле build.gradle.
Я тестирую на реальных устройствах (Samsung SM0G360H API 19 и Samsung SM-G361 API 21). Оба дают одинаковые результаты.
Может ли кто-нибудь сказать мне, как работает Fused Location Api?
Как я могу получить обновления местоположения, когда gps отключен, но сетевое подключение включено?
Мой код:
спросил(а) 2016-09-18T09:07:00+03:00 6 лет, 3 месяца назад
добавить комментарий
пожаловаться
Извините за довольно долгую задержку в попытке ответить на ваш вопрос. Я сам борюсь со всей проблемой местоположения, поэтому я дам вам то, что я заметил и узнал после «много трудностей». Надеюсь, вам по-прежнему нужен ответ.
Android Get Current Location Continuously | Location Service | Fused Location Provider API
Я не помню, как выглядят настройки уровня API 19, но в целом все настройки местоположения от API lvl 15 и выше (плюс минус некоторые опции здесь и там) были настроены на соответствие логике FusedLocationProviderAPI. Что я имею в виду под этим; Вы должны иметь место установки на все время, чтобы получить какие — либо обновления местоположения, как установка/переключатель контролирует общее расположение.
Надеюсь, это ответит на ваш главный вопрос. Предоставить дополнительную информацию. Поскольку masp упоминает в одном из комментариев, вы можете контролировать то, что поставщик фактически использует через разрешения и константы API Fused Location. Для разрешений вам необходимо выбрать ACCESS_COARSE_LOCATION или ACCESS_FINE_LOCATION. Разница заключается в том (я цитирую):
Если вы используете как NETWORK_PROVIDER, так и GPS_PROVIDER, вам необходимо запросить только разрешение ACCESS_FINE_LOCATION, поскольку оно включает разрешение для обоих поставщиков. Разрешение для ACCESS_COARSE_LOCATION позволяет получить доступ только к NETWORK_PROVIDER.
И тогда у нас есть константы FusedLocationProviderAPI, где ситуация становится немного сложнее. Также из API lvl 21 и выше мы имеем следующее: Если вы входите в режим, вы получаете:
Я больше не буду вдаваться в константы.
Они были опробованы в принятом ответе на этот вопрос. Я предлагаю вам иметь гусака. Я должен упомянуть, однако, что независимо от того, что вы делаете с ними, режим в настройках имеет приоритет. Вы можете запросить GPS в приложении, но если пользователь говорит, что сохранение батареи в настройках, то это все.
Последнее, о чем я, вероятно, должен упомянуть, заключается в том, что если вы установите разрешение ACCESS_COARSE_LOCATION, тогда ожидаете ужасающей точности (это также показано в тесте, который я связал выше). Мое предложение — использовать ACCESS_FINE_LOCATION, а затем поиграть с константами Fused Location и интервалами (setInterval и setFastestInterval) Надеюсь, это поможет немного, даже если довольно поздно.
Приложение GPS трекер / Часть 1/ Android Studio курс
ответил(а) 2017-02-15T14:30:00+03:00 5 лет, 10 месяцев назад
добавить комментарий
пожаловаться
Еще в рубрике
Синяя точка и круг не отображаются на MyLocation с использованием сплайсированного аффилированного местоположения api
Android Fused location api’s, обеспечивает неправильное обновление местоположения, когда я дома, и защелкаю к моей сети WiFi
Выключить значок местоположения без вызова removeLocationUpdates
Android FusedLocation getTime() возвращает разные времена
Другие вопросы
У слушателя местоположения есть проблемы для работы на некоторых устройствах и проблемы для перехода на FusedLocationListener
Можно получить свежие данные (точное текущее местоположение) с помощью Android FusedLocationApi?
Google API LocationResult возвращается со старыми повторяющимися значениями
- Вопросы
- Android-fusedlocation
- Как получить местоположение с помощью Fused Location Provider в android с помощью сети?
Источник: progi.pro
Следим за своей девушкой с помощью Android
Сегодня мы проведем небольшое шпионское исследование и попробуем незаметно собрать данные о передвижении интересующего нас объекта — подруги, ребенка или, скажем, бабушки. Разумеется, с их письменно заверенного разрешения на сбор и обработку личной информации — как же иначе?
WARNING
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
Шпион, выйди вон
Общеизвестно, что любой современный смартфон (или планшет) оснащен модулем системы глобального позиционирования GPS, а то и православным ГЛОНАСС. Но даже если ты умудришься найти аппарат без него, карты Google (и не только) все равно смогут быстро обнаружить тебя на этом многострадальном голубом шарике. Для этого используется методика определения координат с помощью вышек сотовой связи, информацию о положении которых собирают абсолютно все игроки рынка геолокационных сервисов.
Ok, Google, вырубаем GPS и вынимаем симку, запускаем «Карты» и. внезапно снова видим свое положение. Оказывается, информации об окружающих точках Wi-Fi вполне достаточно для определения местоположения смартфона, пускай и не такого точного. В этой связи примечателен давний скандал с «картомобилем» Google, который тихо-мирно себе ездил и снимал улицы, попутно собирая названия всех точек доступа Wi-Fi. Тогда Google заявляла о некоем техническом сбое (!), но мы-то знаем.
Одним словом, смартфон почти всегда сможет определить свою ориентацию в родной Солнечной системе, чем мы и воспользуемся.
Операция «Спектр»
Театр начинается с вешалки, а приложение Android — с манифеста. Для доступа к GPS-приемнику необходимо добавить тег в секцию uses-permission:
Константа ACCESS_FINE_LOCATION задает высокий уровень точности для определения местоположения пользователя. Есть еще ACCESS_COARSE_LOCATION для более грубой геолокации, но нам она принципиально не интересна. К слову, приложение, которому было выдано полномочие fine, автоматически получает еще и полномочие coarse.
В Android для работы с геолокацией используется специальный интерфейс, предоставляемый системным объектом LocationManager:
String svcName = Context.LOCATION_SERVICE; LocationManager locationManager = (LocationManager) getSystemService(svcName);
Вторая геосоставляющая — LocationProvider, набор источников данных, каждый из которых отражает отдельную технологию поиска местоположения. Так, GPS_PROVIDER основывается на данных, полученных со спутников, NETWORK_PROVIDER шпионит за вышками сотовой связи и Wi-Fi.
Наверное, в твоей голове уже созрел коварный план — периодически запрашивать координаты у GPS_PROVIDER и NETWORK_PROVIDER (например, с помощью фонового сервиса) и отправлять их в командный центр. Такое решение в лоб, конечно, имеет право на жизнь, но разве популярнейший журнал о безопасности стал бы о нем писать? Во-первых, это заметно — любое включение GPS отображается в статусной строке значком (рис. 1); во-вторых, это банально сажает батарею, что может заставить владельца задуматься и поискать прожорливое приложение; и, в-третьих, фоновый трафик прекрасно виден в системном журнале.
Другие статьи в выпуске:
Xakep #203. Лесорубы Windows
- Содержание выпуска
- Подписка на «Хакер» -60%
Специально для нас Google придумала отдельный провайдер — PASSIVE_PROVIDER, который получает информацию о местоположении только в том случае, если ее запрашивает другое приложение. Благодаря этому наш шпион будет получать обновления скрытым образом, без активации какого-либо источника LocationProvider. Иными словами, стоит пользователю запустить карту, клиент социальной сети, выйти в интернет, отправить сообщение и далее по списку, как наше приложение уже будет в курсе (рис. 2–3). Обратной стороной пассивности (и скрытности) является полное доверие к получаемым данным, мы никак не сможем проверить их достоверность.
Координаты «Скайфолл»
Для получения координат от источника данных существует метод getLastKnownLocation:
String provider = LocationManager.PASSIVE_PROVIDER; Location location = locationManager.getLastKnownLocation(provider);
Возвращаемый объект Location содержит всю информацию о местонахождении, которую поддерживает источник. Он может включать в себя время, точность полученных координат, широту, долготу, высоту над уровнем моря (вот оно, вмешательство в частную жизнь!) и скорость. Все эти свойства доступны через геттеры:
private void updateWithNewLocation(Location location) < TextView myText = (TextView) findViewById(R.id.myText); String latLongString = «нет информации»; if (location != null) < double lat = location.getLatitude(); double lng = location.getLongitude(); latLongString = «Lat: » + lat + «nLong: » + lng; >myText.setText(«Местоположение:n» + latLongString); >
Как уже отмечалось, ни PASSIVE_PROVIDER, ни getLastKnownLocation не запрашивают у LocationProvider обновление местоположения. Если смартфон долго не обновлял текущую позицию, полученное значение может быть неактуальным или вовсе не существовать (например, сразу после загрузки).
Если ты снова подумал об использовании фонового сервиса для «дергания» PASSIVE_PROVIDER, спешу тебя огорчить: все гораздо проще. Наш выбор — широковещательный приемник (если не знаешь, что это, срочно загляни в сентябрьский «Хакер» или читай дальше).
Шаровая молния
Данные GPS, возвращаемые методом getLastKnownLocation или широковещательным приемником, не изменятся, пока хотя бы одна программа не запросит обновление местоположения. В итоге при первом запуске эмулятора getLastKnownLocation, скорее всего, вернет null, а приемник и вовсе откажется срабатывать.
Чтобы это исправить, можно воспользоваться следующим трюком:
Поместив это код в OnCreate активности, мы заставим приложение непрерывно опрашивать координаты, что приведет к срабатыванию нашего же широковещательного приемника. Разумеется, после отладки этот код на стероидах нужно выжечь раскаленным железом. Не забудь!
На секретной службе Ее Величества
Вкратце напомню: в качестве механизма передачи сообщений на уровне системы намерения (Intent) способны отправлять структурированные данные от процесса к процессу (например, информацию от GPS-модуля). Для отслеживания таких данных и реакции на них реализуются специальные объекты — широковещательные приемники. Основное их достоинство (для нас) — они срабатывают даже тогда, когда приложение находится в фоне, а некоторые (например, прием СМС) вообще не требуют запуска родительского приложения.
Каркас нашего приемника представлен ниже:
Метод onReceive будет срабатывать всякий раз при изменении координат устройства, но сначала приведенный приемник необходимо зарегистрировать в манифесте:
Далее мы должны настроить частоту срабатывания приемника, иначе любое сколь угодно малое движение объекта наблюдения в пространстве попросту заDoSит наш жучок координатами. В тестовом примере поместим соответствующий код в метод onCreate главной (и единственной) активности:
Метод requestLocationUpdates, используемый для инициирования регулярных обновлений местоположения, принимает в качестве первого параметра название конкретного типа провайдера — PASSIVE_PROVIDER. Далее следует минимальный интервал и дистанция между обновлениями. В приведенном коде обновления координат будут поступать не чаще, чем раз в минуту (60 000 мс), и только в случае перемещения объекта на 25 м от последней точки. Почему эти числа нужно выбирать как можно аккуратнее, читай на врезке.
Умри, но не сейчас
Android 5 очень внимательно следит за всеми приложениями, запрашивающими координаты (даже в пассивном режиме), и выискивает наиболее прожорливые. Чтобы не попасть в топ, старайся устанавливать как можно большие значения для минимального временного интервала и дистанции между обновлениями.
Последний параметр — ожидающее (или отложенное) намерение, которое и будет передано в широковещательный приемник LocationUpdateReceiver. Объекты PendingIntent используются для упаковки намерений, срабатывающих в ответ на будущие события, как, например, в нашем варианте — получение координат.
К слову, чтобы прекратить выполнение обновлений, вызывается метод removeUpdates:
locationManager.removeUpdates(pendingIntent);
Так как наша активность не предполагает никакого взаимодействия с пользователем, не содержит интерфейса, да и вообще работает негласно, логично будет ее закрыть, вызвав метод finish. При этом приемник LocationUpdateReceiver продолжит свою работу как ни в чем не бывало. Кстати, к статье я прикладываю небольшой исходник (естественно, только в мирных отладочных целях), в котором координаты выводятся на экран (рис. 4) в виде всплывающих сообщений (класс Toast).
И целого мира мало
Итак, у нас есть множество координат объекта, то есть трекинг его передвижения. Возникает вопрос: что с этим массивом информации делать и как его хранить? В сентябрьском выпуске «Хакера» была отличная статья, касающаяся темы хранения пользовательской информации. Для нашей цели подойдет любой из описанных методов — Shared Preferences, Internal/External Storage, SQLite Database или даже Cache Files.
Я выбрал базу SQLite со следующей таблицей:
private static final String SQL_CREATE_TABLE = «CREATE TABLE coord » + «(_id INTEGER PRIMARY KEY AUTOINCREMENT, utime NUMERIC, lat REAL, lng REAL)»;
О том, как вносить записи в базу SQLite, «Хакер» рассказывает регулярно (да ладно, когда это мы регулярно об этом писали? — Прим. ред.), так что я не буду касаться этой скучной темы, а вот об отправке накопленных данных поговорим.
Конечно, полученные координаты можно вовсе не помещать в базу данных, а отправлять сразу же, по факту, но весьма высока вероятность, что доступа в интернет в отдельно взятый момент времени не окажется. Кроме того, как мы уже говорили, фоновая передача данных довольно заметна (предполагаем, что у объекта обычный нерутованный смартфон). Другое дело Wi-Fi — отличная скорость, малое время отклика, да и вряд ли кому-нибудь придет в голову изучать трафик (бесплатно же!).
Из России с любовью
Геокодирование в Android позволяет переводить координаты (широту и долготу) в уличный адрес и наоборот. Чтобы получить строку с адресом, можно воспользоваться функцией
public String revGeocode(Location location) < if (location == null) return «»; double lat = location.getLatitude(); double lng = location.getLongitude(); StringBuilder sb = new StringBuilder(); Geocoder gc = new Geocoder(this, Locale.getDefault()); try < Listaddresses = gc.getFromLocation(lat, lng, 1); if (addresses.size() > 0) < Address address = addresses.get(0); for (int i = 0; i < address.getMaxAddressLineIndex(); i++) sb.append(address.getAddressLine(i)).append(«n»); sb.append(address.getLocality()).append(«n»); sb.append(address.getPostalCode()).append(«n»); sb.append(address.getCountryName()); >> catch (IOException e) < e.printStackTrace(); >return sb.toString(); >
Метод getFromLocation вернет список адресов, которые так или иначе совпадают с переданными координатами. В рассмотренном примере берется только первый адрес, из которого извлекаются все дополнительные строки, после чего добавляется область, почтовый индекс и страна. Точность этой информации зависит от детализации карт региона в сервисе Google Maps.
Следующий вопрос — что отправлять? Извлекать каждую строчку из базы и посылать? Можно, но как-то некрасиво, не по-хакерски, что ли. А что, если послать сразу всю базу в виде двоичного файла? Физически база находится в приватной директории приложения и доступна только нам, содержимое таблиц — только числа (размер будет минимальным), Wi-Fi — высокоскоростное подключение.
В общем, сплошные плюсы.
Ну а чтобы довести идею до высот перфекционизма, перед отправкой поместим файл базы в архив, благо файлы SQLite очень хорошо сжимаются. Прямо из коробки Android в паре с Java поддерживает работу с архивами формата ZIP. Для архивирования произвольного файла соорудим функцию:
public static final int BUFFER_SIZE = 1024; public void zipFile(String file, String zipFile) throws IOException < BufferedInputStream origin; ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile))); try < byte data[] = new byte[BUFFER_SIZE]; FileInputStream fi = new FileInputStream(file); origin = new BufferedInputStream(fi, BUFFER_SIZE); try < ZipEntry entry = new ZipEntry(file.substring(file.lastIndexOf(«/») + 1)); out.putNextEntry(entry); int c; while ((c = origin.read(data, 0, BUFFER_SIZE)) != -1) out.write(data, 0, c); >finally < origin.close(); >> finally < out.close(); >>
Путь к базе данных можно получить следующим образом:
String file = Environment.getDataDirectory().getPath() + «//data//com.example.gpsspy//databases//» + «имя_базы»;
Здесь «com.example.gpsspy» — имя пакета нашего примера, а «имя_базы» задается при ее создании (без расширения). Таким образом, приведенную выше функцию можно использовать так:
String fileZip = file + «.zip»; try < zipFile(file, fileZip); >catch (IOException e)
Чтобы не было никаких подвисаний в программе, процедуру архивирования рекомендую вынести в фоновую задачу (AsyncTask).
Полученный архив можно смело отправлять по сети. Механизм доставки будет зависеть от выбранной технологии — это могут быть сокеты, локальная шара, web-интерфейс, анонимный FTP, Wi-Fi Direct и тому подобное.
При использовании сокетов подход может быть таким:
В любом случае потребуется разрешение работы в интернете:
После передачи файла базу необходимо очистить. Сделать это можно с помощью традиционной SQL-команды DELETE * FROM имя_таблицы, но размер файла в этом случае не уменьшится, либо можно стереть сам файл:
public static void deletePrivateFile(String Name)< File data = Environment.getDataDirectory(); String Path = «//data//com.example.gpsspy//databases//» + Name; File file = new File(data, Path); file.delete(); >
При следующем обращении к базе данных Android автоматически создаст новый файл.
Бриллианты навсегда
Для перевода старого доброго UNIX-time в формат, понятный нам и шпионам, можно использовать Java-объект «Календарь» (Calendar):
public String getDateFromUNIX(long uTime)
Лунный гонщик
Мы определились с тем, что и как будем посылать, осталось только решить когда. И здесь нам снова поможет механизм трансляции намерения с помощью широковещательного приемника, только системного.
Класс WiFiManager представляет собой сервис для работы с Wi-Fi в Андроиде. Он может применяться как для установки соединения с точкой доступа, так и для отслеживания состояния подключения. Так как мы используем пассивный алгоритм работы, то единственное, что нужно сделать, — дождаться активного подключения к точке Wi-Fi и попробовать отправить файл.
Официальный SDK от Google определяет несколько действий для срабатывания широковещательного приемника при изменении статуса Wi-Fi: WIFI_STATE_CHANGED_ACTION, SUPPLICANT_CONNECTION_CHANGE_ACTION и NETWORK_STATE_CHANGED. Описывать их смысла нет, так как они банально не работают. Нет, все компилируется и запускается, но приемник не срабатывает. Причина такого поведения мне неизвестна (может быть, Google постепенно превращается в Microsoft?).
В любом случае ситуация вовсе не безвыходная. Независимо от вида соединения (Wi-Fi, 3G, GPRS/EDGE) в Android предусмотрено действие CONNECTIVITY_CHANGE, которое срабатывает при включении и отключении передачи данных. Используя класс ConnectivityManager, предназначенный для управления сетевыми подключениями, мы можем определить тип подключения, что нам и нужно.
Итак, добавляем в манифест разрешения для доступа к состоянию сетевых интерфейсов:
Определяем широковещательный приемник:
Наконец, код самого приемника:
Здесь в цикле перебираются все активные подключения, и, если найдено активное Wi-Fi, базы координат начинают передаваться в командный центр. Отдельно отмечу, что при подключении к точке Wi-Fi данный приемник может сработать несколько раз, имей это в виду.
Завтра не умрет никогда
Сегодня мы познакомились с пассивным геопозиционированием в Android, научились архивировать и отправлять базу данных SQLite по сети, а также познакомились с разными видами широковещательных приемников. Одним словом, с основными инструментами тайного агента!
Только для твоих глаз
Чтобы не было совсем уж просто, я намеренно не стал выносить функциональность в фоновый сервис. В мартовском «Хакере» я уже рассказывал о том, как работает подобный сервис и механизм сигнализаций. Эти технологии вполне сгодятся для создания незаметного фонового сервиса. Там же ищи информацию о «выживаемости» после перезагрузки устройства.
Источник: xakep.ru
Фоновая служба с прослушивателем местоположения в android
Я создаю фоновую службу, которая будет работать в своем собственном процессе. Это должно позволить мне слушать, если местоположение устройства изменилось. Я должен быть в состоянии изменить критерии, как расстояние до уведомления пользовательского интерфейса.
Как я могу сделать то же самое? У меня есть немного знаний о службе и LocationListener реализаций. Любые учебники по сети будут оценены.
Я получил одну ссылку от переполнения стека, но я не очень его понимаю.
4 ответов:
сначала вам нужно создать Service . В этом Service создать класс, расширяющий LocationListener . Для этого, используйте следующий фрагмент кода Service :
>
добавить Service в любом месте вашего проекта, как вы хотите! 🙂
2018-10-05 13:39:49 Usman Kurd
Я знаю, что я публикую этот ответ немного поздно, но я чувствовал, что стоит использовать службу поставщика местоположения предохранителя Google, чтобы получить текущее местоположение.
основные характеристики этого api:
1.Простые API: позволяет выбрать уровень точности, а также энергопотребление.
2.Сразу же доступны: дает вашим приложениям немедленный доступ к лучшему, самому последнему местоположению.
3.Энергоэффективность: It выбирает наиболее эффективный способ получить местоположение с меньшими затратами энергии
4.Универсальность: удовлетворяет широкий спектр потребностей, от использования переднего плана, которые нуждаются в очень точном местоположении, до фоновых применений, которые нуждаются в периодических обновлениях местоположения с незначительным воздействием мощности.
Она является гибкой, в то время как обновление на месте также. Если вы хотите текущее местоположение только при запуске приложения, то вы можете использовать getLastLocation(GoogleApiClient) метод.
Если вы хотите обновить свой расположение непрерывно, то вы можете использовать requestLocationUpdates(GoogleApiClient,LocationRequest, LocationListener)
Вы можете найти очень хороший блог о расположении предохранителей здесь и google doc для расположения предохранителя также можно найти здесь.
обновление
согласно документам разработчика, начиная с Android O, они добавили новые ограничения на фоновое местоположение.
Если ваше приложение работает в фоновом режиме, система обслуживания, вычисляет новый расположение для вашего приложения только несколько раз в час. Этот это происходит даже тогда, когда ваше приложение запрашивает более частое местоположение новинки. Однако, если ваше приложение работает на переднем плане, нет никаких изменений в частота дискретизации местоположения по сравнению с Android 7.1.1 (уровень API 25).
2017-08-23 09:59:30 Kunu
фоновая служба определения местоположения, и я начну даже после того, как убью приложение.
MainActivity.java
BookingTrackingService.java
AlarmReceive.java (BroadcastReceiver)
AndroidManifest.xml
Источник: codengineering.net