AUI Framework
develop
Cross-platform base for C++ UI apps
|
Deliver updates on non-centralized distribution methods. More...
aui.updater
module expects your program to be installed to user's directory (i.e., updating does not require admin priveleges). If that's not your case, you'll need to update your installer configuration to install to user's directory (i.e., in AppData
).
aui::updater
supports the following platforms:
On a supported platform, aui::updater
checks if the app executable is writable by the current user. If the executable is not writeable, or running on a non-supported platform, AUpdater
stubs it's methods (i.e., they do nothing). You can check that the aui::updater
functionality is engaged by calling AUpdater::isAvailable()
.
Updating process requires the initial application running instance to be stopped to replace its files with newer ones. Additionally, the updater process starts the newer version of the application after replacing the files (applying/deploying an update). To minimize downtime for end-users, the replacement should be seamless and quick and thus the deployment process just copies newer files (overwriting old ones), it does not involve network operations.
AUpdater
lives inside entrypoint of your application. It needs you to pass program arguments. It might decide to terminate process execution via std::exit.
You can pass updater instance to your window (as shown in the example) and display update information from AUpdater::status
and perform the update when requested.
Status of the AUpdater to observe from outside, i.e., by UI.
status
is updated in UI thread only.
status
is designed in such a way the user can use their own custom status types or any of predefined ones:
These statuses might be set by AUpdater itself.
Typical observer of status is a UI projection displaying its value. You can even display controls in it:
AUpdater expects AUpdater::checkForUpdates to be called to check for updates. It can be called once per some period of time. It calls user-defined AUpdater::checkForUpdatesImpl to perform an update checking.
The update steps are reported by changing AUpdater::status
property.
You might want to store update check results (i.e., download url) in your implementation of AUpdater::checkForUpdatesImpl so your AUpdater::downloadUpdateImpl might reuse this information.
When an update is found, your app should call AUpdater::downloadUpdate to download and unpack the update. It is up to you to decide when to download an update. If you wish, you can call AUpdater::downloadUpdate in AUpdater::checkForUpdatesImpl to proceed to download process right after update was found (see Updater workflows for more information about update workflow decisions). It calls user-defined AUpdater::downloadUpdateImpl which might choose to call default AUpdater::downloadAndUnpack(<YOUR DOWNLOAD URL>, unpackedUpdateDir)
.
At this moment, AUpdater waits AUpdater::applyUpdateAndRestart to be called. When AUpdater::applyUpdateAndRestart is called (i.e., when user accepted update installation), AUpdater executes the newer copy of your app downloaded before with a special command line argument which is handled by AUpdater::handleStartup in that executable. The initial app process is finished, closing your app window as well. From now, your app is in "downtime" state, so we need to apply the update and reopen app back again as quickly as possible. This action is required to perform update installation. The copy then replaces old application (where it actually installed) with itself (that is, the downloaded, newer copy). After operation is complete, it passes the control back to the updated application executable. At last, the newly updated application performs a cleanup after update.
After these operations complete, your app is running in its normal lifecycle.
AUpdater is an abstract class; it needs some functions to be implemented by you.
In this example, let's implement auto update from GitHub release pages.
When using AUpdater for your application, you need to consider several factors including usability, user experience, system resources, and particular needs of your project.
Either way, you might want to implement a way to disable auto update feature in your application.
This approach is implemented in AUI's App Template ⚡.
The updater checks for updater periodically or upon user request and informs the user that an update is available. The user then decides whether to proceed with update or not. If they agree the application will download and install the update.
This way can be considered as better approach because the user may feel they control the situation and the application never does things that user never asked to (trust concerns). On the other hand, such requirement of additional user interaction to can distract them from doing their work, so these interactions should not be annoying.
You should not use AMessageBox (unless user explicitly asked to check for update) as it literally interrupts the user's workflow, opting them to make a decision before they can continue their work. A great example of a bad auto update implementation is qBittorrent client on Windows: hence this application typically launches on OS startup, it checks for updates in background and pops the message box if update was found, even if user is focused on another application or away from keyboard.
This approach is implemented in AUI Telegram Client (AUIgram), as well as in official Qt-based Telegram Desktop client.
The updater silently downloads the update in the background while the user continues working within the application or even other tasks. The update then is applied automatically upon restart. Optionally, the application might show a button/message/notification bubble to restart and apply update.
Despite user trust concerns, this approach allows seamless experience - users don't need to be interrupted during their work. They even might not care about updates.
Classes# | |
struct | aui::updater::AppropriatePortablePackagePredicate |
Determines whether the passed package name is a portable package that matches current arch and platform. More... | |
class | AUpdater |
Updater class. More... | |
struct | aui::updater::Semver |
Semantic version. More... | |