6.1.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 разрешена установка приложений.
Подключение в проект
Для подключения выполните следующие шаги.
- Скопируйте содержимое папки
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);
Запуск скачивания обновления
Отложенное обновление
Запуск сценария обновления
Для запуска скачивания обновления приложения используйте метод 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
, должен быть вызван метод установки обновления.
Принудительное обновление
Запуск сценария обновления
После получения 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
описана в разделе Обработка ошибок.
При успешном обновлении дальнейших действий не требуется.
Тихое обновление
Запуск сценария обновления
Для запуска скачивания обновления приложения используйте метод 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)
— неизвестная ошибка отрытия активити.