提交 71c6fac0 编写于 作者: E ester.zhou 提交者: Gitee

Merge branch 'master' of gitee.com:openharmony/docs into TR-18192

Signed-off-by: Nester.zhou <ester.zhou@huawei.com>
...@@ -12,10 +12,13 @@ The **AccessibilityExtensionAbility** module provides accessibility extension ca ...@@ -12,10 +12,13 @@ The **AccessibilityExtensionAbility** module provides accessibility extension ca
This document is organized as follows: This document is organized as follows:
- [Creating an AccessibilityExtAbility File](#creating-an-accessibility-extension-service) - [AccessibilityExtensionAbility Development](#accessibilityextensionability-development)
- [Processing an Accessibility Event](#processing-an-accessibility-event) - [Creating an Accessibility Extension Service](#creating-an-accessibility-extension-service)
- [Declaring Capabilities of Accessibility Extension Services](#declaring-capabilities-of-accessibility-extension-services) - [Creating a Project](#creating-a-project)
- [Enabling a Custom Accessibility Extension Service](#enabling-a-custom-accessibility-extension-service) - [Creating an AccessibilityExtAbility File](#creating-an-accessibilityextability-file)
- [Processing an Accessibility Event](#processing-an-accessibility-event)
- [Declaring Capabilities of Accessibility Extension Services](#declaring-capabilities-of-accessibility-extension-services)
- [Enabling a Custom Accessibility Extension Service](#enabling-a-custom-accessibility-extension-service)
## Creating an Accessibility Extension Service ## Creating an Accessibility Extension Service
...@@ -79,13 +82,13 @@ You can also process physical key events in the accessibility extension service. ...@@ -79,13 +82,13 @@ You can also process physical key events in the accessibility extension service.
## Declaring Capabilities of Accessibility Extension Services ## Declaring Capabilities of Accessibility Extension Services
After developing the custom logic for an accessibility extension service, you must add the configuration information of the service to the corresponding module-level **module.json5** file in the project directory. In the file, the **srcEntrance** tag indicates the path to the accessibility extension service. Make sure the value of the **type** tag is fixed at **accessibility**. Otherwise, the connection to the service will fail. After developing the custom logic for an accessibility extension service, you must add the configuration information of the service to the corresponding module-level **module.json5** file in the project directory. In the file, the **srcEntry** tag indicates the path to the accessibility extension service. Make sure the value of the **type** tag is fixed at **accessibility**. Otherwise, the connection to the service will fail.
```json ```json
"extensionAbilities": [ "extensionAbilities": [
{ {
"name": "AccessibilityExtAbility", "name": "AccessibilityExtAbility",
"srcEntrance": "./ets/AccessibilityExtAbility/AccessibilityExtAbility.ts", "srcEntry": "./ets/AccessibilityExtAbility/AccessibilityExtAbility.ts",
"label": "$string:MainAbility_label", "label": "$string:MainAbility_label",
"description": "$string:MainAbility_desc", "description": "$string:MainAbility_desc",
"type": "accessibility", "type": "accessibility",
......
...@@ -22,8 +22,6 @@ A static subscriber is started once it receives a target event published by the ...@@ -22,8 +22,6 @@ A static subscriber is started once it receives a target event published by the
You can implement service logic in the **onReceiveEvent** callback. You can implement service logic in the **onReceiveEvent** callback.
2. Project Configuration for a Static Subscriber 2. Project Configuration for a Static Subscriber
After writing the static subscriber code, configure the subscriber in the **module.json5** file. The configuration format is as follows: After writing the static subscriber code, configure the subscriber in the **module.json5** file. The configuration format is as follows:
...@@ -35,12 +33,12 @@ A static subscriber is started once it receives a target event published by the ...@@ -35,12 +33,12 @@ A static subscriber is started once it receives a target event published by the
"extensionAbilities": [ "extensionAbilities": [
{ {
"name": "StaticSubscriber", "name": "StaticSubscriber",
"srcEntrance": "./ets/StaticSubscriber/StaticSubscriber.ts", "srcEntry": "./ets/StaticSubscriber/StaticSubscriber.ts",
"description": "$string:StaticSubscriber_desc", "description": "$string:StaticSubscriber_desc",
"icon": "$media:icon", "icon": "$media:icon",
"label": "$string:StaticSubscriber_label", "label": "$string:StaticSubscriber_label",
"type": "staticSubscriber", "type": "staticSubscriber",
"visible": true, "exported": true,
"metadata": [ "metadata": [
{ {
"name": "ohos.extension.staticSubscriber", "name": "ohos.extension.staticSubscriber",
...@@ -56,7 +54,7 @@ A static subscriber is started once it receives a target event published by the ...@@ -56,7 +54,7 @@ A static subscriber is started once it receives a target event published by the
Pay attention to the following fields in the JSON file: Pay attention to the following fields in the JSON file:
- **srcEntrance**: entry file path of the ExtensionAbility, that is, the file path of the static subscriber declared in Step 2. - **srcEntry**: entry file path of the ExtensionAbility, that is, the file path of the static subscriber declared in Step 2.
- **type**: ExtensionAbility type. For a static subscriber, set this field to **staticSubscriber**. - **type**: ExtensionAbility type. For a static subscriber, set this field to **staticSubscriber**.
......
...@@ -60,15 +60,15 @@ To implement EnterpriseAdminExtensionAbility, you need to activate the device ad ...@@ -60,15 +60,15 @@ To implement EnterpriseAdminExtensionAbility, you need to activate the device ad
}; };
``` ```
4. Register **ServiceExtensionAbility** in the [**module.json5**](../quick-start/module-configuration-file.md) file corresponding to the project module. Set **type** to **enterpriseAdmin** and **srcEntrance** to the path of the ExtensionAbility code. 4. Register **ServiceExtensionAbility** in the [**module.json5**](../quick-start/module-configuration-file.md) file corresponding to the project module. Set **type** to **enterpriseAdmin** and **srcEntry** to the path of the ExtensionAbility code.
```ts ```ts
"extensionAbilities": [ "extensionAbilities": [
{ {
"name": "ohos.samples.enterprise_admin_ext_ability", "name": "ohos.samples.enterprise_admin_ext_ability",
"type": "enterpriseAdmin", "type": "enterpriseAdmin",
"visible": true, "exported": true,
"srcEntrance": "./ets/enterpriseextability/EnterpriseAdminAbility.ts" "srcEntry": "./ets/enterpriseextability/EnterpriseAdminAbility.ts"
} }
] ]
``` ```
......
...@@ -54,7 +54,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth ...@@ -54,7 +54,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth
1. **InputMethodService.ts** file: 1. **InputMethodService.ts** file:
In this file, add the dependency package for importing InputMethodExtensionAbility. Customize a class that inherits from InputMethodExtensionAbility and add the required lifecycle callbacks. In the **InputMethodService.ts** file, add the dependency package for importing InputMethodExtensionAbility. Customize a class that inherits from InputMethodExtensionAbility and add the required lifecycle callbacks.
```ts ```ts
import InputMethodExtensionAbility from '@ohos.InputMethodExtensionAbility'; import InputMethodExtensionAbility from '@ohos.InputMethodExtensionAbility';
...@@ -233,7 +233,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth ...@@ -233,7 +233,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth
Add the path to this file to the **src** field in the **resources/base/profile/main_pages.json** file. Add the path to this file to the **src** field in the **resources/base/profile/main_pages.json** file.
```ets ```ts
import { numberSourceListData, sourceListType } from './keyboardKeyData' import { numberSourceListData, sourceListType } from './keyboardKeyData'
@Component @Component
...@@ -342,7 +342,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth ...@@ -342,7 +342,7 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth
} }
``` ```
Register the InputMethodExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the target module. Set **type** to **"inputMethod"** and **srcEntrance** to the code path of the InputMethodExtensionAbility component. Register the InputMethodExtensionAbility in the [module.json5 file](../quick-start/module-configuration-file.md) corresponding to the target module. Set **type** to **"inputMethod"** and **srcEntry** to the code path of the InputMethodExtensionAbility component.
```ts ```ts
{ {
...@@ -353,9 +353,9 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth ...@@ -353,9 +353,9 @@ The minimum template contains four files: **KeyboardController.ts**, **InputMeth
"description": "inputMethod", "description": "inputMethod",
"icon": "$media:icon", "icon": "$media:icon",
"name": "InputMethodExtAbility", "name": "InputMethodExtAbility",
"srcEntrance": "./ets/inputmethodextability/InputMethodService.ts", "srcEntry": "./ets/inputmethodextability/InputMethodService.ts",
"type": "inputMethod", "type": "inputMethod",
"visible": true, "exported": true,
} }
] ]
} }
......
...@@ -44,7 +44,6 @@ Note that you must set the **bundleType** field to **atomicService** in the [app ...@@ -44,7 +44,6 @@ Note that you must set the **bundleType** field to **atomicService** in the [app
"versionName": "1.0.0", "versionName": "1.0.0",
"icon": "$media:app_icon", "icon": "$media:app_icon",
"label": "$string:app_name", "label": "$string:app_name",
"distributedNotificationEnabled": true,
"targetAPIVersion": 9 "targetAPIVersion": 9
} }
} }
...@@ -78,7 +77,7 @@ Pre-loading is triggered after the first frame of the newly accessed module is r ...@@ -78,7 +77,7 @@ Pre-loading is triggered after the first frame of the newly accessed module is r
"module": { "module": {
"name": "entry", "name": "entry",
"type": "entry", "type": "entry",
"srcEntrance": "./ets/Application/MyAbilityStage.ts", "srcEntry": "./ets/Application/MyAbilityStage.ts",
"description": "$string:entry_desc", "description": "$string:entry_desc",
"mainElement": "MainAbility", "mainElement": "MainAbility",
"deviceTypes": [ "deviceTypes": [
...@@ -98,13 +97,13 @@ Pre-loading is triggered after the first frame of the newly accessed module is r ...@@ -98,13 +97,13 @@ Pre-loading is triggered after the first frame of the newly accessed module is r
"abilities": [ "abilities": [
{ {
"name": "MainAbility", "name": "MainAbility",
"srcEntrance": "./ets/MainAbility/MainAbility.ts", "srcEntry": "./ets/MainAbility/MainAbility.ts",
"description": "$string:MainAbility_desc", "description": "$string:MainAbility_desc",
"icon": "$media:icon", "icon": "$media:icon",
"label": "$string:MainAbility_label", "label": "$string:MainAbility_label",
"startWindowIcon": "$media:icon", "startWindowIcon": "$media:icon",
"startWindowBackground": "$color:white", "startWindowBackground": "$color:white",
"visible": true, "exported": true,
"skills": [ "skills": [
{ {
"entities": [ "entities": [
...@@ -170,7 +169,7 @@ import router from '@ohos.router'; ...@@ -170,7 +169,7 @@ import router from '@ohos.router';
@Entry @Entry
@Component @Component
struct Index { struct Index {
@State message: string = 'Hello World' @State message: string = 'Hello World';
build() { build() {
Row() { Row() {
...@@ -200,19 +199,20 @@ struct Index { ...@@ -200,19 +199,20 @@ struct Index {
}).catch(err => { }).catch(err => {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`); console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
}) })
} })
.width('100%') .width('100%')
} }
.height('100%') .height('100%')
} }
}
} }
``` ```
The input parameter **url** of the **router.pushUrl** API is as follows: The input parameter **url** of the **router.pushUrl** API is as follows:
```ets ```ts
'@bundle:com.example.hmservice/library/ets/pages/menu' '@bundle:com.example.hmservice/library/ets/pages/menu'
``` ```
The **url** content template is as follows: The **url** content template is as follows:
```ets ```ts
'@bundle:bundle name/module name/path/page file name (without the extension .ets)' '@bundle:bundle name/module name/path/page file name (without the extension .ets)'
``` ```
# app.js # app.js
## Application Lifecycle<sup>4+</sup>
You can implement lifecycle logic specific to your application in the **app.js** file. Available application lifecycle functions are as follows: You can implement lifecycle logic specific to your application in the **app.js** file. Available application lifecycle functions are as follows:
...@@ -11,14 +12,76 @@ You can implement lifecycle logic specific to your application in the **app.js** ...@@ -11,14 +12,76 @@ You can implement lifecycle logic specific to your application in the **app.js**
In the following example, logs are printed only in the lifecycle functions. In the following example, logs are printed only in the lifecycle functions.
```js
// app.js
export default {
onCreate() {
console.info('Application onCreate');
},
onDestroy() {
console.info('Application onDestroy');
},
}
``` ```
## Application Object<sup>10+</sup>
| Attribute | Type | Description |
| ------ | -------- | ---------------------------------------- |
| getApp | Function | Obtains the data object exposed in **app.js** from the page JS file. This API works globally.|
> **NOTE**
>
> The application object is global data and occupies JS memory before the application exits. Although it facilitates data sharing between different pages, exercise caution when using it on small-system devices, whose memory is small. If they are overused, exceptions may occur due to insufficient memory when the application displays complex pages.
The following is an example:
Declare the application object in **app.js**.
```javascript
// app.js // app.js
export default { export default {
data: {
test: "by getAPP"
},
onCreate() { onCreate() {
console.info('Application onCreate'); console.info('Application onCreate');
}, },
onDestroy() { onDestroy() {
console.info('Application onDestroy'); console.info('Application onDestroy');
}, },
};
```
Access the application object on a specific page.
```javascript
// index.js
export default {
data: {
title: ""
},
onInit() {
if (typeof getApp !== 'undefined') {
var appData = getApp().data;
if (typeof appData !== 'undefined') {
this.title = appData.name; // read from app data
}
}
},
clickHandler() {
if (typeof getApp !== 'undefined') {
var appData = getApp().data;
if (typeof appData !== 'undefined') {
appData.name = this.title; // write to app data
}
}
}
} }
``` ```
> **NOTE**
>
> To ensure that the application can run properly on an earlier version that does not support **getApp**, compatibility processing must be performed in the code. That is, before using **getApp**, check whether it is available.
...@@ -52,7 +52,7 @@ IPC/RPC的主要工作是让运行在不同进程的Proxy和Stub互相通信, ...@@ -52,7 +52,7 @@ IPC/RPC的主要工作是让运行在不同进程的Proxy和Stub互相通信,
#include "iremote_broker.h" #include "iremote_broker.h"
//定义消息码 //定义消息码
const int TRANS_ID_PING_ABILITY = 5 const int TRANS_ID_PING_ABILITY = 5;
const std::string DESCRIPTOR = "test.ITestAbility"; const std::string DESCRIPTOR = "test.ITestAbility";
...@@ -180,138 +180,178 @@ IPC/RPC的主要工作是让运行在不同进程的Proxy和Stub互相通信, ...@@ -180,138 +180,178 @@ IPC/RPC的主要工作是让运行在不同进程的Proxy和Stub互相通信,
1. 添加依赖 1. 添加依赖
```ts ```ts
import rpc from "@ohos.rpc" import rpc from "@ohos.rpc";
import featureAbility from "@ohos.ability.featureAbility" // 仅FA模型需要导入@ohos.ability.featureAbility
// import featureAbility from "@ohos.ability.featureAbility";
``` ```
Stage模型需要获取context
```ts
import Ability from "@ohos.app.ability.UIAbility";
export default class MainAbility extends Ability {
onCreate(want, launchParam) {
console.log("[Demo] MainAbility onCreate");
globalThis.context = this.context;
}
onDestroy() {
console.log("[Demo] MainAbility onDestroy");
}
onWindowStageCreate(windowStage) {
// Main window is created, set main page for this ability
console.log("[Demo] MainAbility onWindowStageCreate");
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
console.log("[Demo] MainAbility onWindowStageDestroy");
}
onForeground() {
// Ability has brought to foreground
console.log("[Demo] MainAbility onForeground");
}
onBackground() {
// Ability has back to background
console.log("[Demo] MainAbility onBackground");
}
}
```
2. 绑定Ability 2. 绑定Ability
首先,构造变量want,指定要绑定的Ability所在应用的包名、组件名,如果是跨设备的场景,还需要绑定目标设备NetworkId(组网场景下对应设备的标识符,可以使用deviceManager获取目标设备的NetworkId);然后,构造变量connect,指定绑定成功、绑定失败、断开连接时的回调函数;最后,使用featureAbility提供的接口绑定Ability。 首先,构造变量want,指定要绑定的Ability所在应用的包名、组件名,如果是跨设备的场景,还需要绑定目标设备NetworkId(组网场景下对应设备的标识符,可以使用deviceManager获取目标设备的NetworkId);然后,构造变量connect,指定绑定成功、绑定失败、断开连接时的回调函数;最后,FA模型使用featureAbility提供的接口绑定Ability,Stage模型通过context获取服务后用提供的接口绑定Ability。
```ts ```ts
import rpc from "@ohos.rpc" import rpc from "@ohos.rpc";
import featureAbility from "@ohos.ability.featureAbility" // 仅FA模型需要导入@ohos.ability.featureAbility
// import featureAbility from "@ohos.ability.featureAbility";
let proxy = null let proxy = null;
let connectId = null let connectId = null;
// 单个设备绑定Ability // 单个设备绑定Ability
let want = { let want = {
// 包名和组件名写实际的值 // 包名和组件名写实际的值
"bundleName": "ohos.rpc.test.server", "bundleName": "ohos.rpc.test.server",
"abilityName": "ohos.rpc.test.server.ServiceAbility", "abilityName": "ohos.rpc.test.server.ServiceAbility",
} };
let connect = { let connect = {
onConnect:function(elementName, remote) { onConnect:function(elementName, remote) {
proxy = remote proxy = remote;
}, },
onDisconnect:function(elementName) { onDisconnect:function(elementName) {
}, },
onFailed:function() { onFailed:function() {
proxy = null proxy = null;
} }
} };
connectId = featureAbility.connectAbility(want, connect) // FA模型使用此方法连接服务
// connectId = featureAbility.connectAbility(want, connect);
connectId = globalThis.context.connectServiceExtensionAbility(want,connect);
// 如果是跨设备绑定,可以使用deviceManager获取目标设备NetworkId // 如果是跨设备绑定,可以使用deviceManager获取目标设备NetworkId
import deviceManager from '@ohos.distributedHardware.deviceManager' import deviceManager from '@ohos.distributedHardware.deviceManager';
function deviceManagerCallback(deviceManager) { function deviceManagerCallback(deviceManager) {
let deviceList = deviceManager.getTrustedDeviceListSync() let deviceList = deviceManager.getTrustedDeviceListSync();
let networkId = deviceList[0].networkId let networkId = deviceList[0].networkId;
let want = { let want = {
"bundleName": "ohos.rpc.test.server", "bundleName": "ohos.rpc.test.server",
"abilityName": "ohos.rpc.test.service.ServiceAbility", "abilityName": "ohos.rpc.test.service.ServiceAbility",
"networkId": networkId, "networkId": networkId,
"flags": 256 "flags": 256
} };
connectId = featureAbility.connectAbility(want, connect) // 建立连接后返回的Id需要保存下来,在断开连接时需要作为参数传入
// FA模型使用此方法连接服务
// connectId = featureAbility.connectAbility(want, connect);
connectId = globalThis.context.connectServiceExtensionAbility(want,connect);
} }
// 第一个参数是本应用的包名,第二个参数是接收deviceManager的回调函数 // 第一个参数是本应用的包名,第二个参数是接收deviceManager的回调函数
deviceManager.createDeviceManager("ohos.rpc.test", deviceManagerCallback) deviceManager.createDeviceManager("ohos.rpc.test", deviceManagerCallback);
``` ```
3. 服务端处理客户端请求 3. 服务端处理客户端请求
服务端被绑定的Ability在onConnect方法里返回继承自rpc.RemoteObject的对象,该对象需要实现onRemoteMessageRequest方法,处理客户端的请求。 服务端被绑定的Ability在onConnect方法里返回继承自rpc.RemoteObject的对象,该对象需要实现onRemoteMessageRequest方法,处理客户端的请求。
```ts ```ts
onConnect(want: Want) { onConnect(want: Want) {
var robj:rpc.RemoteObject = new Stub("rpcTestAbility") var robj:rpc.RemoteObject = new Stub("rpcTestAbility");
return robj return robj;
} }
class Stub extends rpc.RemoteObject { class Stub extends rpc.RemoteObject {
constructor(descriptor) { constructor(descriptor) {
super(descriptor) super(descriptor);
} }
onRemoteMessageRequest(code, data, reply, option) { onRemoteMessageRequest(code, data, reply, option) {
// 根据code处理客户端的请求 // 根据code处理客户端的请求
return true return true;
} }
} }
``` ```
4. 客户端处理服务端响应 4. 客户端处理服务端响应
客户端在onConnect回调里接收到代理对象,调用sendRequestAsync方法发起请求,在期约(JavaScript期约:用于表示一个异步操作的最终完成或失败及其结果值)或者回调函数里接收结果。 客户端在onConnect回调里接收到代理对象,调用sendRequest方法发起请求,在期约(JavaScript期约:用于表示一个异步操作的最终完成或失败及其结果值)或者回调函数里接收结果。
```ts ```ts
// 使用期约 // 使用期约
let option = new rpc.MessageOption() let option = new rpc.MessageOption();
let data = rpc.MessageParcel.create() let data = rpc.MessageParcel.create();
let reply = rpc.MessageParcel.create() let reply = rpc.MessageParcel.create();
// 往data里写入参数 // 往data里写入参数
proxy.sendRequestAsync(1, data, reply, option) proxy.sendRequest(1, data, reply, option)
.then(function(result) { .then(function(result) {
if (result.errCode != 0) { if (result.errCode != 0) {
console.error("send request failed, errCode: " + result.errCode) console.error("send request failed, errCode: " + result.errCode);
return return;
} }
// 从result.reply里读取结果 // 从result.reply里读取结果
}) })
.catch(function(e) { .catch(function(e) {
console.error("send request got exception: " + e) console.error("send request got exception: " + e);
} })
.finally(() => { .finally(() => {
data.reclaim() data.reclaim();
reply.reclaim() reply.reclaim();
}) })
// 使用回调函数 // 使用回调函数
function sendRequestCallback(result) { function sendRequestCallback(result) {
try { try {
if (result.errCode != 0) { if (result.errCode != 0) {
console.error("send request failed, errCode: " + result.errCode) console.error("send request failed, errCode: " + result.errCode);
return return;
} }
// 从result.reply里读取结果 // 从result.reply里读取结果
} finally { } finally {
result.data.reclaim() result.data.reclaim();
result.reply.reclaim() result.reply.reclaim();
} }
} }
let option = new rpc.MessageOption() let option = new rpc.MessageOption();
let data = rpc.MessageParcel.create() let data = rpc.MessageParcel.create();
let reply = rpc.MessageParcel.create() let reply = rpc.MessageParcel.create();
// 往data里写入参数 // 往data里写入参数
proxy.sendRequest(1, data, reply, option, sendRequestCallback) proxy.sendRequest(1, data, reply, option, sendRequestCallback);
``` ```
5. 断开连接 5. 断开连接
IPC通信结束后,使用featureAbility的接口断开连接。 IPC通信结束后,FA模型使用featureAbility的接口断开连接,Stage模型在获取context后用提供的接口断开连接。
```ts ```ts
import rpc from "@ohos.rpc" import rpc from "@ohos.rpc";
import featureAbility from "@ohos.ability.featureAbility" // 仅FA模型需要导入@ohos.ability.featureAbility
// import featureAbility from "@ohos.ability.featureAbility";
function disconnectCallback() { function disconnectCallback() {
console.info("disconnect ability done") console.info("disconnect ability done");
} }
featureAbility.disconnectAbility(connectId, disconnectCallback) // FA模型使用此方法断开连接
// featureAbility.disconnectAbility(connectId, disconnectCallback);
globalThis.context.disconnectServiceExtensionAbility(connectId);
``` ```
...@@ -3,35 +3,25 @@ ...@@ -3,35 +3,25 @@
## 基本概念 ## 基本概念
IPC(Inter-Process Communication)与RPC(Remote Procedure Call)用于实现跨进程通信,不同的是前者使用Binder驱动,用于设备内的跨进程通信,后者使用软总线驱动,用于跨设备跨进程通信。需要跨进程通信的原因是因为每个进程都有自己独立的资源和内存空间,其他进程不能随意访问不同进程的内存和资源,IPC/RPC便是为了突破这一点。IPC和RPC通常采用客户端-服务器(Client-Server)模型,在使用时,请求服务的(Client)一端进程可获取提供服务(Server)一端所在进程的代理(Proxy),并通过此代理读写数据来实现进程间的数据通信,更具体的讲,首先请求服务的(Client)一端会建立一个服务提供端(Server)的代理对象,这个代理对象具备和服务提供端(Server)一样的功能,若想访问服务提供端(Server)中的某一个方法,只需访问代理对象中对应的方法即可,代理对象会将请求发送给服务提供端(Server);然后服务提供端(Server)处理接受到的请求,处理完之后通过驱动返回处理结果给代理对象;最后代理对象将请求结果进一步返回给请求服务端(Client)。通常,Server会先注册系统能力(System Ability)到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理,然后使用代理和SA通信。下文直接使用Proxy表示服务请求方,Stub表示服务提供方。 IPC(Inter-Process Communication)与RPC(Remote Procedure Call)用于实现跨进程通信,不同的是前者使用Binder驱动,用于设备内的跨进程通信,后者使用软总线驱动,用于跨设备跨进程通信。需要跨进程通信的原因是因为每个进程都有自己独立的资源和内存空间,其他进程不能随意访问不同进程的内存和资源,IPC/RPC便是为了突破这一点。
![IPC&RPC通信机制](figures/075sd302-aeb9-481a-bb8f-e552sdb61ead.PNG) > **说明:**
> Stage模型不能直接使用本文介绍的IPC和RPC,需要通过以下能力实现相关业务场景:
>- IPC典型使用场景为[后台服务](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/application-models/background-services.md),后台服务通过IPC机制提供跨进程的服务调用能力。
## 约束与限制 >- RPC典型使用场景为[多端协同](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/application-models/hop-multi-device-collaboration.md),多端协同通过RPC机制提供远端接口调用与数据传递。
- 单个设备上跨进程通信时,传输的数据量最大约为1MB,过大的数据量请使用[匿名共享内存](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-rpc.md#ashmem8)
- 不支持在RPC中订阅匿名Stub对象(没有向SAMgr注册Stub对象)的死亡通知。
- 不支持把跨设备的Proxy对象传递回该Proxy对象所指向的Stub对象所在的设备,即指向远端设备Stub的Proxy对象不能在本设备内进行二次跨进程传递。
## 使用建议
首先,需要编写接口类,接口类中必须定义消息码,供通信双方标识操作,可以有未实现的的方法,因为通信双方均需继承该接口类且双方不能是抽象类,所以此时定义的未实现的方法必须在双方继承时给出实现,这保证了继承双方不是抽象类。然后,需要编写Stub端相关类及其接口,并且实现AsObject方法及OnRemoteRequest方法。同时,也需要编写Proxy端,实现接口类中的方法和AsObject方法,也可以封装一些额外的方法用于调用SendRequest向对端发送数据。以上三者都具备后,便可以向SAMgr注册SA了,此时的注册应该在Stub所在进程完成。最后,在需要的地方从SAMgr中获取Proxy,便可通过Proxy实现与Stub的跨进程通信了。
相关步骤: ## 实现原理
- 实现接口类:需继承IRemoteBroker,需定义消息码,可声明不在此类实现的方法 IPC和RPC通常采用客户端-服务器(Client-Server)模型,在使用时,请求服务的(Client)一端进程可获取提供服务(Server)一端所在进程的代理(Proxy),并通过此代理读写数据来实现进程间的数据通信,更具体的讲,首先请求服务的(Client)一端会建立一个服务提供端(Server)的代理对象,这个代理对象具备和服务提供端(Server)一样的功能,若想访问服务提供端(Server)中的某一个方法,只需访问代理对象中对应的方法即可,代理对象会将请求发送给服务提供端(Server);然后服务提供端(Server)处理接受到的请求,处理完之后通过驱动返回处理结果给代理对象;最后代理对象将请求结果进一步返回给请求服务端(Client)。通常,Server会先注册系统能力(System Ability)到系统能力管理者(System Ability Manager,缩写SAMgr)中,SAMgr负责管理这些SA并向Client提供相关的接口。Client要和某个具体的SA通信,必须先从SAMgr中获取该SA的代理,然后使用代理和SA通信。下文直接使用Proxy表示服务请求方,Stub表示服务提供方
- 实现服务提供端(Stub):需继承IRemoteStub或者RemoteObject,需重写AsObject方法及OnRemoteRequest方法。 ![IPC&RPC通信机制](figures/075sd302-aeb9-481a-bb8f-e552sdb61ead.PNG)
- 实现服务请求端(Proxy):需继承IRemoteProxy或RemoteProxy,需重写AsObject方法,封装所需方法调用SendRequest。
- 注册SA:申请SA的唯一ID,向SAMgr注册SA。
- 获取SA:通过SA的ID和设备ID获取Proxy,使用Proxy与远端通信 ## 约束与限制
- 单个设备上跨进程通信时,传输的数据量最大约为1MB,过大的数据量请使用[匿名共享内存](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-rpc.md#ashmem8)
## 相关模块 - 不支持在RPC中订阅匿名Stub对象(没有向SAMgr注册Stub对象)的死亡通知。
[分布式任务调度子系统](https://gitee.com/openharmony/ability_dmsfwk) - 不支持把跨设备的Proxy对象传递回该Proxy对象所指向的Stub对象所在的设备,即指向远端设备Stub的Proxy对象不能在本设备内进行二次跨进程传递。
\ No newline at end of file
# 远端状态订阅开发实例 # 远端状态订阅开发实例
IPC/RPC提供对远端Stub对象状态的订阅机制, 在远端Stub对象消亡时,可触发消亡通知告诉本地Proxy对象。这种状态通知订阅需要调用特定接口完成,当不再需要订阅时也需要调用特定接口取消。使用这种订阅机制的用户,需要实现消亡通知接口DeathRecipient并实现onRemoteDied方法清理资源。该方法会在远端Stub对象所在进程消亡或所在设备离开组网时被回调。值得注意的是,调用这些接口有一定的顺序。首先,需要Proxy订阅Stub消亡通知,若在订阅期间Stub状态正常,则在不再需要时取消订阅;若在订阅期间Stub所在进程退出或者所在设备退出组网,则会自动触发Proxy自定义的后续操作。 IPC/RPC提供对远端Stub对象状态的订阅机制,在远端Stub对象消亡时,可触发消亡通知告诉本地Proxy对象。这种状态通知订阅需要调用特定接口完成,当不再需要订阅时也需要调用特定接口取消。使用这种订阅机制的用户,需要实现消亡通知接口DeathRecipient并实现onRemoteDied方法清理资源。该方法会在远端Stub对象所在进程消亡或所在设备离开组网时被回调。值得注意的是,调用这些接口有一定的顺序。首先,需要Proxy订阅Stub消亡通知,若在订阅期间Stub状态正常,则在不再需要时取消订阅;若在订阅期间Stub所在进程退出或者所在设备退出组网,则会自动触发Proxy自定义的后续操作。
## 使用场景 ## 使用场景
...@@ -21,7 +21,6 @@ IPC/RPC提供对远端Stub对象状态的订阅机制, 在远端Stub对象消 ...@@ -21,7 +21,6 @@ IPC/RPC提供对远端Stub对象状态的订阅机制, 在远端Stub对象消
#include "iremote_broker.h" #include "iremote_broker.h"
#include "iremote_stub.h" #include "iremote_stub.h"
//定义消息码 //定义消息码
enum { enum {
TRANS_ID_PING_ABILITY = 5, TRANS_ID_PING_ABILITY = 5,
...@@ -61,9 +60,6 @@ int TestServiceProxy::TestPingAbility(const std::u16string &dummy){ ...@@ -61,9 +60,6 @@ int TestServiceProxy::TestPingAbility(const std::u16string &dummy){
} }
``` ```
```c++ ```c++
#include "iremote_object.h" #include "iremote_object.h"
...@@ -87,15 +83,51 @@ result = object->RemoveDeathRecipient(deathRecipient); // 移除消亡通知 ...@@ -87,15 +83,51 @@ result = object->RemoveDeathRecipient(deathRecipient); // 移除消亡通知
## JS侧接口 ## JS侧接口
| 接口名 | 返回值类型 | 功能描述 | | 接口名 | 返回值类型 | 功能描述 |
| -------------------- | ---------- | ------------------------------------------------------------ | | ------------------------ | ---------- | ----------------------------------------------------------------- |
| addDeathRecippient | boolean | 注册用于接收远程对象消亡通知的回调,增加proxy对象上的消亡通知。 | | registerDeathRecipient | void | 注册用于接收远程对象消亡通知的回调,增加 proxy 对象上的消亡通知。 |
| removeDeathRecipient | boolean | 注销用于接收远程对象消亡通知的回调。 | | unregisterDeathRecipient | void | 注销用于接收远程对象消亡通知的回调。 |
| onRemoteDied | void | 在成功添加死亡通知订阅后,当远端对象死亡时,将自动调用本方法。 | | onRemoteDied | void | 在成功添加死亡通知订阅后,当远端对象死亡时,将自动调用本方法。 |
### 获取context
Stage模型在连接服务前需要先获取context
```ts
import Ability from "@ohos.app.ability.UIAbility";
export default class MainAbility extends Ability {
onCreate(want, launchParam) {
console.log("[Demo] MainAbility onCreate");
globalThis.context = this.context;
}
onDestroy() {
console.log("[Demo] MainAbility onDestroy");
}
onWindowStageCreate(windowStage) {
// Main window is created, set main page for this ability
console.log("[Demo] MainAbility onWindowStageCreate");
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
console.log("[Demo] MainAbility onWindowStageDestroy");
}
onForeground() {
// Ability has brought to foreground
console.log("[Demo] MainAbility onForeground");
}
onBackground() {
// Ability has back to background
console.log("[Demo] MainAbility onBackground");
}
}
```
### 参考代码 ### 参考代码
```ts ```ts
import FA from "@ohos.ability.featureAbility"; // 仅FA模型需要导入@ohos.ability.featureAbility
// import FA from "@ohos.ability.featureAbility";
let proxy; let proxy;
let connect = { let connect = {
onConnect: function(elementName, remoteProxy) { onConnect: function(elementName, remoteProxy) {
...@@ -113,15 +145,19 @@ let want = { ...@@ -113,15 +145,19 @@ let want = {
"bundleName": "com.ohos.server", "bundleName": "com.ohos.server",
"abilityName": "com.ohos.server.EntryAbility", "abilityName": "com.ohos.server.EntryAbility",
}; };
FA.connectAbility(want, connect); // FA模型通过此方法连接服务
// FA.connectAbility(want, connect);
globalThis.context.connectServiceExtensionAbility(want, connect);
class MyDeathRecipient { class MyDeathRecipient {
onRemoteDied() { onRemoteDied() {
console.log("server died"); console.log("server died");
} }
} }
let deathRecipient = new MyDeathRecipient(); let deathRecipient = new MyDeathRecipient();
proxy.addDeathRecippient(deathRecipient, 0); proxy.registerDeathRecippient(deathRecipient, 0);
proxy.removeDeathRecipient(deathRecipient, 0); proxy.unregisterDeathRecipient(deathRecipient, 0);
``` ```
## Stub感知Proxy消亡(匿名Stub的使用) ## Stub感知Proxy消亡(匿名Stub的使用)
......
...@@ -167,4 +167,4 @@ USB设备可作为Host设备连接Device设备进行数据传输。开发示例 ...@@ -167,4 +167,4 @@ USB设备可作为Host设备连接Device设备进行数据传输。开发示例
针对USB管理开发,有以下相关实例可供参考: 针对USB管理开发,有以下相关实例可供参考:
- [`USBManager`:USB管理(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/DeviceManagement/USBManager) - [`DeviceManagementCollection`:设备管理合集(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/DeviceManagement/DeviceManagementCollection)
\ No newline at end of file \ No newline at end of file
...@@ -73,7 +73,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; ...@@ -73,7 +73,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
try { try {
atManager.checkAccessToken(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS").then((data) => { atManager.checkAccessToken(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS').then((data) => {
console.log(`checkAccessToken success, data->${JSON.stringify(data)}`); console.log(`checkAccessToken success, data->${JSON.stringify(data)}`);
}).catch((err) => { }).catch((err) => {
console.log(`checkAccessToken fail, err->${JSON.stringify(err)}`); console.log(`checkAccessToken fail, err->${JSON.stringify(err)}`);
...@@ -117,7 +117,7 @@ verifyAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus ...@@ -117,7 +117,7 @@ verifyAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus
```js ```js
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let data = atManager.verifyAccessTokenSync(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); let data = atManager.verifyAccessTokenSync(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS');
console.log(`data->${JSON.stringify(data)}`); console.log(`data->${JSON.stringify(data)}`);
``` ```
...@@ -168,7 +168,7 @@ let atManager = abilityAccessCtrl.createAtManager(); ...@@ -168,7 +168,7 @@ let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let permissionFlags = 1; let permissionFlags = 1;
try { try {
atManager.grantUserGrantedPermission(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS", permissionFlags).then(() => { atManager.grantUserGrantedPermission(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS', permissionFlags).then(() => {
console.log('grantUserGrantedPermission success'); console.log('grantUserGrantedPermission success');
}).catch((err) => { }).catch((err) => {
console.log(`grantUserGrantedPermission fail, err->${JSON.stringify(err)}`); console.log(`grantUserGrantedPermission fail, err->${JSON.stringify(err)}`);
...@@ -220,7 +220,7 @@ let atManager = abilityAccessCtrl.createAtManager(); ...@@ -220,7 +220,7 @@ let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let permissionFlags = 1; let permissionFlags = 1;
try { try {
atManager.grantUserGrantedPermission(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS", permissionFlags, (err, data) => { atManager.grantUserGrantedPermission(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS', permissionFlags, (err, data) => {
if (err) { if (err) {
console.log(`grantUserGrantedPermission fail, err->${JSON.stringify(err)}`); console.log(`grantUserGrantedPermission fail, err->${JSON.stringify(err)}`);
} else { } else {
...@@ -279,7 +279,7 @@ let atManager = abilityAccessCtrl.createAtManager(); ...@@ -279,7 +279,7 @@ let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let permissionFlags = 1; let permissionFlags = 1;
try { try {
atManager.revokeUserGrantedPermission(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS", permissionFlags).then(() => { atManager.revokeUserGrantedPermission(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS', permissionFlags).then(() => {
console.log('revokeUserGrantedPermission success'); console.log('revokeUserGrantedPermission success');
}).catch((err) => { }).catch((err) => {
console.log(`revokeUserGrantedPermission fail, err->${JSON.stringify(err)}`); console.log(`revokeUserGrantedPermission fail, err->${JSON.stringify(err)}`);
...@@ -331,7 +331,7 @@ let atManager = abilityAccessCtrl.createAtManager(); ...@@ -331,7 +331,7 @@ let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let permissionFlags = 1; let permissionFlags = 1;
try { try {
atManager.revokeUserGrantedPermission(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS", permissionFlags, (err, data) => { atManager.revokeUserGrantedPermission(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS', permissionFlags, (err, data) => {
if (err) { if (err) {
console.log(`revokeUserGrantedPermission fail, err->${JSON.stringify(err)}`); console.log(`revokeUserGrantedPermission fail, err->${JSON.stringify(err)}`);
} else { } else {
...@@ -388,7 +388,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; ...@@ -388,7 +388,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
try { try {
atManager.getPermissionFlags(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS").then((data) => { atManager.getPermissionFlags(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS').then((data) => {
console.log(`getPermissionFlags success, data->${JSON.stringify(data)}`); console.log(`getPermissionFlags success, data->${JSON.stringify(data)}`);
}).catch((err) => { }).catch((err) => {
console.log(`getPermissionFlags fail, err->${JSON.stringify(err)}`); console.log(`getPermissionFlags fail, err->${JSON.stringify(err)}`);
...@@ -466,10 +466,10 @@ import bundleManager from '@ohos.bundle.bundleManager'; ...@@ -466,10 +466,10 @@ import bundleManager from '@ohos.bundle.bundleManager';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let appInfo = bundleManager.getApplicationInfoSync('com.example.myapplication', 0, 100); let appInfo = bundleManager.getApplicationInfoSync('com.example.myapplication', 0, 100);
let tokenIDList: Array<number> = [appInfo.accessTokenId]; let tokenIDList: Array<number> = [appInfo.accessTokenId];
let permissionList: Array<Permissions> = ["ohos.permission.DISTRIBUTED_DATASYNC"]; let permissionList: Array<Permissions> = ['ohos.permission.DISTRIBUTED_DATASYNC'];
try { try {
atManager.on('permissionStateChange', tokenIDList, permissionList, (data) => { atManager.on('permissionStateChange', tokenIDList, permissionList, (data) => {
console.debug("receive permission state change, data:" + JSON.stringify(data)); console.debug('receive permission state change, data:' + JSON.stringify(data));
}); });
} catch(err) { } catch(err) {
console.log(`catch err->${JSON.stringify(err)}`); console.log(`catch err->${JSON.stringify(err)}`);
...@@ -504,7 +504,7 @@ off(type: 'permissionStateChange', tokenIDList: Array&lt;number&gt;, permissionL ...@@ -504,7 +504,7 @@ off(type: 'permissionStateChange', tokenIDList: Array&lt;number&gt;, permissionL
| 错误码ID | 错误信息 | | 错误码ID | 错误信息 |
| -------- | -------- | | -------- | -------- |
| 12100001 | The parameter is invalid. The tokenIDs or permissionNames in the list are all invalid. | | 12100001 | The parameter is invalid. The tokenIDs or permissionNames in the list are all invalid. |
| 12100004 | The interface is not used together with "on". | | 12100004 | The interface is not used together with 'on'. |
| 12100007 | Service is abnormal. | | 12100007 | Service is abnormal. |
| 12100008 | Out of memory. | | 12100008 | Out of memory. |
...@@ -517,7 +517,7 @@ import bundleManager from '@ohos.bundle.bundleManager'; ...@@ -517,7 +517,7 @@ import bundleManager from '@ohos.bundle.bundleManager';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let appInfo = bundleManager.getApplicationInfoSync('com.example.myapplication', 0, 100); let appInfo = bundleManager.getApplicationInfoSync('com.example.myapplication', 0, 100);
let tokenIDList: Array<number> = [appInfo.accessTokenId]; let tokenIDList: Array<number> = [appInfo.accessTokenId];
let permissionList: Array<Permissions> = ["ohos.permission.DISTRIBUTED_DATASYNC"]; let permissionList: Array<Permissions> = ['ohos.permission.DISTRIBUTED_DATASYNC'];
try { try {
atManager.off('permissionStateChange', tokenIDList, permissionList); atManager.off('permissionStateChange', tokenIDList, permissionList);
} catch(err) { } catch(err) {
...@@ -557,7 +557,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; ...@@ -557,7 +557,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let promise = atManager.verifyAccessToken(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); let promise = atManager.verifyAccessToken(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS');
promise.then(data => { promise.then(data => {
console.log(`promise: data->${JSON.stringify(data)}`); console.log(`promise: data->${JSON.stringify(data)}`);
}); });
...@@ -598,10 +598,10 @@ requestPermissionsFromUser(context: Context, permissionList: Array&lt;Permission ...@@ -598,10 +598,10 @@ requestPermissionsFromUser(context: Context, permissionList: Array&lt;Permission
import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
try { try {
atManager.requestPermissionsFromUser(this.context, ["ohos.permission.CAMERA"], (err, data)=>{ atManager.requestPermissionsFromUser(this.context, ['ohos.permission.CAMERA'], (err, data)=>{
console.info("data:" + JSON.stringify(data)); console.info('data:' + JSON.stringify(data));
console.info("data permissions:" + data.permissions); console.info('data permissions:' + data.permissions);
console.info("data authResults:" + data.authResults); console.info('data authResults:' + data.authResults);
}); });
} catch(err) { } catch(err) {
console.log(`catch err->${JSON.stringify(err)}`); console.log(`catch err->${JSON.stringify(err)}`);
...@@ -649,12 +649,12 @@ requestPermissionsFromUser(context: Context, permissionList: Array&lt;Permission ...@@ -649,12 +649,12 @@ requestPermissionsFromUser(context: Context, permissionList: Array&lt;Permission
import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
try { try {
atManager.requestPermissionsFromUser(this.context, ["ohos.permission.CAMERA"]).then((data) => { atManager.requestPermissionsFromUser(this.context, ['ohos.permission.CAMERA']).then((data) => {
console.info("data:" + JSON.stringify(data)); console.info('data:' + JSON.stringify(data));
console.info("data permissions:" + data.permissions); console.info('data permissions:' + data.permissions);
console.info("data authResults:" + data.authResults); console.info('data authResults:' + data.authResults);
}).catch((err) => { }).catch((err) => {
console.info("data:" + JSON.stringify(err)); console.info('data:' + JSON.stringify(err));
}) })
} catch(err) { } catch(err) {
console.log(`catch err->${JSON.stringify(err)}`); console.log(`catch err->${JSON.stringify(err)}`);
...@@ -693,7 +693,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; ...@@ -693,7 +693,7 @@ import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let promise = atManager.verifyAccessToken(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); let promise = atManager.verifyAccessToken(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS');
promise.then(data => { promise.then(data => {
console.log(`promise: data->${JSON.stringify(data)}`); console.log(`promise: data->${JSON.stringify(data)}`);
}); });
...@@ -733,7 +733,7 @@ checkAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus; ...@@ -733,7 +733,7 @@ checkAccessTokenSync(tokenID: number, permissionName: Permissions): GrantStatus;
```js ```js
let atManager = abilityAccessCtrl.createAtManager(); let atManager = abilityAccessCtrl.createAtManager();
let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取 let tokenID = 0; // 系统应用可以通过bundleManager.getApplicationInfo获取,普通应用可以通过bundleManager.getBundleInfoForSelf获取
let data = atManager.checkAccessTokenSync(tokenID, "ohos.permission.GRANT_SENSITIVE_PERMISSIONS"); let data = atManager.checkAccessTokenSync(tokenID, 'ohos.permission.GRANT_SENSITIVE_PERMISSIONS');
console.log(`data->${JSON.stringify(data)}`); console.log(`data->${JSON.stringify(data)}`);
``` ```
......
...@@ -197,7 +197,7 @@ import featureAbility from '@ohos.ability.featureAbility'; ...@@ -197,7 +197,7 @@ import featureAbility from '@ohos.ability.featureAbility';
let context = featureAbility.getContext(); let context = featureAbility.getContext();
try { try {
data_preferences.deletePreferences(context, 'mystore', function (err, val) { data_preferences.deletePreferences(context, 'mystore', function (err) {
if (err) { if (err) {
console.info("Failed to delete preferences. code =" + err.code + ", message =" + err.message); console.info("Failed to delete preferences. code =" + err.code + ", message =" + err.message);
return; return;
...@@ -217,7 +217,7 @@ import UIAbility from '@ohos.app.ability.UIAbility'; ...@@ -217,7 +217,7 @@ import UIAbility from '@ohos.app.ability.UIAbility';
class EntryAbility extends UIAbility { class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage) { onWindowStageCreate(windowStage) {
try { try {
data_preferences.deletePreferences(this.context, 'mystore', function (err, val) { data_preferences.deletePreferences(this.context, 'mystore', function (err) {
if (err) { if (err) {
console.info("Failed to delete preferences. code =" + err.code + ", message =" + err.message); console.info("Failed to delete preferences. code =" + err.code + ", message =" + err.message);
return; return;
...@@ -334,7 +334,7 @@ import featureAbility from '@ohos.ability.featureAbility'; ...@@ -334,7 +334,7 @@ import featureAbility from '@ohos.ability.featureAbility';
let context = featureAbility.getContext(); let context = featureAbility.getContext();
try { try {
data_preferences.removePreferencesFromCache(context, 'mystore', function (err, val) { data_preferences.removePreferencesFromCache(context, 'mystore', function (err) {
if (err) { if (err) {
console.info("Failed to remove preferences. code =" + err.code + ", message =" + err.message); console.info("Failed to remove preferences. code =" + err.code + ", message =" + err.message);
return; return;
...@@ -354,7 +354,7 @@ import UIAbility from '@ohos.app.ability.UIAbility'; ...@@ -354,7 +354,7 @@ import UIAbility from '@ohos.app.ability.UIAbility';
class EntryAbility extends UIAbility { class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage) { onWindowStageCreate(windowStage) {
try { try {
data_preferences.removePreferencesFromCache(this.context, 'mystore', function (err, val) { data_preferences.removePreferencesFromCache(this.context, 'mystore', function (err) {
if (err) { if (err) {
console.info("Failed to remove preferences. code =" + err.code + ", message =" + err.message); console.info("Failed to remove preferences. code =" + err.code + ", message =" + err.message);
return; return;
......
...@@ -58,7 +58,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -58,7 +58,7 @@ import privacyManager from '@ohos.privacyManager';
let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId
try { try {
privacyManager.addPermissionUsedRecord(tokenID, "ohos.permission.PERMISSION_USED_STATS", 1, 0).then(() => { privacyManager.addPermissionUsedRecord(tokenID, 'ohos.permission.PERMISSION_USED_STATS', 1, 0).then(() => {
console.log('addPermissionUsedRecord success'); console.log('addPermissionUsedRecord success');
}).catch((err) => { }).catch((err) => {
console.log(`addPermissionUsedRecord fail, err->${JSON.stringify(err)}`); console.log(`addPermissionUsedRecord fail, err->${JSON.stringify(err)}`);
...@@ -108,7 +108,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -108,7 +108,7 @@ import privacyManager from '@ohos.privacyManager';
let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId
try { try {
privacyManager.addPermissionUsedRecord(tokenID, "ohos.permission.PERMISSION_USED_STATS", 1, 0, (err, data) => { privacyManager.addPermissionUsedRecord(tokenID, 'ohos.permission.PERMISSION_USED_STATS', 1, 0, (err, data) => {
if (err) { if (err) {
console.log(`addPermissionUsedRecord fail, err->${JSON.stringify(err)}`); console.log(`addPermissionUsedRecord fail, err->${JSON.stringify(err)}`);
} else { } else {
...@@ -160,14 +160,14 @@ getPermissionUsedRecord(request: PermissionUsedRequest): Promise&lt;PermissionUs ...@@ -160,14 +160,14 @@ getPermissionUsedRecord(request: PermissionUsedRequest): Promise&lt;PermissionUs
import privacyManager from '@ohos.privacyManager'; import privacyManager from '@ohos.privacyManager';
let request = { let request = {
"tokenId": 1, 'tokenId': 1,
"isRemote": false, 'isRemote': false,
"deviceId": "device", 'deviceId': 'device',
"bundleName": "bundle", 'bundleName': 'bundle',
"permissionNames": [], 'permissionNames': [],
"beginTime": 0, 'beginTime': 0,
"endTime": 1, 'endTime': 1,
"flag":privacyManager.PermissionUsageFlag.FLAG_PERMISSION_USAGE_DETAIL, 'flag':privacyManager.PermissionUsageFlag.FLAG_PERMISSION_USAGE_DETAIL,
}; };
try { try {
privacyManager.getPermissionUsedRecord(request).then((data) => { privacyManager.getPermissionUsedRecord(request).then((data) => {
...@@ -215,14 +215,14 @@ getPermissionUsedRecord(request: PermissionUsedRequest, callback: AsyncCallback& ...@@ -215,14 +215,14 @@ getPermissionUsedRecord(request: PermissionUsedRequest, callback: AsyncCallback&
import privacyManager from '@ohos.privacyManager'; import privacyManager from '@ohos.privacyManager';
let request = { let request = {
"tokenId": 1, 'tokenId': 1,
"isRemote": false, 'isRemote': false,
"deviceId": "device", 'deviceId': 'device',
"bundleName": "bundle", 'bundleName': 'bundle',
"permissionNames": [], 'permissionNames': [],
"beginTime": 0, 'beginTime': 0,
"endTime": 1, 'endTime': 1,
"flag":privacyManager.PermissionUsageFlag.FLAG_PERMISSION_USAGE_DETAIL, 'flag':privacyManager.PermissionUsageFlag.FLAG_PERMISSION_USAGE_DETAIL,
}; };
try { try {
privacyManager.getPermissionUsedRecord(request, (err, data) => { privacyManager.getPermissionUsedRecord(request, (err, data) => {
...@@ -280,7 +280,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -280,7 +280,7 @@ import privacyManager from '@ohos.privacyManager';
let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId
try { try {
privacyManager.startUsingPermission(tokenID, "ohos.permission.PERMISSION_USED_STATS").then(() => { privacyManager.startUsingPermission(tokenID, 'ohos.permission.PERMISSION_USED_STATS').then(() => {
console.log('startUsingPermission success'); console.log('startUsingPermission success');
}).catch((err) => { }).catch((err) => {
console.log(`startUsingPermission fail, err->${JSON.stringify(err)}`); console.log(`startUsingPermission fail, err->${JSON.stringify(err)}`);
...@@ -328,7 +328,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -328,7 +328,7 @@ import privacyManager from '@ohos.privacyManager';
let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId
try { try {
privacyManager.startUsingPermission(tokenID, "ohos.permission.PERMISSION_USED_STATS", (err, data) => { privacyManager.startUsingPermission(tokenID, 'ohos.permission.PERMISSION_USED_STATS', (err, data) => {
if (err) { if (err) {
console.log(`startUsingPermission fail, err->${JSON.stringify(err)}`); console.log(`startUsingPermission fail, err->${JSON.stringify(err)}`);
} else { } else {
...@@ -383,7 +383,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -383,7 +383,7 @@ import privacyManager from '@ohos.privacyManager';
let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId
try { try {
privacyManager.stopUsingPermission(tokenID, "ohos.permission.PERMISSION_USED_STATS").then(() => { privacyManager.stopUsingPermission(tokenID, 'ohos.permission.PERMISSION_USED_STATS').then(() => {
console.log('stopUsingPermission success'); console.log('stopUsingPermission success');
}).catch((err) => { }).catch((err) => {
console.log(`stopUsingPermission fail, err->${JSON.stringify(err)}`); console.log(`stopUsingPermission fail, err->${JSON.stringify(err)}`);
...@@ -431,7 +431,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -431,7 +431,7 @@ import privacyManager from '@ohos.privacyManager';
let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId let tokenID = 0; // 可以通过getApplicationInfo获取accessTokenId
try { try {
privacyManager.stopUsingPermission(tokenID, "ohos.permission.PERMISSION_USED_STATS", (err, data) => { privacyManager.stopUsingPermission(tokenID, 'ohos.permission.PERMISSION_USED_STATS', (err, data) => {
if (err) { if (err) {
console.log(`stopUsingPermission fail, err->${JSON.stringify(err)}`); console.log(`stopUsingPermission fail, err->${JSON.stringify(err)}`);
} else { } else {
...@@ -481,7 +481,7 @@ import privacyManager from '@ohos.privacyManager'; ...@@ -481,7 +481,7 @@ import privacyManager from '@ohos.privacyManager';
let permissionList = []; let permissionList = [];
try { try {
privacyManager.on('activeStateChange', permissionList, (data) => { privacyManager.on('activeStateChange', permissionList, (data) => {
console.debug("receive permission state change, data:" + JSON.stringify(data)); console.debug('receive permission state change, data:' + JSON.stringify(data));
}); });
} catch(err) { } catch(err) {
console.log(`catch err->${JSON.stringify(err)}`); console.log(`catch err->${JSON.stringify(err)}`);
...@@ -513,7 +513,7 @@ off(type: 'activeStateChange', permissionList: Array&lt;Permissions&gt;, callbac ...@@ -513,7 +513,7 @@ off(type: 'activeStateChange', permissionList: Array&lt;Permissions&gt;, callbac
| 错误码ID | 错误信息 | | 错误码ID | 错误信息 |
| -------- | -------- | | -------- | -------- |
| 12100001 | The permissionNames in the list are all invalid, or the list size exceeds 1024 bytes. | | 12100001 | The permissionNames in the list are all invalid, or the list size exceeds 1024 bytes. |
| 12100004 | The interface is not used together with "on"| | 12100004 | The interface is not used together with 'on'|
| 12100007 | Service is abnormal. | | 12100007 | Service is abnormal. |
| 12100008 | Out of memory. | | 12100008 | Out of memory. |
......
...@@ -4856,7 +4856,7 @@ readException(): void ...@@ -4856,7 +4856,7 @@ readException(): void
Stage模型的应用在获取服务前需要先获取context,具体方法可参考[获取context](#获取context) Stage模型的应用在获取服务前需要先获取context,具体方法可参考[获取context](#获取context)
```ts ```ts
// 仅FA模型需要导入@ohos.ability.;featureAbility // 仅FA模型需要导入@ohos.ability.featureAbility
// import FA from "@ohos.ability.featureAbility"; // import FA from "@ohos.ability.featureAbility";
let proxy; let proxy;
...@@ -5450,6 +5450,7 @@ marshalling(dataOut: MessageSequence): boolean ...@@ -5450,6 +5450,7 @@ marshalling(dataOut: MessageSequence): boolean
| 类型 | 说明 | | 类型 | 说明 |
| ------- | -------------------------------- | | ------- | -------------------------------- |
| boolean | true:封送成功,false:封送失败。| | boolean | true:封送成功,false:封送失败。|
**示例:** **示例:**
```ts ```ts
...@@ -5555,6 +5556,7 @@ marshalling(dataOut: MessageParcel): boolean ...@@ -5555,6 +5556,7 @@ marshalling(dataOut: MessageParcel): boolean
| 类型 | 说明 | | 类型 | 说明 |
| ------- | -------------------------------- | | ------- | -------------------------------- |
| boolean | true:封送成功,false:封送失败。 | | boolean | true:封送成功,false:封送失败。 |
**示例:** **示例:**
```ts ```ts
...@@ -7093,9 +7095,9 @@ MessageOption构造函数。 ...@@ -7093,9 +7095,9 @@ MessageOption构造函数。
**参数:** **参数:**
| 参数名 | 类型 | 必填 | 说明 | | 参数名 | 类型 | 必填 | 说明 |
| --------- | ------ | ---- | -------------------------------------- | | ------ | ------- | ---- | -------------------------------------- |
| syncFlags | number | 否 | 同步调用或异步调用标志。默认同步调用。 | | async | boolean | 否 | 同步调用或异步调用标志。默认同步调用。 |
**示例:** **示例:**
...@@ -7823,7 +7825,7 @@ sendMessageRequest(code: number, data: MessageSequence, reply: MessageSequence, ...@@ -7823,7 +7825,7 @@ sendMessageRequest(code: number, data: MessageSequence, reply: MessageSequence,
| 类型 | 说明 | | 类型 | 说明 |
| ---------------------------- | --------------------------------------------- | | ---------------------------- | --------------------------------------------- |
| Promise&lt;RequestResult&gt; | 返回一个期约,兑现值是sendRequestResult实例。 | | Promise&lt;RequestResult&gt; | 返回一个期约,兑现值是RequestResult实例。 |
**示例:** **示例:**
...@@ -9099,6 +9101,7 @@ readFromAshmem(size: number, offset: number): number[] ...@@ -9099,6 +9101,7 @@ readFromAshmem(size: number, offset: number): number[]
```ts ```ts
import Ability from '@ohos.app.ability.UIAbility'; import Ability from '@ohos.app.ability.UIAbility';
export default class MainAbility extends Ability { export default class MainAbility extends Ability {
onCreate(want, launchParam) { onCreate(want, launchParam) {
console.log("[Demo] MainAbility onCreate"); console.log("[Demo] MainAbility onCreate");
......
...@@ -127,3 +127,5 @@ ...@@ -127,3 +127,5 @@
- [热场景定制开发指导](subsys-thermal_scene.md) - [热场景定制开发指导](subsys-thermal_scene.md)
- 电源管理 - 电源管理
- [电源模式定制开发指导](subsys-power-mode-customization.md) - [电源模式定制开发指导](subsys-power-mode-customization.md)
- [电源默认休眠行为定制开发指导](subsys-power-default-sleep-behavior-customization.md)
- [唤醒源定制开发指导](subsys-power-wakeup-source-customization.md)
# 电源默认休眠行为定制开发指导
## 概述
### 简介
当前OpenHarmony灭屏后会启动运行锁循环检测线程,然后默认进入休眠状态。不同设备的灭屏方式不相同,可能为合盖灭屏、超时灭屏或是按电源键灭屏等;灭屏后的默认行为也不相同,可能为无动作、将屏幕下电,或是进入休眠状态等。为此,OpenHarmony提供电源默认休眠行为的定制方式,产品可以根据具体的设计规格来定制此特性。
### 约束与限制
配置策略:
产品定制的配置路径,需要根据[配置策略](https://gitee.com/openharmony/customization_config_policy)决定。本开发指导中的定制路径以`/vendor`进行举例,请开发者根据具体的产品配置策略,修改定制路径。
## 开发指导
### 搭建环境
设备要求:
标准系统开发板,如DAYU200/Hi3516DV300开源套件。
环境要求:
Linux调测环境,相关要求和配置可参考《[快速入门](../quick-start/quickstart-overview.md)
### 开发步骤
本文以[DAYU200](https://gitee.com/openharmony/vendor_hihope/tree/master/rk3568)为例介绍电源默认休眠行为的定制方法。
1. 在产品目录`/vendor/hihope/rk3568`下创建power_manager文件夹。
2. 参考电源管理服务组件中的[电源默认休眠行为配置文件夹](https://gitee.com/openharmony/powermgr_power_manager/tree/master/services/native/profile)创建目标文件夹,并安装到`/vendor/hihope/rk3568/power_manager`目录下,文件格式如下:
```text
profile
├── BUILD.gn
├── power_suspend.json
```
3. 编写定制的power_suspend.json,定制后的电源默认休眠行为示例如下:
```json
{
"powerkey": {
"action": 1,
"delayMs": 0
},
"timeout": {
"action": 1,
"delayMs": 0
},
"lid": {
"action": 1,
"delayMs": 0
},
"switch": {
"action": 1,
"delayMs": 0
}
}
```
**表1** 休眠源说明
| 休眠源 | 描述 |
| -------- | -------- |
| powerkey | 电源键灭屏 |
| timeout | 超时灭屏 |
| lid | 皮套灭屏 |
| switch | 合盖灭屏 |
**表2** 休眠源配置说明
| 配置项 | 描述 |
| -------- | -------- |
| action | 执行动作,需配置具体枚举值数字,详细说明见下表。 |
| delayMs | 延迟时间,单位毫秒。 |
**表3** action说明
| action | 取值 | 描述 |
| -------- | -------- | -------- |
| ACTION_NONE | 0 | 无动作 |
| ACTION_AUTO_SUSPEND | 1 | 自动进入睡眠 |
| ACTION_FORCE_SUSPEND | 2 | 强制进入睡眠 |
| ACTION_HIBERNATE | 3 | 进入休眠 |
| ACTION_SHUTDOWN | 4 | 关机 |
4. 参考[电源默认休眠行为的配置文件夹中的BUILD.gn](https://gitee.com/openharmony/powermgr_power_manager/blob/master/services/native/profile/BUILD.gn)编写BUILD.gn文件,将power_suspend.json打包到`/vendor/etc/power_config`目录下,配置如下:
```shell
import("//build/ohos.gni") #引用build/ohos.gni
ohos_prebuilt_etc("suspend_config") {
source = "power_suspend.json"
relative_install_dir = "power_config"
install_images = [ chipset_base_dir ] #安装到vendor目录下的必要配置
part_name = "product_rk3568" #part_name为product_rk3568,以实现后续编译
}
```
5. 将编译目标添加到`/vendor/hihope/rk3568`目录下[ohos.build](https://gitee.com/openharmony/vendor_hihope/blob/master/rk3568/ohos.build)的"module_list"中,例如:
```json
{
"parts": {
"product_rk3568": {
"module_list": [
"//vendor/hihope/rk3568/default_app_config:default_app_config",
"//vendor/hihope/rk3568/image_conf:custom_image_conf",
"//vendor/hihope/rk3568/preinstall-config:preinstall-config",
"//vendor/hihope/rk3568/resourceschedule:resourceschedule",
"//vendor/hihope/rk3568/etc:product_etc_conf",
"//vendor/hihope/rk3568/power_manager/profile:suspend_config" //添加suspend_config的编译
]
}
},
"subsystem": "product_hihope"
}
```
“//vendor/hihope/rk3568/power_manager/”为文件夹路径,“profile”为创建的文件夹名字,“suspend_config”为编译目标。
6. 参考《[快速入门](../quick-start/quickstart-overview.md)》编译定制版本,编译命令如下:
```shell
./build.sh --product-name rk3568 --ccache
```
7. 将定制版本烧录到DAYU200开发板中。
### 调测验证
1. 以新的休眠源配置文件为例,更改之后:
```json
{
"powerkey": {
"action": 4,
"delayMs": 0
},
"timeout": {
"action": 1,
"delayMs": 0
},
"lid": {
"action": 1,
"delayMs": 0
},
"switch": {
"action": 1,
"delayMs": 0
}
}
```
2. 开机后,点击电源按键。
设备进入关机状态。
3. 再次开机后等待一段时间。
设备进入黑屏状态。
# 唤醒源定制开发指导
## 概述
### 简介
OpenHarmony支持多种唤醒源,如电源键、键盘、鼠标等,并提供了定制开启和关闭的方式。当设备进入休眠状态后,用户可以通过按电源键、按键盘、鼠标事件等,来点亮屏幕并唤醒设备。但不同的产品可能支持不同的外设,比如无手写笔、无皮套等。为此,OpenHarmony提供唤醒源的定制方式,产品可以根据具体的设计规格来定制此特性。
### 约束与限制
配置策略:
产品定制的配置路径,需要根据[配置策略](https://gitee.com/openharmony/customization_config_policy)决定。本开发指导中的定制路径以`/vendor`进行举例,请开发者根据具体的产品配置策略,修改定制路径。
## 开发指导
### 搭建环境
设备要求:
标准系统开发板,如DAYU200/Hi3516DV300开源套件。
环境要求:
Linux调测环境,相关要求和配置可参考《[快速入门](../quick-start/quickstart-overview.md)
### 开发步骤
本文以[DAYU200](https://gitee.com/openharmony/vendor_hihope/tree/master/rk3568)为例介绍唤醒源的定制方法。
1. 在产品目录`/vendor/hihope/rk3568`下创建power_manager文件夹。
2. 参考[唤醒源文件夹](https://gitee.com/openharmony/powermgr_power_manager/tree/master/services/native/profile)创建目标文件夹,并安装到`/vendor/hihope/rk3568/power_manager`目录下,文件格式如下:
```text
profile
├── BUILD.gn
├── power_wakeup.json
```
3. 编写定制的power_wakeup.json,包含定制后的唤醒源如下:
```json
{
"powerkey": {
"enable": true
},
"keyborad": {
"enable": true
},
"mouse": {
"enable": true
},
"touchscreen": {
"enable": true,
"click": 2
},
"touchpad": {
"enable": true
},
"pen": {
"enable": true
},
"lid": {
"enable": true
},
"switch": {
"enable": true
}
}
```
**表1** 唤醒源说明
| 休眠源 | 描述 |
| -------- | -------- |
| powerkey | 电源键唤醒 |
| keyborad | 键盘唤醒 |
| mouse | 鼠标唤醒 |
| touchscreen | 触摸屏幕唤醒 |
| touchpad | 触摸板唤醒 |
| pen | 手写笔唤醒 |
| lid | 皮套唤醒 |
| switch | 盖子唤醒 |
**表2** 唤醒源配置说明
| 配置项 | 类型 | 描述 |
| -------- | -------- | -------- |
| enable | bool | 是否开启唤醒监听 |
| click | int | 点击次数 |
4. 参考[唤醒源的配置文件夹中的BUILD.gn](https://gitee.com/openharmony/powermgr_power_manager/blob/master/services/native/profile/BUILD.gn)编写BUILD.gn文件,将power_wakeup.json打包到`/vendor/etc/power_config`目录下,配置如下:
```shell
import("//build/ohos.gni") #引用build/ohos.gni
ohos_prebuilt_etc("wakeup_config") {
source = "power_wakeup.json"
relative_install_dir = "power_config"
install_images = [ chipset_base_dir ] #安装到vendor目录下的必要配置
part_name = "product_rk3568" #part_name为product_rk3568,以实现后续编译
}
```
5. 将编译目标添加到`/vendor/hihope/rk3568`目录下[ohos.build](https://gitee.com/openharmony/vendor_hihope/blob/master/rk3568/ohos.build)的"module_list"中,例如:
```json
{
"parts": {
"product_rk3568": {
"module_list": [
"//vendor/hihope/rk3568/default_app_config:default_app_config",
"//vendor/hihope/rk3568/image_conf:custom_image_conf",
"//vendor/hihope/rk3568/preinstall-config:preinstall-config",
"//vendor/hihope/rk3568/resourceschedule:resourceschedule",
"//vendor/hihope/rk3568/etc:product_etc_conf",
"//vendor/hihope/rk3568/power_manager/profile:wakeup_config" //添加wakeup_config的编译
]
}
},
"subsystem": "product_hihope"
}
```
“//vendor/hihope/rk3568/power_manager/”为文件夹路径,“profile”为创建的文件夹名字,“wakeup_config”为编译目标。
6. 参考《[快速入门](../quick-start/quickstart-overview.md)》编译定制版本,编译命令如下:
```shell
./build.sh --product-name rk3568 --ccache
```
7. 将定制版本烧录到DAYU200开发板中。
### 调测验证
1. 以新的唤醒源配置文件为例,更改之后:
```json
{
"powerkey": {
"enable": true
},
"keyborad": {
"enable": true
},
"mouse": {
"enable": true
},
"touchscreen": {
"enable": false,
"click": 2
},
"touchpad": {
"enable": false
},
"pen": {
"enable": false
},
"lid": {
"enable": false
},
"switch": {
"enable": false
}
}
```
2. 开机后,点击电源键使设备进入休眠状态,再次点击电源键。
设备屏幕点亮,设备被唤醒。
3. 点击电源键使设备进入休眠状态,按下键盘。
设备屏幕点亮,设备被唤醒。
4. 点击电源键使设备进入休眠状态,滑动鼠标。
设备屏幕点亮,设备被唤醒。
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册