Сегодня огромное количество приложений пытается получить информацию о местоположении устройства пользователя.
Но и вам как разработчику эта информация также может понадобиться. Например, вы разрабатываете приложение новой социальной сети. В специальном разделе пользователи будут просматривать популярные публикации. А хитрый алгоритм настолько хитрый, что подсовывает свои рекомендации, основываясь на местоположении устройства пользователя.
Получить данные о местоположении устройства особого труда не составит, и после некоторой обработки они будут использоваться хитрым алгоритмом.
Но параноик внимательный читатель спросит: "Погодите-ка... А что если пользователь будет отдавать приложению фиктивные данные о своём местоположении?"
И будет прав! Если пользователи включат фиктивное местоположение, описанный функционал вашего приложения должным образом работать не будет. Хитрый алгоритм будет думать, что он всех перехитрил, но по факту пользователи из Индии увидят бесполезный для них контент, к примеру, на китайском языке от пользователей "из Китая".
Итог: киллер-фича вашего приложения не работает.
Может, есть выход?
Да, выход есть. Конкретно в нашем случае нет необходимости знать точное местоположение пользователя. Достаточно знать район/город, где он находится.
Чтобы узнать примерное местоположение пользователя, нужно узнать местоположение базовой станции оператора сотовой связи, к которой подключен пользователь. А для этого нужно получить кое-какие данные с SIM-карты на устройстве пользователя.
Кстати, известное приложение TikTok так и делает: оно получает данные с SIM-карты и определяет местоположение пользователя, предотвращая подделку местоположения.
Как мы к этому пришли?
Мы разрабатывали продукт, который сильно зависел от местоположения пользователя, и подумали: "Что делать, если определение местоположения будет недоступно из-за сбоя на устройстве, плохой погоды или если пользователь предоставит фиктивное местоположение?"
Мы тщательно изучили эти сценарии со всеми аспектами и решили использовать данные SIM-карты для получения информации о базовой станции и её координатах. Это позволило нам определить местоположение пользователя с помощью триангуляции. Качество данных, которое мы получили нас устроило.
В этой статье я опишу способ получения информации о местоположении базовой станции, к которой подключен пользователь. Для этого нам понадобится смартфон с SIM-картой.
Примечание: не имеет значения, включен GPS или выключен. В описанном процессе он не используется.
Начнём, пожалуй
Прежде всего, нам нужно API для доступа к информации о геолокации. Мне известно два:
Google Geolocation API — удобный API, но требуется подключенная платёжная учётная запись для вашего проекта;
OpenCellID от Unwiredlabs — простой в использовании API, крупнейшая в мире открытая база данных вышек сотовой связи.
Перейдите по ссылке выше, зарегистрируйтесь и получите API-ключ. И почитайте документацию, там всё подробно описано.
Как же оно всё работает?
Ваше приложение должно сделать запрос к API, отправив такие данные:
{
"token": "Your_API_Token",
"radio": "gsm",
"mcc": 310,
"mnc": 404,
"cells": [{
"lac": 7033,
"cid": 17811
}],
"address": 1
}
Описание полей для ясности:
token
— ваш API-ключ;radio
— тип сети, например GSM, LTE и пр.;mcc
— Mobile Country Code, уникальный идентификатор сотового оператора;mnc
— Mobile Network Code, код мобильной сети. В комбинации с MCC является уникальным идентификатором сотового оператора;lac
— Location Area Code;cid
— Cell ID.
Ответ вы получите в таком формате:
{
"status": "ok",
"balance": 100,
"lat": 39.573726,
"lon": -105.005387,
"accuracy": 730,
"address": "1289-1425 West Mineral Avenue, Littleton, CO 80120, USA"
}
То, что нужно. Приступим к реализации.
Реализация
Запустите Android Studio. Создайте новый проект или клонируйте/импортируйте этот.
Создаём модель запроса
Она будет использоваться для запроса к API:
Создаём модель ответа
Она будет использоваться при получении ответа от API:
Создаём сервис
Он используется для взаимодействия с API:
В приложении мы использовали Retrofit. Полную реализацию здесь я приводить не буду, но исходный код доступен. Мы реализовали ViewModel и Activity, которые будут взаимодействовать с API.
Важно! Для доступа к сетевой информации на устройстве всё же необходимо запросить соответствующее разрешение:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Получаем сведения о сети
Мы создали метод getCurrentCellInfo()
, который будет извлекать данные:
Для получения сведений о сети нам нужно проверить, является ли тип сети GSM, CDMA или LTE. Для этого создаём метод getCellInfo()
для каждого типа сети.
Ниже код для сети типа GSM:
Этот же метод необходимо реализовать для каждого типа сети.
На этом реализация киллер-фичи приложения закончена. Как видите, мы не использовали ни GPS, ни службу определения местоположения. Полученные данные мы отправляем к API, а в ответ сразу получаем информацию о местоположении устройства.
GIF, 650 КБ
Приложение работает, как ожидалось. На этом всё.
Комментарии (26)
yaguarundi
30.08.2021 09:48+2Как видите, мы не использовали ни GPS, ни службу определения местоположения. Полученные данные мы отправляем к API, а в ответ сразу получаем информацию о местоположении устройства.
А Google Geolocation API - это не служба определения местоположения?
И, насколько я знаю, у этого API есть ограничение на скорость запросов. Если вы хотите часто к нему обращаться, то платите денежки.
xslibris
30.08.2021 09:49+1Это позволило нам определить местоположение пользователя с помощью триангуляции.
Не критики ради, а информации для - в тексте, кроме этого предложения, нет больше ни одного упоминания и тем более использования заявленного метода.
Простое использование информации о базовой станции, на которой зарегистрирован телефон.
steff Автор
30.08.2021 12:08Согласен. В оригинальной статье конкретная реализация алгоритма не раскрыта.
Но, уверен, многие пользователи просто не рассчитывают, что приложение регулярно может получать информацию о местоположении телефона (с той или иной точностью), несмотря на отключенный GPS.lair
30.08.2021 12:31+2В оригинальной статье конкретная реализация алгоритма не раскрыта.
А там нет никакого алгоритма, достойного раскрытия. Они взяли у телефона доступную через официальное апи информацию о том, к какой БС тот подключен, а потом засунули эту информацию в публично доступный сервис. Все.
dobergroup
30.08.2021 19:55+1Но, уверен, многие пользователи просто не рассчитывают, что приложение регулярно может получать информацию о местоположении телефона (с той или иной точностью), несмотря на отключенный GPS.
Но ведь пользователи сами выдают разрешение ACCESS_COARSE_LOCATION.
Без этого пермишена приложение просто молча падает.
nixtonixto
30.08.2021 11:41+1На этом реализация киллер-фичи приложения закончена
А как простой пользователь может заблокировать эту киллер-фичу? Чтобы приложение условного калькулятора не отслеживало координаты…Airrr
30.08.2021 12:01+1Ваше приложение должно сделать запрос к API
То есть с моей мобилы идёт запрос на Unwiredlabs...?
Получается просто заблокировать *.unwiredlabs.com?
steff Автор
30.08.2021 12:02Не давать этому условному калькулятору разрешение на определение местоположения… Правда, будет ли он после этого выполнять свою основную функцию — вопрос :)
lair
30.08.2021 12:03+3А как простой пользователь может заблокировать эту киллер-фичу?
Не давать разрешение
android.permission.ACCESS_FINE_LOCATION
. И доступ к симке тоже не давать. Зачем это все калькулятору?
syrslava
30.08.2021 11:57+3Мы подумали: «Что делать,… если пользователь предоставит фиктивное местоположение?»
Даже не знаю, может, отвалить от пользователя?
OnelaW
30.08.2021 14:26+1Не знаю кто там какое приложение делает, но мне тут стало любопытно, зачем приложениям такие как управление наушников или часов с браслетами и всяких калькуляторов получать разрешение на получение информации о контактах пользователя, доступ к пользовательскому контенту и местоположении. И почему запрет этих разрешений, влечет за собой неработоспособность приложения. Дома валяются четыре комплекта ушей и браслет, приложениям для которых нужно предоставлять практически неограниченный доступ к данным на телефоне.
Однажды я подобный вопрос на хабре уже задавал, но особо не получил внятного ответа зачем это. Кто то ещё не знает что на телефонах бывает контент 34? Китайским, корейским, израильским и прочим товарищмайорамполковникам злой пейсбук с гуглом и яндексом не продают данные о пользователях?yaguarundi
31.08.2021 14:07+1Кажется это особенность реализации Bluetooth в андроиде, вообще или ранних версий - он просто не работает без доступа к данным геолокации.
sirocco
30.08.2021 14:32+1Тфу... Думал таки найду действительно карту вышек/антенн сотовой связи. А тут тоже фуфло.
Есть в деревне за 700км от МКАД три вышки, вроде как сотовой связи. Реально их видел, давно стоят. Сам я не там. И вот надо подобрать антенки, чтоб модем хорошо настроить на определённого провайдера. Но где он, на какой из вышек? Та, что за 7км, та, что за 4км, или та, что за 2км, но скрывается за тополями на горизонте?
Ни на одной карте этих вышек не нашёл. Придется два выезда делать, сначала приехать замеры устроить, потом оборудование закупать-везти.
Nosgoth
30.08.2021 17:10+2Сразу вспомнил про программу для дроида "Cell info" и то, что она делает привязки станций к карте. Небольшой поиск привел меня на https://location.services.mozilla.com
Уже там можно забрать файлик со списком станций, координатами и т.п.
Посмотрите, возможно это то, что Вам нужно.
FirsofMaxim
06.09.2021 07:43+1Разбейте задачу на подэтапы:
определение высоты антенны (сопоставить рельеф вышек и места антенны)
-
юстировка положения антенны (делается на месте) + CellInfo аппа для Android.
Сам год назад решал аналогичную проблему.
CAJAX
30.08.2021 19:28+2Ваше приложение для Китая? В принципе вы описали Fused Location Provider в Play Services, только менее точный.
yaguarundi
По-моему, вы узнаёте не местоположение устройства, а местоположение базовой станции, на которой оно обслуживается.
nixtonixto
Во многих случаях достаточно километровой погрешности, иногда вообще достаточно узнать, из какого города пользователь.
mrBarabas
Даже просто страна (или ее регион) вполне достаточны для большинства задач не связанных напрямую с геолокацией (то есть маршрутами, отслеживанием и подобным)