Перейти к основному содержимому

SDK обновлений для Godot (версия 6.0.0)

Общие сведения

RuStore In-app updates SDK поддерживает актуальную версию приложения на устройстве пользователя. Это помогает пользователю увидеть обновления, оценить улучшение производительности и результат исправления ошибок.

Пример реализации

Используйте RuStore In-app updates SDK для реализации различных способов обновлений. В настоящий момент поддерживаются: отложенное, тихое (без UI от RuStore) и принудительное обновление.

Ознакомьтесь с приложением-примером чтобы узнать, как правильно интегрировать SDK обновлений.

Пользовательские сценарии

Условия корректной работы SDK

Для работы RuStore In-app updates SDK необходимо соблюдение следующих условий.

  • Приложение загружено в Консоль RuStore.
  • Приложение прошло модерацию (публиковать приложение необязательно).
Важно
  • Подпись тестируемой сборки (например, debug) приложения должна совпадать с подписью сборки приложения, которая была загружена в консоль и прошла модерацию ранее (например, release).
  • ОС Android версии 7.0 или выше.
  • Версия RuStore на устройстве пользователя актуальная.
  • Пользователь авторизован в RuStore.
  • Приложению RuStore разрешена установка приложений.

Подключение в проект

предупреждение

Библиотеки плагинов в репозитории собраны для Godot Engine 4.2.1. Если вы используете другую версию Godot Engine, выполните шаги раздела Пересборка плагина.

  1. Скопируйте проекты плагина из официального репозитория RuStore на GitFlic.

  2. Скопируйте содержимое папки godot_example/android/plugins в папку your_project/android/plugins.

  3. В пресете сборки Android в списке Плагины отметьте строки Ru Store Godot App Update и Ru Store Godot Core.

Создание менеджера обновлений

Перед вызовом методов библиотеки необходимо создать менеджер обновлений.

Создание синглтона RuStoreGodotAppUpdateManager
var _appUpdate_client: RuStoreGodotAppUpdateManager = null

func _ready():
_appUpdate_client = RuStoreGodotAppUpdateManager.get_instance();

Проверка наличия обновлений

Прежде чем запрашивать обновление, проверьте, доступно ли обновление для вашего приложения. Для проверки наличия обновлений вызовите метод get_app_update_info. При вызове данного метода проверяются следующие условия.
  • На устройстве пользователя установлена актуальная версия RuStore.
  • Пользователь и приложение не должны быть заблокированы в RuStore.
  • Приложению RuStore разрешена установка приложений.
  • Пользователь авторизован в RuStore.

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

  • on_get_app_update_info_success;
  • on_get_app_update_info_failure.
Подписка на события
func _ready():
# Инициализация _appUpdate_client

_appUpdate_client.on_get_app_update_info_success.connect(_on_get_app_update_info_success)
_appUpdate_client.on_get_app_update_info_failure.connect(_on_get_app_update_info_failure)

func _on_get_app_update_info_success(response: RuStoreAppUpdateInfo):
pass

func _on_get_app_update_info_failure(error: RuStoreError):
pass
Вызов метода get_app_update_info
_appUpdate_client.get_app_update_info()
Обратный вызов (callback) on_get_app_update_info_success возвращает объект, который содержит информацию о необходимости обновления. Запросите информацию заранее, чтобы выполнить запуск скачивания обновления без задержки в удобный для пользователя момент времени.

Класс RuStoreAppUpdateInfo
class_name RuStoreAppUpdateInfo extends Object

var updateAvailability: ERuStoreUpdateAvailability.Item
var installStatus: ERuStoreInstallStatus.Item
var availableVersionCode: int

func _init(json: String = ""):
if json == "":
updateAvailability = ERuStoreUpdateAvailability.Item.UNKNOWN
installStatus = ERuStoreInstallStatus.Item.UNKNOWN
availableVersionCode = 0
else:
var obj = JSON.parse_string(json)
updateAvailability = int(obj["updateAvailability"])
installStatus = int(obj["installStatus"])
availableVersionCode = int(obj["availableVersionCode"])
  • updateAvailability — доступность обновления:

    • UNKNOWN (int == 0) — по умолчанию.
    • UPDATE_NOT_AVAILABLE (int == 1) — обновление не нужно.
    • UPDATE_AVAILABLE (int == 2) — обновление требуется загрузить или обновление уже загружено на устройство пользователя.
    • DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS (int == 3) — обновление уже скачивается или установка уже запущена.
  • installStatus — статус установки обновления, если пользователь уже устанавливает обновление в текущий момент времени:

    • UNKNOWN (int == 0) — по умолчанию.
    • DOWNLOADED (int == 1) — скачано.
    • DOWNLOADING (int == 2) — скачивается.
    • FAILED (int == 3) — ошибка.
    • PENDING (int == 5) — в ожидании.
  • availableVersionCode — код версии обновления.

к сведению

Запуск скачивания обновления возможен только в том случае, если поле updateAvailability содержит значение UPDATE_AVAILABLE.

Обратный вызов (callback) on_get_app_update_info_failure возвращает объект с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.

Скачивание и установка обновлений

Использование слушателя

После подтверждения доступности обновления (RuStoreAppUpdateInfo) вы можете получать статус скачивания обновления. Для этого необходимо выполнить подписку на событие on_state_updated и вызовом метода register_listener запустить слушатель статуса скачивания.

Проверка статуса скачивания обновления

Подписка на событие on_state_updated выполняется единожды. Прослушивание процесса скачивания активируется с помощью метода register_listener.

Запуск слушателя
func _ready():
# Инициализация _appUpdate_client

_appUpdate_client.on_state_updated.connect(_on_state_updated)
_appUpdate_client.register_listener()

func _on_state_updated(installState: RuStoreInstallState):
pass

Обратный вызов (callback) on_state_updated возвращает объект RuStoreInstallState с информацией о ходе процесса обновления.

Класс RuStoreInstallState
class_name RuStoreInstallState extends Object

var bytesDownloaded: int
var totalBytesToDownload: int
var percentDownloaded: float
var installStatus: ERuStoreInstallStatus.Item
var installErrorCode: ERuStoreInstallErrorCode.Item

func _init(json: String = ""):
if json == "":
bytesDownloaded = 0
totalBytesToDownload = 0
percentDownloaded = 0
installStatus = ERuStoreInstallStatus.Item.UNKNOWN
installErrorCode = ERuStoreInstallErrorCode.Item.ERROR_UNKNOWN
else:
var obj = JSON.parse_string(json)
bytesDownloaded = int(obj["bytesDownloaded"])
totalBytesToDownload = int(obj["totalBytesToDownload"])
installStatus = int(obj["installStatus"])
installErrorCode = int(obj["installErrorCode"])
if totalBytesToDownload > 0:
percentDownloaded = float(bytesDownloaded) / totalBytesToDownload * 100
else:
percentDownloaded = 0
if installStatus == ERuStoreInstallStatus.Item.DOWNLOADED:
percentDownloaded = 100
  • installStatus — статус установки обновления, если пользователь уже устанавливает обновление в текущий момент времени:

    • UNKNOWN (Int = 0) — по умолчанию;
    • DOWNLOADED (Int = 1) — скачано;
    • DOWNLOADING (Int = 2) — скачивается;
    • FAILED (Int = 3) — ошибка;
    • PENDING (Int = 5) — в ожидании;
ОБРАТИТЕ ВНИМАНИЕ

В SDK обновлений нет особого статуса для ситуации, когда пользователь отменил скачивание обновления. Если пользователь прервал обновление на этапе скачивания, installStatus возвращает исходный статус UNKNOWN (0) с кнопкой Скачать.

Если пользователь уже скачал обновление, но отменил установку, то installStatus вернёт значение DOWNLOADED (1).

Рассмотрим следующие варианты.

  • Пользователь начал скачивание обновления, но отменил скачивание — в этом случае:
    • updateAvailabilityUPDATE_AVAILABLE (2);
    • installStatusUNKNOWN (0).
  • Пользователь скачал файл обновления, но не стал его устанавливать — в этом случае:
    • updateAvailabilityUPDATE_AVAILABLE (2);
    • installStatusDOWNLOADED (1).
  • bytesDownloaded — количество загруженных байт;
  • totalBytesToDownload — общее количество байт, которое необходимо скачать;
  • packageName — имя пакета обновления;
  • installErrorCode — код ошибки во время скачивания. Коды ошибок описаны в разделе Обработка ошибок.

Удаление слушателя

Если необходимости в слушателе больше нет, воспользуйтесь методом удаления слушателя unregisterListener.

Вызов метода unregister_listener
_appUpdate_client.unregister_listener()

Запуск скачивания обновления

Отложенное обновление

Запуск сценария обновления

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

  • on_start_update_flow_success;
  • on_start_update_flow_failure.

Для запуска скачивания обновления приложения используйте метод start_update_flow_delayed.

к сведению

Объект RuStoreAppUpdateInfo после однократного использования становится невалидным. Для повторного вызова метода start_update_flow_delayed запросите объект RuStoreAppUpdateInfo повторно, используя метод get_app_update_info.

См. раздел Проверка наличия обновлений.

Подписка на события
func _ready():
# Инициализация _appUpdate_client

_appUpdate_client.on_start_update_flow_success.connect(_on_start_update_flow_success)
_appUpdate_client.on_start_update_flow_failure.connect(_on_start_update_flow_failure)

func _on_start_update_flow_success(flowResult: ERuStoreUpdateFlowResult.Item):
pass

func _on_start_update_flow_failure(error: RuStoreError):
pass
Вызов метода start_update_flow_delayed
_appUpdate_client.start_update_flow_delayed()

Обратный вызов (callback) on_start_update_flow_success возвращает перечисление ERuStoreUpdateFlowResult.Item с информацией о результате обновления:

  • RESULT_OK (int = -1) — пользователь подтвердил скачивание обновления;
  • RESULT_CANCELED (int = 0) — пользователь отказался от скачивания обновления.

Обратный вызов (callback) on_start_update_flow_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки RuStoreError описана в разделе Обработка ошибок.

После получения статуса ERuStoreUpdateFlowResult.Item.DOWNLOADED в поле installStatus объекта RuStoreInstallState, должен быть вызван метод установки обновления.

Принудительное обновление

Запуск сценария обновления

После получения успешного ответа от get_appupdateinfo можно проверить доступность принудительного обновления, используя метод check_is_immediate_update_allowed.

Вызов метода check_is_immediate_update_allowed
# Инициализация _appUpdate_client

var isAvailable: bool = _appUpdate_client.check_is_immediate_update_allowed()
  • true — принудительное обновление доступно.
  • false — принудительное обновление недоступно.

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

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

  • on_start_update_flow_success;
  • on_start_update_flow_failure.

Для запуска скачивания обновления приложения используйте метод start_update_flow_immediate.

к сведению

Объект RuStoreAppUpdateInfo после однократного использования становится невалидным. Для повторного вызова метода start_update_flow_immediate запросите объект RuStoreAppUpdateInfo повторно, используя метод get_app_update_info.

Подписка на события
func _ready():
# Инициализация _appUpdate_client

_appUpdate_client.on_start_update_flow_success.connect(_on_start_update_flow_success)
_appUpdate_client.on_start_update_flow_failure.connect(_on_start_update_flow_failure)

func _on_start_update_flow_success(flowResult: ERuStoreUpdateFlowResult.Item):
pass

func _on_start_update_flow_failure(error: RuStoreError):
pass
Вызов метода start_update_flow_immediate
_appUpdate_client.start_update_flow_immediate()

Обратный вызов (callback) on_start_update_flow_success возвращает перечисление ERuStoreUpdateFlowResult.Item с информацией о результате обновления:

  • RESULT_OK (int = -1) — обновление выполнено, код может быть не получен, т.к. приложение в момент обновления завершается;
  • RESULT_CANCELED (int = 0) — флоу прервано пользователем или произошла ошибка. Предполагается, что при получении этого кода, следует завершить работу приложения.
  • ACTIVITY_NOT_FOUND (int = 2) — RuStore не установлен, либо установлена версия, которая не поддерживает принудительное обновление (RuStore versionCode < 191).

Обратный вызов (callback) on_start_update_flow_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки RuStoreError описана в разделе Обработка ошибок.

При успешном обновлении дальнейших действий не требуется.

Тихое обновление

Запуск сценария обновления

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

  • on_start_update_flow_success;
  • on_start_update_flow_failure.

Для запуска скачивания обновления приложения используйте метод start_update_flow_silent.

к сведению

Объект RuStoreAppUpdateInfo после однократного использования становится невалидным. Для повторного вызова метода start_update_flow_silent запросите объект RuStoreAppUpdateInfo повторно, используя метод get_app_update_info.

См. раздел Проверка наличия обновлений.

Подписка на события
func _ready():
# Инициализация _appUpdate_client

_appUpdate_client.on_start_update_flow_success.connect(_on_start_update_flow_success)
_appUpdate_client.on_start_update_flow_failure.connect(_on_start_update_flow_failure)

func _on_start_update_flow_success(flowResult: ERuStoreUpdateFlowResult.Item):
pass

func _on_start_update_flow_failure(error: RuStoreError):
pass
Вызов метода start_update_flow_silent
_appUpdate_client.start_update_flow_silent()

Обратный вызов (callback) on_start_update_flow_success возвращает перечисление ERuStoreUpdateFlowResult.Item с информацией о результате обновления:

  • RESULT_OK (int = -1) — задача на скачивание обновления зарегистрирована.

Обратный вызов (callback) on_start_update_flow_failure возвращает объект RuStoreError с информацией об ошибке. Структура ошибки RuStoreError описана в разделе Обработка ошибок.

Вызовите метод установки обновления после получения статуса ERuStoreUpdateFlowResult.Item.DOWNLOADED в поле installStatus объекта RuStoreInstallState.

подсказка

Для тихого обновления рекомендуется реализовать свой интерфейс.

Установка обновления

После завершения скачивания файла обновления вы можете запустить установку обновления. Обновление происходит через нативный инструмент Android. Для запуска установки обновления используйте методы:

  • complete_update_flexible — обновление и перезапуск приложения;
  • complete_update_silent — обновление и закрытие приложения.
подсказка

Рекомендуется уведомить пользователя о готовности обновления к установке.

Перед использованием методов необходимо единожды выполнить подписку на событие:

  • on_complete_update_failure.
Подписка на событие
func _ready():
# Инициализация _appUpdate_client

_appUpdate_client.on_complete_update_failure.connect(_on_complete_update_failure)

func _on_complete_update_failure(error: RuStoreError):
pass

Обратный вызов (callback) on_complete_update_failure возвращает объект RuStoreError с информацией об ошибке в параметре error. Структура ошибки RuStoreError описана в разделе Обработка ошибок.

Гибкое завершение обновления

Вызов метода complete_update_flexible
_appUpdate_client.complete_update_flexible()

Обновление с UI от RuStore:

img
  1. Пользователю будет показан UI-диалог завершения обновления.

  2. В случае успешного обновления приложение будет перезапущено.

Тихое завершение обновления

Вызов метода complete_update_silent
_appUpdate_client.complete_update_silent()

Обновление без UI от RuStore:

  1. UI-диалог завершения обновления не будет показан.
  2. В случае успешного обновления приложение будет закрыто.

Обработка ошибок

подсказка

При получении любого события *_failure не рекомендуется самостоятельно отображать ошибку пользователю. Отображение ошибки может негативно повлиять на пользовательский опыт.

Класс RuStoreError
class_name RuStoreError extends Object

var name: String = ""
var description: String = ""

func _init(json: String = ""):
if json != "":
var obj = JSON.parse_string(json)

if obj.has("simpleName"):
name = obj["simpleName"]

if obj.has("detailMessage"):
description = obj["detailMessage"]
  • namesimpleName класса ошибки.
  • description – описание ошибки.

Возможные ошибки

  • RuStoreNotInstalledException — на устройстве пользователя не установлен RuStore;
  • RuStoreOutdatedException — версия RuStore, установленная на устройстве пользователя, не поддерживает данный SDK;
  • RuStoreUserUnauthorizedException — пользователь не авторизован в RuStore;
  • RuStoreException — базовая ошибка RuStore, от которой наследуются остальные ошибки;
  • RuStoreInstallException(public val code: Int) — ошибка скачивания и установки.
    • ERROR_UNKNOWN(Int = 4001) — неизвестная ошибка.
    • ERROR_DOWNLOAD(Int = 4002) — ошибка при скачивании.
    • ERROR_BLOCKED(Int = 4003) — установка заблокированна системой.
    • ERROR_INVALID_APK(Int = 4004) — некорректный APK обновления.
    • ERROR_CONFLICT(Int = 4005) — конфликт с текущей версией приложения.
    • ERROR_STORAGE(Int = 4006) — недостаточно памяти на устройстве.
    • ERROR_INCOMPATIBLE(Int = 4007) — несовместимо с устройством.
    • ERROR_APP_NOT_OWNED(Int = 4008) — приложение не куплено.
    • ERROR_INTERNAL_ERROR(Int = 4009) — внутренняя ошибка.
    • ERROR_ABORTED(Int = 4010) — пользователь отказался от установки обновления.
    • ERROR_APK_NOT_FOUND(Int = 4011) — APK для запуска установки не найден.
    • ERROR_EXTERNAL_SOURCE_DENIED(Int = 4012) — запуск обновления запрещён. Например, в первом методе вернулся ответ о том, что обновление недоступно, но пользователь вызывает второй метод.
    • ERROR_ACTIVITY_SEND_INTENT(Int = 9901) — ошибка отправки intent на открытие активити.
    • ERROR_ACTIVITY_UNKNOWN(Int = 9902) — неизвестная ошибка отрытия активити.