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

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

В игре коты появляются с трехзначными числами. Теоретически котов может быть 1000 штук от 000 до 999 (на самом деле нет, в программе используется другой алгоритм, но для нас это не принципиально).

Мне стало интересно, как они хранятся в приложении. Поиск в интернете привел меня на ресурс, где выложены исходники пасхального яйца Easter Egg.

Позже на Гитхабе я нашел модифицированный код, который позволяет запускать игру как обычное приложение на любом устройстве, а не только на Android 7. Собранную версию из этих исходников можно найти Google Play по ключевым словам Neko Collector.

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

Было не трудно догадаться, что основная магия происходит в классе Cat.

Усы, лапы, хвост — вот мои документы


Оказалось, что коты не хранятся в приложении в виде отдельных картинок. Вполне объяснимо, большое количество изображений раздует программу. В папке drawable в виде векторных ресурсов хранятся отдельные части кота. Например, так хранится хвост в файле tail.xml.


Аналогичным образом хранятся лапы, глаза, туловище, ошейник, бантик и т.д. А затем всё это собирается в конструкторе внутреннего класса CatParts

        CatParts(Context context) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                body = context.getDrawable(R.drawable.body);
                head = context.getDrawable(R.drawable.head);
                leg1 = context.getDrawable(R.drawable.leg1);
                leg2 = context.getDrawable(R.drawable.leg2);
                leg3 = context.getDrawable(R.drawable.leg3);
                leg4 = context.getDrawable(R.drawable.leg4);
                tail = context.getDrawable(R.drawable.tail);
                leftEar = context.getDrawable(R.drawable.left_ear);
                rightEar = context.getDrawable(R.drawable.right_ear);
                rightEarInside = context.getDrawable(R.drawable.right_ear_inside);
                leftEarInside = context.getDrawable(R.drawable.left_ear_inside);
                faceSpot = context.getDrawable(R.drawable.face_spot);
                cap = context.getDrawable(R.drawable.cap);
                mouth = context.getDrawable(R.drawable.mouth);
                foot4 = context.getDrawable(R.drawable.foot4);
                foot3 = context.getDrawable(R.drawable.foot3);
                foot1 = context.getDrawable(R.drawable.foot1);
                foot2 = context.getDrawable(R.drawable.foot2);
                leg2Shadow = context.getDrawable(R.drawable.leg2_shadow);
                tailShadow = context.getDrawable(R.drawable.tail_shadow);
                tailCap = context.getDrawable(R.drawable.tail_cap);
                belly = context.getDrawable(R.drawable.belly);
                back = context.getDrawable(R.drawable.back);
                rightEye = context.getDrawable(R.drawable.right_eye);
                leftEye = context.getDrawable(R.drawable.left_eye);
                nose = context.getDrawable(R.drawable.nose);
                collar = context.getDrawable(R.drawable.collar);
                bowtie = context.getDrawable(R.drawable.bowtie);
            } else {
                // здесь код для старых версий
            }
            drawingOrder = getDrawingOrder();
        }

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

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


Определённо стоит покопаться в коде приложение и изучить другие методы. Например, когда вы хотите поделиться пойманным котом в социальных сетях, то генерируется отдельное изображение PNG размером 512х512 хорошего разрешения на устройствах не ниже Android 6.0 Marshmallow. На старых устройствах изображение формируется через другой метод, и картинки получаются смазанными.

Для сравнения первая картинка, которую я получил на эмуляторе Android 7.


А это картинка, полученная на устройстве Android 4.4.2


Тем, кто изучает программирование под Android, пригодятся приёмы запуска служб с регистрацией планировщика JobSheduler, создание диалогов, использование SharedPreferences.

На мой взгляд, пасхалка получилась красивая и подняла мне настроение.
Собирайте котиков!
Поделиться с друзьями
-->

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


  1. Iqorek
    28.10.2016 00:24
    +1

    Дизайнер котов — гений, я не сразу заметил, что контур кота совпадает с лого андроида


  1. mr-cpp
    28.10.2016 11:26

    По-моему, сыроватой пасхалка получилась. То, что есть в релизной версии, уже присутствовало начиная с developer preview. Ощущение, что не стали заморачиваться под конец этим просто
    Особенно мне не нравятся два смайлика под буквой N на главном экране. Очень мелкие, сложно разглядеть
    Хотя идея и реализация котиков впечатлила. Спасибо!


  1. rostopira
    29.10.2016 07:33

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


    1. tehnolog
      29.10.2016 07:34

      Речь идёт не о самих векторах в приложении (там все в порядке), а сохранении вектора в PNG. Для этой цели используется класс android.graphics.drawable.Icon, который появился в API 23.
      Хотя может действительно криво реализовано, я не изучал этот вопрос.