目录

On-Demand Feature Distribution (C/C++)

Starting from version 26.0.0, a new API is added to allow users to pause download tasks.

Use Cases

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.

Basic Concepts

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.

Constraints

API Description

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.

Instructions

To use the on-demand distribution capability provided by ModuleInstall, add the corresponding header file.

[h2]Linking the Dynamic Library in the CMake Script

target_link_libraries(entry PUBLIC ${module_install_lib})

[h2]Adding the Header File

You can use APIs related to on-demand distribution only after importing the module_install.h header file.

#include "AppGalleryKit/module_install.h"

Obtaining Module Installation Information

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;
}

Loading a Module on Demand

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;
}

Pausing a Download Task

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.
}

Resuming a Download Task

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;
    }
}

Canceling a Download Task

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.
}

Displaying a Mobile Data Reminder Pop-up

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.
}

Listening for Download Tasks

[h2]Defining a Callback Function to Listen for Download Tasks

void onEvent(char *bundleName, char *eventInfo) {
    // Handle the callback.
    // ...
}

[h2]Initializing the Download Progress 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);

[h2]Listening for the Download Progress

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);

Canceling the Download Task Listener

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.
}

Complete Sample Code

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);
}