• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Launching the UIAbility of the Widget Provider in the Background Through the call Event
2
3
4There may be cases you want to provide in a widget access to features available in your application running in the foreground, for example, the play, pause, and stop buttons in a music application widget. This is where the **call** capability of the [postCardAction](../reference/apis-arkui/js-apis-postCardAction.md#postcardaction) API comes in handy. This capability, when used in a widget, can start the specified UIAbility of the widget provider in the background. It also allows the widget to call the specified method of the application and transfer data so that the application, while in the background, can behave accordingly in response to touching of the buttons on the widget.
5
6> **NOTE**
7>
8> This topic describes development for dynamic widgets. For static widgets, see [FormLink](../reference/apis-arkui/arkui-ts/ts-container-formlink.md).
9
10## How to Develop
111. Create a dynamic widget.
12
13   Create a dynamic widget named WidgetEventCallCardArkTs.
14
152. Implement page layout.
16
17   In this example, two buttons are laid out on the widget page. When one button is clicked, the **postCardAction** API is called to send a call event to the target UIAbility. Note that the **method** parameter in the API indicates the method to call in the target UIAbility. It is mandatory and of the string type.
18   ```ts
19    //src/main/ets/widgeteventcallcard/pages/WidgetEventCallCardCard.ets
20    @Entry
21    @Component
22    struct WidgetEventCallCard {
23      @LocalStorageProp('formId') formId: string = '12400633174999288';
24
25      build() {
26        Column() {
27          //...
28          Row() {
29            Column() {
30              Button() {
31              //...
32              }
33              //...
34              .onClick(() => {
35                postCardAction(this, {
36                  action: 'call',
37                  abilityName: 'WidgetEventCallEntryAbility', // Only the UIAbility of the current application is allowed. The ability name must be the same as that defined in module.json5.
38                  params: {
39                    formId: this.formId,
40                    method: 'funA' // Set the name of the method to call in the EntryAbility.
41                  }
42                });
43              })
44
45              Button() {
46              //...
47              }
48              //...
49              .onClick(() => {
50                postCardAction(this, {
51                  action: 'call',
52                  abilityName: 'WidgetEventCallEntryAbility', // Only the UIAbility of the current application is allowed. The ability name must be the same as that defined in module.json5.
53                  params: {
54                    formId: this.formId,
55                    method: 'funB', // Set the name of the method to call in the EntryAbility.
56                    num: 1 // Set other parameters to be passed in.
57                  }
58                });
59              })
60            }
61          }.width('100%').height('80%')
62          .justifyContent(FlexAlign.Center)
63        }
64        .width('100%')
65        .height('100%')
66        .alignItems(HorizontalAlign.Center)
67      }
68    }
69    ```
703. Create a UIAbility.
71
72   The UIAbility receives the call event and obtains the transferred parameters. It then executes the target method specified by the **method** parameter. Other data can be obtained through the [readString](../reference/apis-ipc-kit/js-apis-rpc.md#readstring) method. Listen for the method required by the call event in the **onCreate** callback of the UIAbility.
73    ```ts
74    //src/main/ets/widgeteventcallcard/WidgetEventCallEntryAbility/WidgetEventCallEntryAbility.ets
75    import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
76    import { promptAction } from '@kit.ArkUI';
77    import { BusinessError } from '@kit.BasicServicesKit';
78    import { rpc } from '@kit.IPCKit';
79    import { hilog } from '@kit.PerformanceAnalysisKit';
80
81    const TAG: string = 'WidgetEventCallEntryAbility';
82    const DOMAIN_NUMBER: number = 0xFF00;
83    const CONST_NUMBER_1: number = 1;
84    const CONST_NUMBER_2: number = 2;
85
86    class MyParcelable implements rpc.Parcelable {
87      num: number;
88      str: string;
89
90      constructor(num: number, str: string) {
91        this.num = num;
92        this.str = str;
93      }
94
95      marshalling(messageSequence: rpc.MessageSequence): boolean {
96        messageSequence.writeInt(this.num);
97        messageSequence.writeString(this.str);
98        return true;
99      }
100
101      unmarshalling(messageSequence: rpc.MessageSequence): boolean {
102        this.num = messageSequence.readInt();
103        this.str = messageSequence.readString();
104          return true;
105      }
106    }
107
108    export default class WidgetEventCallEntryAbility extends UIAbility {
109      // If the UIAbility is started for the first time, onCreate is triggered after the call event is received.
110      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
111        try {
112          // Listen for the method required by the call event.
113          this.callee.on('funA', (data: rpc.MessageSequence) => {
114            // Obtain all parameters passed in the call event.
115            hilog.info(DOMAIN_NUMBER, TAG, `FunACall param:  ${JSON.stringify(data.readString())}`);
116            promptAction.showToast({
117              message: 'FunACall param:' + JSON.stringify(data.readString())
118            });
119            return new MyParcelable(CONST_NUMBER_1, 'aaa');
120          });
121          this.callee.on('funB', (data: rpc.MessageSequence) => {
122            // Obtain all parameters passed in the call event.
123            hilog.info(DOMAIN_NUMBER, TAG, `FunBCall param:  ${JSON.stringify(data.readString())}`);
124            promptAction.showToast({
125              message: 'FunBCall param:' + JSON.stringify(data.readString())
126            });
127            return new MyParcelable(CONST_NUMBER_2, 'bbb');
128          });
129        } catch (err) {
130          hilog.error(DOMAIN_NUMBER, TAG, `Failed to register callee on. Cause: ${JSON.stringify(err as BusinessError)}`);
131        }
132      }
133
134      // Deregister the listener when the process exits.
135      onDestroy(): void | Promise<void> {
136        try {
137          this.callee.off('funA');
138          this.callee.off('funB');
139        } catch (err) {
140          hilog.error(DOMAIN_NUMBER, TAG, `Failed to register callee off. Cause: ${JSON.stringify(err as BusinessError)}`);
141        }
142      }
143    }
144    ```
1454. Configure the background running permission.
146
147   To receive the call event, the widget provider must add the background running permission ([ohos.permission.KEEP_BACKGROUND_RUNNING](../security/AccessToken/permissions-for-all.md#ohospermissionkeep_background_running)) to the top-level module in the **module.json5** file.
148    ```ts
149    //src/main/module.json5
150    "requestPermissions": [
151       {
152         "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
153       }
154     ]
155    ```
1565. Configure the UIAbility.
157
158   Add the configuration of the WidgetEventCallEntryAbility to the **abilities** array of the top-level module in the **module.json5** file.
159    ```ts
160    //src/main/module.json5
161   "abilities": [
162     {
163       "name": 'WidgetEventCallEntryAbility',
164       "srcEntry": './ets/widgeteventcallcard/WidgetEventCallEntryAbility/WidgetEventCallEntryAbility.ets',
165       "description": '$string:WidgetEventCallCard_desc',
166       "icon": "$media:app_icon",
167       "label": "$string:WidgetEventCallCard_label",
168       "startWindowIcon": "$media:app_icon",
169       "startWindowBackground": "$color:start_window_background"
170     }
171   ]
172    ```
173