ЧатЯдро подано в RuStore 7 августа 2026, отклонено 11-го, пересобрано в тот же вечер и опубликовано 16-го. Ниже — что именно пришлось узнать по дороге. Документация магазина в день подачи отдавала 429, так что половина лимитов выяснилась только в живой форме.
Форма подачи: пять шагов и их ловушки
Загрузка версии в консоли RuStore — это пять экранов: Файлы → Безопасность → Информация → Медиафайлы → Параметры публикации. Проходили их по одному, с проверкой каждого поля, и ни разу не пришлось возвращаться. Что стоит знать заранее:
Файлы. Комментарий для модератора ограничен 180 символами. Заготовленный текст на тысячу знаков не влез. Единственное, что туда действительно нужно уместить, — данные тестового входа. Всё остальное уходит в «Обоснование» на следующем шаге, где места 1500. Подпись для AAB не нужна, если грузите APK.
Безопасность. «Типы собираемых данных» — 38 чекбоксов, мы отметили 17. Разрешения консоль вытаскивает из APK сама и показывает списком. Обоснование чувствительных разрешений — до 1500 символов.
Информация. Краткое описание — 80 символов, полное — 4000. Категории «Социальные сети» в RuStore нет вообще; из двадцати доступных единственный честный вариант для платформы сообществ — «Общение». Поисковые теги — только из готового списка, свои слова вписать нельзя, максимум пять. Вторую категорию сознательно не ставили: любая дополнительная обещает то, что у нас работает только внутри сообщества, а это путь к плохим отзывам на старте.
Медиафайлы. Иконка 1:1, до 512 пикселей. Скриншотов от трёх до десяти, и ориентацию всей витрины задаёт первый файл. Видео нельзя загрузить файлом — только ссылкой на VK Видео. Полей два, и их легко перепутать: верхнее «Видео» принимает 16:9 и 9:16, а «Фоновое видео для карточки» — только горизонтальное, и вертикальную ссылку отвергает невнятным «Проверьте правильность ввода». Мы на этом месте сначала решили, что магазин вообще не принимает клипы. Принимает, просто не в том поле.
Параметры публикации. «Автоматически, сразу после одобрения», если релиз не привязан к дате.
Отдельная деталь про тестовый аккаунт для модератора. Его лучше завести заранее и проверить вход, потому что на бэкенде стоит лимит попыток входа с одного IP. Модератор, упёршийся в него, решит, что приложение не работает.
Отказ 11 августа
Модератор написал: для публикации нужно быть зарегистрированным в реестре операторов персональных данных, подтверждение — на почту поддержки. Само приложение при этом не смотрели.
Формально это был не отказ приложению, а запрос документа: в реестре мы были с 24 июля, за две недели до подачи, просто в консоли нет поля, куда это вписать. Отправили выписку из реестра и скриншот проверки статуса. Побочная находка: поиск по реестру Роскомнадзора по ИНН физлица ничего не находит, работает только прямая ссылка на запись.
Поддержка подтверждение приняла и попросила отправить приложение повторно. И тут второе правило магазина: тот же versionCode повторно не принимается. Пришлось собирать новую версию.
Пересборка из боевого коммита
Проблема в том, что за четыре дня в бете накопились правки, которые ни разу не собирались в релизный APK. Тащить их в магазин вслепую не хотелось. Решение: отдельная рабочая копия (git worktree) на боевом коммите, в ней поднят только номер версии, и из неё собрана сборка 462. Набор разрешений проверен и совпал с 461 один в один.
Сама сборка для магазина отличается от обычной четырьмя вещами, и они зашиты в отдельный скрипт:
--dart-define=DISTRIBUTION=rustoreотключает собственный апдейтер. Обновления в магазине ставит магазин, а свой механизм обновления внутри — известная причина отказов на модерации.- Из манифеста вырезается
REQUEST_INSTALL_PACKAGES: у модератора закономерный вопрос, зачем приложению право устанавливать другие приложения. - Версия не поднимается автоматически, иначе номера в магазине и на сайте разойдутся.
- Веб не собирается: RuStore принимает только APK.
Две ловушки в самом скрипте. Первая: без flutter clean Flutter может взять из кэша Dart-код,
собранный без флага, то есть с живым апдейтером внутри, и снаружи это не видно. Вторая: папку
build/ сносит любая следующая сборка. Собранный для магазина APK однажды был стёрт сборкой
беты через полчаса. Теперь скрипт сразу копирует файл наружу и кладёт рядом sha256.
Как проверять APK: не grep
За час до подачи я дважды ошибся одинаково — искал строки внутри libapp.so и делал из находки
вывод.
Первый раз искал версию 1.8.74 (461) и не нашёл: чуть не объявил сборку испорченной. На деле
версия собирается в рантайме из двух констант, целой строки в файле нет. Второй раз вытащил из
APK все строки вида android.permission.*, увидел DUMP и предложил его убирать. Оказалось,
это не запрошенное разрешение, а защита нашего же компонента: атрибут android:permission у
приёмника AndroidX ProfileInstaller. В том же разборе я пропустил два настоящих разрешения.
Правильные инструменты:
| Что проверяем | Чем |
|---|---|
| Версия, имя пакета | aapt2 dump badging app.apk, строка package: |
| Запрошенные разрешения | uses-permission из объединённого манифеста в build/…/merged_manifest/, разбором XML, не grep: бывают многострочные теги и maxSdkVersion |
| Кто добавил разрешение | manifest-merger-release-report.txt |
| Отключён ли апдейтер | по отсутствию строк, которые есть только в обычной сборке: адрес version.json и имя файла обновления. Компилятор выбрасывает мёртвый код вместе с адресами |
| Иконка | вскрытием, по размеру ресурса |
Ключевое различие, которое я тогда не держал в голове: <uses-permission android:name="X">
значит «прошу право X», а android:permission="X" внутри <receiver> или <service> значит
«до меня можно достучаться, только имея X». Второе у пользователя не спрашивается и в карточке
магазина не показывается.
И общее правило: если проверка дала неожиданный результат, сначала усомниться в проверке, и только потом в сборке.
После публикации
Модерацию прошли 16 августа. Больше половины новых участников в следующие дни пришли из магазина, без рекламы: это видно по версии сборки в журналах сервера.
Есть и обратная сторона: люди из RuStore не получают обновления с сайта, только из магазина. К началу сентября они отстали от беты на одиннадцать версий, и каждый релиз теперь нужно подавать в магазин отдельно. Форма при повторной подаче заполняется без правок, разрешения и описание остаются с прошлой версии, но модерация занимает дни.
Ещё один эффект магазина всплыл у пользователя, переустановившего приложение: Android вернул
из резервной копии зашифрованные данные, а ключ шифрования выдал новый, и приложение открылось
белым экраном. Лечится allowBackup="false" в манифесте и защитой на чтение хранилища.
Что бы я сделал иначе
- Завёл бы регистрацию в реестре операторов ПД в чек-лист подачи, рядом с иконкой и скриншотами, и приложил бы выписку в комментарий модератору сразу.
- Написал бы скрипт проверки APK до первой подачи, а не после двух ошибок.
- Не тратил бы день на вопрос «принимает ли магазин вертикальное видео». Принимает.