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




Условия корректной работы SDK
Для работы RuStore In-app updates SDK необходимо соблюдение следующих условий.
- Загружены данные о приложении в разделе Push-уведомления > Проекты из Консоль RuStore.
Приложение прошло модерацию (публиковать приложение необязательно).
.
- Подпись и package name различных типов сборок вашего приложения (debug, release и т.д.) могут отличаться друг от друга. В таком случае вы должны создать в разделе Push-уведомления > Проекты из Консоль RuStore проект под каждый тип сборки..
- ОС Android версии 7.0 или выше.
- Версия RuStore на устройстве пользователя актуальная.
- Пользователь авторизован в RuStore.
- Приложению RuStore разрешена установка приложений.
Подключение в проект
Для подключения выполните следующие шаги.
- Скопируйте содержимое папки
Plugins
из официального репозитория RuStore на gitflic в папкуPlugins
внутри своего проекта. - Перезапустите Unreal Engine.
- В списке плагинов (Edit > Plugins > Project > Mobile) отметьте плагины RuStoreAppUpdate и RuStoreCore.
- Подключите модули модули
RuStoreCore
иRuStoreAppUpdate
в файлеYourProject.Build.cs
в спискеPublicDependencyModuleNames
. - В настройках проекта (Edit > Project Settings > Android) установите параметр
Minimum SDK Version
на уровень не ниже24
и параметрTarget SDK Version
не ниже31
.
Создание менеджера обновлений
Перед вызовом методов библиотеки необходимо создать менеджер обновлений.
Инициализация
Перед вызовом методов библиотеки необходимо выполнить её инициализацию.
URuStoreAppUpdateManager::Instance()->Init();
Все операции с объектом менеджера также доступны из Blueprints. Ниже преставлен пример инициализации.

Вызов Init
привязывает объект к корню сцены, и если дальнейшая работа с объектом больше не планируется, для освобождения памяти необходимо выполнить метод Dispose
. Вызов метода Dispose
отвяжет объект от корня и безопасно завершит все отправленные запросы.
Деинициализация
URuStoreAppUpdateManager::Instance()->Dispose();

Проверка инициализации
Если вам нужно проверить факт инициализации библиотеки, используйте метод GetIsInitialized
. Метод возвращает значение типа bool
:
true
— если библиотека инициализирована;false
— еслиInit
еще не был вызван.
bool bIsInitialized = URuStoreAppUpdateManager::Instance()->GetIsInitialized();

Проверка наличия обновлений
Прежде чем запрашивать обновление, проверьте, доступно ли обновление для вашего приложения. Для проверки наличия обновлений вызовите методGetAppUpdateInfo
. При вызове данного метода проверяются следующие условия.
- На устройстве пользователя установлена актуальная версия RuStore.
- Пользователь и приложение не должны быть заблокированы в RuStore.
- Приложению RuStore разрешена установка приложений.
- Пользователь авторизова н в RuStore.
FURuStoreAppUpdateInfo
, который будет содержать в себе информацию о необходимости обновления. Запросите этот объект заранее и закэшируйте его, чтобы запросить у пользователя запуск скачивания обновления без задержки и в удобный для пользователя момент времени.
Каждый запрос GetAppUpdateInfo
возвращает requestId
, который уникален в рамках одного запуска приложения. Каждое событие возвращает requestId
того запроса, который запустил это событие.
long requestId = GetAppUpdateInfo(
[](long requestId, TSharedPtr<FURuStoreAppUpdateInfo, ESPMode::ThreadSafe> response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

Уведомление обратного вызов (callback) Success
возвращает структуру FURuStoreAppUpdateInfo
в параметре Response
. Структура содержит набор параметров, необходимых для определения доступности обновления.
USTRUCT(BlueprintType)
struct RUSTOREAPPUPDATE_API FURuStoreAppUpdateInfo
{
GENERATED_USTRUCT_BODY()
FURuStoreAppUpdateInfo()
{
updateAvailability = EURuStoreUpdateAvailability::UNKNOWN;
installStatus = EURuStoreInstallStatus::UNKNOWN;
availableVersionCode = 0;
}
UPROPERTY(BlueprintReadOnly)
EURuStoreUpdateAvailability updateAvailability;
UPROPERTY(BlueprintReadOnly)
EURuStoreInstallStatus installStatus;
UPROPERTY(BlueprintReadOnly)
int64 availableVersionCode;
};
-
updateAvailability
— доступность обновления:UNKNOWN (uint8 = 0)
— по умолчанию;UPDATE_NOT_AVAILABLE (uint8 = 1)
— обновление не нужно;UPDATE_AVAILABLE (uint8 = 2)
— обновление требуется загрузить или обновление уже загружено на устройство пользователя;DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS (uint8 = 3)
— обновление уже скачивается или установка уже запущена.
-
installStatus
— статус установки обновления, если пользователь уже устанавливает обновление в текущий момент времени:UNKNOWN (uint8 = 0)
— по умолчанию;DOWNLOADED (uint8 = 1)
— скачано;DOWNLOADING (uint8 = 2)
— скачивается;FAILED (uint8 = 3)
— ошибка;PENDING (uint8 = 5)
— в ожидании.
-
availableVersionCode
— код версии обновления.
Запуск скачивания обновления возможен только в том случае, если поле updateAvailability
содержит значение UPDATE_AVAILABLE
.
Failure
возвращает структуру с информацией об ошибке. Структура ошибки описана в разделе Обработка ошибок.
Скачивание и установка обновлений
Использование слушателя
После подтверждения доступности запуска процесса обновления вы можете получить статус скачивания обновления в событии OnStateUpdatedInstanceEvent
объекта URuStoreAppUpdateManager
.
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRuStoreOnStateUpdatedInstanceDelegate, int64, listenerId, FURuStoreInstallState, state);
UPROPERTY(BlueprintAssignable, Category = "RuStore AppUpdate Manager")
FRuStoreOnStateUpdatedInstanceDelegate OnStateUpdatedInstanceEvent;
FScriptDelegate Delegate;
Delegate.BindUFunction(YourUObjectPtr, FName("YourCallbackMethod"));
URuStoreAppUpdateManager::Instance()->OnStateUpdatedInstanceEvent.Add(Delegate);
UFUNCTION()
void YourCallbackMethod(int64 listenerId, FURuStoreInstallState state) {
// Process callback
}
Подписка на событие слушателя из Blueprint.

Событие OnStateUpdatedInstanceEvent
возвращает объект FURuStoreInstallState
в параметре state
с описанием текущего статуса скачивания. Структура FURuStoreInstallState
описана в разделе Проверка статуса скачивания обновления.
Интерфейс слушателя
Класс URuStoreAppUpdateManager
реализует стандартный слушатель. Вы можете создать собственный класс слушателя используя интерфейс IRuStoreInstallStateUpdateListenerInterface
.
UINTERFACE(Blueprintable)
class RUSTOREAPPUPDATE_API URuStoreInstallStateUpdateListenerInterface : public UInterface
{
GENERATED_BODY()
};
class IRuStoreInstallStateUpdateListenerInterface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "RuStore InstallStateUpdate Listener Interface")
void OnStateUpdated(int64 listenerId, FURuStoreInstallState& state);
};
Событие OnStateUpdated
возвращает объект FURuStoreInstallState
в параметре state
с описанием текущего статуса скачивания. Структура FURuStoreInstallState
описана в разделе Проверка статуса скачивания обновления.
Вызов метода RegisterListener
выполняет регистрацию слушателя.
Для стандартного слушателя URuStoreAppUpdateManager
вызов RegisterListener
не требуется.
int64 listenerId = URuStoreAppUpdateManager::Instance()->RegisterListener(YourListenerPtr);
YourListenerPtr
— указатель на объект класса, реализующего интерфейс IRuStoreInstallStateUpdateListenerInterface
.

Проверка статуса скачивания обновления
Структура FURuStoreInstallState
описывает текущий статус скачивания.
USTRUCT(BlueprintType)
struct RUSTOREAPPUPDATE_API FURuStoreInstallState
{
GENERATED_USTRUCT_BODY()
FURuStoreInstallState()
{
bytesDownloaded = 0;
totalBytesToDownload = 0;
percentDownloaded = 0;
installStatus = EURuStoreInstallStatus::UNKNOWN;
installErrorCode = EURuStoreInstallErrorCode::ERROR_UNKNOWN;
}
UPROPERTY(BlueprintReadWrite)
int64 bytesDownloaded;
UPROPERTY(BlueprintReadWrite)
int64 totalBytesToDownload;
UPROPERTY(BlueprintReadWrite)
float percentDownloaded;
UPROPERTY(BlueprintReadWrite)
EURuStoreInstallStatus installStatus;
UPROPERTY(BlueprintReadWrite)
EURuStoreInstallErrorCode installErrorCode;
};
bytesDownloaded
— количество загруженных байт;totalBytesToDownload
— общее количество байт, которое необходимо загрузить;percentDownloaded
— процент прогресса загрузки обновления;installStatus
— статус установки обновления, если пользователь уже устанавливает обновление в текущий момент времени:UNKNOWN (int == 0)
— статус по умолчанию.DOWNLOADED (int == 1)
— загружено.DOWNLOADING (int == 2)
— загружается.FAILED (int == 3)
— ошибка.PENDING (int == 5)
— в ожидании.
В SDK обновлений нет особого статуса для ситуации, когда пользователь отменил скачивание обновления. Если пользователь прервал обновление на этапе скачивания, installStatus
возвращает исходный статус UNKNOWN
(0
) с кнопкой Скачать.
Если пользователь уже скачал обновление, но отменил установку, то installStatus
вернёт значение DOWNLOADED
(1
).
Рассмотрим следующие варианты.
- Пользователь начал скачивание обновления, но отменил скачивание — в этом случае:
updateAvailability
—UPDATE_AVAILABLE
(2
);installStatus
—UNKNOWN
(0
).
- Пользователь скачал файл обновления, но не стал его устанавливать — в этом случае:
updateAvailability
—UPDATE_AVAILABLE
(2
);installStatus
—DOWNLOADED
(1
).
installErrorCode
— код ошибки во время скачивания. Коды ошибок описаны в разделе Обработка ошибок.
Удаление слушателя
Если необходимости в слушателе больше нет, воспользуйтесь методом удаления слушателя UnregisterListener
, передав в метод ранее зарегистрированный слушатель. UnregisterListener
должен быть вызван для всех слушателей до завершения работы приложения.
Для стандартного слушателя URuStoreAppUpdateManager
вызов UnregisterListener
при завершении работы приложения не требуется.
bool bIsDone = URuStoreAppUpdateManager::Instance()->UnregisterListener(YourListenerPtr);
YourListenerPtr
— указатель на объект класса, реализующего интерфейс IRuStoreInstallStateUpdateListenerInterface
.

В случае реализации собственного слушателя, для экономии ресурсов, вы также можете выполнить отмену регистрации стандартного слушателя.
auto instance = URuStoreAppUpdateManager::Instance();
bool bIsDone = instance->UnregisterListener(instance);

Запуск скачивания обновления
Отложенное обновление
Описание сценария отложенного обновления
Обновление с UI от RuStore

- Пользователю будет показан диалог с UI от RuStore для подтверждения обновления.
- При нажатии на кнопку Обновить покажется диалоговое окно для подтверждения установки обновления.
Запуск сценария обновления
Для запуска скачивания обновления приложения используйте метод StartUpdateFlow
.
Объект FURuStoreAppUpdateInfo
после однократного использования становится невалидным. Для повторного вызова метода StartUpdateFlow
запросите FURuStoreAppUpdateInfo
снова, используя метод GetAppUpdateInfo
.
См. раздел Проверка наличия обновлений.
StartUpdateFlow
возвращает requestId
, который уникален в рамках одного запуска приложения. Каждое событие возвращает requestId
того запроса, который запустил это событие.
EURuStoreAppUpdateOptions appUpdateOptions = EURuStoreAppUpdateOptions::DELAYED;
long requestId = StartUpdateFlow(
appUpdateOptions,
[](long requestId, EURuStoreUpdateFlowResult response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

appUpdateOptions
— тип процедуры обновления:DELAYED
— отложенное обновление. Пользователю будет показан диалог с UI от RuStore для подтверждения скачивания обновления.SILENT
— тихое обновление. Обновление будет скачано в фоне.IMMEDIATE
— принудительное обновление. Использование приложения будет заблокировано до тех пор, пока обновление не будет установлено.
Уведомление обратного вызова (callback) Success
возвращает значение EURuStoreUpdateFlowResult
в параметре Response
:
EURuStoreUpdateFlowResult::RESULT_OK
— пользователь подтвердил скачивание обновления.EURuStoreUpdateFlowResult::RESULT_CANCELED
— пользователь отказался от скачивания обновления.
Уведомление обратного вызова (callback) Failure
возвращает структуру FURuStoreError
с информацией об ошибке в параметре Error
. Структура ошибки FURuStoreError
описана в разделе Обработка ошибок.
После вызова метода StartUpdateFlow
за статусом скачивания обновления можно следить в событии OnStateUpdatedInstanceEvent
.
После получения статуса EURuStoreInstallStatus::DOWNLOADED
в поле installStatus
объекта FURuStoreInstallState
, должен быть вызван метод установки обновления.
Принудительное обновление
Описание сценария принудительного обновления
Обновление с UI от RuStore

- Пользователю будет показан полноэкранный диалог с UI от RuStore для подтверждения обновления. Использование приложения будет заблокировано до тех пор, пока обновление не будет установлено.
- При нажатии на кнопку Обновить отобразится диа логовое окно для подтверждения установки обновления.
- Далее при нажатии на кнопку Установить появится полноэкранный диалог об установке новой версии приложения.
- После завершения установки приложение перезапустится.
Приложение будет перезапущено, если версия Rustore больше, либо равна 1.37. Если версия Rustore ниже, то приложение закроется для установки обновления и не будет открыто заново, когда закончится обновление.
Запуск сценария обновления
После получения FURuStoreAppUpdateInfo
вы можете проверить доступность принудительного обновления.
bool bIsAvailable = URuStoreAppUpdateManager::Instance()->CheckIsImmediateUpdateAllowed();

Результат метода CheckIsImmediateUpdateAllowed
рекомендуется использовать для принятия решения о запуске принудительного обновления, но данный результат не влияет на возможность запуска сценария. Необходимость запуска сценария обновления может происходить по вашей внутренней логике.
Для запуска скачивания обновления приложения используйте метод StartUpdateFlow
.
Объект FURuStoreAppUpdateInfo
после однократного использования становится невалидным. Для повторного вызова метода StartUpdateFlow
запросите FURuStoreAppUpdateInfo
снова, используя метод GetAppUpdateInfo
.
См. раздел Проверка наличия обновлений.
StartUpdateFlow
возвращает requestId
, который уникален в рамках одного запуска приложения. Каждое событие возвращает requestId
того запроса, который запустил это событие.
EURuStoreAppUpdateOptions appUpdateOptions = EURuStoreAppUpdateOptions::IMMEDIATE;
long requestId = StartUpdateFlow(
appUpdateOptions,
[](long requestId, EURuStoreUpdateFlowResult response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

appUpdateOptions
— тип процедуры обновления:DELAYED
— отложенное обновление. Пользователю будет показан диалог с UI от RuStore для подтверждения скачивания обновления.SILENT
— тихое обновление. Обновление будет скачано в фоне.IMMEDIATE
— принудительное обновление. Использование приложения будет заблокировано до тех пор, пока обновление не будет установлено.
Уведомление обратного вызова (callback) Success
возвращает значение EURuStoreUpdateFlowResult
в параметре Response
:
EURuStoreUpdateFlowResult::RESULT_OK
— обновление выполнено, код может не быть получен, т. к. приложение в момент обновления завершается.EURuStoreUpdateFlowResult::RESULT_CANCELED
— флоу прервано пользователем, или произошла ошибка. Предполагается, что при получении этого кода следует завершить работу приложения.EURuStoreUpdateFlowResult::ACTIVITY_NOT_FOUND
— RuStore не установлен, либо установлена версия, которая не поддерживает принудительное обновление (RuStore versionCode
<191
).
Уведомление обратного вызова (callback) Failure
возвращает структуру FURuStoreError
с информацией об ошибке в параметре Error
. Структура ошибки FURuStoreError
описана в разделе Обработка ошибок.
При успешном обновлении дальнейших действий не требуется.
Тихое обновление
Описание сценария тихого обновления
Обновление без UI от RuStore

Пользователю будет показано диалоговое окно для подтверждения установки обновления (обновление будет скачано в фоне).
Запуск сценария обновления
Для запуска скачивания обновления приложения используйте метод StartUpdateFlow
.
Объект FURuStoreAppUpdateInfo
после однократного использования становится невалидным. Для повторного вызова метода StartUpdateFlow
запросите FURuStoreAppUpdateInfo
снова, используя метод GetAppUpdateInfo
.
См. раздел Проверка наличия обновлений.
StartUpdateFlow
возвращает requestId
, который уникален в рамках одного запуска приложения. Каждое событие возвращает requestId
того запроса, который запустил это событие.
EURuStoreAppUpdateOptions appUpdateOptions = EURuStoreAppUpdateOptions::SILENT;
long requestId = StartUpdateFlow(
appUpdateOptions,
[](long requestId, EURuStoreUpdateFlowResult response) {
// Process response
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

appUpdateOptions
— тип процедуры обновления:DELAYED
— отложенное обновление. Пользователю будет показан диалог с UI от RuStore для подтверждения скачивания обновления.SILENT
— тихое обновление. Обновление будет скачано в фоне.IMMEDIATE
— принудительное обновление. Использование приложения будет заблокировано до тех пор, пока обновление не будет установлено.
Уведомление обратного вызова (callback) Success
возвращает значение EURuStoreUpdateFlowResult
в параметре Response
:
EURuStoreUpdateFlowResult::RESULT_OK
— задача на скачивание обновления зарегистрирована.
Уведомление обратного вызова (callback) Failure
возвращает структуру FURuStoreError
с информацией об ошибке в параметре Error
. Структура ошибки FURuStoreError
описана в разделе Обработка ошибок.
После вызова метода StartUpdateFlow
за статусом скачивания обновления можно следить в событии OnStateUpdatedInstanceEvent
.
После получения статуса EURuStoreInstallStatus::DOWNLOADED
в поле installStatus
объекта FURuStoreInstallState
, должен быть вызван метод установки обновления.
Для тихого обновления рекомендуется реализовать свой интерфейс.
Установка обновления
Для запуска установки обновления используйте метод CompleteUpdate
. Обновление происходит через нативный инструмент Android.
Рекомендуется уведомить пользователя о готовности обновления к установке.
Гибкое завершение обновления
Обновление с UI от RuStore:

-
Пользователю будет показан UI-диалог завершения обновления.
-
В случае успешного обновления приложение будет перезапущено.
Метод CompleteUpdate
должен быть вызван с параметром FLEXIBLE
.
EURuStoreAppUpdateOptions appUpdateOptions = EURuStoreAppUpdateOptions::FLEXIBLE;
requestId = CompleteUpdate(
appUpdateOptions,
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

appUpdateOptions
— тип процедуры завершения обновления:
FLEXIBLE
— обновление и перезапуск приложения.
Уведомление обратного вызова (callback) Failure
возвращает структуру FURuStoreError
с информацией об ошибке в параметре Error
. Структура ошибки FURuStoreError
описана в разделе Обработка ошибок.
Тихое завершение обновления
Обновление без UI от RuStore:
- UI-диалог завершения обновления не будет показан.
- В случае успешного обновления приложение будет закрыто.
Метод CompleteUpdate
должен быть вызван с параметром SILENT
.
EURuStoreAppUpdateOptions appUpdateOptions = EURuStoreAppUpdateOptions::SILENT;
requestId = CompleteUpdate(
appUpdateOptions,
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);

appUpdateOptions
— тип процедуры завершения обновления:
SILENT
— обновление и закрытие приложения.
Уведомление обратного вызова (callback) Failure
возвращает структуру FURuStoreError
с информацией об ошибке в параметре Error
. Структура ошибки FURuStoreError
описана в разделе Обработка ошибок.
Обработка ошибок
Если вы получили в ответ onFailure
, не рекомендуется самостоятельно отображать ошибку пользователю. Отображение ошибки может негативно повлиять на пользовательский опыт.
USTRUCT(BlueprintType)
struct RUSTORECORE_API FURuStoreError
{
GENERATED_USTRUCT_BODY()
FURuStoreError()
{
name = "";
description = "";
}
UPROPERTY(BlueprintReadOnly)
FString name;
UPROPERTY(BlueprintReadOnly)
FString description;
};
name
—simpleName
класса ошибки.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)
— неизвестная ошибка отрытия активити.