7.0.0
Overview
The RuStore In-app Updates SDK ensures that users have the most up-to-date version of your application on their devices. This helps users experience the latest features, benefit from performance improvements, and receive bug fixes.
Implementation Example
Use the RuStore In-app Updates SDK to implement various update methods. Currently supported methods include: deferred, silent (without RuStore UI), and forced updates.
- Kotlin
- Java
Refer to the example application to learn how to properly integrate the Updates SDK.
Refer to the example application to learn how to properly integrate the Updates SDK.
User Scenarios
- Deferred Update
- Forced Update
- Silent Update
Integrating into Your Project
- Kotlin
- Java
Add the repository as shown in the example below.
repositories {
maven {
url = uri("https://artifactory-external.vkpartner.ru/artifactory/maven")
}
}
- BOM Dependency
- Direct Version Dependency
Using the BOM file allows you to manage multiple RuStore SDK versions.
Advantages of using the BOM file for configuration:
-
Unified Version Management:
- With the BOM, you can control the versions of all dependencies from a single file. This is especially helpful when using multiple libraries that need to be compatible with each other.
- For instance, if you have several RuStore libraries like
ru.rustore.sdk:billingclient
andru.rustore.sdk:pushclient
, you can use the BOM to ensure that they are all compatible.
-
Simplified Updates:
- Updating dependencies becomes simpler because you only need to change the version in one place — in the BOM file. This reduces the risk of missing an update for a dependency and avoids version conflicts.
- For example, if a new version of the BOM contains updated versions of all libraries, you only need to update the BOM file, not each dependency individually.
-
Enhanced Compatibility:
- Using the BOM helps to avoid version conflicts between different libraries. This is particularly important when libraries have dependencies on each other.
- For instance, if two libraries depend on different versions of the same library, this can cause conflicts. The BOM helps to avoid these situations by ensuring that all dependencies are compatible.
dependencies {
implementation(platform("ru.rustore.sdk:bom:7.0.0"))
implementation("ru.rustore.sdk:appupdate")
}
dependencies {
implementation("ru.rustore.sdk:appupdate:7.0.0")
}
Add the repository as shown in the example below.
repositories {
maven {
url "https://artifactory-external.vkpartner.ru/artifactory/maven"
}
}
- BOM Dependency
- Direct Version Dependency
dependencies {
implementation platform("ru.rustore.sdk:bom:7.0.0")
implementation "ru.rustore.sdk:appupdate"
}
dependencies {
implementation "ru.rustore.sdk:appupdate:7.0.0"
}
Creating an Update Manager
- Kotlin
- Java
Before calling the library methods, you must create an update manager.
val updateManager = RuStoreAppUpdateManagerFactory.create(context)
Before calling the library methods, you must create an update manager.
RuStoreAppUpdateManager ruStoreAppUpdateManager = RuStoreAppUpdateManagerFactory.INSTANCE.create(context);
Checking for Updates
- Kotlin
- Java
Before requesting an update, verify if an update is available for your app. To check for updates, call the getAppUpdateInfo()
method. This method checks the following conditions:
- The user's device has the latest version of RuStore installed.
- The user and the application must not be blocked in RuStore.
- The RuStore app is authorized to install applications.
- The user is logged into RuStore.
This method returns an AppUpdateInfo
object containing information about the need for an update. Request this object in advance and cache it to prompt the user to start downloading the update without delay and at a time convenient for the user.
ruStoreAppUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener { appUpdateInfo ->
if (appUpdateInfo.updateAvailability == UpdateAvailability.UPDATE_AVAILABLE) {
// An update is available (you can register a listener and start the download here)
}
}
.addOnFailureListener { throwable ->
Log.e(TAG, "getAppUpdateInfo error", throwable)
}
The AppUpdateInfo
object includes a set of parameters needed to determine update availability.
updateAvailability
— update availability:
UNKNOWN (int == 0)
— default;UPDATE_NOT_AVAILABLE (int == 1)
— no update needed;UPDATE_AVAILABLE (int == 2)
— update required to download or update already downloaded on the user's device;DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS (int == 3)
— update is already downloading or installation has already started.
installStatus
— the status of the update installation if the user is already installing the update at the current time:
UNKNOWN (int == 0)
— default;DOWNLOADED (int == 1)
— downloaded;DOWNLOADING (int == 2)
— downloading;FAILED (int == 3)
— error;PENDING (int == 5)
— pending.
Starting the update download is only possible if the updateAvailability
field contains the value UPDATE_AVAILABLE
.
Before requesting an update, verify if an update is available for your app. To check for updates, call the getAppUpdateInfo()
method. This method checks the following conditions:
- The user's device has the latest version of RuStore installed.
- The user and the application must not be blocked in RuStore.
- The RuStore app is authorized to install applications.
- The user is logged into RuStore.
- This method returns an
AppUpdateInfo
object containing information about the need for an update. Request this object in advance and cache it to prompt the user to start downloading the update without delay and at a time convenient for the user.
ruStoreAppUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(appUpdateInfo -> {
if (appUpdateInfo.getUpdateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
// An update is available (you can register a listener and start the download here)
}
})
.addOnFailureListener(throwable ->
Log.e(TAG, "getAppUpdateInfo error", throwable)
);
The AppUpdateInfo
object includes a set of parameters needed to determine update availability.
updateAvailability
— update availability:
UNKNOWN (int == 0)
— default;UPDATE_NOT_AVAILABLE (int == 1)
— no update needed;UPDATE_AVAILABLE (int == 2)
— update required to download or update already downloaded on the user's device;DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS (int == 3)
— update is already downloading or installation has already started.
installStatus
— the status of the update installation if the user is already installing the update at the current time:
UNKNOWN (int == 0)
— default;DOWNLOADED (int == 1)
— downloaded;DOWNLOADING (int == 2)
— downloading;FAILED (int == 3)
— error;PENDING (int == 5)
— pending.
Starting the update download is only possible if the updateAvailability
field contains the value UPDATE_AVAILABLE
.
Downloading and Installing Updates
Using a Listener
After confirming the availability of the update (AppUpdateInfo
), you can request the download status of the update - for this, start a listener for the download status.
Checking the Download Status
- Kotlin
- Java
Use the registerListener()
method.
ruStoreAppUpdateManager.registerListener { state ->
when (state.installStatus) {
InstallStatus.DOWNLOADED -> {
// Update is ready to be installed
}
InstallStatus.DOWNLOADING -> {
val totalBytes = state.totalBytesToDownload
val bytesDownloaded = state.bytesDownloaded
// Here you can display the download progress
}
InstallStatus.FAILED -> {
Log.e(TAG, "Downloading error")
}
}
}
Use the registerListener()
method.
ruStoreAppUpdateManager.registerListener(state -> {
switch (state.getInstallStatus()) {
case InstallStatus.DOWNLOADED:
// Update is ready to be installed
break;
case InstallStatus.DOWNLOADING:
long totalBytes = installState.getTotalBytesToDownload();
long bytesDownloaded = installState.getBytesDownloaded();
// Here you can display the download progress
break;
case InstallStatus.FAILED:
Log.e(TAG, "Downloading error");
break;
}
});
The state
object describes the current download status. The content of the object is presented below.
installStatus
— the status of the update installation if the user is already installing the update at the current time:
UNKNOWN (int == 0)
— default;DOWNLOADED (int == 1)
— downloaded;DOWNLOADING (int == 2)
— downloading;FAILED (int == 3)
— error;PENDING (int == 5)
— pending;
The Updates SDK does not have a specific status for the situation when the user has canceled the update download. If the user interrupted the update at the download stage, installStatus returns the original status UNKNOWN (0) with the Download button.
If the user has already downloaded the update but canceled the installation, then installStatus will return the value DOWNLOADED (1).
Consider the following options:
The user started downloading the update but canceled the download — in this case:
updateAvailability
— UPDATE_AVAILABLE (2);installStatus
— UNKNOWN (0).- The user downloaded the update file but did not install it — in this case:
updateAvailability
— UPDATE_AVAILABLE (2);installStatus
— DOWNLOADED (1).bytesDownloaded
— the number of bytes downloaded;totalBytesToDownload
— the total number of bytes to download;installErrorCode
— the error code during download. Error codes are described in the Error Handling section.
Removing the Listener
- Kotlin
- Java
If you no longer need the listener, use the unregisterListener()
method to remove the listener, passing the previously registered listener to the method.
ruStoreAppUpdateManager.unregisterListener(listener)
If you no longer need the listener, use the unregisterListener()
method to remove the listener, passing the previously registered listener to the method.
ruStoreAppUpdateManager.unregisterListener(listener);
Starting the Update Download
Deferred Update
- Kotlin
- Java
Starting the Update Scenario
To start downloading the app update, call the startUpdateFlow()
method.
The AppUpdateInfo
object becomes invalid after a single use. To call the startUpdateFlow()
method again, request AppUpdateInfo
again using the getAppUpdateInfo()
method.
ruStoreAppUpdateManager
.startUpdateFlow(appUpdateInfo, AppUpdateOptions.Builder().build())
.addOnSuccessListener { resultCode ->
if (resultCode == Activity.RESULT_CANCELED) {
// User cancelled the download
}
}
.addOnFailureListener { throwable ->
Log.e(TAG, "startUpdateFlow error", throwable)
}
If the user confirmed the update download, then resultCode = Activity.RESULT_OK
; if they declined, then resultCode = Activity.RESULT_CANCEL
.
After receiving the DOWNLOADED
status, you can call the update installation method completeUpdate().
It is recommended to notify the user that the update is ready to be installed.
The method may return an error.
Starting the Update Scenario
To start downloading the app update, call the startUpdateFlow()
method.
The AppUpdateInfo
object becomes invalid after a single use. To call the startUpdateFlow()
method again, request AppUpdateInfo
again using the getAppUpdateInfo()
method.
ruStoreAppUpdateManager
.startUpdateFlow(appUpdateInfo, new AppUpdateOptions.Builder().build())
.addOnSuccessListener(resultCode -> {
if (resultCode == Activity.RESULT_CANCELED) {
// User cancelled the download
}
})
.addOnFailureListener(throwable ->
Log.e(TAG, "startUpdateFlow error", throwable)
);
If the user confirmed the update download, then resultCode = Activity.RESULT_OK
; if they declined, then resultCode = Activity.RESULT_CANCEL
.
After receiving the DOWNLOADED
status, you can call the update installation method completeUpdate().
It is recommended to notify the user that the update is ready to be installed.
The method may return an error.
Forced Update
- Kotlin
- Java
Starting the Update Scenario
After receiving the AppUpdateInfo
, you can check the availability of a forced update.
if (appUpdateInfo.isUpdateTypeAllowed(IMMEDIATE)) {
// Forced update is available
}
It is recommended to use the result of the isUpdateTypeAllowed
function to decide whether to start a forced update, but this result does not affect the ability to start the scenario. The need to start the update scenario can occur according to your internal logic.
To start the update scenario, use the startUpdateFlow()
method.
ruStoreAppUpdateManager
.startUpdateFlow(appUpdateInfo, AppUpdateOptions.Builder().appUpdateType(IMMEDIATE).build())
.addOnSuccessListener { resultCode ->
}
.addOnFailureListener { throwable ->
}
resultCode (Int)
:
Activity.RESULT_OK (-1)
— the update is complete, the code may not be received because the application is terminated at the time of the update.Activity.RESULT_CANCELED (0)
— the flow was interrupted by the user or an error occurred. It is assumed that upon receiving this code, the application should be terminated.ActivityResult.ACTIVITY_NOT_FOUND (2)
— RuStore is not installed, or the installed version does not support forced updates (RuStore versionCode
<191
).
throwable
— an error starting the update scenario.
No further action is required upon successful update.
Starting the Update Scenario
After receiving the AppUpdateInfo
, you can check the availability of a forced update.
if (appUpdateInfo.isUpdateTypeAllowed(IMMEDIATE)) {
// Forced update is available
}
It is recommended to use the result of the isUpdateTypeAllowed
function to decide whether to start a forced update, but this result does not affect the ability to start the scenario. The need to start the update scenario can occur according to your internal logic.
To start the update scenario, use the startUpdateFlow()
method.
ruStoreAppUpdateManager
.startUpdateFlow(appUpdateInfo, new AppUpdateOptions.Builder().appUpdateType(AppUpdateType.IMMEDIATE).build()
.addOnSuccessListener(resultCode ->
)
.addOnFailureListener(throwable ->
);
resultCode (Int)
:
Activity.RESULT_OK (-1)
— the update is complete, the code may not be received because the application is terminated at the time of the update.Activity.RESULT_CANCELED (0)
— the flow was interrupted by the user or an error occurred. It is assumed that upon receiving this code, the application should be terminated.ActivityResult.ACTIVITY_NOT_FOUND (2)
— RuStore is not installed, or the installed version does not support forced updates (RuStore versionCode
<191
).
throwable
— an error starting the update scenario.
No further action is required upon successful update.
Silent Update
- Kotlin
- Java
Starting the Update Scenario
To start downloading the application update, you need to call the startUpdateFlow()
method with the AppUpdateInfo
argument, obtained in the getAppUpdateInfo()
method, and set the update type in AppUpdateOptions
to SILENT
.
ruStoreAppUpdateManager
.startUpdateFlow(appUpdateInfo, AppUpdateOptions.Builder().appUpdateType(SILENT).build())
.addOnSuccessListener { resultCode ->
}
.addOnFailureListener { throwable ->
}
When calling onSuccessListener
with resultCode = Activity.RESULT_OK
, a task to download the update will be registered.
In this scenario, only onSuccessListener
with resultCode = Activity.RESULT_OK
or onFailureListener
can be called.
After calling the method, you can monitor the update download status in the listener.
After receiving the DOWNLOADED
status, you can call the update installation method completeUpdate(). It is recommended to notify the user that the update is ready to be installed.
It is recommended to implement your own interface for silent updates.
Starting the Update Scenario
To start downloading the application update, you need to call the startUpdateFlow()
method with the AppUpdateInfo
argument, obtained in the getAppUpdateInfo()
method, and set the update type in AppUpdateOptions
to SILENT
.
ruStoreAppUpdateManager
.startUpdateFlow(appUpdateInfo, new AppUpdateOptions.Builder().appUpdateType(AppUpdateType.SILENT).build())
.addOnSuccessListener(resultCode ->
)
.addOnFailureListener(throwable ->
);
When calling onSuccessListener
with resultCode = Activity.RESULT_OK
, a task to download the update will be registered.
In this scenario, only onSuccessListener
with resultCode = Activity.RESULT_OK
or onFailureListener
can be called.
After calling the method, you can monitor the update download status in the listener.
After receiving the DOWNLOADED
status, you can call the update installation method completeUpdate(). It is recommended to notify the user that the update is ready to be installed.
It is recommended to implement your own interface for silent updates.
Installing the Update
- Kotlin
- Java
To start the update installation, call the completeUpdate()
method.
To start the update installation, call the completeUpdate(appUpdateOptions: AppUpdateOptions)
method. You can only pass two types of installation completion to the method: FLEXIBLE
and SILENT
, deferred and silent updates, respectively.
var type: Int = AppUpdateType.FLEXIBLE
ruStoreAppUpdateManager
.completeUpdate(AppUpdateOptions.Builder().appUpdateType(type).build())
.addOnFailureListener { throwable ->
Log.e(TAG, "update error", throwable)
}
type
- the update type AppUpdateType
.
If you pass the update type FLEXIBLE
, the application will restart. An example of a user flow is shown below.

If you pass the update type SILENT
, the application will close without restarting. An example of a user flow is shown below.
Update without UI from RuStore:
- The UI dialog for completing the update will not be shown.
- If the update is successful, the application will be closed.
To start the update installation, call the completeUpdate()
method.
To start the update installation, call the completeUpdate(appUpdateOptions: AppUpdateOptions)
method. You can only pass two types of installation completion to the method: FLEXIBLE
and SILENT
, deferred and silent updates, respectively.
int type = AppUpdateType.FLEXIBLE;
ruStoreAppUpdateManager
.completeUpdate(new AppUpdateOptions.Builder().appUpdateType(AppUpdateType.FLEXIBLE).build())
.addOnFailureListener(throwable ->
Log.d(TAG, "Throwable: " + throwable);
);
type
- the update type AppUpdateType
.
If you pass the update type FLEXIBLE
, the application will restart:

If you pass the update type SILENT
, the application will close without restarting. An example of a user flow is shown below.
Update without UI from RuStore:
- The UI dialog for completing the update will not be shown.
- If the update is successful, the application will be closed.
Error Handling
If you receive onFailure
in response, it is not recommended to display the error to the user yourself. Displaying the error can negatively affect the user experience.
Possible Errors
RuStoreNotInstalledException
— RuStore is not installed on the user's device;RuStoreOutdatedException
— the version of RuStore installed on the user's device does not support this SDK;RuStoreUserUnauthorizedException
— the user is not authorized in RuStore;RuStoreException
— the basic RuStore error from which other errors inherit;RuStoreInstallException(public val code: Int)
— download and installation error.ERROR_UNKNOWN(Int = 4001)
— unknown error.ERROR_DOWNLOAD(Int = 4002)
— download error.ERROR_BLOCKED(Int = 4003)
— installation blocked by the system.ERROR_INVALID_APK(Int = 4004)
— incorrect update APK.ERROR_CONFLICT(Int = 4005)
— conflict with the current version of the application.ERROR_STORAGE(Int = 4006)
— not enough memory on the device.ERROR_INCOMPATIBLE(Int = 4007)
— incompatible with the device.ERROR_APP_NOT_OWNED(Int = 4008)
— the application has not been purchased.ERROR_INTERNAL_ERROR(Int = 4009)
— internal error.ERROR_ABORTED(Int = 4010)
— the user has canceled the update installation.ERROR_APK_NOT_FOUND(Int = 4011)
— APK not found to start the installation.ERROR_EXTERNAL_SOURCE_DENIED(Int = 4012)
— update start denied. For example, the first method returned a response that the update is not available, but the user calls the second method.ERROR_ACTIVITY_SEND_INTENT(Int = 9901)
— error sending intent to open the activity.ERROR_ACTIVITY_UNKNOWN(Int = 9902)
— unknown error opening activity.