Pull to refresh
0

Детский лаунчер 2.Х и единый премиум-аккаунт

Reading time 7 min
Views 10K


Что нового


После публикации первой версии приложения к нам поступило большое количество отзывов. Собрав воедино пожелания пользователей и наши собственные идеи, мы начали работу над второй версией. Спустя два месяца упорного труда обновленные приложения Детский Лаунчер и Родительский Контроль доступны для скачивания в Google Play.

Шестизначный пин-код

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

Возможность смены обоев

Одним из самых частых обращений была просьба включить возможность менять обои. Мы пошли чуть дальше и решили предоставить эту возможность не только родителям, но и детям — теперь можно сделать так, чтобы ребенок сам устанавливал обои. При необходимости эта опция отключается.

Расписание, будни и выходные

Как быть, если ребенок играет по ночам или во время уроков? Как настроить временные ограничения так, чтобы в воскресенье можно было поиграть дольше, чем в понедельник? Очевидно, что требуется расширенная настройка временных ограничений с созданием собственного расписания.
В новой версии можно устанавливать временной промежуток, когда можно запускать приложение или категорию приложений. Например: приложения категории “Игры” можно запускать с 15:00 до 20:00.

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

Помимо отдельных приложений и категорий, можно настроить временные ограничения и для всего устройства. Например: устройство можно запускать по будням с 15:00 до 20:00, разрешенное время работы — 2 часа; по выходным — с 13:00 до 21:00, разрешенное время работы — 4 часа. В данном случае разрешенное время работы — это совокупное время работы любых приложений. По истечении разрешенного времени работы, либо вне разрешенного временного интервала, запрещается запуск любых приложений, кроме звонков и смс.

Эта функция доступна только с премиум-аккаунтом.

История перемещений ребенка

Если раньше можно было посмотреть текущее местоположение ребенка, то теперь приложение показывает историю перемещений за последние 12 часов. Как и раньше, координаты обновляются каждые 15 минут, точка фиксируется на карте. Информация о перемещениях ребенка может быть полезна даже без использования приложения “Родительский контроль” — например, родители могут взять устройство ребенка и в разделе “Отслеживание” посмотреть, где и в какое время он находился.

Данная функция также является премиумной. Отслеживание текущего местоположения ребенка по-прежнему остается бесплатным.



Премиум-подписка


Для монетизации приложения мы решили использовать премиум-аккаунт, который открывает недоступные простому пользователю функции. Покупается премиум-функционал через подписки в Google Play In-App Billing. Рассмотрим коротко, что представляет собой подписка, и какие у нее ограничения.

Введение

При оформлении подписки у пользователя периодически списывается со счета определенная сумма денег — цена подписки. Она ограничена минимальной ценой в 30 рублей и максимальной в 6000 рублей и аналогичными размерами в долларовом эквиваленте. Google позволяет устанавливать только 2 типа периодичности: ежемесячная подписка и ежегодная. Есть возможность добавлять триальный период от 7 до 999 дней. Что касается отмены подписки, пользователь может отменить ее в любой момент, но деньги за текущий период ему не возвращаются. После отмены подписки пользователь может пользоваться всеми премиум-функциями до конца оплаченного периода. При удалении приложения с подпиской, подписка не отменяется, но Google Play выдает нотификацию о том, что вы удалили приложение, но деньги с вас все равно будут снимать пока вы не отмените подписку.

Единый премиум для разных приложений

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

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

Реализация

Для покупки подписки на клиенте мы использовали классы из TrivialDrive. TrivialDrive — это классическое мобильное приложение с in-app purchase sample, который идет вместе с Google Play Billing Library. Описывать детально как и что делать для покупки in-app purchases мы не будем, но та часть, которой коснемся, будет в терминах классов утилит из TrivialDrive.

Проверка при авторизации

Первый раз мы проверяем, активен ли премиум при авторизации, и если он активен и его время не вышло, то мы включаем премиум-функционал на клиенте. Это самый простой вариант.

Покупка премиум-подписки

Другой вариант — у пользователя при авторизации премиума нет.



Шаг 1.
При нажатии на кнопку “Купить премиум” идет запрос на сервер, чтобы узнать, а не куплен ли премиум на другом устройстве этого же пользователя. Если премиум был куплен ранее и не закончился, включаем премиум-функционал на клиенте.

Шаг 2.
Если же премиум куплен не был, то запускаем процесс покупки подписки через IabHelper.launchPurchaseFlow. Помимо прочих параметров в функцию передается payload. Payload — это строка, определяемая разработчиком и однозначно связывающая пользователя с этой покупкой. Мы в этот параметр передаем имя аккаунта пользователя.

Далее управление на себя берет google services и по завершению покупки, удачному или не очень, вызывает наш callback. Сейчас рассмотрим удачное стечение обстоятельств, когда у пользователя не был куплен премиум до этого и не возникло никаких ошибок. В этом случае в callback возвращается объект Purchase, в котором содержатся необходимые нам поля: payload, purchaseTime, productId, orderId и purchaseToken. Все эти данные, а так же идентификатор устройства мы оправляем на серверную часть (Шаг 3) для верификации покупки.

Шаг 3.
Сервер, в лице Parse, использует Google Play Developer API для получения данных о только что купленной подписке. Для использования Google Play Developer API нужно создать приложение в Google Cloud Console, включить Google Play Developer API и получить access_token (он, к сожалению, не вечен, но об этом позже). Узнать информацию о подписке можно, отправив GET запрос на https адрес вида: «www.googleapis.com/androidpublisher/v1/applications{packageName}/subscriptions/{productId}/purchases/{purchaseToken}?accessToken={accessToken}»
В ответ приходит JSON с информацией о датах начала и окончания подписки, а так же о том, продлится ли автоматически подписка, когда выйдет время (видимо, отменил пользователь подписку или нет — нам это поле не понадобилось). Документация по запросам небольшая, потому что писать там особо и нечего — developers.google.com/android-publisher/v1/purchases

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

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

Пользоваться Детским Лаунчером можно в offline-режиме, значит нужно иметь возможность верифицировать премиум-аккаунт без интернета. Для этого мы сохраняем данные о премиум-аккаунте (дату окончания, идентификатор подписки и пр.) локально в SharedPreference в зашифрованном виде. Проверяем состояние премиум-аккаунта каждый раз при входе в родительский режим. Если интернет есть, то после успешной локальной проверки мы обращаемся на Parse за подтверждением; если Parse подтверждает премиум-аккаунт, то мы перезаписываем локальные данные (возможно, обновилось время окончания подписки). Если нет соединения с сетью, то мы ничего не делаем и считаем премиум активным, т.к. локальная проверка подтверждает факт покупки премиум-аккаунта. Факт продления подписки без соединения с сетью проверить не удастся, поэтому, даже если локально хранимое время подписки закончилось, премиум-аккаунт остается активированным.

Возможные ситуации



Обновление токена.
На третьем шаге используется приложение в Google Cloud Console со включенным Google Play Developer API. Про создание приложения и получение токенов (access_token и refresh_token) можно почитать здесь — developers.google.com/android-publisher/authorization. Скажу лишь только, что для всех вызовов API используется access_token, а он не вечен и довольно быстро умирает. Как только время действия access_token закончится, API вернет 401 ошибку, и, используя refresh_token, мы сможем получить новый access_token. Т.е. шаг 3 может немного растянуться, если время действия access_token закончится.

Продление премиум-подписки.
На этапе авторизации или на этапе проверки премиума может возникнуть ситуация, что пользователь активировал премиум ранее, но сохраненное на сервере время окончания подписки прошло; в таком случае сервер снова обращается к Google Play Developer API за получением новых данных о подписке — узнать, продлилась подписка или нет. Если подписка продлилась, сервер перезаписывает у себя данные об окончании времени подписки и отправляет их на устройство. Если же подписку отменили, то также сервер сообщает об этом устройству, и устройство затирает информацию о подписке в SharedPreference.

Подписка уже куплена.
На этапе покупки подписки может возникнуть такая ситуация, что у пользователя уже куплена эта подписка. Сообщит нам об этом Google Services через callback, переданный в функцию IabHelper.launchPurchaseFlow. В этот callback вернется ошибка с кодом BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED, и в этом случае нужно будет снова обратиться к Google Services за списком всех купленных внутренних покупок/подписок. Делается это через функцию IabHelper.queryInventoryAsync, в которую передается очередной callback. Из полученного списка всех совершенных покупок (Inventory) мы достаем нужную нам подписку по идентификатору и смотрим ее payload; если payload не совпадает с аккаунтом текущего пользователя (а других ситуаций быть не должно, если наш механизм работает корректно), то мы сообщаем пользователю, что подписка у него уже куплена, но для другого аккаунта. Если всё же payload совпадает с текущим аккаунтом пользователя (не, ну а вдруг?), то в google service мы выполняем все те же действия, что и при обычной покупке, но уже с Purchase, который до этого вернулся в callback.

Что дальше


  • Интервалы отдыха.
  • Создание собственных категорий приложений.
  • Фильтрация входящих, исходящих звонков и SMS.

Дальше — больше. Ждём ваших комментариев и предложений. Спасибо.

P.S. Статья написана совместно с хабраюзером belozerow
Tags:
Hubs:
+8
Comments 24
Comments Comments 24

Articles

Information

Website
appgranula.com
Registered
Founded
Employees
11–30 employees
Location
Россия