Всем привет! Меня зовут Антон, я ведущий разработчик в одной из команд мобильной разработки в компании DD Planet. В этой статье поделюсь личным опытом и опытом нашей команды по прохождению ревью в магазин приложений Google Play на примере реального бизнес‑кейса.

Последствия санкций в современной мобильной разработке в России

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

  • подсанкционных российских банков, таких как «Сбер», «Тинькофф», «Альфа‑Банк» и др.;

  • авиакомпаний «Аэрофлот», «Utair», «S7»;

  • других сервисов: «РЖД Пассажирам», «СберМаркет», «Ситидрайв.

Список удаленных приложений постоянно пополняется. В этой связи компании обращают внимание на альтернативные магазины приложений, такие как хорошо известный Huawei App Gallery или развивающийся RuStore, но их доля на рынке все еще невелика. Людям по‑прежнему удобнее и привычнее пользоваться приложениями магазинов‑гигантов, и, вероятно, эта тенденция не скоро изменится.

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

Борьба с Google и новые требования к обновлению приложений. В каких случаях обновление могут не пропустить. Наш кейс.

На протяжении последних лет Google периодически ужесточает требования к обновлениям приложений. Кроме требования к регулярному повышению целевой версии Android API, сюда добавляется заполнение формы данных безопасности (Data Safety). Здесь разработчики должны подробно описать, какие данные они запрашивают у пользователей, хранят в приложении, передают сторонним сервисам и с какой целью.

По каждому типу данных, например:

  • данные авторизации,

  • фотографии/видео,

  • контакты,

  • геолокация,

  • платежные данные и др.,

нужно указать подробное описание. Также ужесточаются требования к запрашиваемым приложениями разрешениям. Например, если приложение запрашивает доступ к конфиденциальной информации или разрешения с высоким уровнем риска (например, доступ к SMS или списку вызовов), вам потребуется заполнить форму «Декларация разрешений» и получить одобрение Google Play.

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

Рассмотрим пример с данными геолокации

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

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

Но во время очередного релиза мы обнаружили, что обновление отклонено. По словам Google, наше приложение злостно собирает данные геолокации пользователей в фоне, не уведомляя их об этом и не спрашивая разрешения. Мы стали разбираться и обнаружили, что в старых версиях Яндекс Метрики по умолчанию действительно включена опция сбора данных о геолокации устройства. А начиная с нативной версии библиотеки 5.0.0 она была по умолчанию выключена разработчиками.

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

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

В письме Google снова явно упоминалась Яндекс Метрика с предложением удалить ее из приложения или обновить до версии 5.0.0.

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

И вновь получили точно такое же письмо с требованиями обновить или удалить Яндекс Метрику. Но в приложении уже была обновленная версия.

Опыт общения со службой поддержки Google Play. Есть ли шанс добиться успеха при апелляции?

Тут мы перестали понимать, чего от нас хочет Google, и решили обратиться в службу поддержки Google Play за разъяснениями. Для этого есть два способа:

  • онлайн‑чат с сотрудником,

  • обращение по email.

Как показала практика, онлайн‑чат работает нестабильно, часто не бывает свободных сотрудников. К тому же ранее у нас уже был неудачный опыт общения с оператором по другой проблеме — решить вопрос в чате тогда не удалось. Специалист на все наши вопросы и доводы отвечал одними и теми же шаблонными фразами.

Поэтому в этот раз мы решили сразу подавать апелляцию на решение Google с помощью email.

Мы написали подробное, обстоятельное письмо, в котором указали, что обновили Яндекс Метрику до необходимой версии 5.0.0, и попросили разъяснить, какие еще изменения нам необходимо внести в соответствии с политикой Google.

Довольно быстро получили ответ. Он был как под копирку. В ответе снова предлагалось обновить версию Yandex Metrica SDK или избавиться от нее совсем.

Мы решили проверить гипотезу: вдруг Google действительно не нравится сам SDK. Полностью удалили из приложения Яндекс Метрику и все ее упоминания. Пересобрали сборку и стали ждать ревью. Через некоторое время уже ожидаемо получили то же самое письмо о наличии в приложении SDK, нарушающего политику Google.

В ответ на него мы подали новую апелляцию. В письме подробно разъяснили, что с данным обновлением из приложения полностью удалена Yandex.Metrica SDK. Таким образом, наше приложение никоим образом не собирает данные о геолокации пользователей. Как говорится, «программа не запускается ввиду отсутствия компьютера».

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

Причины отклонения сборки. Как Google Play анализирует файл .AAB и что ему может не понравиться.

У нас возникла новая гипотеза: возможно, мы все‑таки не до конца удаляем Яндекс Метрику, а какие‑то ее части/метаданные, оставшиеся в сборке, указывают Google на ее наличие. Google Play анализирует файл сборки в автоматическом режиме, находит эти указания и отклоняет сборку.

В случае с обновлением Yandex.Metrica SDK до версии 5.0.0, возможно, какие‑то оставшиеся метаданные указывают на его старую версию. Или Google не устраивает обертка над нативной библиотекой под Xamarin.

Чтобы попытаться найти такие метаданные, мы решили покопаться во внутренностях сборки. Для декомпиляции.APK‑файла использовали общедоступную утилиту apktool.

Выполняем команду:

apktool ‑d <path to APK file>/app.apk

В результате получаем папку с файлами внутренностей сборки:

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

В итоговом файле манифеста также были прописаны сервисы, необходимые для работы Метрики. В сборке без Yandex.Metrica SDK их не было.

<service android:enabled="true" android:exported="false" android:name="com.yandex.metrica.MetricaService" android:process=":Metrica">
   <intent-filter>
      <category android:name="android.intent.category.DEFAULT"/>
      <action android:name="com.yandex.metrica.IMetricaService"/>
      <data android:scheme="metrica"/>
   </intent-filter>
   <meta-data android:name="metrica:api:level" android:value="105"/>
</service>
<service android:enabled="true" android:exported="false" android:name="com.yandex.metrica.ConfigurationService" android:process=":Metrica">
   <meta-data android:name="metrica:configuration:api:level" android:value="3"/>
   <intent-filter>
      <action android:name="com.yandex.metrica.configuration.ACTION_INIT"/>
   </intent-filter>
</service>

Ну и, наконец, в сборке с Метрикой нужной версии (5.0.0) присутствовали:

  • все необходимые файлы библиотек, скомпилированные в нативный формат .so,

  • декомпилированные исполняемые файлы в формате .smali.

В сборке без Yandex.Metrica SDK их не было.

Из всего вышеперечисленного можно было сделать следующие выводы:

  • сборка с удаленной Яндекс Метрикой действительно не содержит никаких ее следов;

  • сборка с оберткой Метрики под Xamarin содержит все необходимые файлы и конфигурационные настройки для ее работы.

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

Тем временем, пока мы экспериментировали, над нашим приложением нависла угроза реального удаления из Google Play. На странице приложения в Google Play Console появился баннер о необходимости внести исправления в течение 14 календарных дней, иначе приложение будет удалено из стора. Получалось так, что Google Play не только не нравилось наше обновление в любом виде (с Метрикой версии 5.0.0 или вовсе без нее), но и не нравилась наша Production‑версия приложения по причине наличия в ней устаревшей версии Метрики 2.3.0. С этого дня Production‑версия также объявлялась нарушителем политики Google и подлежала удалению. Спасти ситуацию было призвано обновление, которое, однако, Google не пропускал по той же самой причине. Замкнутый круг.

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

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

Через некоторое время в ответ пришло письмо, которое несколько отличалось от стандартных предыдущих писем. В нем по‑прежнему сообщалось о нарушении политики Location Permissions из‑за наличия в приложении Yandex Metrica SDK.

Но на этот раз упор был сделан именно на Production‑версию приложения, которую мы и стремились обновить:

“Before resubmitting your app for further review, please make sure to deactivate the non‑compliant App Bundle Version: 649, Track: Production and increment the version code of app bundle in the Production / Open test / Closed test / Internal test track”.

В тексте письма предлагалось деактивировать несоответствующую политике Google Productionверсию приложения, а совместимое обновление загрузить во все треки Google Play:

  • открытое тестирование (альфа),

  • закрытое тестирование (бета),

  • внутреннее тестирование.

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

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

Был предложен следующий алгоритм действий:

  1. Мы сами снимем приложение с публикации, тем самым деактивируем его Production‑версию.

  2. Приложение перестанет быть доступным пользователям.

  3. После этого мы загрузим обновление (сборку без Yandex Metrica SDK) во все треки Google Play на ревью.

  4. Как только сборка пройдет ревью, мы заново опубликуем приложение в сторе.

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

Бизнес просил дать гарантии того, что наше решение сработает. Что после добровольного снятия приложения с публикации Google одобрит новую сборку и пустит нас обратно. Но таких гарантий мы дать не могли. Для нас ситуация была абсолютно новой и незнакомой. В документации полного и ясного описания на такой случай не было. Но и другого варианта решения проблемы тоже не было. До удаления приложения из стора самим Google в соответствии с предупреждением оставалось менее недели. Кто‑то из представителей бизнеса уже даже начал принимать мысль о том, что нам придется распрощаться с Google Play и активнее переходить на другие сторы, запускать рекламные кампании по продвижению приложения в них. Мы объяснили, что в процессе снятия с публикации и прохождения ревью приложение продолжит работу у тех пользователей, у кого оно уже было установлено. И в итоге получили зеленый свет.

Приложение было снято с публикации и на время прохождения ревью новой сборкой перестало быть доступно новым пользователям. В какой‑то момент менеджеры со стороны бизнеса начали бить тревогу, но весь процесс прохождения ревью занял не больше суток. Ревью было успешно пройдено и мы заново опубликовали сборку без Яндекс Метрики в Production. Немного позднее мы отправили на ревью новую сборку с необходимой версией Метрики 5.0.0, и она тоже в течение суток успешно его прошла.

Почти месяц нашей борьбы с Google увенчался успехом!

Выводы и рекомендации по прохождению ревью в Google Play:

  • Необходимо обязательно отслеживать изменения в требованиях к обновлениям приложений и к активным Production‑сборкам. Обращать внимание на появление в Google Play Console информационных сообщений в виде баннеров.

  • При отклонении сборки на ревью или появлении баннеров с предупреждениями сразу же обращаться в службу поддержки. Как правило, на исправление подобных проблем Google отводит разработчикам от нескольких недель до нескольких месяцев.

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

  • Если вам кажется, что технически вы исполнили все требования Google, но сборку по‑прежнему отклоняют, можно проанализировать содержимое с помощью утилит (например, apktool). В первую очередь стоит обращать внимание на итоговый Android.manifest‑файл и файлы метаданных (assemblies.manifest и др.).

  • При обновлении приложения следить за тем, чтобы помимо Production‑версии ни в одном из треков (Открытое тестирование, Закрытое тестирование, Внутреннее тестирование) у вас не оставалось старых версий сборок, нарушающих политику Google. Потому что обновление Production‑сборки может быть отклонено при наличии старой несовместимой сборки в каком‑либо из треков. А явного указания на это в сообщениях/письмах Google может не быть.

  • Быть готовыми к процедуре снятия приложения с публикации и его временного отсутствия в сторе для новых пользователей, если проблема будет в Production‑сборке, а обновить ее стандартным способом не удастся. Разъяснять бизнесу возможную необходимость такого шага.

Желаю вам всегда безболезненного и легкого процесса прохождения ревью в любые сторы! Были ли у вас такие ситуации? Есть ли способ прохождения ревью без удаления приложения из Google Play в таких случаях?