Starting from version 26.0.0, a new API is added to allow users to pause download tasks.
As HarmonyOS apps continue to evolve, their features are becoming increasingly diverse. 80% of users tend to use just 20% of app features, while the remaining features are tailored to specific users. To prevent first-time app downloads from taking too long and using too much users' device space, AppGallery Kit offers on-demand distribution, which allows users to dynamically download enhanced features as needed.
On-demand distribution: An app is packaged into multiple installation packages, which contain all app code and static resources. The app downloaded from AppGallery contains only basic features. When a user needs to use enhanced features, they can download the corresponding installation packages from the server to their devices.
The app must be released on AppGallery.
On-demand feature distribution supports phones, tablets, and PCs/2-in-1 devices. Starting from version 5.1.1(19), it is also supported on TVs.
Before using on-demand feature distribution, you need to split your app into a basic package and enhanced feature modules. For details, please refer to Managing Modules.
On-demand feature distribution provides the following C APIs. For details, please refer to ModuleInstall.
| API | Description |
|---|---|
| HMS_ModuleInstall_GetInstalledModule | Queries whether a module has been installed. |
| HMS_ModuleInstall_GetInstalledModuleName | Obtains the module name. |
| HMS_ModuleInstall_GetInstalledModuleType | Obtains the module type. |
| HMS_ModuleInstall_GetModuleInstallStatus | Obtains the module installation status. |
| HMS_ModuleInstall_FetchModules | Requests to download a module. |
| HMS_ModuleInstall_GetFetchModulesRequestCode | Obtains the module download request code. |
| HMS_ModuleInstall_GetFetchModulesTaskStatus | Obtains the module download task status. |
| HMS_ModuleInstall_GetFetchModulesTaskId | Obtains the module download task ID. |
| HMS_ModuleInstall_GetFetchModulesDesc | Obtains the module download description. |
| HMS_ModuleInstall_GetFetchModules | Obtains the name of the downloaded module. |
| HMS_ModuleInstall_GetFetchModulesTotalSize | Obtains the total size of the downloaded module. |
| HMS_ModuleInstall_GetFetchModulesDownloadedSize | Obtains the downloaded size of the module. |
| HMS_ModuleInstall_CancelTask | Cancels a download task. |
| HMS_ModuleInstall_PauseTask | Pauses a download task. |
| HMS_ModuleInstall_ShowCellularDataConfirmation | Displays a mobile data reminder pop-up. |
| HMS_ModuleInstall_CreateStatusCallback | Creates a callback for listening for the download progress. |
| HMS_ModuleInstall_On | Listens for the download progress. |
| HMS_ModuleInstall_ReleaseStatusCallback | Releases the callback used for download progress listening. |
| HMS_ModuleInstall_Off | Cancels the download progress listener. |
To use the on-demand distribution capability provided by ModuleInstall, add the corresponding header file.
target_link_libraries(entry PUBLIC ${module_install_lib}) You can use APIs related to on-demand distribution only after importing the module_install.h header file.
#include "AppGalleryKit/module_install.h"
Before using the on-demand distribution capability, call the HMS_ModuleInstall_GetInstalledModule API to check whether the module to be distributed on demand has been installed. Then you can obtain the module name, module type, and module installation status through the HMS_ModuleInstall_GetInstalledModuleName, HMS_ModuleInstall_GetInstalledModuleType, and HMS_ModuleInstall_GetModuleInstallStatus APIs, respectively.
char *moduleName;
ModuleInstall_InstalledModule *installedModule;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_GetInstalledModule(moduleName, strlen(moduleName), &installedModule);
if (ret == E_NO_ERROR) {
char *installedModuleName = HMS_ModuleInstall_GetInstalledModuleName(installedModule);
int moduleType = HMS_ModuleInstall_GetInstalledModuleType(installedModule);
int installStatus = HMS_ModuleInstall_GetModuleInstallStatus(installedModule);
}
if (installedModule != nullptr) {
delete installedModule;
installedModule = nullptr;
} You can load a module for your app as required through the HMS_ModuleInstall_FetchModules API. Then you can obtain the module download information through the HMS_ModuleInstall_GetFetchModulesRequestCode, HMS_ModuleInstall_GetFetchModulesTaskStatus, HMS_ModuleInstall_GetFetchModulesTaskId, HMS_ModuleInstall_GetFetchModulesDesc, HMS_ModuleInstall_GetFetchModules, HMS_ModuleInstall_GetFetchModulesTotalSize, and HMS_ModuleInstall_GetFetchModulesDownloadedSize APIs.
char *bundleName;
unsigned int arraySize = 1;
// ...
char **moduleNames = new char *[arraySize];
for (int i = 0; i < arraySize; i++) {
moduleNames[i] = new char[256];
}
// ...
ModuleInstall_FetchModulesResult *fetchModulesResult;
ModuleInstall_ErrCode ret =
HMS_ModuleInstall_FetchModules(bundleName, strlen(bundleName), moduleNames, arraySize, &fetchModulesResult);
// ...
if (ret == E_NO_ERROR) {
ModuleInstall_RequestCode code = HMS_ModuleInstall_GetFetchModulesRequestCode(fetchModulesResult);
ModuleInstall_TaskStatus taskStatus = HMS_ModuleInstall_GetFetchModulesTaskStatus(fetchModulesResult);
char *taskId = HMS_ModuleInstall_GetFetchModulesTaskId(fetchModulesResult);
char *desc = HMS_ModuleInstall_GetFetchModulesDesc(fetchModulesResult);
char *modules = HMS_ModuleInstall_GetFetchModules(fetchModulesResult);
int totalSize = HMS_ModuleInstall_GetFetchModulesTotalSize(fetchModulesResult);
int downloadedSize = HMS_ModuleInstall_GetFetchModulesDownloadedSize(fetchModulesResult);
// ...
}
if (moduleNames != nullptr) {
delete[] moduleNames;
moduleNames = nullptr;
}
if (fetchModulesResult != nullptr) {
delete fetchModulesResult;
fetchModulesResult = nullptr;
} Call the HMS_ModuleInstall_PauseTask API to pause a download task.
char *taskId; // Download task ID.
// ...
ModuleInstall_ErrCode ret = HMS_ModuleInstall_PauseTask(taskId);
if (ret == E_NO_ERROR) {
// Download paused successfully.
} After a download task is paused using HMS_ModuleInstall_PauseTask, you can call the HMS_ModuleInstall_FetchModules API to resume the download task from the point where it was paused.
#include <cstring>
#include "AppGalleryKit/module_install.h"
// ...
// Pause a download task.
void PauseTask() {
char *taskId;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_PauseTask(taskId);
if (ret == E_NO_ERROR) {
// Download paused successfully.
}
}
// Resume the download task.
void FetchModules() {
char *bundleName;
int arraySize = 1;
char **moduleNames = new char *[arraySize];
for (int i = 0; i < arraySize; i++) {
moduleNames[i] = new char[256];
}
ModuleInstall_FetchModulesResult *fetchModulesResult;
ModuleInstall_ErrCode ret =
HMS_ModuleInstall_FetchModules(bundleName, strlen(bundleName), moduleNames, arraySize, &fetchModulesResult);
if (ret == E_NO_ERROR) {
ModuleInstall_TaskStatus taskStatus = HMS_ModuleInstall_GetFetchModulesTaskStatus(fetchModulesResult);
char *taskId = HMS_ModuleInstall_GetFetchModulesTaskId(fetchModulesResult);
ModuleInstall_RequestCode code = HMS_ModuleInstall_GetFetchModulesRequestCode(fetchModulesResult);
if (code == DOWNLOAD_WAIT_WIFI) {
int showResult;
ModuleInstall_ErrCode ret =
HMS_ModuleInstall_ShowCellularDataConfirmation(taskId, strlen(taskId), showResult);
}
char *desc = HMS_ModuleInstall_GetFetchModulesDesc(fetchModulesResult);
char *modules = HMS_ModuleInstall_GetFetchModules(fetchModulesResult);
int totalSize = HMS_ModuleInstall_GetFetchModulesTotalSize(fetchModulesResult);
int downloadedSize = HMS_ModuleInstall_GetFetchModulesDownloadedSize(fetchModulesResult);
}
if (moduleNames != nullptr) {
delete[] moduleNames;
moduleNames = nullptr;
}
if (fetchModulesResult != nullptr) {
delete fetchModulesResult;
fetchModulesResult = nullptr;
}
} Call the HMS_ModuleInstall_CancelTask API to cancel a download task.
char *taskId; // Download task ID.
int cancelResult; // Result of canceling the download task.
// ...
ModuleInstall_ErrCode ret = HMS_ModuleInstall_CancelTask(taskId, strlen(taskId), cancelResult);
if (ret == E_NO_ERROR && cancelResult == 0) {
// Download task canceled successfully.
} If DOWNLOAD_WAIT_WIFI is returned after the HMS_ModuleInstall_GetFetchModulesRequestCode API is called, you need to call the HMS_ModuleInstall_ShowCellularDataConfirmation API to display the mobile data reminder pop-up.
char *taskId; // Download task ID.
int showResult; // Result of displaying the mobile data reminder pop-up.
// ...
ModuleInstall_ErrCode ret = HMS_ModuleInstall_ShowCellularDataConfirmation(taskId, strlen(taskId), showResult);
if (ret == E_NO_ERROR && showResult == 0) {
// The mobile data reminder pop-up is successfully displayed.
} void onEvent(char *bundleName, char *eventInfo) {
// Handle the callback.
// ...
} The app can call HMS_ModuleInstall_CreateStatusCallback to initialize the download progress callback.
ModuleInstall_StatusCallback *statusCallback; ModuleInstall_OnStatusCallback onStatusCallback = onEvent; statusCallback = HMS_ModuleInstall_CreateStatusCallback(&onStatusCallback);
The app can listen for the download progress through the HMS_ModuleInstall_On API.
char *bundleName; // App package name. int appIndex; // App twin index. int period; // Listening period. // ... ModuleInstall_ErrCode ret = HMS_ModuleInstall_On(bundleName, strlen(bundleName), appIndex, period, &statusCallback);
The app can cancel the download progress listener through the HMS_ModuleInstall_Off API.
char *bundleName; // App package name.
int appIndex; // App twin index.
// ...
ModuleInstall_ErrCode ret = HMS_ModuleInstall_Off(bundleName, strlen(bundleName), appIndex);
if (ret == E_NO_ERROR) {
// The listener is successfully canceled.
} Refer to the following example to complete the on-demand distribution process:
#include <cstring>
#include "AppGalleryKit/module_install.h"
void GetInstalledModule() {
char *moduleName;
ModuleInstall_InstalledModule *installedModule;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_GetInstalledModule(moduleName, strlen(moduleName), &installedModule);
if (ret == E_NO_ERROR) {
char *installedModuleName = HMS_ModuleInstall_GetInstalledModuleName(installedModule);
int moduleType = HMS_ModuleInstall_GetInstalledModuleType(installedModule);
int installStatus = HMS_ModuleInstall_GetModuleInstallStatus(installedModule);
}
if (installedModule != nullptr) {
delete installedModule;
installedModule = nullptr;
}
}
void ShowCellularDataConfirmation(char *taskId) {
int showResult;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_ShowCellularDataConfirmation(taskId, strlen(taskId), showResult);
}
void CancelTask() {
char *taskId;
int cancelResult;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_CancelTask(taskId, strlen(taskId), cancelResult);
}
// Pause a download task.
void PauseTask() {
char *taskId;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_PauseTask(taskId);
if (ret == E_NO_ERROR) {
// Download paused successfully.
}
}
// Resume the download task.
void FetchModules() {
char *bundleName;
int arraySize = 1;
char **moduleNames = new char *[arraySize];
for (int i = 0; i < arraySize; i++) {
moduleNames[i] = new char[256];
}
ModuleInstall_FetchModulesResult *fetchModulesResult;
ModuleInstall_ErrCode ret =
HMS_ModuleInstall_FetchModules(bundleName, strlen(bundleName), moduleNames, arraySize, &fetchModulesResult);
if (ret == E_NO_ERROR) {
ModuleInstall_TaskStatus taskStatus = HMS_ModuleInstall_GetFetchModulesTaskStatus(fetchModulesResult);
char *taskId = HMS_ModuleInstall_GetFetchModulesTaskId(fetchModulesResult);
ModuleInstall_RequestCode code = HMS_ModuleInstall_GetFetchModulesRequestCode(fetchModulesResult);
if (code == DOWNLOAD_WAIT_WIFI) {
int showResult;
ModuleInstall_ErrCode ret =
HMS_ModuleInstall_ShowCellularDataConfirmation(taskId, strlen(taskId), showResult);
}
char *desc = HMS_ModuleInstall_GetFetchModulesDesc(fetchModulesResult);
char *modules = HMS_ModuleInstall_GetFetchModules(fetchModulesResult);
int totalSize = HMS_ModuleInstall_GetFetchModulesTotalSize(fetchModulesResult);
int downloadedSize = HMS_ModuleInstall_GetFetchModulesDownloadedSize(fetchModulesResult);
}
if (moduleNames != nullptr) {
delete[] moduleNames;
moduleNames = nullptr;
}
if (fetchModulesResult != nullptr) {
delete fetchModulesResult;
fetchModulesResult = nullptr;
}
}
void onEvent(char *bundleName, char *eventInfo) {
// ...
}
void On() {
char *bundleName;
int appIndex;
int period;
ModuleInstall_StatusCallback *statusCallback;
ModuleInstall_OnStatusCallback onStatusCallback = onEvent;
statusCallback = HMS_ModuleInstall_CreateStatusCallback(&onStatusCallback);
ModuleInstall_ErrCode ret = HMS_ModuleInstall_On(bundleName, strlen(bundleName), appIndex, period, &statusCallback);
}
void Off() {
char *bundleName;
int appIndex;
ModuleInstall_ErrCode ret = HMS_ModuleInstall_Off(bundleName, strlen(bundleName), appIndex);
}