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

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

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

Но параноик внимательный читатель спросит: "Погодите-ка... А что если пользователь будет отдавать приложению фиктивные данные о своём местоположении?"

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

Итог: киллер-фича вашего приложения не работает.

Может, есть выход?

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

Чтобы узнать примерное местоположение пользователя, нужно узнать местоположение базовой станции оператора сотовой связи, к которой подключен пользователь. А для этого нужно получить кое-какие данные с 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)


  1. yaguarundi
    30.08.2021 09:42

    По-моему, вы узнаёте не местоположение устройства, а местоположение базовой станции, на которой оно обслуживается.


    1. nixtonixto
      30.08.2021 11:50
      +1

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


      1. mrBarabas
        31.08.2021 04:26
        +1

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


  1. yaguarundi
    30.08.2021 09:48
    +2

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

    А Google Geolocation API - это не служба определения местоположения?

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


  1. xslibris
    30.08.2021 09:49
    +1

    Это позволило нам определить местоположение пользователя с помощью триангуляции.

    Не критики ради, а информации для - в тексте, кроме этого предложения, нет больше ни одного упоминания и тем более использования заявленного метода.

    Простое использование информации о базовой станции, на которой зарегистрирован телефон.


    1. steff Автор
      30.08.2021 12:08

      Согласен. В оригинальной статье конкретная реализация алгоритма не раскрыта.
      Но, уверен, многие пользователи просто не рассчитывают, что приложение регулярно может получать информацию о местоположении телефона (с той или иной точностью), несмотря на отключенный GPS.


      1. lair
        30.08.2021 12:31
        +2

        В оригинальной статье конкретная реализация алгоритма не раскрыта.

        А там нет никакого алгоритма, достойного раскрытия. Они взяли у телефона доступную через официальное апи информацию о том, к какой БС тот подключен, а потом засунули эту информацию в публично доступный сервис. Все.


        1. steff Автор
          30.08.2021 12:38

          Я имею в виду не тот код, что в статье (и на гитхабе), а тот, что в продукте, о котором упоминается в статье.


          1. lair
            30.08.2021 12:40
            +1

            Это продукт третьей стороны, естественно, автор статьи про него ничего не может написать. Но какова на этом фоне ценность самой статьи?


      1. dobergroup
        30.08.2021 19:55
        +1

        Но, уверен, многие пользователи просто не рассчитывают, что приложение регулярно может получать информацию о местоположении телефона (с той или иной точностью), несмотря на отключенный GPS.

        Но ведь пользователи сами выдают разрешение ACCESS_COARSE_LOCATION.

        Без этого пермишена приложение просто молча падает.


  1. lair
    30.08.2021 10:02
    +4

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

    А столько было обещаний...


    1. steff Автор
      30.08.2021 12:03

      Да, для разработчика это основной затык…


  1. nixtonixto
    30.08.2021 11:41
    +1

    На этом реализация киллер-фичи приложения закончена

    А как простой пользователь может заблокировать эту киллер-фичу? Чтобы приложение условного калькулятора не отслеживало координаты…


    1. Airrr
      30.08.2021 12:01
      +1

      Ваше приложение должно сделать запрос к API

      То есть с моей мобилы идёт запрос на Unwiredlabs...?
      Получается просто заблокировать *.unwiredlabs.com?


    1. steff Автор
      30.08.2021 12:02

      Не давать этому условному калькулятору разрешение на определение местоположения… Правда, будет ли он после этого выполнять свою основную функцию — вопрос :)


    1. lair
      30.08.2021 12:03
      +3

      А как простой пользователь может заблокировать эту киллер-фичу?

      Не давать разрешение android.permission.ACCESS_FINE_LOCATION. И доступ к симке тоже не давать. Зачем это все калькулятору?


      1. dobergroup
        30.08.2021 19:56
        +1

        В данном случае - ACCESS_COARSE_LOCATION


        1. lair
          30.08.2021 19:57
          +1

          Я сварщик ненастоящий, статью цитировал.


  1. syrslava
    30.08.2021 11:57
    +3

    Мы подумали: «Что делать,… если пользователь предоставит фиктивное местоположение?»

    Даже не знаю, может, отвалить от пользователя?


  1. OnelaW
    30.08.2021 14:26
    +1

    Не знаю кто там какое приложение делает, но мне тут стало любопытно, зачем приложениям такие как управление наушников или часов с браслетами и всяких калькуляторов получать разрешение на получение информации о контактах пользователя, доступ к пользовательскому контенту и местоположении. И почему запрет этих разрешений, влечет за собой неработоспособность приложения. Дома валяются четыре комплекта ушей и браслет, приложениям для которых нужно предоставлять практически неограниченный доступ к данным на телефоне.
    Однажды я подобный вопрос на хабре уже задавал, но особо не получил внятного ответа зачем это. Кто то ещё не знает что на телефонах бывает контент 34? Китайским, корейским, израильским и прочим товарищмайорамполковникам злой пейсбук с гуглом и яндексом не продают данные о пользователях?


    1. yaguarundi
      31.08.2021 14:07
      +1

      Кажется это особенность реализации Bluetooth в андроиде, вообще или ранних версий - он просто не работает без доступа к данным геолокации.


  1. sirocco
    30.08.2021 14:32
    +1

    Тфу... Думал таки найду действительно карту вышек/антенн сотовой связи. А тут тоже фуфло.

    Есть в деревне за 700км от МКАД три вышки, вроде как сотовой связи. Реально их видел, давно стоят. Сам я не там. И вот надо подобрать антенки, чтоб модем хорошо настроить на определённого провайдера. Но где он, на какой из вышек? Та, что за 7км, та, что за 4км, или та, что за 2км, но скрывается за тополями на горизонте?

    Ни на одной карте этих вышек не нашёл. Придется два выезда делать, сначала приехать замеры устроить, потом оборудование закупать-везти.


    1. Nosgoth
      30.08.2021 17:10
      +2

      Сразу вспомнил про программу для дроида "Cell info" и то, что она делает привязки станций к карте. Небольшой поиск привел меня на https://location.services.mozilla.com
      Уже там можно забрать файлик со списком станций, координатами и т.п.
      Посмотрите, возможно это то, что Вам нужно.


    1. FirsofMaxim
      06.09.2021 07:43
      +1

      Разбейте задачу на подэтапы:

      1. определение высоты антенны (сопоставить рельеф вышек и места антенны)

      2. юстировка положения антенны (делается на месте) + CellInfo аппа для Android.

        Сам год назад решал аналогичную проблему.


  1. CAJAX
    30.08.2021 19:28
    +2

    Ваше приложение для Китая? В принципе вы описали Fused Location Provider в Play Services, только менее точный.


  1. ARfan
    31.08.2021 14:33
    +1

    Речь идёт только для Android?