Хабрахабр

Как защитить своего ребенка от мусора на YouTube и сделать кастомный плеер с белым списком каналов

Кто-то говорит что это вредно для глаз или для психики, кто-то — что родителям надо бы самим играть и читать с детьми, а не пытаться отгородится от них гаджетами. Можно долго спорить на тему, стоит ли давать маленьким детям доступ к планшетам и смартфонам. И которые не знают, какое это блаженство — когда чадо замолкает хотя бы на полчаса, перестает крушить все вокруг, спокойненько лежит на диване и смотрит мультики. Что характерно, чаще всего такое говорят люди, у которых своих детей нет. Есть и еще один аргумент — дети чутко все повторяют за родителями, если родители непрерывно сидят уткнувшись в телефон, то очень сложно объяснить детям, почему родителям можно, а им — нет.

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

Про это даже на Хабре уже был перевод статьи. К сожалению, я очень быстро уяснил, что детский ютуб — это просто АДОВЫЙ ТРЕШ. По какой-то причине все это является очень привлекательным для маленьких детей, которые бросаются кликать на такие видео как только увидят их в рекомендованных. Детские каналы — это какие-то бездонные клоаки, наполненные вырвиглазными видео типа "разворачиваем сто киндер-сюрпризов", "дурацкие стишки с убогой 3д графикой под крикливую музыку" и "гоняем машинки в Beam NG под дурацкие комментарии". Даже дав своему сыну планшет с включенными "нормальными" мультиками, я уже через пару минут наблюдаю, как он за два клика по рекомендациям опять находит эти чертовы шоколадные яйца и снова начинает в них залипать. А YouTube не позволяет управлять рекомендациями.

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

Хреново сделанная бессмысленная 3д анимация под дурацкую музыку — и 142 миллиона просмотров. Вот вам один пример трешевидео, с которыми мы будем бороться. Почему-то такие видео детей просто зомбируют, они готовы их пересматривать и пересматривать.

Для сравнения масштабов — крутейший ролик где Крис Хэдфилд поет под гитару на МКС имеет всего 40 миллионов просмотров, а замечательный клип OK GO с настоящей невесомостью (никаких тросов и хромакея, только честная невесомость на борту специального самолета) — всего 12 миллионов, в десять раз меньше.

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

Постановка задачи

Такие попытки уже есть, в том числе и тут на хабре — там режут все подряд, чтобы ребенок не мог выйти из приложения, купить что-то, открыть браузер и т.п. Сразу скажу, что я не ставил задачу сделать непробиваемое для детей приложение. Но это все имеет смысл для детей постарше, которые уже во всю исследуют возможности своих гаджетов. Есть и варианты с хардверными блокировками, отключенными портами, кастомными оболочками андроида и прочими сложностями (например вот статья за 2012 год, проект вроде все еще жив). Главное, чтобы эти ролики были какими надо, а не какие предложит YouTube (а предложит он нескончаемые шоколадные яйца и baby fingers). Для детей же 2-3 лет никакая особая защита не нужна, их вполне устраивает смотреть видео и время от времени тыкать в превьюшки других роликов.

Из этого родился список требований:

  • Настраиваемый список каналов
  • Защита его от изменений (скорее от случайных, ибо у хитрых взрослых детей уже есть куча способов вызнавания паролей родителей)
  • Само приложение — похоже на ютубовское, слева играет видео, справа колонка превьюшек, на которые можно нажимать
  • Основной use-case — случайное тыкание по видео, ребенку в общем-то все равно что именно смотреть

Причем вариантов проигрывания видео внутри собственного приложения я на данный момент обнаружил два: При этом работа приложения состоит из двух основных частей: поис и настройка каналов с помощью YouTube Data API и затем воспроизведение видео.

YouTube Android Player API

https://developers.google.com/youtube/android/player/

Для его работы на девайсе пользователя уже должно быть установлено официальное приложение YouTube, которое в своем составе включает некую службу, которую можно использовать из других приложений. Это официальный способ проигрывать видео в своем андроид приложении. Так что этот самый Player API представляет из себя маленькую библиотеку, взаимодействующую с отдельно устанавливаемым приложением.

В нем нельзя толком кастомизировать внешний вид плеера, в частности управлять кнопками (можно только спрятать вообще все целиком, но тогда лишишься и кнопки полноэкранного режима). Сперва я воспользовался им, но после некоторого времени использования выяснилось, что у него есть критичная проблема. И дети легко (случайно или нет) нажимают на нее, переходят к нефильтрованному приложению, и через неколько минут я уже снова слышу "baby finger, baby finger where are you" и вижу какие-то вырвиглазные трешеанимации на экране. А на панели управления плеером есть нехорошая кнопочка "перейти к просмотру на YouTube", которая открывает официальное приложение (которое обязательно должно быть на девайсе), в котром уже нет никакой фильтрации.

Больше 900 миллионов просмотров! Еще немножко треша, который дети находят за пару кликов.

Поэтому от официального плеера я отказался, найдя ему замену в виде следующей библиотеки.

Android-YouTube-Player

https://github.com/PierfrancescoSoffritti/android-youtube-player

Из плюсов — возможность полной кастомизации интерфейса. Библиотечка похоже представляет собой обертку вокруг WebView, управляющую веб-плеером через его JavaScript API.

Инициализация плеера слегка неочевидна, особенно после перехода с официальной библиотеки:

  1. Получаем нашу вьюху класса com.pierfrancescosoffritti.androidyoutubeplayer.player.YouTubePlayerView
  2. Зовем ей initialize(), передавая листенер
  3. У листенера вызывается метод onInitSuccess(@Nonnull final YouTubePlayer youTubePlayer), получающий экземпляр объекта плеера. Это единственный способ его получить. До этого момента процесс инициализации был идентичен таковому у официального клиента
  4. У плеера вызываем метод addListener(), передавая в него еще один листенер (больше листенеров богу листенеров!)
  5. У этого листенера вызывается метод onReady() — только после этого момента можно загружать и показывать видео и пользоваться плеером. Если по ошибке попробовать что-то загрузить в onInitSuccess то библиотека начнет плеваться странными ошибками.

В таком случае библиотека всю рутину возьмет на себя. Управлять жизненным циклом плеера (остановка воспроизведения в onPause() и все в таком духе) можно вручную, а можно зарегистрировать нашу вьюху как Lifecycle Observer (для чего наша Activity должна наследоваться от AppCompatActivity).

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

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

youTubePlayerView.addFullScreenListener(new YouTubePlayerFullScreenListener() @Override public void onYouTubePlayerExitFullScreen() { fullScreenHelper.exitFullScreen(); rootLayout.setPadding(8, 8, 8, 8); youTubePlayerView.getLayoutParams().height = LinearLayout.LayoutParams.MATCH_PARENT; } });

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

Мне было достаточно спрятать кнопку "показать на YouTube", сохранив при этом полноэкранный режим: Вообще как-то много минусов получилось у этой библиотеки, но все перекрывает главный плюс — возможность настраивать интерфейс проигрывателя.

youTubePlayerView.getPlayerUIController().showFullscreenButton(true);
youTubePlayerView.getPlayerUIController().showYouTubeButton(false);

— в итоге по возможностям кастомизации эта библиотека оставляет своего официального конкурента далеко позади. А вообще там можно управлять всеми кнопками, отображением текущего времени, можно добавлять свои собственне View и т.п.

Ну и после работы по настройке плеера новое видео грузится просто как youTubePlayer.loadVideo(url, startTime);

Получение списков видео, работа с YouTube Data API

К счастью у YouTube есть богатое API, позволяющее делать всякие поисковые запросы и получать сведения о каналах. URL видео надо еще откуда-то получить. Чтобы начать его использовать нужно подключить его в своей Developer Console и получить ключ.

Поиск выглядит как-то так, мы хотим искать каналы и плейлисты по запросу "Peppa Pig". Для работы приложения нам нужны две функции: поиск каналов и получение списка видео для данного канала. Нас интересует id (чтобы в дальнейшем скачивать список видео для канала по его id) и snippet в нем содержатся основные данные о сущности: название, картинка-превью, описание.

YouTube.Search.List searchListByKeywordRequest = youTube.search().list("snippet,id"); searchListByKeywordRequest.setMaxResults(10L); searchListByKeywordRequest.setQ("Peppa Pig"); searchListByKeywordRequest.setType("channel,playlist"); searchListByKeywordRequest.setKey("<api key>"); SearchListResponse response = searchListByKeywordRequest.execute();

YouTube API использует довольно сложную систему лимитирования запросов: по умолчанию ежедневная квота составляет миллион единиц, но при этом один запрос может потреблять много единиц. Важно правильно задавать список тех частей объекта (в данном случае это snippet и id) которые мы хотим получать. Запросы на чтение данных потребляют одну единицу квоты сами по себе, плюс по две единицы на каждый фрагмент данных. Больше всего потребляют запросы записывающие что-то (заливающие видео, или меняющие плейлисты), но читающие запросы могут тоже потреблять немало. например вот этот вот запрос что указан выше потребляет 5 единиц (одну за сам запрос и по 2 за фрагменты sinppet и id). Т.е. Для видео доступны 10 фрагментов, так что полный запрос съест 21 единицу квоты. А полный запрос всех данных о канале, у которого 6 фрагментов, съел бы 13. Поэтому имеет смысл запрашивать только то, что вам нужно.

Запрос на получение списка видео из канала выглядит вот так:

YouTube.Search.List request = youTube.search().list("snippet,id");
request.setChannelId("<channel id>");
request.setType("video");
request.setMaxResults(50L);
request.setKey("<api key>");
SearchListResponse response = request.execute();

Несколько неочевидно сделано разбиение ответа на страницы, вместо того чтобы явно указывать номер страницы и количество результатов, в ответе может присутствовать параметр nextPageToken, если он есть — значит впереди еще есть страницы, надо поместить этот параметр в объект запроса и выполнить запрос еще раз.

if (response.getNextPageToken() != null) { request.setPageToken(response.getNextPageToken()); response = request.execute();
}

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

Опыт использования

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

  1. Кроме каналов понадобились и плейлисты. Так как на одном канале зачастую нормальные видео совмещались с адовым трешем. Например на "Теремок ТВ" есть неплохие мультики про царевну и всякая вырвиглазная хрень ("бибика" или "доктор машинкова"), из-за которых добавлять канал целиком не хотелось.
  2. А потом — еще и отдельные видео. Например есть каналы, где есть подборки типа "все серии мультсериала в одном видео", и опять же хочется выбрать отдельные видео, а не канал целиком.
  3. Понадобился возврат назад к предыдущему видео. Ибо истерика ребенка, который случайно ткнул пальцем в следующе видео и уже не может вернуться назад к тому, которое только что смотрел — это не шутки.
  4. Сейчас я понял что нужен еще и поиск. Потому что "хочу мультик про машинки и приведение", а поиска пока в приложении нет, а тыкать пальцем в надежде что рандом таки выдаст этот чертов мультик можно долго.
  5. Про отключение кнопки просмотра на ютубе я уже выше писал.
  6. Еще хочется прикрутить Pinned Mode — начиная с пятого андроида можно сделать так, что чтобы свернуть приложение надо было нажать и подержать несколько кнопок сразу.

А я пока потихоньку допиливаю новые фичи по реквестам, ну и радуюсь что теперь могу быть уверен в качестве того, что мой сын смотрит. Если идея кому-то приглянулась — https://play.google.com/store/apps/details?id=ru.sundogs.youtubekiosk В бесплатной версии можно добавить только три канала, пишите в личку — дам ключ на снятие ограничения.

Планшет и мультфильмы — лишь один из возможных инструментов развлечения ребенка, но при этом один из наиболее сложно управляемых. И нет, он не просиживает дни напролет за планшетом, а скорее предпочитает прогулки и активные игры, прятки-догонялки и рисование на всем подряд (от обоев до игрушек), а вечером любит слушать сказки. С чем отчасти и призвано бороться мое приложение.

Так что если вам пишет что ключ уже истек или не найден — пишите, пришлю новый. UPD: Много кто попросил ключи, я мог случайно перепутать и отправить один ключ нескольким людям. Ключ надо вводить в Play Market в разделе "Промокоды"

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть