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