· Разработчикам · 6 мин чтения

Обновление листинга Play Store через Google Play Developer API

Обновление листинга Play Store через Google Play Developer API
TL;DR. Обновление листинга Play через Android Publisher API — это одна транзакция. Ты открываешь edit (edits.insert), меняешь текст листинга и изображения внутри него (edits.listings.update, edits.images.upload), затем вызываешь edits.commit, чтобы проверить и опубликовать изменения — или edits.abandon, чтобы отменить их. Ничего не публикуется до commit. Авторизация выполняется через сервисный аккаунт Google Cloud, и есть один шаг, на котором спотыкаются почти все: сервисный аккаунт нужно пригласить именно в Play Console, а не просто назначить ему роль в Google Cloud IAM.

Google Play Developer API (его официальное название — Android Publisher API) позволяет менять листинг в сторе — название, описания, скриншоты, feature graphic — не открывая Play Console. Это то, что нужно, если ты отправляешь локализованные тексты из CMS, синхронизируешь скриншоты из билд-пайплайна или обновляешь листинги на десятках языков сразу. Ниже — полный процесс, как сделать это правильно, включая нюансы, которые в официальной документации спрятаны глубоко.

Edit — это транзакция, а не набор прямых изменений

Модель, которая избавит тебя от большинства проблем: ты никогда не редактируешь живой листинг напрямую. Ты открываешь edit — приватную черновую копию текущего опубликованного состояния приложения: листинги, изображения, треки — всё копируется туда. Все изменения ты вносишь в эту копию. Затем ты фиксируешь всё сразу одним commit — либо отменяешь, и ничего не происходит.

Формулировка самого Google предельно прямая: «Changes made within an edit are not live until the edit is committed» («Изменения внутри edit не публикуются, пока edit не зафиксирован»). При commit, если ошибок валидации нет, все изменения в edit публикуются одновременно, заменяя текущее состояние. Если валидация не проходит, API выбрасывает ошибку, а живой листинг остаётся нетронутым. Итого, жизненный цикл — ровно четыре шага:

  • edits.insert — создать edit, получить editId.
  • измененияedits.listings.update для текста по каждому языку, edits.images.upload / deleteall для скриншотов и графики.
  • edits.commit — проверить всё, затем опубликовать атомарно.
  • edits.abandon — отбросить черновик, живой листинг не меняется.

Важное ограничение, которое стоит учитывать в архитектуре: у аккаунта может быть открыт только один edit одновременно, и если кто-то зафиксирует edit или изменит приложение через интерфейс Play Console, все остальные открытые edit'ы для этого приложения станут недействительными. Относись к edit как к короткоживущей сущности — открыл, записал, зафиксировал. Не держи его открытым часами, пока человек кликает в консоли.

Авторизация: сервисный аккаунт плюс приглашение, о котором все забывают

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

  1. Google Cloud. Создай сервисный аккаунт, включи Google Play Android Developer API в проекте и скачай JSON-ключ. Единственный нужный scope — https://www.googleapis.com/auth/androidpublisher.
  2. Play Console. Перейди в раздел Users & permissions, нажми Invite new users, вставь email сервисного аккаунта (адрес вида ...@...iam.gserviceaccount.com) и предоставь доступ к приложению. Только после этого ключ сможет работать с твоим листингом.

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

Четыре вызова в виде REST

Обновление текста листинга

edits.listings.update — это PUT, то есть полная замена листинга для данного языка. Всё, что ты отправишь, становится листингом; поля, которые ты не укажешь, будут очищены, а не сохранены. Поэтому, если нужно изменить только краткое описание, всё равно придётся отправить и название, и полное описание — иначе они будут стёрты. Когда действительно нужно частичное изменение, есть отдельный метод edits.listings.patch, который объединяет только переданные поля. Для большинства пайплайнов полный PUT удобнее — ты и так формируешь весь листинг из своего источника истины, так что заменить его целиком — правильное решение.

Три текстовых поля и их лимиты: title — до 30 символов, shortDescription — до 80, fullDescription — до 4000. Один ресурс листинга на язык, определяемый тегом языка BCP-47 в URL (en-US, de-DE, ja-JP и так далее). Чтобы обновить десять языков, ты делаешь десять вызовов listings.update внутри одного edit — затем один commit публикует их все вместе.

Загрузка скриншотов и feature graphic

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

  • phoneScreenshots, sevenInchScreenshots, tenInchScreenshots — наборы скриншотов для телефона и планшета.
  • tvScreenshots, wearScreenshots — Android TV и Wear OS.
  • featureGraphic — баннер 1024×500, показываемый в верхней части листинга.
  • icon, tvBanner — значок приложения и баннер для TV.

edits.images.upload добавляет в edit одно изображение заданного языка и типа. Метода «задать весь массив целиком» не существует, поэтому надёжный способ заменить скриншоты — сначала вызвать edits.images.deleteall для этого языка и типа изображения, а затем загрузить новый набор в том порядке, в котором они должны отображаться. edits.images.list показывает, что сейчас находится в edit, а edits.images.delete удаляет одно изображение по id, если нужны точечные изменения. Всё это остаётся внутри edit до момента commit.

Commit — и что на самом деле значит «опубликовано»

Несколько моментов, в которых стоит быть точным, потому что они удивляют людей:

  • Новая сборка не требуется. Commit edit'а, затрагивающего только листинг, не требует свежего APK/AAB. Текст и изображения — это метаданные; их можно обновлять сколько угодно раз для уже существующего релиза (нужен лишь тот единственный предыдущий релиз).
  • Commit сначала проверяет, потом публикует. Если у скриншота неверные размеры или поле слишком длинное, commit завершится ошибкой, а живой листинг не изменится — ты исправляешь и повторяешь commit.
  • Публикация не мгновенная. После успешного commit изменения могут появиться спустя несколько часов — так же, как и при ручном редактировании в Play Console. Не считай код 200 при commit признаком того, что изменения уже видны пользователям.
  • Отмена ничего не стоит. Если пробный запуск выглядит неправильно, edits.abandon отбрасывает черновик без каких-либо последствий для живого листинга. Удобно для проверки пайплайна без риска.

Путь без кода: дизайн, перевод, публикация

Описанный выше API — правильный инструмент, если у тебя есть время инженеров и источник истины для синхронизации. Чего он не делает — так это не создаёт сами материалы. Тебе всё равно нужно спроектировать скриншоты, написать название и оба описания и подготовить всё это на каждом языке — API лишь публикует то, что ты ему передашь.

Именно эту часть берёт на себя Mokbi. Ты проектируешь скриншоты прямо в браузере, тут же составляешь название, краткое и полное описание и переводишь весь листинг на 50 языков за один проход — так что для десяти вызовов listings.update выше у тебя уже есть настоящий, локализованный текст вместо заглушек.

А сама публикация? Mokbi делает и это. Для Google Play под капотом выполняется ровно этот процесс (edits.insertlistings.update → загрузка изображений → commit), так что твой локализованный листинг и материалы публикуются без единой строки кода, описанного выше. Для App Store Mokbi подготавливает версию в App Store Connect, полностью заполненную и готовую к отправке — Apple требует, чтобы финальный Submit нажимал ты сам и проходил проверку. Проектирование скриншотов и feature graphic, написание листинга, перевод на 50 языков и публикация — это один непрерывный процесс.

Что читать дальше

Открыть редактор →