10.5.1
Overview
RuStore In-app updates SDK supports the current version of the application on the user's device. This helps the user see updates, evaluate performance improvements and the result of bug fixes.
Changed
Supported by RuStore appupdate SDK 10.5.1
Implementation Example
Use RuStore In-app updates SDK to implement various update methods. Currently supported: delayed, silent (without UI from RuStore) and forced update.
Check out the sample application to learn how to properly integrate the update SDK.
User Scenarios
- Delayed Update
- Forced Update
- Silent Update



Prerequisites for Correct SDK Operation
For the RuStore In-app updates SDK to work, the following conditions must be met.
- Data about the application has been loaded in the Push Notifications > Projects section from RuStore Console.
- The application has been moderated (it is not necessary to publish the application).
Signature and package name of various types of builds of your application (debug, release, etc.) may differ from each other. In this case, you should create in the section Push notifications > Projects from RuStore Console a project for each type of assembly.
- Android OS version 7.0 or higher.
- The version of RuStore on the user’s device is current.
- The user is authorized in RuStore.
- The RuStore application is allowed to install applications.
Connecting to the Project
To connect the package to your project, run the following command.
flutter pub add flutter_rustore_update
This command will add a line to the pubspec.yaml file.
dependencies:
flutter_rustore_update: ^10.5.0
Checking for Available Updates
Before requesting an update, check to see if an update is available for your application. To check for updates, call the methodinfo(). When calling this method, the following conditions are checked.
- The current version of RuStore is installed on the user's device.
- The user and the app are not banned in RuStore.
- RuStore app is allowed to install applications.
- User is authorized in RuStore.
info object, which will contain 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 the user's convenience.
RustoreUpdateClient.info().then((info) {
print(info);
}).catchError((err) {
print(err);
});
info contains a set of parameters necessary to determine whether an update is available.
-
updateAvailability— update availability:UPDATE_AVAILABILITY_UNKNOWN(int == 0) - default;UPDATE_AVAILABILITY_NOT_AVAILABLE(int == 1) - no update required;UPDATE_AVAILABILITY_AVAILABLE(int == 2) - the update needs to be downloaded or the update has already been downloaded to the user’s device;UPDATE_AVAILABILITY_IN_PROGRESS(int == 3) - the update is already being downloaded or the installation has already started.
-
installStatus— update installation status if the user is already installing the update at the current time:INSTALL_STATUS_UNKNOWN(int == 0) - default;INSTALL_STATUS_DOWNLOADED(int == 1) - downloaded;INSTALL_STATUS_DOWNLOADING(int == 2) - downloading;INSTALL_STATUS_FAILED(int == 3) - error;INSTALL_STATUS_INSTALLING(int == 4) - installation is in progress;INSTALL_STATUS_PENDING(int == 5) - pending.
The package also provides a type-safe representation of these values:
info.updateAvailabilityValue— значение типаUpdateAvailability;info.installStatusValue— значение типаInstallStatus.
Example:
RustoreUpdateClient.info().then((info) {
if (info.updateAvailabilityValue == UpdateAvailability.available) {
print('The update is available');
}
});
Starting an update download is possible only if the updateAvailability field contains the value UPDATE_AVAILABILITY_AVAILABLE.
For backward compatibility, the package retains the legacy constants UPDATE_AILABILITY_*. For new integrations, it is recommended to use UPDATE_AVAILABILITY_*.
Downloading and installing updates
Track update status
After confirming that the update is available (AppUpdateInfo), you can request the download status of the update. To do this, subscribe to the update status stream.
Checking update download status
For a silent update, it is recommended to implement your own interface.
Use RustoreUpdateClient.stateStream.
import 'dart:async';
late final StreamSubscription<RequestResponse> updateSubscription;
void initState() {
super.initState();
updateSubscription = RustoreUpdateClient.stateStream.listen((state) {
switch (state.installStatusValue) {
case InstallStatus.downloaded:
// The update is ready to install.
break;
case InstallStatus.downloading:
// Here you can display the download progress
print('progress: ${state.downloadProgress}');
break;
case InstallStatus.failed:
print('err ${state.installError.description}');
break;
default:
break;
}
});
}
void dispose() {
updateSubscription.cancel();
super.dispose();
}
stateStream returns a broadcast Stream<RequestResponse> and is suitable for securely working with the lifecycle of a screen or service. After canceling a subscription via cancel(), the stream of events stops flowing into the application.
For backward compatibility, the listener(callback) method is also retained, but for new integrations it is recommended to use stateStream.
The state object describes the current download status. Below is the contents of the object.
-
installStatus— update installation status if the user is already installing the update at the current time:INSTALL_STATUS_UNKNOWN(int == 0) - default;INSTALL_STATUS_DOWNLOADED(int == 1) - downloaded;INSTALL_STATUS_DOWNLOADING(int == 2) - downloading;INSTALL_STATUS_FAILED(int == 3) - error;INSTALL_STATUS_INSTALLING(int == 4) - installation is in progress;INSTALL_STATUS_PENDING(int == 5) - pending.
-
bytesDownloaded— number of bytes downloaded; -
totalBytesToDownload— the total number of bytes to download; -
installErrorCode— error code during download. Error codes are described in the section Error handling.
The package also provides additional properties:
state.installStatusValue- value of typeInstallStatus;state.installError- value of typeRustoreUpdateError;state.downloadProgress- download progress in the range from 0.0 to 1.0 if the total download size is known.
Example of displaying download progress:
RustoreUpdateClient.stateStream.listen((state) {
if (state.installStatusValue == InstallStatus.downloading) {
print('Downloaded: ${state.bytesDownloaded}/${state.totalBytesToDownload}');
print('Progress: ${state.downloadProgress}');
}
});
The update SDK does not have a special status for the situation when the user has canceled the update download. If the user aborted the update during the download phase, installStatus returns the original status INSTALL_STATUS_UNKNOWN (0) with a Download button.
If the user has already downloaded the update, but canceled the installation, then installStatus will return the value INSTALL_STATUS_DOWNLOADED (1).
Let's consider the following options.
- The user started downloading the update, but canceled the download - in this case:
updateAvailability-UPDATE_AVAILABILITY_AVAILABLE(2);installStatus-INSTALL_STATUS_UNKNOWN(0).
- The user downloaded the update file, but did not install it - in this case:
updateAvailability-UPDATE_AVAILABILITY_AVAILABLE(2);installStatus-INSTALL_STATUS_DOWNLOADED(1).
The RustoreUpdateClient.listener(callback) method has been preserved for backward compatibility. For new integrations, it is recommended to use RustoreUpdateClient.stateStream.
Start downloading the update
Delayed update
Run update script
To start downloading an application update, call the download() method.
The AppUpdateInfo object becomes invalid after a single use. To call the startUpdateFlow() method again, request AppUpdateInfo using the info() method again.
RustoreUpdateClient.download().then((value) {
print("download code ${value.code}");
if (value.code == ACTIVITY_RESULT_CANCELED) {
// The user refused to download
}
}).catchError((err) {
print("download err ${err}");
}
);
If the user confirmed downloading the update, then resultCode = ACTIVITY_RESULT_OK, if he refused, then resultCode = ACTIVITY_RESULT_CANCELED.
After receiving the INSTALL_STATUS_DOWNLOADED status or the InstallStatus.downloaded value, you can call the install update method.
It is recommended to notify the user that the update is ready for installation.
The method may return an error.
Forced update
Run update script
To start downloading a forced application update, call the immediate() method.
RustoreUpdateClient.immediate().then((value) {
print("silent code ${value.code}");
}).catchError((err) {
print("immediate err ${err}");
}
);
resultCode (Int):
ACTIVITY_RESULT_OK (-1)- the update has been completed, the code may not be received because the application is being terminated at the time of the update.ACTIVITY_RESULT_CANCELED (0)- the flow was interrupted by the user, or an error occurred. When you receive this code, you are expected to exit the application.ACTIVITY_RESULT_NOT_FOUND (2)- RuStore is not installed, or a version is installed that does not support forced updating (RuStore versionCode<191).
throwable — error starting the update script.
If the update is successful, no further action is required.
Silent update
Run update script
To start downloading a silent application update, call the silent() method.
RustoreUpdateClient.silent().then((value) {
print("silent code ${value.code}");
}).catchError((err) {
print("silent err ${err}");
}
);
Calling then with code = ACTIVITY_RESULT_OK will register a task to download the update.
In this scenario, only then can be called with ACTIVITY_RESULT_OK, or catchError.
After calling the method, you can monitor the update download status via RustoreUpdateClient.stateStream.
After receiving the INSTALL_STATUS_DOWNLOADED status or the InstallStatus.downloaded value, you can call the install update method. It is recommended to notify the user that the update is ready for installation.
For a silent update, it is recommended to implement your own interface.
Installing the update
Once the update file download is complete, you can start installing the update. The update occurs through the native Android tool. To start the update installation, use the following methods:
completeUpdateFlexible()- update and restart the application;completeUpdateSilent()- update and close the application.
It is recommended to notify the user that the update is ready for installation.
Flexible update completion
RustoreUpdateClient.completeUpdateFlexible().catchError((err) {
print("completeUpdateFlexible err ${err}");
});
Update with UI from RuStore:
-
The user will be shown a UI dialog to complete the update.
-
If the update is successful, the application will be restarted.
Silent completion of the update
RustoreUpdateClient.completeUpdateSilent().catchError((err) {
print("completeUpdateSilent err ${err}");
});
Update without UI from RuStore:
- The update completion UI dialog will not be shown.
- If the update is successful, the application will be closed.
Error handling
Errors in the plugin are still accessible through constants declared in the const.dart file.
Additionally, the package provides a type-safe error representation:
RustoreUpdateError;state.installError;state.installError.description.
Example of download error handling:
RustoreUpdateClient.stateStream.listen((state) {
if (state.installStatusValue == InstallStatus.failed) {
print(state.installError.description);
}
});
The RustoreUpdateClient.listener(callback) method has been preserved for backward compatibility. For new integrations, it is recommended to use RustoreUpdateClient.stateStream.
List of possible errors
RuStoreNotInstalledException— RuStore is not installed on the user's device;RuStoreOutdatedException— RuStore version installed on the user's device does not support this SDK;RuStoreUserUnauthorizedException— user is not authorized in RuStore;RuStoreException— basic RuStore error from which other errors are inherited;RuStoreInstallException(public val code: Int)— download and installation error.ERROR_UNKNOWN(Int = 4001)— unknown error.ERROR_DOWNLOAD(Int = 4002)— error while downloading.ERROR_BLOCKED(Int = 4003)— installation blocked by system.ERROR_INVALID_APK(Int = 4004)— invalid update APK.ERROR_CONFLICT(Int = 4005)— conflict with the current app version.ERROR_STORAGE(Int = 4006)— insufficient device storage.ERROR_INCOMPATIBLE(Int = 4007)— incompatible with device.ERROR_APP_NOT_OWNED(Int = 4008)— application not purchased.ERROR_INTERNAL_ERROR(Int = 4009)— internal error.ERROR_ABORTED(Int = 4010)— user refused to install the update.ERROR_APK_NOT_FOUND(Int = 4011)— APK for installation not found.ERROR_EXTERNAL_SOURCE_DENIED(Int = 4012)— update prohibited. For example, the first method responses that an update is not available, but the user calls the second method.ERROR_ACTIVITY_SEND_INTENT(Int = 9901)— error while sending intent for opening an activity.ERROR_ACTIVITY_UNKNOWN(Int = 9902)— unknown error on activity opening.
List of dependencies for updating the application
ru.rustore.sdk:core:0.1.10— GNU Lesser General Public License v3.0;ru.rustore.sdk:analytics:0.1.5— GNU Lesser General Public License v3.0;org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20— The Apache Software License, Version 2.0;org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4— The Apache Software License, Version 2.0;androidx.core:core-ktx:1.9.0— The Apache Software License, Version 2.0;androidx.appcompat:appcompat:1.5.1— The Apache Software License, Version 2.0;androidx.activity:activity:1.5.1— The Apache Software License, Version 2.0.