Задача: наступает лето, дети все больше времени проводят где-то на улице, и я бы хотел знать, где они находятся. Идеальный вариант — я просто даю им с собой старый андроидный телефон, и затем наблюдаю за ними по карте на большом домашнем мониторе.
В этой статье я расскажу, почему и как я написал свое первое приложение для Андроид с функциями GPS «KidsTrack», и какие открытия при этом сделал. Статья будет полезна тем, кто недавно начал программировать под Android.


Поиски на Google Play выдали мне сотни различных приложений с функциями GPS-мониторов. Я уж начал их было перебирать, но примерно на 2-м десятке я осознал, что затраты времени на выбор могут оказаться вполне сравнимыми с затратами времени на разработку. Ведь мои функциональные требования очень просты:
  • приложение должно периодически отправлять анонимные координаты на сервер,
  • сервер должен показывать карту с маркером в соответствующем месте.

Это все!

Есть еще требования, которые не связаны с функциональностью, но которые не менее важны:
  • отсутствие необходимости регистрации, и привязки аккаунтов
  • бесплатность
  • отсутствие рекламы
  • отсутствие ненужных функций, которые уже есть или в телефоне, или в других приложениях, типа обмена сообщениями, тревожных кнопок, уведомлений, стираний данных, блокировок телефона, чата, и т.п.
И да, координаты будут хранится на сервере, который не бесплатен. Но хостинг сейчас стоит такие копейки, что я считаю неправильным брать с людей деньги за хранение пары чисел (или даже нескольких килобайт).

Одним словом, попробовав несколько приложений из Google Play, я решил написать трекер сам.

Далее, все тривиально: установил Android Studio, нарисовал единственный экран с 3-мя кнопками, написал, как мне казалось, сервис, отладил все в эмуляторе, затем в USB-дебаггере, вроде все заработало.
Экран с 3-мя кнопками



Но как только попробовал запустить на физическом устройстве — начались сюрпризы. О некоторых из них я хотел бы рассказать.

Сюрпризы управления питанием



Реальные андроид-устройства стремятся отключить себе питание при любой возможности. Постоянно получают питание лишь весьма примитивные системные часы (модуль мобильной связи здесь он не рассматривается). В часах есть регистр(ы), куда посредством AlarmManager можно записать время следующей пробудки процессора телефона. Если процессор не разбудят часы, то он так и будет продолжать спать ничего не делая. Сделано это по простой причине: включенный процессор разрядит батарею за час. Поэтому если надо, чтобы сервис что-то делал раз в минуту, то приемы десктопного программирования вроде Thread.sleep(60000) не подойдут, а вместо этого надо пользоваться AlarmManager, примерно вот так:

public class YourService extends Service {

    public int onStartCommand(Intent intent, int flags, int startId) {
        /* Что-то делаем */
        ...
        /* Планируем следующий страрт */
        Intent ai = new Intent("info.izhforum.kidstrack.START_ALARM");
        PendingIntent pai = PendingIntent.getBroadcast(mInstance, 0, ai, 0);
        mAlarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+60000, pai);
        ...
    }
}

В этом примере мы программируем AlarmManager разбудить телефон через 1 минуту, и отправить интент START_ALARM всем приложениям, кто на него подписан.

Прием интентов во всех учебниках осуществляется объектом BroadcastReceiver, однако если нам нужно, чтобы:
  1. телефон пробуждался из глубокого сна
  2. запускал наш сервис,
  3. не засыпал до завершения работы

то BroadcastReceiver не подойдет, и вместо него надо использовать WakefulBroadcastReceiver — этот объект гарантировано не допустит впадения телефона в сон до тех пор, пока не будет вызван метод completeWakefulIntent. Во всяком случае у меня так и не получилось заставить BroadcastReceiver работать надежно на физическом устройстве.

Если ваш сервис теоретически может выходить в интернет через WiFi, то вам необходимо позаботится, чтобы у WiFi-модуля во время соединения тоже было включено питание, так как оно у него отдельное. Если этого не сделать, то бывает трудно понять почему приложение не работает на физическом устройстве: ведь при отладке на эмуляторе или устройстве, подключенном к дебаггеру через USB, питание модуля WiFi не выключается, и все отлично работает. Запретить отключать питание WiFi можно так:

private WifiManager mWifiManager = null;
private WifiManager.WifiLock mWifiManagerLock = null;
...
mWifiManagerLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "MyWFL");
mWifiManagerLock.acquire();
/* Здесь осуществляем сетевой ввод/вывод */
mWifiManagerLock.release();


Сюрпризы GPS


В первой версии приложения я сделал определение координат устройства только с использованием провайдера «GPS». И очень было мне удивительно наблюдать на сервере, как более 90% устройств не смогли определить координаты и присылали нули.
Как оказалось, GPS – довольно капризная технология с множеством ограничений, низкой скоростью и непредсказуемой точностью. При использовании традиционной GPS сенсор приемника должен получить данные обо всех GPS-спутниках (а их более 2х десятков), среди всех них выбрать наиболее подходящие, и уже по ним вычислять координаты. Получение данных и перебор могут занимать 5 минут и более, поэтому первый «холодный» старт GPS всегда самый медленный.
Если GPS-приемник имеет часы и помнит прошлые координаты и положения спутников, то он может использовать эти данные для определения тех спутников, к которым можно привязаться в данный момент. Поэтому повторный запуск GPS обычно происходит намного быстрее.
В современных смартфонах первоначальное грубое определение координат может осуществляться по близлежащим передающим сотовым вышкам, что так же позволяет ускорить «холодный старт» GPS. Для использования этого способа требуется разрешение на использование провайдера «network» в Manifest-е, так для определения я координат вышек может использоваться интернет.
Еще одна функция провайдера «network» — определять координаты по видимым WiFi — сетям. Определение осуществляется путем поиска координат видимых в данный момент сетей по их именам и MAC-адресам на серверах Google через интернет. Разумеется, в фоновом режиме и без лишних уведомлений идет и обратный трафик: телефон, когда определил свои координаты по GPS, может по-тихому послать данные об окружающих его WiFi-сетях на серверы Google, чтобы таким образом поддерживать актуальное состояние базы WiFi-сетей. Грустные размышления о потенциальной власти Google над владельцами Андроидов и WiFi-сетей оставим за рамками этой статьи…
Прояснив все эти нюансы я в авральном порядке подправил приложение, чтобы оно использовало не только провайдера «GPS» но и «network». После этого типичная последовательность вызовов метода onLocationChanged стала выглядеть так:
  1) 00:00.234 провайдер = “network”, точность = 1672m // пришли координаты по сотовым вышкам
  2) 00:00.933 провайдер = “network”, точность = 52m // пришли координаты по WiFi
  3) 00:16.310 провайдер = “gps”, точность = 28m // пришли координаты по GPS

Я все-таки очень хотел задействовать GPS, так как обычно это самый точный способ, поэтому я установил время ожидания сигнала от GPS-сенсора 30 секундам, а если это первый пуск — 2-м минутам. И если GPS-сенсор так и не сработал, то используются координаты от провайдера «network». После этого изменения устройства стали присылать на сервер нормальные, ненулевые координаты.
Точность GPS также оказалась весьма условной. Например нередко точность координат, получаемых с сенсора неподвижного лежащего устройства может выглядеть так:
	05:13:05	76m
	05:14:36	68m
	05:15:58	37m
	05:17:20	79m
	05:19:00	116m

Из этих данных ясно, что GPS хорош для нахождения зданий или других больших объектов, но найти человека в толпе, или телефон в сугробе будет непросто.

Отдельно стоит упомянуть питание GPS. Модуль GPS весьма прожорлив, поэтому в учебниках рекомендуют при вызове requestLocationUpdates не устанавливать слишком короткие параметры минимального интервала по времени и по расстоянию. Но в моих опытах с 3-мя различными физическими устройствами оказалось, что постоянно включенный модуль GPS садит батарею одинаково при различных параметрах. Потом уже я нашел где-то упоминание, что эти параметры влияют только на частоту вызова метода onLocationChanged, но не обязательно на энергопотребление самого сенсора.

Прочие сюрпризы



Google Play: Первая версия пролежала на Google Play два дня, после чего была заменена новой, с исправленным алгоритмом определения координат. Несмотря на то, что это произошло уже две недели назад, я на сервере продолжаю видеть, что очень часто продолжают происходить активации старой версии. Я уже и добавил сообщение о необходимости обновления на веб-странице мониторинга, но это не всегда помогает. Непонятно откуда вообще люди берут старую версию. Я не знаю чем это объяснить.

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



Яндекс.Карты: Страница мониторинга изначально была реализована с использованием API Яндекс.Карт, так как там не требуется ID, и нет ограничений на количество загрузок карты в день. Но оказалось, что на слабых устройствах Яндекс.Карты или тормозят, или вообще не открываются. Пришлось эту страничку делать в 2-х вариантах: Яндекс.Карты для настольных компьютеров, и Google Maps для слабых мобильных устройств. Google Maps оказались существенно быстрее.

Итоги


С практической точки зрения итоги, конечно, скромные, так как уже существует множество гораздо более продвинутых GPS-мониторов. Но судя по отзывам, именно простотой KidsTrack и приглянулся многим.
Для меня лично итоги значительно более внушительные. Главный итог — бесценный опыт, который невозможно было бы получить из статей или учебников. Грабли, описанные выше, заставили пересмотреть реалистичность и дизайн других более крупных проектов, над которыми я работаю.

Комментарии (43)


  1. Rumlin
    14.05.2015 08:20

    off Яндекс карты стали «тормозить» не очень давно. Одно время они мне нравились больше Google maps off


    1. Viacheslav01
      14.05.2015 12:39
      +1

      Ужас последнего времени Yandex Map Kit, такой кривой фигни от Я не ожидали :)


  1. musuk
    14.05.2015 08:47

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

    image


    1. amaksr Автор
      14.05.2015 23:01

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


  1. wholeman
    14.05.2015 08:53
    +1

    Есть ещё OpenStreetMap и иногда он намного точнее конкурентов.
    Забавно, когда я делал для себя трекер, с описанными проблемами не столкнулся, т.к. обращения к GPS постоянные, и телефон просто не засыпает. Как я заметил, неточны первые фиксы, а потом ошибка составляет несколько метров, не больше. При хороших условиях, конечно.


    1. variable
      14.05.2015 12:45

      >>Есть ещё OpenStreetMap и иногда он намного точнее конкурентов.
      как относится провайдер картографических данных к gps?


      1. wholeman
        14.05.2015 18:24

        Позицию, полученную с GPS-трекера можно отобразить на картах данного провайдера. Под конкурентами здесь следует понимать Google Maps и Яндекс.карты, которые использует автор статьи.


    1. amaksr Автор
      14.05.2015 17:13
      -3

      У них вроде нет tile-сервера, получается их карты никак не встроить если не сделать такой сервер у себя.


      1. Borz
        14.05.2015 17:58
        +1

        1. amaksr Автор
          14.05.2015 18:45
          -3

          Да, я видел эту страничку. Но проблема в том, что Tile-серверы там или платные, или с ограничениями, или не берут обязательств по стабильности работы и uptime-у. Поэтому рассудил, что на данном этапе OpenStreetMap не имеет существенных преимуществ, и доверился выбору коллективного разума — Яндекс.Картам. Если, например, Яндекс начнет перебирать с рекламой, тогда можно будет и другие варианты рассмотреть.


          1. wholeman
            14.05.2015 19:55
            +1

            А какие обязательства берут Google и Яндекс? В последнее время читаю много условий использования различных сервисов (например, S-Health от Samsung), все обещают постараться обеспечить стабильную работу, но ничего не гарантируют.


          1. Moskus
            15.05.2015 06:31

            Тем не менее, стабильность самого первого из списка (учитывая еще наличие у него CDN) весьма высока и он полностью бесплатен.


            1. amaksr Автор
              15.05.2015 06:52
              -1

              Несколько цитат из Tile Usage Policy первого по списку сервиса, которые меня в итоге от него отвернули:

              OpenStreetMap's own servers are run entirely on donated resources. They have strictly limited capacity.

              OpenStreetMap data is free for everyone to use. Our tile servers are not.

              Heavy use (e.g. distributing an app that uses tiles from openstreetmap.org) is forbidden without prior permission from the System Administrators.

              Подобные ограничения есть у всех.
              Яндекс же компания понятная, мы знаем что они делают деньги на рекламе, а значит несут 1) финансовые обязательства перед рекламодателями 2) бремя репутации перед всеми остальными. Поэтому их надежность и uptime однозначно лучше.
              И повторюсь, я не увидел чем функционально OSM лучше.


              1. Moskus
                15.05.2015 07:01
                +1

                Вы надеетесь создать на тайл-сервисы OSM такую нагрузку, которая будет заметна? Надейтесь дальше.
                Все остальное — голословно, потому что сведения о реальном аптайме серверов OSM у вас отсутствуют.
                Плюс — отсутствие рекламы, возможность (юридическая) использовать в полном оффлайне и так далее.


                1. amaksr Автор
                  15.05.2015 07:12
                  -1

                  Вы надеетесь создать на тайл-сервисы OSM такую нагрузку, которая будет заметна?

                  Я — нет, но обязательно найдется кто-то, кто будет правила нарушать, а страдают при этом все. В Яндексе же и Гугле люди получают зарплату за бесперебойную работу сервисов. Поэтому я посчитал, что сервис от компании надежнее.


                  1. Moskus
                    15.05.2015 07:21
                    +1

                    Сходите посмотрите на wiki.openstreetmap.org/wiki/Servers для самообразования. Графики munin там доступны.


  1. dndred
    14.05.2015 08:58

    Под ваши требования отлично подойдёт OsMoDroid. Выглядит это примерно так: Я тут!


    1. ragman
      14.05.2015 11:35

      Что то Я тут! выдал ошибку:

      Произошла ошибка
      The link is not valid


      1. dndred
        14.05.2015 11:39

        Уже выключил. Новый.


        1. alekseev_ap
          14.05.2015 22:29

          Тоже не работает!


          1. dndred
            15.05.2015 05:39

            Я же не могу вечно транслировать свои координаты. Сделал скришоты

            Я был тут


  1. berezuev
    14.05.2015 10:36
    -1

    Имхо, это не нормально и не правильно, ТАК следить за ребенком… Даже за маленьким.


    1. Rumlin
      14.05.2015 10:38
      +1

      Может пригодиться:

      Вчера 4-летняя девочка заблудилась в тумане
      3 мая днем оперативному дежурному алуштинского «Крым-спас» поступило сообщение о потерявшейся четырехлетней девочке, сообщает сайт МЧС.
      В этот день, когда в Крыму резко испортилась погода, в ряде регионов с гор спустился густой туман, который не рассеялся даже днем. Родители рассказали спасателям, оперативно прибывшим на место, что ребенок бегал вокруг, но внезапно пропал. Родные пробовали разыскать девочку самостоятельно, долго звали ее, но безуспешно: ребенок заблудился в тумане.
      Спасатели нашли девочку буквально за 10 минут, и передали ее родителям. Ребенок был напуган, но не плакал.


    1. Seekeer
      14.05.2015 14:52

      А как надо за ним следить, по-вашему?


      1. berezuev
        14.05.2015 15:55
        +4

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

        Как-то же раньше без этого контроля жили, и ничего.


        1. Seekeer
          14.05.2015 19:34
          -4

          >Наличие заряженного и оплаченного телефона в кармане у ребенка обычно достаточно.
          Ребёнок имеет привычку не замечать сигналов телефона.

          >Как-то же раньше без этого контроля жили, и ничего.
          Раньше вообще без телефонов жили и ничего. Предлагаете вообще от телефонов отказаться?


        1. wholeman
          15.05.2015 11:20

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


    1. amaksr Автор
      14.05.2015 16:43
      -3

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


    1. kavboy
      15.05.2015 08:33
      +1

      В каждой теме про GPS трекинг нет-нет да появляется подобная ветка. Ох уж эти философы…


  1. Viacheslav01
    14.05.2015 12:35
    -1

    Поразили хотелки

    1) Анонимно на сервер
    2) Бесплатно
    3) Без рекламы

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


    1. amaksr Автор
      14.05.2015 17:03

      Я думаю здесь ничего поразительного как раз нет. 18 лет назад Google тоже был бесплатный, анонимный, без рекламы и очень простой.
      Пока что KidsTrack может мирно сосуществовать с моими другими проектами, поэтому дополнительных расходов не требует. Если оно вырастет, то тоже есть выходы, например ввести платные услуги, или показывать рекламу, но не в приложении (незачем ребенку на телефоне ее видеть), а на странице мониторинга.


      1. Viacheslav01
        14.05.2015 17:36

        Это ваше решение, мне оно понятно и вопросов не вызывает.

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


        1. achekalin
          14.05.2015 18:22

          Увы, но иногда автор чего-то там хорошего вешает рекламу, не думая, ЧТО в ней покажут, а потом открываешь игрушку, а в ней полуголые барышни и заголовок полупорнушного содержимого. Я не против посмотреть рекламу, если что, но в рунете полно примеров, где автор рассудил так — «я работал над проектом, но даже реклама дает мало прибыли, ПОВЕШУ-КА Я ЕЕ МНОГО», и это заставляет к нему уже относиться несколько с опаской.


          1. Viacheslav01
            14.05.2015 18:28

            К сожалению да, чувство меры часто отсутствует, но пользователь сам уйдет от такого автора к тому, у которого будет все сбалансированно.
            К сожалению большинство пользователей очень негативно относится даже к мизеру адекватной рекламы.
            Я не знаю откуда такая уверенность в том, что приложения должны быть бесплатными.
            Я сто раз спорил с знакомыми занятыми в других областях, но почему-то никто не хочет меня бесплатно подстричь или сделать мне ремонт, это же работа они заработали! А авторы софта, бездельники которые хотят на них несправедливо нажиться :(


        1. evr1ka
          15.05.2015 10:08

          На Айфоне, в приложении типа Говоряций Попугай (Talking Pierre) выбирал опцию (и оплачивал), чтобы реклама убралась.
          Деньги сняли, реклама осталась. Писал, велся диалог, денег не вернули, и рекламу не убрали.
          На Андроиде такого слава богу нет.
          Поэтому пытаться убрать рекламу на других приложениях (на афоне), даже не стал. Хотя могли заработать.
          Почему не могут сделать отдельную платную версию, без рекламы, или ввести более понятный способ ее убрать (за денежку?) Не понятно
          И да, это приложение для Ребенка, чтобы она с ним «Попугайничала». Она еще не говорит, и на это в числе прочего тоже надежда. И изначально таргетированно на ребенка. Какая реклама 2-5 летнему будет нужна, и что он сможет там для себя получить? Хорошо хоть закрывать умеет (научилась).
          2х летняя еще нет, хнычет и приносит закрыть рекламу мне.


          1. Viacheslav01
            15.05.2015 10:36

            Зато CTR у этой рекламы зашкаливает :)
            На самом деле я не беру в расчет кривую реализацию и замусоривание приложения рекламой.


  1. r_ii
    14.05.2015 12:51

    А чем Google Location History не подошел?


    1. musuk
      14.05.2015 13:01
      +1

      По мне он точки берёт довольно редко, вернее у него крайне нестабильное логирование.
      К тому же, насколько я знаю, Location History может смотреть только сам пользователь, которого логируют.
      В Google Plus есть фича, чтобы показывать местоположение друзей. Но там всё так запрятано, неудобно и неочевидно, что вряд ли этим можно пользоваться.


  1. 0leGG
    14.05.2015 15:36

    Сервер, кстати, можно было бы и довольно бесплатным сделать. Полагаю, в лимиты parse.com он точно уложится, там же и бэкенд с фронтендом держать можно


    1. amaksr Автор
      14.05.2015 17:18

      Пока серверная часть очень проста: там одна таблица и два PHP скрипта. Поэтому parse.com и все его функции не нужны. Если в какой-то момент логика приложения сильно усложнится, то тогда возможно и стоит рассмотреть parse.com и подобные сервисы, но пока этого в планах нет.


  1. alexxprg
    15.05.2015 00:27

    Непонятно откуда вообще люди берут старую версию

    Есть ресурсы, например, getandroidapp.org, которые выгружают себе apk с google play и далее распространяют их, показывая юзерам рекламу и прочие непотребства.


  1. Moskus
    15.05.2015 06:28

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

    Приемник GPS не сканирует никакие частоты спутников. Если приемник не поддерживает ни одну из технологий assisted GPS, он ждет получения блока данных со спутников, который описывает их текущее положение, чтобы иметь возможность решать задачу определения своего положения. (Это называется «холодный старт».)

    Более короткое время повторного старта (так называемого «теплого») обусловлено тем, что информация о положении спутников еще не устарела.

    Точность определения координат средствами GPS в телефонах также может оставлять желать лучшего, если телефон лежит в кармане или сумке, и антенна в той или иной степени перекрыта телом или другими предметами.


  1. getId
    15.05.2015 13:57

    А не подскажите, какой gps-трекер взять до 1200 рублей? Из функций хватит только получение координат по sms, хотя в идеале, передача по GPRS координат на свой сервер.
    Видел на Aliexpress и Ebay mini A8 и TK102B, но они позиционируют себя как жучки, позволяют незаметно организовывать подслушивание. Такое опасно заказывать, так как у нас незаконно. Думал о приобретении смартфона на Android с GPS для этой цели, но самые дешевые от 2400 рублей. Пока, думаю, взять б/у смартфон.