• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Page Ability Development
2
3## Overview
4### Concepts
5The 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. The 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**.
6
7### Page Ability Lifecycle
8
9**Ability lifecycle**
10
11The Page ability lifecycle defines all states of a Page ability, such as **INACTIVE**, **ACTIVE**, and **BACKGROUND**.
12
13The following figure shows the lifecycle state transition of the Page ability.
14
15![PageAbility-Lifecycle](figures/page-ability-lifecycle.png)
16
17
18Description of ability lifecycle states:
19
20  - **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.
21
22  - **INITIAL**: The Page ability is initialized but not running. The Page ability enters the **INACTIVE** state after it is started.
23
24  - **INACTIVE**: The Page ability is visible but does not gain focus.
25
26  - **ACTIVE**: The Page ability runs in the foreground and has focus.
27
28  - **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.
29
30**The following figure shows the relationship between lifecycle callbacks and lifecycle states of the Page ability.**
31
32![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
33
34You 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.
35
36### Launch Type
37The ability supports two launch types: singleton and multi-instance.
38You can specify the launch type by setting **launchType** in the **config.json** file.
39
40| Launch Type    | Description    |Description            |
41| ----------- | -------  |---------------- |
42| standard    | Multi-instance  | A new instance is started each time an ability starts.|
43| singleton   | Singleton  | Only one instance exists in the system. If an instance already exists when an ability is started, that instance is reused.|
44
45By default, **singleton** is used.
46
47
48## Development Guidelines
49### Available APIs
50
51**Table 1** APIs provided by featureAbility
52
53| API                                             | Description           |
54| --------------------------------------------------- | --------------- |
55| void startAbility(parameter: StartAbilityParameter) | Starts an ability.    |
56| Context getContext():                               | Obtains the application context.|
57| void terminateSelf()                                | Terminates the ability.    |
58| bool hasWindowFocus()                               | Checks whether the ability has focus.   |
59
60
61### Starting a Local Page Ability
62
63**Modules to Import**
64
65```js
66  import featureAbility from '@ohos.ability.featureAbility'
67```
68
69**Example**
70
71```javascript
72  import featureAbility from '@ohos.ability.featureAbility'
73  featureAbility.startAbility({
74  want:
75  {
76    action: "",
77    entities: [""],
78    type: "",
79    options: {
80      // Grant the permission to perform read operations on the URI.
81      authReadUriPermission: true,
82      // Grant the permission to perform write operations on the URI.
83      authWriteUriPermission: true,
84      // Support forwarding the Want result to the ability.
85      abilityForwardResult: true,
86      // Enable abiligy continuation.
87      abilityContinuation: true,
88      // Specify that a component does not belong to ohos.
89      notOhosComponent: true,
90      // Specify that an ability is started.
91      abilityFormEnabled: true,
92      // Grant the permission for possible persisting on the URI.
93      authPersistableUriPermission: true,
94      // Grant the permission for possible persisting on the prefix URI.
95      authPrefixUriPermission: true,
96      // Support distributed scheduling system startup on multiple devices.
97      abilitySliceMultiDevice: true,
98      // A service ability is started regardless of whether the host application has been started.
99      startForegroundAbility: true,
100      // Install the specified ability if it is not installed.
101      installOnDemand: true,
102      // Return the result to the ability slice.
103      abilitySliceForwardResult: true,
104      // Install the specified ability with background mode if it is not installed.
105      installWithBackgroundMode: true
106    },
107    deviceId: "",
108    bundleName: "com.example.startability",
109    abilityName: "com.example.startability.MainAbility",
110    uri: ""
111  },
112  },
113  );
114```
115
116You can also include **parameters** in the **want** parameter and set its value in the key-value format.
117
118**Example**
119
120```javascript
121  import featureAbility from '@ohos.ability.featureAbility'
122  featureAbility.startAbility({
123    want:
124    {
125        bundleName: "com.example.startability",
126        uri: "",
127        parameters: {
128            abilityName: "com.example.startability.MainAbility"
129        }
130    },
131  },
132  );
133```
134### Starting a Remote Page Ability
135>Note
136>
137>This feature applies only to system applications, since the **getTrustedDeviceListSync** API of the **DeviceManager** class is open only to system applications.
138
139**Modules to Import**
140
141```
142  import featureAbility from '@ohos.ability.featureAbility'
143  import deviceManager from '@ohos.distributedHardware.deviceManager';
144```
145
146**Example**
147```ts
148  function onStartRemoteAbility() {
149  console.info('onStartRemoteAbility begin');
150  let params;
151  let wantValue = {
152    bundleName: 'ohos.samples.etsDemo',
153    abilityName: 'ohos.samples.etsDemo.RemoteAbility',
154    deviceId: getRemoteDeviceId(),
155    parameters: params
156  };
157  console.info('onStartRemoteAbility want=' + JSON.stringify(wantValue));
158  featureAbility.startAbility({
159    want: wantValue
160  }).then((data) => {
161    console.info('onStartRemoteAbility finished, ' + JSON.stringify(data));
162  });
163  console.info('onStartRemoteAbility end');
164  }
165```
166
167Obtain **deviceId** from **DeviceManager**. The sample code is as follows:
168
169```ts
170  import deviceManager from '@ohos.distributedHardware.deviceManager';
171  let dmClass;
172  function getRemoteDeviceId() {
173    if (typeof dmClass === 'object' && dmClass != null) {
174        let list = dmClass.getTrustedDeviceListSync();
175        if (typeof (list) == 'undefined' || typeof (list.length) == 'undefined') {
176            console.log("MainAbility onButtonClick getRemoteDeviceId err: list is null");
177            return;
178        }
179        console.log("MainAbility onButtonClick getRemoteDeviceId success:" + list[0].deviceId);
180        return list[0].deviceId;
181    } else {
182        console.log("MainAbility onButtonClick getRemoteDeviceId err: dmClass is null");
183    }
184  }
185```
186
187In the cross-device scenario, the application must also apply for the data synchronization permission from end users. The sample code is as follows:
188
189```ts
190  import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
191  import bundle from '@ohos.bundle';
192  async function RequestPermission() {
193  console.info('RequestPermission begin');
194  let array: Array<string> = ["ohos.permission.DISTRIBUTED_DATASYNC"];
195  let bundleFlag = 0;
196  let tokenID = undefined;
197  let userID = 100;
198  let  appInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', bundleFlag, userID);
199  tokenID = appInfo.accessTokenId;
200  let atManager = abilityAccessCtrl.createAtManager();
201  let requestPermissions: Array<string> = [];
202  for (let i = 0;i < array.length; i++) {
203    let result = await atManager.verifyAccessToken(tokenID, array[i]);
204    console.info("verifyAccessToken result:" + JSON.stringify(result));
205    if (result == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
206    } else {
207      requestPermissions.push(array[i]);
208    }
209  }
210  console.info("requestPermissions:" + JSON.stringify(requestPermissions));
211  if (requestPermissions.length == 0 || requestPermissions == []) {
212    return;
213  }
214  let context = featureAbility.getContext();
215  context.requestPermissionsFromUser(requestPermissions, 1, (data)=>{
216    console.info("data:" + JSON.stringify(data));
217    console.info("data requestCode:" + data.requestCode);
218    console.info("data permissions:" + data.permissions);
219    console.info("data authResults:" + data.authResults);
220  });
221  console.info('RequestPermission end');
222  }
223```
224
225### Lifecycle APIs
226
227**Table 2** Lifecycle callbacks
228
229| API      | Description                                                        |
230| ------------ | ------------------------------------------------------------ |
231| onShow()     | Called when the ability is switched from the background to the foreground. In this case, the ability is visible to users.|
232| onHide()     | Called when the ability is switched from the foreground to the background. In this case, the ability is invisible to users.|
233| 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.|
234| onCreate()   | Called when the ability is created for the first time. You can initialize the application in this callback.|
235| onInactive() | Called when the ability loses focus. An ability loses focus when it is about to enter the background state.|
236| onActive()   | Called when the ability is switched to the foreground and gains focus.     |
237
238**Example**
239
240You 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.
241
242```javascript
243export default {
244  onCreate() {
245    console.info('Application onCreate')
246  },
247  onDestroy() {
248    console.info('Application onDestroy')
249  },
250  onShow(){
251    console.info('Application onShow')
252  },
253  onHide(){
254    console.info('Application onHide')
255  },
256  onInactive(){
257    console.info('Application onInactive')
258  },
259  onActive(){
260    console.info('Application onActive')
261  },
262}
263```
264