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 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 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