• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# AppStartup
2
3
4## Overview
5
6During application launch, a series of startup tasks are often required. If all these tasks are placed within the [onCreate](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityoncreate) lifecycle of the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) in the application's main module ([module](../quick-start/application-package-overview.md#module-types) of the entry type), they can only be executed sequentially on the main thread, which significantly affects the application launch speed. In addition, when there are too many tasks, complex dependencies between them make the code difficult to maintain.
7
8AppStartup offers an efficient approach to application launch. By supporting asynchronous initiation of startup tasks, it ensures a smoother startup process. The centralized configuration of execution order and dependencies of multiple startup tasks in a single file simplifies and clarifies the startup codebase, enhancing maintainability.
9
10## Working Mechanism
11
12AppStartup supports startup tasks in automatic or manual mode. By default, automatic mode is used. During the creation of an [AbilityStage](../reference/apis-ability-kit/js-apis-app-ability-abilityStage.md), the configured startup tasks are loaded and executed in automatic mode. You can also call [startupManager.run](../reference/apis-ability-kit/js-apis-app-appstartup-startupManager.md#startupmanagerrun) to execute the startup tasks in manual mode after an AbilityStage is created.
13
14**Figure 1** Startup procedure
15
16![app-startup-procedure](figures/app-startup-procedure.png)
17
18
19## Supported Scope
20
21- AppStartup is only triggered when the entry UIAbility is launched. It is not triggered when ExtensionAbility or non-entry UIAbility are launched.
22
23- Starting from API version 18, AppStartup supports configuring startup tasks in [HSP](../quick-start/har-package.md) and [HAR](../quick-start/in-app-hsp.md) modules. However, startup tasks and .so file preloading tasks in the HSP and HAR modules cannot be explicitly set to automatic mode. They can be initiated by startup tasks and .so file preloading tasks of the entry module that are in automatic mode.
24
25- Starting from API version 18, AppStartup supports the configuration of .so file preloading tasks. For details about how to develop .so files, refer to [Node-API](../napi/use-napi-process.md) to create a native C++ project.
26
27
28## Constraints
29
30- AppStartup must be enabled in the [module.json5 file](../quick-start/module-configuration-file.md) of the entry-type [module](../quick-start/application-package-overview.md#module-types) before being used.
31
32- Circular dependencies between startup tasks or .so file preloading tasks are not allowed.
33
34
35## Development Process
36
371. [Defining an AppStartup Configuration File](#defining-an-appstartup-configuration-file): Create an AppStartup configuration file in the resource file directory, add the configuration about startup tasks, and reference this configuration file in [module.json5](../quick-start/module-configuration-file.md).
382. [Setting Startup Parameters](#setting-startup-parameters): In the startup parameter file, set parameters such as the timeout interval and startup task listener.
393. [Adding a Startup Task for Each Component to Be Initialized](#adding-a-startup-task-for-each-component-to-be-initialized): Implement the [StartupTask](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md) interface.
40
41## How to Develop
42
43### Defining an AppStartup Configuration File
44
451. Create an AppStartup configuration file in the **resources/base/profile** directory of the application's main module ([module](../quick-start/application-package-overview.md#module-types) of the entry type). The file name can be customized. The following uses **startup_config.json** as an example.
46
472. In the **startup_config.json** file, add the configuration for each startup task and .so file preloading task in sequence.
48
49    It is assumed that the application has six startup tasks and six .so file preloading tasks. The dependencies between the tasks are shown in the figure below. To facilitate concurrent execution of startup tasks, a startup task file should contain only one startup task. In this example, each startup task corresponds to a startup task file. You are not advised to run code logic in the loading callback of .so files, as prolonged .so file loading can adversely affect the main thread's operation.
50
51    **Figure 2** Dependencies between the startup tasks and .so file preloading tasks
52
53    ![app-startup](figures/app-startup.png)
54
55    1. In the **ets/startup** directory, create six startup task files and a common startup parameter file. The file names must be unique.
56
57        1. Create six startup task files. In this example, the six files are named from **StartupTask_001.ets** to **StartupTask_006.ets**.
58        2. Create.so files by referring to [Node-API](../napi/use-napi-process.md). In this example, the six files are named from **libentry_001.so** to **libentry_006.so**.
59        3. Create a startup parameter file. In this example, the file name is **StartupConfig.ets**.
60
61    2. Add the information about the startup task files and startup parameter file to the **startup_config.json** file.
62
63        The following is an example of the **startup_config.json** file of the application's main module:
64
65        ```json
66        {
67          "startupTasks": [
68            {
69              "name": "StartupTask_001",
70              "srcEntry": "./ets/startup/StartupTask_001.ets",
71              "dependencies": [
72                "StartupTask_002",
73                "StartupTask_003"
74              ],
75              "runOnThread": "taskPool",
76              "waitOnMainThread": false
77            },
78            {
79              "name": "StartupTask_002",
80              "srcEntry": "./ets/startup/StartupTask_002.ets",
81              "dependencies": [
82                "StartupTask_003",
83                "StartupTask_004"
84              ],
85              "runOnThread": "taskPool",
86              "waitOnMainThread": false
87            },
88            {
89              "name": "StartupTask_003",
90              "srcEntry": "./ets/startup/StartupTask_003.ets",
91              "dependencies": [
92                "StartupTask_004"
93              ],
94              "runOnThread": "taskPool",
95              "waitOnMainThread": false
96            },
97            {
98              "name": "StartupTask_004",
99              "srcEntry": "./ets/startup/StartupTask_004.ets",
100              "runOnThread": "taskPool",
101              "waitOnMainThread": false
102            },
103            {
104              "name": "StartupTask_005",
105              "srcEntry": "./ets/startup/StartupTask_005.ets",
106              "dependencies": [
107                "StartupTask_006"
108              ],
109              "runOnThread": "mainThread",
110              "waitOnMainThread": true,
111              "excludeFromAutoStart": true
112            },
113            {
114              "name": "StartupTask_006",
115              "srcEntry": "./ets/startup/StartupTask_006.ets",
116              "runOnThread": "mainThread",
117              "waitOnMainThread": false,
118              "excludeFromAutoStart": true
119            }
120          ],
121          "appPreloadHintStartupTasks": [
122            {
123              "name": "libentry_001",
124              "srcEntry": "libentry_001.so",
125              "dependencies": [
126                "libentry_002",
127                "libentry_003"
128              ],
129              "runOnThread": "taskPool"
130            },
131            {
132              "name": "libentry_002",
133              "srcEntry": "libentry_002.so",
134              "dependencies": [
135                "libentry_003",
136                "libentry_004"
137              ],
138              "runOnThread": "taskPool"
139            },
140            {
141              "name": "libentry_003",
142              "srcEntry": "libentry_003.so",
143              "dependencies": [
144                "libentry_004"
145              ],
146              "runOnThread": "taskPool"
147            },
148            {
149              "name": "libentry_004",
150              "srcEntry": "libentry_004.so",
151              "runOnThread": "taskPool"
152            },
153            {
154              "name": "libentry_005",
155              "srcEntry": "libentry_005.so",
156              "dependencies": [
157                "libentry_006"
158              ],
159              "runOnThread": "taskPool",
160              "excludeFromAutoStart": true
161            },
162            {
163              "name": "libentry_006",
164              "srcEntry": "libentry_006.so",
165              "runOnThread": "taskPool",
166              "excludeFromAutoStart": true
167            }
168          ],
169          "configEntry": "./ets/startup/StartupConfig.ets"
170        }
171        ```
172
173
174        **Table 1** Fields in the startup_config.json file
175
176        | Field| Description| Data Type| Optional|
177        | -------- | -------- | -------- | -------- |
178        | startupTasks | Configuration about the startup tasks. For details, see the following table.| Object array| Optional, defaults to an empty array|
179        | appPreloadHintStartupTasks | Configuration about the .so file preloading tasks. For details, see the following table.| Object array| Optional, defaults to an empty array|
180        | configEntry | Path of the startup parameter file.<br>**NOTE**<br> Do not configure this field for the HSP and HAR.| String| Mandatory|
181
182
183        **Table 2** Description of startupTasks
184
185        | Field| Description| Data Type| Optional|
186        | -------- | -------- | -------- | -------- |
187        | name | Name of the startup task, which can be customized. It is recommended that the name be the same as the class name.| String| Mandatory|
188        | srcEntry | Path of the file corresponding to the startup task.| String| Mandatory|
189        | dependencies | Array holding the class names of other startup tasks on which this task depends.| Object array| Optional, defaults to an empty array|
190        | excludeFromAutoStart | Whether to exclude automatic mode. For details, see [Changing the Startup Mode](#optional-changing-the-startup-mode).<br>- **true**: manual mode.<br>- **false**: automatic mode.<br>**NOTE**<br> This field must be set to **true** for the HSP and HAR.| Boolean| Optional, defaults to **false**|
191        | runOnThread | Thread where the startup task is executed.<br>- **mainThread**: executed in the main thread.<br>- **taskPool**: executed in an asynchronous thread.| String| Optional, defaults to **mainThread**|
192        | waitOnMainThread | Whether the main thread needs to wait until the startup task finishes execution. This parameter is valid only when **runOnThread** is set to **taskPool**.<br>- **true**: The main thread loads the application home page only the startup task finishes execution.<br>- **false**: The main thread does not wait for the startup task to finish execution.| Boolean| Optional, defaults to **true**|
193
194        **Table 3** appPreloadHintStartupTasks
195
196        | Field| Description| Data Type| Optional|
197        | -------- | -------- | -------- | -------- |
198        | name | Name of the .so file to preload.| String| Mandatory|
199        | srcEntry | File name of the .so file, including the extension.| String| Mandatory|
200        | dependencies | Array holding the .so file names of other preloading tasks on which this task depends.| Object array| Optional, defaults to an empty array|
201        | excludeFromAutoStart | Whether to exclude automatic mode. For details, see [Changing the Startup Mode](#optional-changing-the-startup-mode).<br>- **true**: manual mode.<br>- **false**: automatic mode.<br>**NOTE**<br> This field must be set to **true** for the HSP and HAR.| Boolean| Optional, defaults to **false**|
202        | runOnThread | Thread where preloading is performed.<br>- **taskPool**: executed in an asynchronous thread.<br>**NOTE**<br> Preloading of .so files can be executed only in TaskPool threads.| String| Mandatory|
203
204
2053. Add the index of the AppStartup configuration file to the **appStartup** tag in the [module.json5 file](../quick-start/module-configuration-file.md).
206
207    The following is an example of the **module.json5** file:
208
209    ```json
210    {
211    "module": {
212    "name": "entry",
213    "type": "entry",
214    // ...
215    "appStartup": "$profile:startup_config," // AppStartup configuration file
216    // ...
217    }
218    }
219    ```
220
221### Setting Startup Parameters
222
223In the startup parameter file (**ets/startup/StartupConfig.ets** in this example), call [StartupConfigEntry](../reference/apis-ability-kit/js-apis-app-appstartup-startupConfigEntry.md) to set the common AppStartup parameters, including the timeout interval and listener.
224
225- [StartupConfig](../reference/apis-ability-kit/js-apis-app-appstartup-startupConfig.md): sets the task timeout interval and AppStartup listener.
226- [StartupListener](../reference/apis-ability-kit/js-apis-app-appstartup-startupListener.md): listens for the execution result of the startup task.
227
228```ts
229import { StartupConfig, StartupConfigEntry, StartupListener } from '@kit.AbilityKit';
230import { hilog } from '@kit.PerformanceAnalysisKit';
231import { BusinessError } from '@kit.BasicServicesKit';
232
233export default class MyStartupConfigEntry extends StartupConfigEntry {
234  onConfig() {
235    hilog.info(0x0000, 'testTag', `onConfig`);
236    let onCompletedCallback = (error: BusinessError<void>) => {
237      hilog.info(0x0000, 'testTag', `onCompletedCallback`);
238      if (error) {
239        hilog.info(0x0000, 'testTag', 'onCompletedCallback: %{public}d, message: %{public}s', error.code, error.message);
240      } else {
241        hilog.info(0x0000, 'testTag', `onCompletedCallback: success.`);
242      }
243    };
244    let startupListener: StartupListener = {
245      'onCompleted': onCompletedCallback
246    };
247    let config: StartupConfig = {
248      'timeoutMs': 10000,
249      'startupListener': startupListener
250    };
251    return config;
252  }
253}
254```
255
256### Adding a Startup Task for Each Component to Be Initialized
257
258Through the preceding operations, you have configured the AppStartup configuration file and startup parameters. Now you need to implement [StartupTask](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md) in each startup task file by calling the following two APIs:
259
260- [init](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md#startuptaskinit): starts task initialization. Call **init** to initialize a task only after all startup tasks on which the task depends are executed, that is, after **onDependencyCompleted** is invoked.
261- [onDependencyCompleted](../reference/apis-ability-kit/js-apis-app-appstartup-startupTask.md#startuptaskondependencycompleted): invoked when the startup task on which the current task depends is complete.
262
263
264The following uses the **StartupTask_001.ets** file in [startup_config.json](#defining-an-appstartup-configuration-file) as an example. You must add a startup task for each component to be initialized.
265
266> **NOTE**
267>
268> **StartupTask** follows the [Sendable protocol](../arkts-utils/arkts-sendable.md#sendable-protocol). Therefore, the Sendable annotation must be added when this API is inherited.
269
270```ts
271import { StartupTask, common } from '@kit.AbilityKit';
272import { hilog } from '@kit.PerformanceAnalysisKit';
273
274@Sendable
275export default class StartupTask_001 extends StartupTask {
276  constructor() {
277    super();
278  }
279
280  async init(context: common.AbilityStageContext) {
281    hilog.info(0x0000, 'testTag', 'StartupTask_001 init.');
282    return 'StartupTask_001';
283  }
284
285  onDependencyCompleted(dependence: string, result: Object): void {
286    hilog.info(0x0000, 'testTag', 'StartupTask_001 onDependencyCompleted, dependence: %{public}s, result: %{public}s',
287      dependence, JSON.stringify(result));
288  }
289}
290```
291
292 ### (Optional) Using AppStartup in the HSP and HAR
293
294 Large applications often consist of multiple [HSP](../quick-start/har-package.md) and [HAR](../quick-start/in-app-hsp.md) modules. This section provides an example to demonstrate how to use AppStartup in HSP and HAR packages. This example application includes two HSP packages (hsp1, hsp2) and one HAR package (har1), with startup tasks and .so file preloading tasks.
295
296 Perform the following steps:
297
298  1. Create an AppStartup configuration file under the **resources/base/profile** directory for each HSP and HAR, in addition to the main module. Different modules can use the same file name. The following uses **startup_config.json** as an example.
299
300  2. Configure the **startup_config.json** file for each module.
301
302        The table below lists the startup tasks and .so file preloading tasks available for the application.
303
304        **Table 4** Startup tasks and .so file preloading tasks
305        | Module| Startup Task| Preloading Task|
306        | ------- | -------------------------------- | -------------------------------- |
307        | entry | HAP_Task_01 | libentry_01 |
308        | hsp1 | HSP1_Task_01 <br> HSP1_Task_02 | libhsp1_01 <br> libhsp1_02 |
309        | hsp2 | HSP2_Task_01 | libhsp2_01 |
310        | har | HAR1_Task_01 | libhar1_01 |
311
312        **Figure 3** Dependencies between the startup tasks and .so file preloading tasks
313
314        ![app-startup](figures/hsp-har-startup.png)
315
316        For details about the **startup_config.json** file of the entry module, see [Defining an AppStartup Configuration File](#defining-an-appstartup-configuration-file). For the HSP and HAR, do not configure the **configEntry** field in the **startup_config.json** file. The following uses the configuration file of **hsp1** as an example:
317
318        ```json
319        {
320          "startupTasks": [
321            {
322              "name": "HSP1_Task_01",
323              "srcEntry": "./ets/startup/HSP1_Task_01.ets",
324              "dependencies": [
325                "HSP1_Task_02",
326                "HAR1_Task_01"
327              ],
328              "runOnThread": "taskPool",
329              "waitOnMainThread": false,
330              "excludeFromAutoStart": true
331            }
332          ],
333          "appPreloadHintStartupTasks": [
334            {
335              "name": "libhsp1_01",
336              "srcEntry": "libhsp1_01.so",
337              "dependencies": [
338                "libhsp1_02",
339                "libhar1_01"
340              ],
341              "runOnThread": "taskPool",
342              "excludeFromAutoStart": true
343            }
344          ]
345        }
346        ```
347
348  3. Add the index of the AppStartup configuration file to the **appStartup** tag in the [module.json5 file](../quick-start/module-configuration-file.md) of each module.
349
350        The following are examples of **module.json5** for **hsp1**, **hsp2**, and **har1**:
351
352        ```json
353        {
354          "module": {
355            "name": "hsp1",
356            "type": "shared",
357            // ...
358            "appStartup": "$profile:startup_config," // AppStartup configuration file
359            // ...
360          }
361        }
362        ```
363        ```json
364        {
365          "module": {
366            "name": "hsp2",
367            "type": "shared",
368            // ...
369            "appStartup": "$profile:startup_config," // AppStartup configuration file
370            // ...
371          }
372        }
373        ```
374        ```json
375        {
376          "module": {
377            "name": "har1",
378            "type": "har",
379            // ...
380            "appStartup": "$profile:startup_config," // AppStartup configuration file
381            // ...
382          }
383        }
384        ```
385
386  For details about other steps, see [Setting Startup Parameters](#setting-startup-parameters) and [Adding a Startup Task for Each Component to Be Initialized](#adding-a-startup-task-for-each-component-to-be-initialized).
387
388
389### (Optional) Changing the Startup Mode
390
391AppStartup provides two modes for executing startup tasks: automatic and manual. The entry module defaults to automatic mode, but you can change it to manual mode if needed. The HSP and HAR support the configuration of manual mode only.
392
393- Automatic mode: After an AbilityStage is created, startup tasks are automatically executed.
394- Manual mode: After a UIAbility is created, you need to manually call the API to execute the startup tasks and .so file preloading tasks. Modules that are infrequently used do not need to be initialized when the application is launched. You can change the startup mode of these modules to manual. After the application finishes launching, you can call [startupManager.run](../reference/apis-ability-kit/js-apis-app-appstartup-startupManager.md#startupmanagerrun) to execute the startup tasks and .so file preloading tasks.
395
396The following uses the **onCreate** lifecycle of the UIAbility as an example to describe how to manually trigger a startup task. The sample code is as follows:
397
398```ts
399import { AbilityConstant, UIAbility, Want, startupManager } from '@kit.AbilityKit';
400import { hilog } from '@kit.PerformanceAnalysisKit';
401import { BusinessError } from '@kit.BasicServicesKit';
402
403export default class EntryAbility extends UIAbility {
404  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
405    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
406    let startParams = ["StartupTask_005", "StartupTask_006"];
407    try {
408      startupManager.run(startParams).then(() => {
409        console.log('StartupTest startupManager run then, startParams = ');
410      }).catch((error: BusinessError) => {
411        console.info('StartupTest promise catch error, error = ' + JSON.stringify(error));
412        console.info('StartupTest promise catch error, startParams = '
413          + JSON.stringify(startParams));
414      })
415    } catch (error) {
416      let errMsg = JSON.stringify(error);
417      let errCode: number = error.code;
418      console.log('Startup catch error , errCode= ' + errCode);
419      console.log('Startup catch error ,error= ' + errMsg);
420    }
421  }
422
423  // ...
424}
425```
426
427You can also call the API to trigger the manual mode after a page is loaded. The sample code is as follows:
428
429```ts
430import { startupManager } from '@kit.AbilityKit';
431
432@Entry
433@Component
434struct Index {
435  @State message: string = "Manual Mode";
436  @State startParams1: Array<string> = ["StartupTask_006"];
437  @State startParams2: Array<string> = ["libentry_006"];
438
439  build() {
440    RelativeContainer() {
441      Button(this.message)
442        .id('AppStartup')
443        .fontSize(20)
444        .fontWeight(FontWeight.Bold)
445        .onClick(() => {
446          if (!startupManager.isStartupTaskInitialized("StartupTask_006") ) { // Check whether the startup task finishes execution.
447            startupManager.run(this.startParams1)
448          }
449          if (!startupManager.isStartupTaskInitialized("libentry_006") ) {
450            startupManager.run(this.startParams2)
451          }
452        })
453        .alignRules({
454          center: {anchor: '__container__', align: VerticalAlign.Center},
455          middle: {anchor: '__container__', align: HorizontalAlign.Center}
456        })
457    }
458    .height('100%')
459    .width('100%')
460  }
461}
462```
463