• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Launching UIAbility to the Background (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-1) 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 WidgetEventCall.
14
152. Implement page layout.
16
17    In this example, two buttons (A and B) are laid out on the widget page. When one button is touched, the **postCardAction** API is called to send a call event to the target UIAbility, with the method to be called defined in the event. Button A and button B correspond to the funA and funB methods, respectively. The funA method carries the **formID** parameter, and the funB method carries the **formID** and **num** parameters. Pass parameters as required during development. In **postCardAction**, the **method** parameter is mandatory and identifies the name of the method to be invoked, which should match the method listened for by the UIAbility in step 3. Other parameters are optional.
18    ```ts
19    //src/main/ets/widgeteventcallcard/pages/WidgetEventCall.ets
20    @Entry
21    @Component
22    struct WidgetEventCall {
23      @LocalStorageProp('formId') formId: string = '12400633174999288';
24      private funA: string = 'Button A';
25      private funB: string = 'Button B';
26
27      build() {
28        RelativeContainer() {
29          Button(this.funA)
30          .id('funA__')
31          .fontSize($r('app.float.page_text_font_size'))
32          .fontWeight(FontWeight.Bold)
33          .alignRules({
34            center: { anchor: '__container__', align: VerticalAlign.Center },
35            middle: { anchor: '__container__', align: HorizontalAlign.Center }
36          })
37          .onClick(() => {
38            postCardAction(this, {
39              action: 'call',
40              // Only the UIAbility of the current application is allowed. The ability name must be the same as that defined in module.json5.
41              abilityName: 'WidgetEventCallEntryAbility',
42              params: {
43                formId: this.formId,
44                // Name of the method to be called.
45                method: 'funA'
46              }
47            });
48          })
49          Button(this.funB)
50          .id('funB__')
51          .fontSize($r('app.float.page_text_font_size'))
52          .fontWeight(FontWeight.Bold)
53          .margin({ top: 10 })
54          .alignRules({
55            top: { anchor: 'funA__', align: VerticalAlign.Bottom },
56            middle: { anchor: '__container__', align: HorizontalAlign.Center }
57          })
58          .onClick(() => {
59            postCardAction(this, {
60            action: 'call',
61            abilityName: 'WidgetEventCallEntryAbility',
62            params: {
63              formId: this.formId,
64              // Name of the method to be called.
65              method: 'funB',
66              num: 1
67            }
68          });
69        })
70      }
71      .height('100%')
72      .width('100%')
73      }
74    }
75    ```
763. Create a UIAbility.
77
78    Listen for the call event in the UIAbility, call the corresponding method based on the **method** parameter, and obtain the parameter by using [rpc.Parcelable](../reference/apis-ipc-kit/js-apis-rpc.md#parcelable9). The method in the UIAbility must be the same as that in step 2.
79    ```ts
80    //src/main/ets/widgeteventcallcard/WidgetEventCallEntryAbility/WidgetEventCallEntryAbility.ets
81    import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
82    import { BusinessError } from '@kit.BasicServicesKit';
83    import { rpc } from '@kit.IPCKit';
84    import { hilog } from '@kit.PerformanceAnalysisKit';
85
86    const TAG: string = 'WidgetEventCallEntryAbility';
87    const DOMAIN_NUMBER: number = 0xFF00;
88    const CONST_NUMBER_1: number = 1;
89    const CONST_NUMBER_2: number = 2;
90
91    // Implementation of the RPC return type, which is used for RPC data serialization and deserialization.
92    class MyParcelable implements rpc.Parcelable {
93      num: number;
94      str: string;
95
96      constructor(num: number, str: string) {
97        this.num = num;
98        this.str = str;
99      }
100
101      marshalling(messageSequence: rpc.MessageSequence): boolean {
102        messageSequence.writeInt(this.num);
103        messageSequence.writeString(this.str);
104        return true;
105      }
106
107      unmarshalling(messageSequence: rpc.MessageSequence): boolean {
108        this.num = messageSequence.readInt();
109        this.str = messageSequence.readString();
110          return true;
111      }
112    }
113
114    export default class WidgetEventCallEntryAbility extends UIAbility {
115      // If the UIAbility is started, the onCreate lifecycle callback is triggered after the call event is received.
116      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
117        try {
118          // Listen for the method required by the call event and call the method.
119          this.callee.on('funA', (data: rpc.MessageSequence) => {
120            // Obtain all parameters passed in the call event.
121            hilog.info(DOMAIN_NUMBER, TAG, `FunACall param:  ${JSON.stringify(data.readString())}`);
122            return new MyParcelable(CONST_NUMBER_1, 'aaa');
123          });
124          this.callee.on('funB', (data: rpc.MessageSequence) => {
125            // Obtain all parameters passed in the call event.
126            hilog.info(DOMAIN_NUMBER, TAG, `FunBCall param:  ${JSON.stringify(data.readString())}`);
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 **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 WidgetEventCallEntryAbility configuration information to the abilities array 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