1# Starting UIAbility in the Same Application
2
3
4[UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) is the minimum unit that can be scheduled by the system. Redirection between functional modules in a device involves starting of specific UIAbility components, which belong to the same or a different application (for example, starting the UIAbility of a third-party payment application).
5
6
7This topic describes how to start the UIAbility component that belongs to the same application. For details about component redirection between applications, see [Application Redirection](link-between-apps-overview.md). <!--Del-->For details about cross-device application component interaction, see [Inter-Device Application Component Interaction (Hopping)](inter-device-interaction-hop-overview.md).<!--DelEnd-->
8
9
10- [Starting UIAbility in the Same Application](#starting-uiability-in-the-same-application)
11- [Starting UIAbility in the Same Application and Obtaining the Return Result](#starting-uiability-in-the-same-application-and-obtaining-the-return-result)
12- [Starting a Specified Page of UIAbility](#starting-a-specified-page-of-uiability)
13<!--Del-->
14- [Starting UIAbility with Window Mode Specified (for System Applications Only)](#starting-uiability-with-window-mode-specified-for-system-applications-only)
15- [Using Call to Implement UIAbility Interaction (for System Applications Only)](#using-call-to-implement-uiability-interaction-for-system-applications-only)
16<!--DelEnd-->
17
18
19## Starting UIAbility in the Same Application
20
21This scenario is possible when an application contains multiple [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) components. For example, in a payment application, you may need to start the payment UIAbility from the entry UIAbility.
22
23Assume that your application has two UIAbility components: EntryAbility and FuncAbility, either in the same module or different modules. To start FuncAbility from EntryAbility, proceed as follows:
24
251. In EntryAbility, call [startAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) and pass the [want](../reference/apis-ability-kit/js-apis-app-ability-want.md) parameter to start the UIAbility instance. In the **want** parameter, **bundleName** indicates the bundle name of the application to start; **abilityName** indicates the name of the UIAbility to start; **moduleName** is required only when the target UIAbility belongs to a different module from EntryAbility; **parameters** is used to carry custom information. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability).
26
27    ```ts
28    import { common, Want } from '@kit.AbilityKit';
29    import { hilog } from '@kit.PerformanceAnalysisKit';
30    import { BusinessError } from '@kit.BasicServicesKit';
31
32    const TAG: string = '[Page_UIAbilityComponentsInteractive]';
33    const DOMAIN_NUMBER: number = 0xFF00;
34
35    @Entry
36    @Component
37    struct Page_UIAbilityComponentsInteractive {
38      private context = getContext(this) as common.UIAbilityContext;
39
40      build() {
41        Column() {
42          //...
43          List({ initialIndex: 0 }) {
44            ListItem() {
45              Row() {
46                //...
47              }
48              .onClick(() => {
49                // Context is a member of the ability object and is required for invoking inside a non-ability object.
50                // Pass in the Context object.
51                let wantInfo: Want = {
52                  deviceId: '', // An empty deviceId indicates the local device.
53                  bundleName: 'com.samples.stagemodelabilitydevelop',
54                  moduleName: 'entry', // moduleName is optional.
55                  abilityName: 'FuncAbilityA',
56                  parameters: {
57                    // Custom information.
58                    info: 'From Page_UIAbilityComponentsInteractive of EntryAbility',
59                  },
60                };
61                // context is the UIAbilityContext of the initiator UIAbility.
62                this.context.startAbility(wantInfo).then(() => {
63                  hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.');
64                }).catch((error: BusinessError) => {
65                  hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.');
66                });
67              })
68            }
69            //...
70          }
71          //...
72        }
73        //...
74      }
75    }
76    ```
77
782. In FuncAbility, use [onCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityoncreate) or [onNewWant()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityonnewwant) to receive the parameters passed in by EntryAbility.
79
80    ```ts
81    import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
82
83    export default class FuncAbilityA extends UIAbility {
84      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
85        // Receive the parameters passed by the initiator UIAbility.
86        let funcAbilityWant = want;
87        let info = funcAbilityWant?.parameters?.info;
88      }
89      //...
90    }
91    ```
92
93    > **NOTE**
94    >
95    > In FuncAbility started, you can obtain the PID and bundle name of the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) through **parameters** in the passed [want](../reference/apis-ability-kit/js-apis-app-ability-want.md) parameter.
96
973. To stop the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) instance after the FuncAbility service is not needed, call [terminateSelf()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself) in FuncAbility.
98
99    ```ts
100    import { common } from '@kit.AbilityKit';
101    import { hilog } from '@kit.PerformanceAnalysisKit';
102
103    const TAG: string = '[Page_FromStageModel]';
104    const DOMAIN_NUMBER: number = 0xFF00;
105
106    @Entry
107    @Component
108    struct Page_FromStageModel {
109      build() {
110        Column() {
111          //...
112          Button('FuncAbilityB')
113            .onClick(() => {
114              let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
115              // context is the UIAbilityContext of the UIAbility instance to stop.
116              context.terminateSelf((err) => {
117                if (err.code) {
118                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);
119                  return;
120                }
121              });
122            })
123        }
124        //...
125      }
126    }
127    ```
128
129    > **NOTE**
130    >
131    > When **terminateSelf()** is called to stop the UIAbility instance, the snapshot of the instance is retained by default. That is, the mission corresponding to the instance is still displayed in Recents. If you do not want to retain the snapshot, set **removeMissionAfterTerminate** under the [abilities](../quick-start/module-configuration-file.md#abilities) tag to **true** in the [module.json5 file](../quick-start/module-configuration-file.md) of the corresponding UIAbility.
132
1334. To stop all [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) instances of the application, call [killAllProcesses()](../reference/apis-ability-kit/js-apis-inner-application-applicationContext.md#applicationcontextkillallprocesses) of [ApplicationContext](../reference/apis-ability-kit/js-apis-inner-application-applicationContext.md).
134
135
136## Starting UIAbility in the Same Application and Obtaining the Return Result
137
138When starting FuncAbility from EntryAbility, you may want the result to be returned after the FuncAbility service is finished. For example, after the sign-in operation is finished in the sign-in [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) of your application, you want the sign-in result to be returned to the entry UIAbility.
139
1401. In EntryAbility, call [startAbilityForResult()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartabilityforresult-2) to start FuncAbility. Use **data** in the asynchronous callback to receive information returned after FuncAbility stops itself. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability).
141
142    ```ts
143    import { common, Want } from '@kit.AbilityKit';
144    import { hilog } from '@kit.PerformanceAnalysisKit';
145    import { promptAction } from '@kit.ArkUI';
146    import { BusinessError } from '@kit.BasicServicesKit';
147
148    const TAG: string = '[Page_UIAbilityComponentsInteractive]';
149    const DOMAIN_NUMBER: number = 0xFF00;
150
151    @Entry
152    @Component
153    struct Page_UIAbilityComponentsInteractive {
154      build() {
155        Column() {
156          //...
157          List({ initialIndex: 0 }) {
158            ListItem() {
159              Row() {
160                //...
161              }
162              .onClick(() => {
163                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
164                const RESULT_CODE: number = 1001;
165                let want: Want = {
166                  deviceId: '', // An empty deviceId indicates the local device.
167                  bundleName: 'com.samples.stagemodelabilitydevelop',
168                  moduleName: 'entry', // moduleName is optional.
169                  abilityName: 'FuncAbilityA',
170                  parameters: {
171                    // Custom information.
172                    info: 'From UIAbilityComponentsInteractive of EntryAbility',
173                  }
174                };
175                context.startAbilityForResult(want).then((data) => {
176                  if (data?.resultCode === RESULT_CODE) {
177                    // Parse the information returned by the target UIAbility.
178                    let info = data.want?.parameters?.info;
179                    hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? '');
180                    if (info !== null) {
181                      promptAction.showToast({
182                        message: JSON.stringify(info)
183                      });
184                    }
185                  }
186                  hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? '');
187                }).catch((err: BusinessError) => {
188                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
189                });
190              })
191            }
192            //...
193          }
194          //...
195        }
196        //...
197      }
198    }
199    ```
200
2012. Call [terminateSelfWithResult()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateselfwithresult) to stop FuncAbility. Use the input parameter [abilityResult](../reference/apis-ability-kit/js-apis-inner-ability-abilityResult.md) to carry the information that FuncAbility needs to return to EntryAbility.
202
203    ```ts
204    import { common } from '@kit.AbilityKit';
205    import { hilog } from '@kit.PerformanceAnalysisKit';
206
207    const TAG: string = '[Page_FuncAbilityA]';
208    const DOMAIN_NUMBER: number = 0xFF00;
209
210    @Entry
211    @Component
212    struct Page_FuncAbilityA {
213      build() {
214        Column() {
215          //...
216          List({ initialIndex: 0 }) {
217            ListItem() {
218              Row() {
219                //...
220              }
221              .onClick(() => {
222                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
223                const RESULT_CODE: number = 1001;
224                let abilityResult: common.AbilityResult = {
225                  resultCode: RESULT_CODE,
226                  want: {
227                    bundleName: 'com.samples.stagemodelabilitydevelop',
228                    moduleName: 'entry', // moduleName is optional.
229                    abilityName: 'FuncAbilityB',
230                    parameters: {
231                      info: 'From the Index page of FuncAbility',
232                    },
233                  },
234                };
235                context.terminateSelfWithResult(abilityResult, (err) => {
236                  if (err.code) {
237                    hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`);
238                    return;
239                  }
240                });
241              })
242            }
243            //...
244          }
245          //...
246        }
247        //...
248      }
249    }
250    ```
251
2523. After FuncAbility stops itself, EntryAbility uses [startAbilityForResult()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartabilityforresult-2) to receive the information returned by FuncAbility. The value of **RESULT_CODE** must be the same as that specified in the preceding step.
253
254    ```ts
255    import { common, Want } from '@kit.AbilityKit';
256    import { hilog } from '@kit.PerformanceAnalysisKit';
257    import { promptAction } from '@kit.ArkUI';
258    import { BusinessError } from '@kit.BasicServicesKit';
259
260    const TAG: string = '[Page_UIAbilityComponentsInteractive]';
261    const DOMAIN_NUMBER: number = 0xFF00;
262
263    @Entry
264    @Component
265    struct Page_UIAbilityComponentsInteractive {
266      build() {
267        Column() {
268          //...
269          List({ initialIndex: 0 }) {
270            ListItem() {
271              Row() {
272                //...
273              }
274              .onClick(() => {
275                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
276                const RESULT_CODE: number = 1001;
277
278                let want: Want = {
279                  deviceId: '', // An empty deviceId indicates the local device.
280                  bundleName: 'com.samples.stagemodelabilitydevelop',
281                  moduleName: 'entry', // moduleName is optional.
282                  abilityName: 'FuncAbilityA',
283                  parameters: {
284                    // Custom information.
285                    info: 'From UIAbilityComponentsInteractive of EntryAbility',
286                  }
287                };
288                context.startAbilityForResult(want).then((data) => {
289                  if (data?.resultCode === RESULT_CODE) {
290                    // Parse the information returned by the target UIAbility.
291                    let info = data.want?.parameters?.info;
292                    hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? '');
293                    if (info !== null) {
294                      promptAction.showToast({
295                        message: JSON.stringify(info)
296                      });
297                    }
298                  }
299                  hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? '');
300                }).catch((err: BusinessError) => {
301                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
302                });
303              })
304            }
305            //...
306          }
307          //...
308        }
309        //...
310      }
311    }
312    ```
313
314
315## Starting a Specified Page of UIAbility
316
317### Overview
318
319A [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) component can have multiple pages that each display in specific scenarios.
320
321A UIAbility component can be started in two modes:
322
323- Cold start: The UIAbility instance is totally closed before being started. This requires that the code and resources of the UIAbility instance be completely loaded and initialized.
324- Hot start: The UIAbility instance has been started, running in the foreground, and then switched to the background before being started again. In this case, the status of the UIAbility instance can be quickly restored.
325
326This section describes how to start a specified page in both modes: [cold start](#cold-starting-uiability) and [hot start](#hot-starting-uiability). Before starting a specified page, you will learn how to specify a startup page on the initiator UIAbility.
327
328
329### Specifying a Startup Page
330
331When the initiator [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) starts another UIAbility, it usually needs to redirect to a specified page of the target UIAbility. For example, with FuncAbility, which contains two pages, starting FuncAbility means to redirect to either of the pages: Index (corresponding to the home page) and Second (corresponding to feature A page). You can configure the specified page URL in the want parameter by adding a custom parameter to parameters in [want](../reference/apis-ability-kit/js-apis-app-ability-want.md). For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability).
332
333
334```ts
335import { common, Want } from '@kit.AbilityKit';
336import { hilog } from '@kit.PerformanceAnalysisKit';
337import { BusinessError } from '@kit.BasicServicesKit';
338
339const TAG: string = '[Page_UIAbilityComponentsInteractive]';
340const DOMAIN_NUMBER: number = 0xFF00;
341
342@Entry
343@Component
344struct Page_UIAbilityComponentsInteractive {
345  build() {
346    Column() {
347      //...
348      List({ initialIndex: 0 }) {
349        ListItem() {
350          Row() {
351            //...
352          }
353          .onClick(() => {
354            let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
355            let want: Want = {
356              deviceId: '', // An empty deviceId indicates the local device.
357              bundleName: 'com.samples.stagemodelabilityinteraction',
358              moduleName: 'entry', // moduleName is optional.
359              abilityName: 'FuncAbility',
360              parameters: { // Custom parameter used to pass the page information.
361                router: 'funcA'
362              }
363            };
364            // context is the UIAbilityContext of the initiator UIAbility.
365            context.startAbility(want).then(() => {
366              hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ability.');
367            }).catch((err: BusinessError) => {
368              hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
369            });
370          })
371        }
372        //...
373      }
374      //...
375    }
376    //...
377  }
378}
379```
380
381
382### Cold Starting UIAbility
383
384In cold start mode, obtain the parameters from the initiator [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) through the [onCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityoncreate) callback of the target UIAbility. Then, in the [onWindowStageCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) callback of the target UIAbility, parse the [want](../reference/apis-ability-kit/js-apis-app-ability-want.md) parameter passed by the EntryAbility to obtain the URL of the page to be loaded, and pass the URL to the [windowStage.loadContent()](../reference/apis-arkui/js-apis-window.md#loadcontent9) method.
385
386
387```ts
388import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
389import { hilog } from '@kit.PerformanceAnalysisKit';
390import { window, UIContext } from '@kit.ArkUI';
391
392const DOMAIN_NUMBER: number = 0xFF00;
393const TAG: string = '[EntryAbility]';
394
395export default class EntryAbility extends UIAbility {
396  funcAbilityWant: Want | undefined = undefined;
397  uiContext: UIContext | undefined = undefined;
398
399  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
400    // Receive the parameters passed by the initiator UIAbility.
401    this.funcAbilityWant = want;
402  }
403
404  onWindowStageCreate(windowStage: window.WindowStage): void {
405    // Main window is created. Set a main page for this UIAbility.
406    hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');
407    // Main window is created. Set a main page for this UIAbility.
408    let url = 'pages/Index';
409    if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
410      url = 'pages/Page_ColdStartUp';
411    }
412    windowStage.loadContent(url, (err, data) => {
413      // ...
414    });
415  }
416}
417```
418
419### Hot Starting UIAbility
420
421If the target [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) has been started, the initialization logic is not executed again. Instead, the [onNewWant()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityonnewwant) lifecycle callback is directly triggered. To implement redirection, parse the required parameters in **onNewWant()**.
422
423An example scenario is as follows:
424
4251. A user opens the SMS application. The UIAbility instance of the SMS application is started, and the home page of the application is displayed.
4262. The user returns to the home screen, and the SMS application switches to the background.
4273. The user opens the Contacts application and finds a contact.
4284. The user touches the SMS button next to the contact. The UIAbility instance of the SMS application is restarted.
4295. Since the UIAbility instance of the SMS application has been started, the onNewWant() callback of the UIAbility is triggered, and the initialization logic such as [onCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityoncreate) and [onWindowStageCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) is skipped.
430
431**Figure 1** Hot starting the target UIAbility
432
433![](figures/uiability-hot-start.png)
434
435The development procedure is as follows:
436
4371. When the UIAbility instance of the SMS application is cold started, call [getUIContext()](../reference/apis-arkui/js-apis-window.md#getuicontext10) in the [onWindowStageCreate()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityonwindowstagecreate) lifecycle callback to obtain the [UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md).
438
439    ```ts
440    import { hilog } from '@kit.PerformanceAnalysisKit';
441    import { Want, UIAbility } from '@kit.AbilityKit';
442    import { window, UIContext } from '@kit.ArkUI';
443
444    const DOMAIN_NUMBER: number = 0xFF00;
445    const TAG: string = '[EntryAbility]';
446
447    export default class EntryAbility extends UIAbility {
448      funcAbilityWant: Want | undefined = undefined;
449      uiContext: UIContext | undefined = undefined;
450
451      // ...
452
453      onWindowStageCreate(windowStage: window.WindowStage): void {
454        // Main window is created. Set a main page for this UIAbility.
455        hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');
456        let url = 'pages/Index';
457        if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
458          url = 'pages/Page_ColdStartUp';
459        }
460
461        windowStage.loadContent(url, (err, data) => {
462          if (err.code) {
463            return;
464          }
465
466          let windowClass: window.Window;
467          windowStage.getMainWindow((err, data) => {
468            if (err.code) {
469              hilog.error(DOMAIN_NUMBER, TAG, `Failed to obtain the main window. Code is ${err.code}, message is ${err.message}`);
470              return;
471            }
472            windowClass = data;
473            this.uiContext = windowClass.getUIContext();
474          });
475          hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
476        });
477      }
478    }
479    ```
480
4812. Parse the [want](../reference/apis-ability-kit/js-apis-app-ability-want.md) parameter passed in the [onNewWant()](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityonnewwant) callback of the UIAbility of the SMS application, call [getRouter()](../reference/apis-arkui/js-apis-arkui-UIContext.md#getrouter) in the [UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md) class to obtain a [Router](../reference/apis-arkui/js-apis-arkui-UIContext.md#router) instance, and specify the target page. When the UIAbility instance of the SMS application is started again, the specified page of the UIAbility instance of the SMS application is displayed.
482
483    ```ts
484    import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
485    import { hilog } from '@kit.PerformanceAnalysisKit';
486    import type { Router, UIContext } from '@kit.ArkUI';
487    import type { BusinessError } from '@kit.BasicServicesKit';
488
489    const DOMAIN_NUMBER: number = 0xFF00;
490    const TAG: string = '[EntryAbility]';
491
492    export default class EntryAbility extends UIAbility {
493      funcAbilityWant: Want | undefined = undefined;
494      uiContext: UIContext | undefined = undefined;
495      // ...
496      onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
497        if (want?.parameters?.router && want.parameters.router === 'funcA') {
498          let funcAUrl = 'pages/Page_HotStartUp';
499          if (this.uiContext) {
500            let router: Router = this.uiContext.getRouter();
501            router.pushUrl({
502              url: funcAUrl
503            }).catch((err: BusinessError) => {
504              hilog.error(DOMAIN_NUMBER, TAG, `Failed to push url. Code is ${err.code}, message is ${err.message}`);
505            });
506          }
507        }
508      }
509    }
510    ```
511
512> **NOTE**
513>
514> When the [launch type of the target UIAbility](uiability-launch-type.md) is set to **multiton**, a new instance is created each time the target UIAbility is started. In this case, the **onNewWant()** callback will not be invoked.
515
516<!--Del-->
517## Starting UIAbility with Window Mode Specified (for System Applications Only)
518
519By specifying the window mode when starting the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) of an application, you can have the application displayed in the specified window mode, which can be full-screen, floating window, or split-screen.
520
521In full-screen mode, an application occupies the entire screen after being started. Users cannot view other windows or applications. This mode is suitable for an application that requires users to focus on a specific task or UI.
522
523In floating window mode, an application is displayed on the screen as a floating window after being started. Users can easily switch to other windows or applications. This mode is suitable for an application that allows users to process multiple tasks at the same time.
524
525In split-screen mode, two applications occupy the entire screen, side by side, horizontally or vertically. This mode helps users improve multi-task processing efficiency.
526
527The window mode is specified by the **windowMode** field in the [StartOptions](../reference/apis-ability-kit/js-apis-app-ability-startOptions.md) parameter of [startAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability).
528
529> **NOTE**
530>
531> - If the **windowMode** field is not specified, the UIAbility is started in the default window mode.
532> - To ensure that the application can be displayed in the required window mode, check the **supportWindowMode** field under [abilities](../quick-start/module-configuration-file.md#abilities) in the [module.json5 file](../quick-start/module-configuration-file.md) of the UIAbility and make sure the specified window mode is supported.
533
534The following describes how to start the FuncAbility from the EntryAbility page and display it in floating window mode.
535
5361. Add the **StartOptions** parameter in **startAbility()**.
5372. Set the **windowMode** field in the **StartOptions** parameter to **WINDOW_MODE_FLOATING**. This setting applies only to a system application.
5383. In the case of a third-party application, set the **displayId** field instead.
539
540For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](uiability-usage.md#obtaining-the-context-of-uiability).
541
542```ts
543import { AbilityConstant, common, Want, StartOptions } from '@kit.AbilityKit';
544import { hilog } from '@kit.PerformanceAnalysisKit';
545import { BusinessError } from '@kit.BasicServicesKit';
546
547const TAG: string = '[Page_UIAbilityComponentsInteractive]';
548const DOMAIN_NUMBER: number = 0xFF00;
549
550@Entry
551@Component
552struct Page_UIAbilityComponentsInteractive {
553  build() {
554    Column() {
555      //...
556      List({ initialIndex: 0 }) {
557        ListItem() {
558          Row() {
559            //...
560          }
561          .onClick(() => {
562            let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
563            let want: Want = {
564              deviceId: '', // An empty deviceId indicates the local device.
565              bundleName: 'com.samples.stagemodelabilitydevelop',
566              moduleName: 'entry', // moduleName is optional.
567              abilityName: 'FuncAbilityB',
568              parameters: {
569                // Custom information.
570                info: 'From the Index page of EntryAbility',
571              }
572            };
573            let options: StartOptions = {
574              windowMode: AbilityConstant.WindowMode.WINDOW_MODE_FLOATING
575            };
576            // context is the UIAbilityContext of the initiator UIAbility.
577            context.startAbility(want, options).then(() => {
578              hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in starting ability.');
579            }).catch((err: BusinessError) => {
580              hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
581            });
582          })
583        }
584        //...
585      }
586      //...
587    }
588    //...
589  }
590}
591```
592
593The display effect is shown below.
594
595![](figures/start-uiability-floating-window.png)
596
597
598## Using Call to Implement UIAbility Interaction (for System Applications Only)
599
600Call is an extension of the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) capability. It enables the UIAbility to be invoked by and communicate with external systems. The UIAbility invoked can be either started in the foreground or created and run in the background. You can use the call to implement data sharing between two UIAbility instances (CallerAbility and CalleeAbility) through IPC.
601
602The core API used for the call is [startAbilityByCall()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartabilitybycall), which differs from [startAbility()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) in the following ways:
603
604- **startAbilityByCall()** supports UIAbility launch in the foreground and background, whereas **startAbility()** supports UIAbility launch in the foreground only.
605
606- The CallerAbility can use the [Caller](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#caller) object returned by **startAbilityByCall()** to communicate with the CalleeAbility, but **startAbility()** does not provide the communication capability.
607
608Call is usually used in the following scenarios:
609
610- Communicating with the CalleeAbility
611
612- Starting the CalleeAbility in the background
613
614
615**Table 1** Terms used in the call
616
617| **Term**| Description|
618| -------- | -------- |
619| CallerAbility| UIAbility that triggers the call.|
620| CalleeAbility | UIAbility invoked by the call.|
621| Caller | Object returned by **startAbilityByCall** and used by the CallerAbility to communicate with the CalleeAbility.|
622| Callee | Object held by the CalleeAbility to communicate with the CallerAbility.|
623
624The following figure shows the call process.
625
626**Figure 1** Call process
627
628![call](figures/call.png)
629
630- The CallerAbility uses [startAbilityByCall()](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartabilitybycall) to obtain a [Caller](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#caller) object and uses [call](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#callercall) of the Caller object to send data to the CalleeAbility.
631
632- The CalleeAbility, which holds a [Callee](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#callee) object, uses [on](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#calleeon) of the Callee object to register a callback. This callback is invoked when the CalleeAbility receives data from the CallerAbility.
633
634> **NOTE**
635>
636> Currently, only system applications can use the call.
637>
638> The launch type of the CalleeAbility must be **singleton**.
639>
640> Both local (intra-device) and cross-device calls are supported. The following describes how to initiate a local call. For details about how to initiate a cross-device call, see [Using Cross-Device Call](hop-multi-device-collaboration.md#using-cross-device-call).
641
642
643### Available APIs
644
645The following table describes the main APIs used for the call. For details, see [AbilityContext](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#caller).
646
647**Table 2** Call APIs
648
649| API| Description|
650| -------- | -------- |
651| startAbilityByCall(want: Want): Promise&lt;Caller&gt; | Starts a UIAbility in the foreground (through the **want** configuration) or background (default) and obtains the caller object for communication with the UIAbility. For details, see [AbilityContext](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#abilitycontextstartabilitybycall) or **ServiceExtensionContext**.|
652| on(method: string, callback: CalleeCallBack): void | Callback invoked when the CalleeAbility registers a method.|
653| off(method: string): void | Callback invoked when the CalleeAbility deregisters a method.|
654| call(method: string, data: rpc.Parcelable): Promise&lt;void&gt; | Sends agreed parcelable data to the CalleeAbility.|
655| callWithResult(method: string, data: rpc.Parcelable): Promise&lt;rpc.MessageSequence&gt; | Sends agreed parcelable data to the CalleeAbility and obtains the agreed parcelable data returned by the CalleeAbility.|
656| release(): void | Releases the caller object.|
657| on(type: "release", callback: OnReleaseCallback): void| Callback invoked when the caller object is released.|
658
659The implementation of using the call for [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) interaction involves two parts:
660
661- [Creating a CalleeAbility](#creating-a-calleeability)
662
663- [Accessing the CalleeAbility](#accessing-the-calleeability)
664
665
666### Creating a CalleeAbility
667
668For the CalleeAbility, implement the callback to receive data and the methods to marshal and unmarshal data. When data needs to be received, use [on](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#calleeon) to register a listener. When data does not need to be received, use [off](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#calleeoff) to deregister the listener.
669
6701. Configure the launch type of the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md).
671
672   For example, set the launch type of the CalleeAbility to **singleton**. For details, see [UIAbility Component Launch Type](uiability-launch-type.md).
673
6742. Import the **UIAbility** module.
675
676   ```ts
677   import { UIAbility } from '@kit.AbilityKit';
678   ```
679
6803. Define the agreed parcelable data.
681
682   The data formats sent and received by the CallerAbility and CalleeAbility must be consistent. In the following example, the data formats are number and string.
683
684
685    ```ts
686    import { rpc } from '@kit.IPCKit';
687
688    class MyParcelable {
689      num: number = 0;
690      str: string = '';
691
692      constructor(num: number, string: string) {
693        this.num = num;
694        this.str = string;
695      }
696
697      mySequenceable(num: number, string: string): void {
698        this.num = num;
699        this.str = string;
700      }
701
702      marshalling(messageSequence: rpc.MessageSequence): boolean {
703        messageSequence.writeInt(this.num);
704        messageSequence.writeString(this.str);
705        return true;
706      }
707
708      unmarshalling(messageSequence: rpc.MessageSequence): boolean {
709        this.num = messageSequence.readInt();
710        this.str = messageSequence.readString();
711        return true;
712      }
713    }
714    ```
715
7164. Implement [Callee.on](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#calleeon) and [Callee.off](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#calleeoff).
717
718   The time to register a listener for the CalleeAbility depends on your application. The data sent and received before the listener is registered and that after the listener is deregistered are not processed. In the following example, the 'MSG_SEND_METHOD' listener is registered in [onCreate](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityoncreate) of the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) and deregistered in [onDestroy](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#uiabilityondestroy). After receiving parcelable data, the application processes the data and returns the data result. You need to implement processing based on service requirements. The sample code is as follows:
719
720
721    ```ts
722    import { AbilityConstant, UIAbility, Want, Caller } from '@kit.AbilityKit';
723    import { hilog } from '@kit.PerformanceAnalysisKit';
724    import { rpc } from '@kit.IPCKit';
725
726    const MSG_SEND_METHOD: string = 'CallSendMsg';
727    const DOMAIN_NUMBER: number = 0xFF00;
728    const TAG: string = '[CalleeAbility]';
729
730    class MyParcelable {
731      num: number = 0;
732      str: string = '';
733
734      constructor(num: number, string: string) {
735        this.num = num;
736        this.str = string;
737      }
738
739      mySequenceable(num: number, string: string): void {
740        this.num = num;
741        this.str = string;
742      }
743
744      marshalling(messageSequence: rpc.MessageSequence): boolean {
745        messageSequence.writeInt(this.num);
746        messageSequence.writeString(this.str);
747        return true;
748      }
749
750      unmarshalling(messageSequence: rpc.MessageSequence): boolean {
751        this.num = messageSequence.readInt();
752        this.str = messageSequence.readString();
753        return true;
754      }
755    }
756
757    function sendMsgCallback(data: rpc.MessageSequence): rpc.Parcelable {
758      hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'CalleeSortFunc called');
759
760      // Obtain the parcelable data sent by the CallerAbility.
761      let receivedData: MyParcelable = new MyParcelable(0, '');
762      data.readParcelable(receivedData);
763      hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', `receiveData[${receivedData.num}, ${receivedData.str}]`);
764      let num: number = receivedData.num;
765
766      // Process the data.
767      // Return the parcelable data result to the CallerAbility.
768      return new MyParcelable(num + 1, `send ${receivedData.str} succeed`) as rpc.Parcelable;
769    }
770
771    export default class CalleeAbility extends UIAbility {
772      caller: Caller | undefined;
773
774      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
775        try {
776          this.callee.on(MSG_SEND_METHOD, sendMsgCallback);
777        } catch (error) {
778          hilog.error(DOMAIN_NUMBER, TAG, '%{public}s', `Failed to register. Error is ${error}`);
779        }
780      }
781
782      releaseCall(): void {
783        try {
784          if (this.caller) {
785            this.caller.release();
786            this.caller = undefined;
787          }
788          hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'caller release succeed');
789        } catch (error) {
790          hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', `caller release failed with ${error}`);
791        }
792      }
793
794      onDestroy(): void {
795        try {
796          this.callee.off(MSG_SEND_METHOD);
797          hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Callee OnDestroy');
798          this.releaseCall();
799        } catch (error) {
800          hilog.error(DOMAIN_NUMBER, TAG, '%{public}s', `Failed to register. Error is ${error}`);
801        }
802      }
803    }
804    ```
805
806
807### Accessing the CalleeAbility
808
8091. Import the [UIAbility](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) module.
810
811    ```ts
812    import { UIAbility } from '@kit.AbilityKit';
813    ```
814
8152. Obtain the [Caller](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#caller) object.
816
817   The [UIAbilityContext](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md) attribute implements [startAbilityByCall](../reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartabilitybycall) to obtain the Caller object for communication. The following example uses **this.context** to obtain the UIAbilityContext, uses **startAbilityByCall** to start the CalleeAbility, obtain the Caller object, and register the [onRelease](../reference/apis-ability-kit/js-apis-app-ability-uiAbility.md#calleronrelease) listener of the CallerAbility. You need to implement processing based on service requirements.
818
819
820    ```ts
821    import { common, Want, Caller } from '@kit.AbilityKit';
822    import { hilog } from '@kit.PerformanceAnalysisKit';
823    import { promptAction } from '@kit.ArkUI';
824    import { BusinessError } from '@kit.BasicServicesKit';
825
826    const TAG: string = '[Page_UIAbilityComponentsInteractive]';
827    const DOMAIN_NUMBER: number = 0xFF00;
828
829    @Entry
830    @Component
831    struct Page_UIAbilityComponentsInteractive {
832      caller: Caller | undefined = undefined;
833
834      // Register the onRelease() listener of the CallerAbility.
835      private regOnRelease(caller: Caller): void {
836        hilog.info(DOMAIN_NUMBER, TAG, `caller is ${caller}`);
837        try {
838          caller.on('release', (msg: string) => {
839            hilog.info(DOMAIN_NUMBER, TAG, `caller onRelease is called ${msg}`);
840          })
841          hilog.info(DOMAIN_NUMBER, TAG, 'succeeded in registering on release.');
842        } catch (err) {
843          let code = (err as BusinessError).code;
844          let message = (err as BusinessError).message;
845          hilog.error(DOMAIN_NUMBER, TAG, `Failed to caller register on release. Code is ${code}, message is ${message}`);
846        }
847      };
848
849      build() {
850        Column() {
851          // ...
852          List({ initialIndex: 0 }) {
853            // ...
854            ListItem() {
855              Row() {
856                // ...
857              }
858              .onClick(() => {
859                let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
860                let want: Want = {
861                  bundleName: 'com.samples.stagemodelabilityinteraction',
862                  abilityName: 'CalleeAbility',
863                  parameters: {
864                    // Custom information.
865                    info: 'CallSendMsg'
866                  }
867                };
868                context.startAbilityByCall(want).then((caller: Caller) => {
869                  hilog.info(DOMAIN_NUMBER, TAG, `Succeeded in starting ability.Code is ${caller}`);
870                  if (caller === undefined) {
871                    hilog.info(DOMAIN_NUMBER, TAG, 'get caller failed');
872                    return;
873                  }
874                  else {
875                    hilog.info(DOMAIN_NUMBER, TAG, 'get caller success');
876                    this.regOnRelease(caller);
877                    promptAction.showToast({
878                      message: 'CallerSuccess'
879                    });
880                    try {
881                      caller.release();
882                    } catch (releaseErr) {
883                      console.log('Caller.release catch error, error.code: ' + JSON.stringify(releaseErr.code) +
884                        ' error.message: ' + JSON.stringify(releaseErr.message));
885                    }
886                  }
887                }).catch((err: BusinessError) => {
888                  hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability. Code is ${err.code}, message is ${err.message}`);
889                });
890              })
891            }
892            // ...
893          }
894          // ...
895        }
896        // ...
897      }
898    }
899    ```
900<!--DelEnd-->
901
902