• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Page Ability Development
2
3## Overview
4
5### Concepts
6
7The Page ability implements the ArkUI and provides the capability of interacting with developers. When you create an ability in DevEco Studio, DevEco Studio automatically creates template code.
8
9The capabilities related to the Page ability are implemented through the **featureAbility**, and the lifecycle callbacks are implemented through the callbacks in **app.js** or **app.ets**.
10
11### Page Ability Lifecycle
12
13Introduction to the Page ability lifecycle:
14
15The Page ability lifecycle defines all states of a Page ability, such as **INACTIVE**, **ACTIVE**, and **BACKGROUND**.
16
17The following figure shows the lifecycle state transition of the Page ability.
18
19![PageAbility-Lifecycle](figures/page-ability-lifecycle.png)
20
21
22Description of ability lifecycle states:
23
24  - **UNINITIALIZED**: The Page ability is not initialized. This is a temporary state, from which a Page ability changes directly to the **INITIAL** state upon its creation.
25
26  - **INITIAL**: The Page ability is initialized but not running. The Page ability enters the **INACTIVE** state after it is started.
27
28  - **INACTIVE**: The Page ability is visible but does not gain focus.
29
30  - **ACTIVE**: The Page ability runs in the foreground and has focus.
31
32  - **BACKGROUND**: The Page ability runs in the background. After being re-activated, the Page ability enters the **ACTIVE** state. After being destroyed, the Page ability enters the **INITIAL** state.
33
34The following figure shows the relationship between lifecycle callbacks and lifecycle states of the Page ability.
35
36![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
37
38You can override the lifecycle callbacks provided by the Page ability in the **app.js** or **app.ets** file. Currently, the **app.js** file provides only the **onCreate** and **onDestroy** callbacks, and the **app.ets** file provides the full lifecycle callbacks.
39
40### Launch Type
41
42The ability supports two launch types: singleton and multi-instance.
43
44You can specify the launch type by setting **launchType** in the **config.json** file.
45
46**Table 1** Startup modes
47
48| Launch Type    | Description    |Description            |
49| ----------- | -------  |---------------- |
50| standard | Multi-instance  | A new instance is started each time an ability starts.|
51| singleton   | Singleton  | The ability has only one instance in the system. If an instance already exists when an ability is started, that instance is reused.|
52
53By default, **singleton** is used.
54
55
56## Development Guidelines
57
58### Available APIs
59
60**Table 2** APIs provided by featureAbility
61
62| API                                             | Description           |
63| --------------------------------------------------- | --------------- |
64| void startAbility(parameter: StartAbilityParameter) | Starts an ability.   |
65| Context getContext():                               | Obtains the application context.|
66| void terminateSelf()                                | Terminates the ability.    |
67| bool hasWindowFocus()                               | Checks whether the ability has focus.   |
68
69
70### Starting a Local Page Ability
71
72**Modules to Import**
73
74```js
75  import featureAbility from '@ohos.ability.featureAbility'
76```
77
78**Example**
79
80```javascript
81  import featureAbility from '@ohos.ability.featureAbility'
82  featureAbility.startAbility({
83      want: {
84          action: "",
85          entities: [""],
86          type: "",
87          deviceId: "",
88          bundleName: "com.example.myapplication",
89          /* In the FA model, abilityName consists of package and ability name. */
90          abilityName: "com.example.entry.secondAbility",
91          uri: ""
92      }
93  });
94```
95
96### Starting a Remote Page Ability
97>NOTE
98>
99>This feature applies only to system applications, since the **getTrustedDeviceListSync** API of the **DeviceManager** class is open only to system applications.
100
101**Modules to Import**
102
103```
104  import featureAbility from '@ohos.ability.featureAbility'
105  import deviceManager from '@ohos.distributedHardware.deviceManager';
106```
107
108**Example**
109```ts
110  function onStartRemoteAbility() {
111  console.info('onStartRemoteAbility begin');
112  let params;
113  let wantValue = {
114      bundleName: 'ohos.samples.etsDemo',
115      abilityName: 'ohos.samples.etsDemo.RemoteAbility',
116      deviceId: getRemoteDeviceId(),
117      parameters: params
118  };
119  console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue));
120  featureAbility.startAbility({
121      want: wantValue
122  }).then((data) => {
123      console.info('onStartRemoteAbility finished, ' + JSON.stringify(data));
124  });
125  console.info('onStartRemoteAbility end');
126  }
127```
128
129Obtain **deviceId** from **DeviceManager**. The sample code is as follows:
130
131```ts
132  import deviceManager from '@ohos.distributedHardware.deviceManager';
133  let dmClass;
134  function getRemoteDeviceId() {
135      if (typeof dmClass === 'object' && dmClass != null) {
136          let list = dmClass.getTrustedDeviceListSync();
137          if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') {
138            console.log("MainAbility onButtonClick getRemoteDeviceId err: list is null");
139            return;
140          }
141          console.log("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId);
142          return list[0].deviceId;
143      } else {
144          console.log("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null");
145      }
146  }
147```
148
149In the cross-device scenario, the application must also apply for the data synchronization permission from end users. The sample code is as follows:
150
151```ts
152  import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
153  import bundle from '@ohos.bundle';
154  async function RequestPermission() {
155      console.info('RequestPermission begin');
156      let array: Array<string> = ["ohos.permission.DISTRIBUTED_DATASYNC"];
157      let bundleFlag = 0;
158      let tokenID = undefined;
159      let userID = 100;
160      let  appInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', bundleFlag, userID);
161      tokenID = appInfo.accessTokenId;
162      let atManager = abilityAccessCtrl.createAtManager();
163      let requestPermissions: Array<string> = [];
164      for (let i = 0;i < array.length; i++) {
165          let result = await atManager.verifyAccessToken(tokenID, array[i]);
166          console.info("verifyAccessToken result:" + JSON.stringify(result));
167          if (result != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
168              requestPermissions.push(array[i]);
169          }
170      }
171      console.info("requestPermissions:" + JSON.stringify(requestPermissions));
172      if (requestPermissions.length == 0 || requestPermissions == []) {
173          return;
174      }
175      let context = featureAbility.getContext();
176      context.requestPermissionsFromUser(requestPermissions, 1, (data)=>{
177          console.info("data:" + JSON.stringify(data));
178          console.info("data requestCode:" + data.requestCode);
179          console.info("data permissions:" + data.permissions);
180          console.info("data authResults:" + data.authResults);
181      });
182      console.info('RequestPermission end');
183  }
184```
185
186### Lifecycle APIs
187
188**Table 3** Lifecycle callbacks
189
190| API      | Description                                                        |
191| ------------ | ------------------------------------------------------------ |
192| onShow()     | Called when the ability is switched from the background to the foreground. In this case, the ability is visible to users.|
193| onHide()     | Called when the ability is switched from the foreground to the background. In this case, the ability is invisible to users.|
194| onDestroy()  | Called when the ability is destroyed. In this callback, you can make preparations for application exit, such as recycling resources and clearing the cache.|
195| onCreate()   | Called when the ability is created for the first time. You can initialize the application in this callback.|
196| onInactive() | Called when the ability loses focus. An ability loses focus when it is about to enter the background state.|
197| onActive()   | Called when the ability is switched to the foreground and gains focus.     |
198
199**Example**
200
201You need to override the lifecycle callbacks except **onCreate()** and **onDestroy()** in **app.js** or **app.ets**. The **onCreate()** and **onDestroy()** callbacks are automatically generated in the template code provided by DevEco Studio.
202
203```javascript
204export default {
205  onCreate() {
206    console.info('Application onCreate')
207  },
208  onDestroy() {
209    console.info('Application onDestroy')
210  },
211  onShow(){
212    console.info('Application onShow')
213  },
214  onHide(){
215    console.info('Application onHide')
216  },
217  onInactive(){
218    console.info('Application onInactive')
219  },
220  onActive(){
221    console.info('Application onActive')
222  },
223}
224```
225