提交 511d04e7 编写于 作者: W wangding32

Merge branch 'master' of https://gitee.com/openharmony/docs

此差异已折叠。
......@@ -146,7 +146,7 @@ The following table describes the subsystems of OpenHarmony. For details about t
## Supported Development Boards
Currently, the OpenHarmony community supports 22 types of development boards, which are listed in [Development Boards Supported](device-dev/dev-board-on-the-master.md). The following table describes three of them, which are the first three integrated into the OpenHarmony master. You can visit http://ci.openharmony.cn/dailys/dailybuilds to obtain daily builds.
Currently, the OpenHarmony community supports 22 types of development boards, which are listed in [Development Boards Supported](device-dev/dev-board-on-the-master.md). The following table describes three of them, which are the first three integrated into the OpenHarmony master. You can visit http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist to obtain daily builds.
| System Type| Board Model| Chip Model| <div style="width:200pt">Function Description and Use Case</div> | Application Scenario| Code Repository |
| -------- | -------- | -------- | -------- | -------- | -------- |
......
......@@ -62,7 +62,7 @@ sequenceable a.b..C.D
The preceding statement is parsed into the following code in the C++ header file:
```cpp
#include "a/b/d.h"
#include "a/b/d.h"
using C::D;
```
......@@ -347,11 +347,10 @@ export default {
#### Calling Methods from the Client for IPC
When the client calls **connectAbility()** to connect to a Service ability, the **onConnect** callback in **onAbilityConnectDone** of the client receives the **IRemoteObject** instance returned by the **onConnect()** method of the Service ability. The client and Service ability are in different applications. Therefore, the directory of the client application must contain a copy of the .idl file (the SDK automatically generates the proxy class). The **onConnect** callback then uses the **IRemoteObject** instance to create the **testProxy** instance of the **IdlTestServiceProxy** class and calls the related IPC method. The sample code is as follows:
When the client calls **connectServiceExtensionAbility()** to connect to a Service ability, the **onConnect** callback in **onAbilityConnectDone** of the client receives the **IRemoteObject** instance returned by the **onConnect()** method of the Service ability. The client and Service ability are in different applications. Therefore, the directory of the client application must contain a copy of the .idl file (the SDK automatically generates the proxy class). The **onConnect** callback then uses the **IRemoteObject** instance to create the **testProxy** instance of the **IdlTestServiceProxy** class and calls the related IPC method. The sample code is as follows:
```ts
import IdlTestServiceProxy from './idl_test_service_proxy'
import featureAbility from '@ohos.ability.featureAbility';
function callbackTestIntTransaction(result: number, ret: number): void {
if (result == 0 && ret == 124) {
......@@ -396,13 +395,13 @@ var onAbilityConnectDone = {
}
};
function connectAbility: void {
function connectAbility(): void {
let want = {
bundleName: 'com.example.myapplicationidl',
abilityName: 'com.example.myapplicationidl.ServiceAbility'
};
let connectionId = -1;
connectionId = featureAbility.connectAbility(want, onAbilityConnectDone);
connectionId = this.context.connectServiceExtensionAbility(want, onAbilityConnectDone);
}
......
......@@ -61,7 +61,7 @@
- [Component Startup Rules (Stage Model)](component-startup-rules.md)
- Inter-Device Application Component Interaction (Continuation)
- [Continuation Overview](inter-device-interaction-hop-overview.md)
- [Cross-Device Migration (for System Applications Only)](hop-cross-device-migration.md)
- [Cross-Device Migration](hop-cross-device-migration.md)
- [Multi-device Collaboration (for System Applications Only)](hop-multi-device-collaboration.md)
- [Subscribing to System Environment Variable Changes](subscribe-system-environment-variable-changes.md)
- Process Model
......
......@@ -118,7 +118,12 @@ After developing the custom logic for an accessibility extension service, you mu
```
## Enabling or Disabling a Custom Accessibility Extension Service
To enable or disable an accessibility extension service, run the following command:
You can enable or disable a custom accessibility extension service through the command line interface or the device settings.
**Method 1**: through the command line interface
Run the **hdc shell** command, then the following system command:
- To enable the service: **accessibility enable -a AccessibilityExtAbility -b com.example.demo -c rg**
- To disable the service: **accessibility disable -a AccessibilityExtAbility -b com.example.demo**
......@@ -126,3 +131,9 @@ In the preceding commands, **AccessibilityExtAbility** indicates the name of the
If the service is enabled or disabled successfully, the message "enable ability successfully" or "disable ability successfully" is displayed.
**Method 2**: through the device settings
- From the device settings screen, access the list of installed extended services under accessibility.
If an extended service is not installed, it is grayed out, and "No service" is displayed.
- Select the target extended service, and toggle on or off the switch to enable or disable it.
- If you opt to enable a service, a security reminder is displayed. Wait until the countdown ends and then select the check box indicating that you are aware of and willing to assume the listed risks.
......@@ -54,7 +54,7 @@ Widget-related configuration includes **FormExtensionAbility** configuration and
| formVisibleNotify | Whether the widget is allowed to use the widget visibility notification.| String| Yes (initial value: left empty)|
| metadata | Metadata of the widget. This field contains the array of the **customizeData** field.| Object| Yes (initial value: left empty)|
| dataProxyEnabled | Whether the widget supports the [update-through-proxy](./arkts-ui-widget-update-by-proxy.md) feature.<br>- **true**: The widget supports the update-through-proxy feature.<br>- **false**: The widget does not support the update-through-proxy feature.<br>If this tag is set to **true**, the settings for the scheduled update time will still take effect, but the settings for the update interval and next update time will not.| Boolean| Yes (initial value: **false**)|
| isDynamic | Whether the widget is a dynamic widget. This tag only applies to ArkTS widgets.<br>- **true**: The widget is a dynamic widget.<br>- **false**: The widget is a static widget. In this case, the widget is displayed as a static image after being added.| Boolean| Yes (initial value: **true**)|
| isDynamic | Whether the widget is a dynamic widget. This tag applies only to ArkTS widgets.<br>- **true**: The widget is a dynamic widget.<br>- **false**: The widget is a static widget. In this case, the widget is displayed as a static image after being added.| Boolean| Yes (initial value: **true**)|
**Table 2** Internal structure of the window object
......
......@@ -26,7 +26,7 @@ In view of this, OpenHarmony formulates a set of component startup rules, as fol
- If the **exported** field of the target component is **false**, verify the **ohos.permission.START_INVISIBLE_ABILITY** permission.
- For details, see [Component exported Configuration](../quick-start/module-configuration-file.md#abilities).
- **Before starting a component of a background application, verify the BACKGROUND permission.**
- **Before starting a UIAbility component of a background application, verify the BACKGROUND permission.**
- An application is considered as a foreground application only when the application process gains focus or its UIAbility component is running in the foreground.
- Verify the **ohos.permission.START_ABILITIES_FROM_BACKGROUND** permission.
......@@ -45,7 +45,9 @@ In view of this, OpenHarmony formulates a set of component startup rules, as fol
The rules for starting components on the same device vary in the following scenarios:
- Starting or connecting to the UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components
- Starting the UIAbility component
- Starting the ServiceExtensionAbility and DataShareExtensionAbility components
- Using **startAbilityByCall()** to start the UIAbility component
......@@ -56,9 +58,10 @@ In view of this, OpenHarmony formulates a set of component startup rules, as fol
The rules for starting components on a different device vary in the following scenarios:
- Starting or connecting to the UIAbility, ServiceExtensionAbility, and DataShareExtensionAbility components
- Starting the UIAbility component
- Starting the ServiceExtensionAbility and DataShareExtensionAbility components
- Using **startAbilityByCall()** to start the UIAbility component
![component-startup-rules](figures/component-startup-inter-stage.png)
......@@ -10,7 +10,7 @@
| [getBundleName(callback : AsyncCallback&lt;string&gt;): void;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7)<br>[getBundleName(): Promise&lt;string&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetbundlename7-1) | application\UIAbilityContext.d.ts | [abilityInfo.bundleName: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [getDisplayOrientation(callback : AsyncCallback&lt;bundle.DisplayOrientation&gt;): void;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7)<br>[getDisplayOrientation(): Promise&lt;bundle.DisplayOrientation&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetdisplayorientation7-1) | \@ohos.screen.d.ts | [readonly orientation: Orientation;](../reference/apis/js-apis-screen.md#orientation) |
| [setDisplayOrientation(orientation:bundle.DisplayOrientation, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetdisplayorientation7)<br>[setDisplayOrientation(orientation:bundle.DisplayOrientation):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetdisplayorientation7-1) | \@ohos.screen.d.ts | [setOrientation(orientation: Orientation, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-screen.md#setorientation)<br>[setOrientation(orientation: Orientation): Promise&lt;void&gt;;](../reference/apis/js-apis-screen.md#setorientation-1) |
| [setShowOnLockScreen(show:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreen7)<br>[setShowOnLockScreen(show:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreen7-1) | \@ohos.window.d.ts | [setShowOnLockScreen(showOnLockScreen: boolean): void;](../reference/apis/js-apis-window.md#setshowonlockscreen9) |
| [setShowOnLockScreen(show:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreendeprecated)<br>[setShowOnLockScreen(show:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetshowonlockscreendeprecated-1) | \@ohos.window.d.ts | [setShowOnLockScreen(showOnLockScreen: boolean): void;](../reference/apis/js-apis-window.md#setshowonlockscreen9) |
| [setWakeUpScreen(wakeUp:boolean, callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextsetwakeupscreen7)<br>[setWakeUpScreen(wakeUp:boolean):Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextsetwakeupscreen7-1) | \@ohos.window.d.ts | [setWakeUpScreen(wakeUp: boolean): void;](../reference/apis/js-apis-window.md#setwakeupscreen9) |
| [getProcessInfo(callback:AsyncCallback&lt;ProcessInfo&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessinfo7)<br>[getProcessInfo():Promise&lt;ProcessInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetprocessinfo7-1) | \@ohos.app.ability.abilityManager.d.ts | [getAbilityRunningInfos(callback: AsyncCallback&lt;Array&lt;AbilityRunningInfo&gt;&gt;): void;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos)<br>[getAbilityRunningInfos(): Promise&lt;Array&lt;AbilityRunningInfo&gt;&gt;;](../reference/apis/js-apis-app-ability-abilityManager.md#getabilityrunninginfos-1) |
| [getElementName(callback:AsyncCallback&lt;ElementName&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetelementname7)<br>[getElementName():Promise&lt;ElementName&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetelementname7-1) | application\UIAbilityContext.d.ts | [abilityInfo.name: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)<br>[abilityInfo.bundleName: string;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
......@@ -26,5 +26,3 @@
| [getAbilityInfo(callback:AsyncCallback&lt;AbilityInfo&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7)<br>[getAbilityInfo():Promise&lt;AbilityInfo&gt;;](../reference/apis/js-apis-inner-app-context.md#contextgetabilityinfo7-1) | application\UIAbilityContext.d.ts | [abilityInfo: AbilityInfo;](../reference/apis/js-apis-inner-application-uiAbilityContext.md#attributes)|
| [isUpdatingConfigurations(callback:AsyncCallback&lt;boolean&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7)<br>[isUpdatingConfigurations():Promise&lt;boolean&gt;;](../reference/apis/js-apis-inner-app-context.md#contextisupdatingconfigurations7-1) | There is no corresponding API in the stage model.| OpenHarmony applications do not restart when the system environment changes. The **onConfigurationUpdated** callback is invoked to notify the applications of the changes. This API provides an empty implementation in the FA model, and the stage model does not provide a corresponding API.|
| [printDrawnCompleted(callback:AsyncCallback&lt;void&gt;):void;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7)<br>[printDrawnCompleted():Promise&lt;void&gt;;](../reference/apis/js-apis-inner-app-context.md#contextprintdrawncompleted7-1) | There is no corresponding API in the stage model.| This API provides an empty implementation in the FA model. The stage model does not provide a corresponding API.|
<!--no_check-->
\ No newline at end of file
......@@ -18,7 +18,7 @@ The table below describes the matching rules of explicit [Want](../reference/api
| action | string | No| No| This field is not used for matching. It is passed to the target application component as a parameter.|
| entities | Array&lt;string&gt; | No| No| This field is not used for matching. It is passed to the target application component as a parameter.|
| flags | number | No| No| This field is not used for matching and is directly transferred to the system for processing. It is generally used to set runtime information, such as URI data authorization.|
| parameters | {[key:&nbsp;string]:&nbsp;any} | No| No| This field is not used for matching. It is passed to the target application component as a parameter.|
| parameters | {[key:&nbsp;string]:&nbsp;Object} | No| No| This field is not used for matching. It is passed to the target application component as a parameter.|
## Matching Rules for Implicit Want
......@@ -35,7 +35,7 @@ The table below describes the matching rules of implicit [Want](../reference/api
| action | string | Yes | No | |
| entities | Array&lt;string&gt; | Yes | No | |
| flags | number | No | No | This field is not used for matching and is directly transferred to the system for processing. It is generally used to set runtime information, such as URI data authorization.|
| parameters | {[key:&nbsp;string]:&nbsp;any} | No | No | This field is not used for matching. It is passed to the target application component as a parameter. |
| parameters | {[key:&nbsp;string]:&nbsp;Object} | No | No | This field is not used for matching. It is passed to the target application component as a parameter. |
Get familiar with the following about implicit Want:
......
......@@ -9,11 +9,11 @@
| onCreate?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate) |
| onWindowDisplayModeChanged?(isShownInMultiWindow: boolean, newConfig: resourceManager.Configuration): void; | There is no corresponding API in the stage model.| No corresponding API is provided.|
| onStartContinuation?(): boolean; | There is no corresponding API in the stage model.| In the stage model, an application does not need to detect whether the continuation is successful (detected when the application initiates the continuation request). Therefore, the **onStartContinuation()** callback is deprecated.|
| onSaveData?(data: Object): boolean; | \@ohos.app.ability.UIAbility.d.ts | [onContinue(wantParam : {[key: string]: any}): AbilityConstant.OnContinueResult;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncontinue) |
| onSaveData?(data: Object): boolean; | \@ohos.app.ability.UIAbility.d.ts | [onContinue(wantParam : {[key: string]: Object}): AbilityConstant.OnContinueResult;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncontinue) |
| onCompleteContinuation?(result: number): void; | application\ContinueCallback.d.ts | [onContinueDone(result: number): void;](../reference/apis/js-apis-distributedMissionManager.md#continuecallback) |
| onRestoreData?(data: Object): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate)<br>[onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonnewwant)<br>In multiton or singleton mode, the target ability completes data restoration in the **onCreate()** callback. In the callback, **launchParam.launchReason** is used to determine whether it is a continuation-based launch scenario. If it is, the data saved before continuation can be obtained from the **want** parameter.|
| onRemoteTerminated?(): void; | application\ContinueCallback.d.ts | [onContinueDone(result: number): void;](../reference/apis/js-apis-distributedMissionManager.md#continuecallback) |
| onSaveAbilityState?(outState: PacMap): void; | \@ohos.app.ability.UIAbility.d.ts | [onSaveState(reason: AbilityConstant.StateType, wantParam : {[key: string]: any}): AbilityConstant.OnSaveResult;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonsavestate) |
| onSaveAbilityState?(outState: PacMap): void; | \@ohos.app.ability.UIAbility.d.ts | [onSaveState(reason: AbilityConstant.StateType, wantParam : {[key: string]: Object}): AbilityConstant.OnSaveResult;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonsavestate) |
| onRestoreAbilityState?(inState: PacMap): void; | \@ohos.app.ability.UIAbility.d.ts | [onCreate(want: Want, param: AbilityConstant.LaunchParam): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityoncreate)<br>After an application is restarted, the **onCreate()** callback is triggered. In the callback, **launchParam.launchReason** is used to determine whether it is a self-recovery scenario. If it is, the data saved before the restart can be obtained from the **want** parameter.|
| onInactive?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onBackground(): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonbackground) |
| onActive?(): void; | \@ohos.app.ability.UIAbility.d.ts | [onForeground(): void;](../reference/apis/js-apis-app-ability-uiAbility.md#abilityonforeground) |
......
......@@ -10,4 +10,4 @@
| onEvent?(formId: string, message: string): void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onFormEvent(formId: string, message: string): void;](../reference/apis/js-apis-app-form-formExtensionAbility.md#onformevent) |
| onDestroy?(formId: string): void; | \@ohos.app.form.FormExtensionAbility.d.ts | [onRemoveForm(formId: string): void;](../reference/apis/js-apis-app-form-formExtensionAbility.md#onremoveform) |
| onAcquireFormState?(want: Want): formInfo.FormState; | \@ohos.app.form.FormExtensionAbility.d.ts | [onAcquireFormState?(want: Want): formInfo.FormState;](../reference/apis/js-apis-app-form-formExtensionAbility.md#onacquireformstate) |
| onShare?(formId: string): {[key: string]: any}; | \@ohos.app.form.FormExtensionAbility.d.ts | [onShareForm?(formId: string): { [key: string]: any };](../reference/apis/js-apis-app-form-formExtensionAbility.md#onshareform) |
| onShare?(formId: string): {[key: string]: Object}; | \@ohos.app.form.FormExtensionAbility.d.ts | [onShareForm?(formId: string): { [key: string]: Object };](../reference/apis/js-apis-app-form-formExtensionAbility.md#onshareform) |
......@@ -8,7 +8,5 @@
| [connectAbility(request: Want, options:ConnectOptions ): number;](../reference/apis/js-apis-ability-particleAbility.md#particleabilityconnectability) | application\ServiceExtensionContext.d.ts | [connectAbility(want: Want, options: ConnectOptions): number;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextconnectserviceextensionability)<br>[connectServiceExtensionAbility(want: Want, options: ConnectOptions): number;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextconnectserviceextensionability) |
| [disconnectAbility(connection: number, callback:AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitydisconnectability)<br>[disconnectAbility(connection: number): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitydisconnectability-1) | application\ServiceExtensionContext.d.ts | [disconnectAbility(connection: number, callback:AsyncCallback&lt;void&gt;): void; ](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability)<br>[disconnectAbility(connection: number): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability-1)<br>[disconnectServiceExtensionAbility(connection: number, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability)<br>[disconnectServiceExtensionAbility(connection: number): Promise&lt;void&gt;;](../reference/apis/js-apis-inner-application-serviceExtensionContext.md#serviceextensioncontextdisconnectserviceextensionability-1) |
| [acquireDataAbilityHelper(uri: string): DataAbilityHelper;](../reference/apis/js-apis-ability-particleAbility.md#particleabilityacquiredataabilityhelper) | \@ohos.data.dataShare.d.ts<br>[\@ohos.data.fileAccess.d.ts | [createDataShareHelper(context: Context, uri: string, callback: AsyncCallback&lt;DataShareHelper&gt;): void;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper)<br>[createDataShareHelper(context: Context, uri: string): Promise&lt;DataShareHelper&gt;;](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper-1)<br>[createFileAccessHelper(context: Context): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper-1)<br>[createFileAccessHelper(context: Context, wants: Array&lt;Want&gt;): FileAccessHelper;](../reference/apis/js-apis-fileAccess.md#fileaccesscreatefileaccesshelper) |
| [startBackgroundRunning(id: number, request: NotificationRequest, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning)<br>[startBackgroundRunning(id: number, request: NotificationRequest): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent, callback: AsyncCallback): void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningcallback)<br>[startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent): Promise&lt;void&gt;;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunningpromise) |
| [cancelBackgroundRunning(callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning)<br>[cancelBackgroundRunning(): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [stopBackgroundRunning(context: Context, callback: AsyncCallback): void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningcallback)<br>[stopBackgroundRunning(context: Context): Promise&lt;void&gt;;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunningpromise) |
<!--no_check-->
\ No newline at end of file
| [startBackgroundRunning(id: number, request: NotificationRequest, callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning)<br>[startBackgroundRunning(id: number, request: NotificationRequest): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitystartbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent, callback: AsyncCallback): void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunning)<br>[startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent): Promise&lt;void&gt;;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunning-1) |
| [cancelBackgroundRunning(callback: AsyncCallback&lt;void&gt;): void;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning)<br>[cancelBackgroundRunning(): Promise&lt;void&gt;;](../reference/apis/js-apis-ability-particleAbility.md#particleabilitycancelbackgroundrunning-1) | \@ohos.resourceschedule.backgroundTaskManager.d.ts | [stopBackgroundRunning(context: Context, callback: AsyncCallback): void;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunning)<br>[stopBackgroundRunning(context: Context): Promise&lt;void&gt;;](../reference/apis/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstopbackgroundrunning-1) |
......@@ -8,6 +8,10 @@ This topic describes how the two application components of the stage model start
A UIAbility starts a PageAbility in the same way as it starts another UIAbility.
> **NOTE**
>
> In the FA model, **abilityName** consists of **bundleName** and **AbilityName**. For details, see the code snippet below.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
......@@ -25,7 +29,7 @@ export default class EntryAbility extends UIAbility {
});
let want = {
bundleName: "com.ohos.fa",
abilityName: "EntryAbility",
abilityName: "com.ohos.fa.EntryAbility",
};
this.context.startAbility(want).then(() => {
console.info('Start Ability successfully.');
......
......@@ -14,7 +14,7 @@ import featureAbility from '@ohos.ability.featureAbility';
let parameter = {
"want": {
bundleName: "com.ohos.stage",
abilityName: "com.ohos.stage.EntryAbility"
abilityName: "EntryAbility"
}
};
featureAbility.startAbility(parameter).then((code) => {
......
......@@ -35,8 +35,8 @@ Assume that your application has two UIAbility components: EntryAbility and Func
let want = {
deviceId: '', // An empty deviceId indicates the local device.
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName is optional.
abilityName: 'FuncAbility',
parameters: { // Custom information.
info: 'From the Index page of EntryAbility',
},
......@@ -100,8 +100,8 @@ When starting FuncAbility from EntryAbility, you may want the result to be retur
let want = {
deviceId: '', // An empty deviceId indicates the local device.
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName is optional.
abilityName: 'FuncAbility',
parameters: { // Custom information.
info: 'From the Index page of EntryAbility',
},
......@@ -123,8 +123,8 @@ When starting FuncAbility from EntryAbility, you may want the result to be retur
resultCode: RESULT_CODE,
want: {
bundleName: 'com.example.myapplication',
moduleName: 'func', // moduleName is optional.
abilityName: 'FuncAbility',
moduleName: 'func',
parameters: {
info: 'From the Index page of FuncAbility',
},
......@@ -219,7 +219,8 @@ The following example describes how to start the UIAbility of another applicatio
})
```
The following figure shows the effect. When you click **Open PDF**, a dialog box is displayed for you to select the application to use.
The following figure shows the effect. When you click **Open PDF**, a dialog box is displayed for you to select the application to use.
![](figures/uiability-intra-device-interaction.png)
3. To stop the **UIAbility** instance when the document application is not in use, call [terminateSelf()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextterminateself).
......@@ -296,9 +297,9 @@ If you want to obtain the return result when using implicit Want to start the UI
let abilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.example.myapplication',
bundleName: 'com.example.funcapplication',
moduleName: 'entry', // moduleName is optional.
abilityName: 'EntryAbility',
moduleName: 'entry',
parameters: {
payResult: 'OKay',
},
......@@ -366,8 +367,8 @@ let context = ...; // UIAbilityContext
let want = {
deviceId: '', // An empty deviceId indicates the local device.
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName is optional.
abilityName: 'FuncAbility',
parameters: { // Custom information.
info: 'From the Index page of EntryAbility',
},
......@@ -383,7 +384,7 @@ context.startAbility(want, options).then(() => {
})
```
The display effect is shown below.
The display effect is shown below.
![](figures/start-uiability-floating-window.png)
......@@ -400,13 +401,13 @@ When the initiator UIAbility starts another UIAbility, it usually needs to redir
```ts
let context = ...; // UIAbilityContext
let want = {
deviceId: '', // An empty deviceId indicates the local device.
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
moduleName: 'func', // moduleName is optional.
parameters: { // Custom parameter used to pass the page information.
router: 'funcA',
},
deviceId: '', // An empty deviceId indicates the local device.
bundleName: 'com.example.funcapplication',
moduleName: 'entry', // moduleName is optional.
abilityName: 'EntryAbility',
parameters: { // Custom parameter used to pass the page information.
router: 'funcA',
},
}
// context is the UIAbilityContext of the initiator UIAbility.
context.startAbility(want).then(() => {
......@@ -423,24 +424,24 @@ When the target UIAbility is started for the first time, in the **onWindowStageC
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
import Window from '@ohos.window'
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
export default class FuncAbility extends UIAbility {
funcAbilityWant;
funcAbilityWant: Want;
onCreate(want, launchParam) {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
// Receive the parameters passed by the initiator UIAbility.
this.funcAbilityWant = want;
}
onWindowStageCreate(windowStage: Window.WindowStage) {
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created. Set a main page for this UIAbility.
let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router) {
if (this.funcAbilityWant.parameters.router === 'funA') {
url = 'pages/Second';
}
if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
url = 'pages/Second';
}
windowStage.loadContent(url, (err, data) => {
...
......@@ -449,51 +450,90 @@ export default class FuncAbility extends UIAbility {
}
```
### Starting a Page When the Target UIAbility Is Not Started for the First Time
You start application A, and its home page is displayed. Then you return to the home screen and start application B. Now you need to start application A again from application B and access a specified page of application A. An example scenario is as follows: When you open the home page of the SMS application and return to the home screen, the SMS application is in the opened state with its home page. Then you open the home page of the Contacts application, access user A's details page, and touch the SMS icon to send an SMS message to user A. The SMS application is started again and the sending page is displayed.
If the target UIAbility has been started, the initialization logic is not executed again. Instead, the **onNewWant()** lifecycle callback is directly triggered. To implement redirection, parse the required parameters in **onNewWant()**.
An example scenario is as follows:
1. A user opens the SMS application. The UIAbility instance of the SMS application is started, and the home page of the application is displayed.
2. The user returns to the home screen, and the SMS application switches to the background.
3. The user opens the Contacts application and finds a contact.
4. The user touches the SMS button next to the contact. The UIAbility instance of the SMS application is restarted.
5. Since the UIAbility instance of the SMS application has been started, the **onNewWant()** callback of the UIAbility is triggered, and the initialization logic such as **onCreate()** and **onWindowStageCreate()** is skipped.
```mermaid
sequenceDiagram
Participant U as User
Participant S as SMS app
Participant C as Contacts app
U->>S: Open the SMS app.
S-->>U: The home page of the SMS app is displayed.
U->>S: Return to the home screen.
S->>S: The SMS app enters the background.
U->>C: Open the Contacts app.
C-->>U: The page of the Contact app is displayed.
U->>C: Touch the SMS button next to a contact.
C->>S: Start the SMS app with Want.
S-->>U: The page for sending an SMS message to the contact is displayed.
```
![uiability_not_first_started](figures/uiability_not_first_started.png)
The development procedure is as follows:
In summary, when a UIAbility instance of application A has been created and the main page of the UIAbility instance is displayed, you need to start the UIAbility of application A from application B and access a different page.
1. When the UIAbility instance of the SMS application is started for the first time, call [getUIContext()](../reference/apis/js-apis-window.md#getuicontext10) in the **onWindowStageCreate()** lifecycle callback to obtain the [UIContext](../reference/apis/js-apis-arkui-UIContext.md).
1. In the target UIAbility, the **Index** page is loaded by default. The UIAbility instance has been created, and the **onNewWant()** callback rather than **onCreate()** and **onWindowStageCreate()** will be invoked. In the **onNewWant()** callback, parse the **want** parameter and bind it to the global variable **globalThis**.
```ts
import UIAbility from '@ohos.app.ability.UIAbility'
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
export default class FuncAbility extends UIAbility {
onNewWant(want, launchParam) {
// Receive the parameters passed by the initiator UIAbility.
globalThis.funcAbilityWant = want;
import { Router, UIContext } from '@ohos.arkui.UIContext';
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want;
uiContext: UIContext;
...
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created. Set a main page for this UIAbility.
...
let windowClass: window.Window;
windowStage.getMainWindow((err, data) => {
if (err.code) {
console.error(`Failed to obtain the main window. Code is ${err.code}, message is ${err.message}`);
return;
}
windowClass = data;
this.uiContext = windowClass.getUIContext();
})
}
}
```
2. In FuncAbility, use the router module to implement redirection to the specified page on the **Index** page. Because the **Index** page of FuncAbility is active, the variable will not be declared again and the **aboutToAppear()** callback will not be triggered. Therefore, the page routing functionality can be implemented in the **onPageShow()** callback of the **Index** page.
2. Parse the **want** parameter passed in the **onNewWant()** callback of the UIAbility of the SMS application, call [getRouter()](../reference/apis/js-apis-arkui-UIContext.md#getrouter) in the **UIContext** class to obtain a [Router](../reference/apis/js-apis-arkui-UIContext.md#router) instance, and specify the target page. When the UIAbility instance of the SMS application is started again, the specified page of the UIAbility instance of the SMS application is displayed.
```ts
import router from '@ohos.router';
@Entry
@Component
struct Index {
onPageShow() {
let funcAbilityWant = globalThis.funcAbilityWant;
let url2 = funcAbilityWant?.parameters?.router;
if (url2 && url2 === 'funcA') {
router.replaceUrl({
url: 'pages/Second',
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want;
uiContext: UIContext;
onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam) {
if (want?.parameters?.router && want.parameters.router === 'funcA') {
let funcAUrl = 'pages/Second';
let router: Router = this.uiContext.getRouter();
router.pushUrl({
url: funcAUrl
}).catch((err) => {
console.error(`Failed to push url. Code is ${err.code}, message is ${err.message}`);
})
}
}
// Page display.
build() {
...
}
...
}
```
......
......@@ -157,4 +157,4 @@ The following steps are used as an example.
1. Open file A. A UIAbility instance, UIAbility instance 1, is started.
2. Close the process of file A in Recents. UIAbility instance 1 is destroyed. Return to the home screen and open file A again. A new UIAbility instance, UIAbility instance 2, is started.
3. Return to the home screen and open file B. A new UIAbility instance, UIAbility instance 3, is started.
4. Return to the home screen and open file A again. UIAbility instance 2 is started. This is because the system automatically matches the key with the UIAbility instance and starts the UIAbility instance that has a matching key. In this example, UIAbility instance 2 has the same key as file A. Therefore, the system pulls back UIAbility instance 2 and focuses it without creating a new instance.hao
4. Return to the home screen and open file A again. UIAbility instance 2 is started. This is because the system automatically matches the key with the UIAbility instance and starts the UIAbility instance that has a matching key. In this example, UIAbility instance 2 has the same key as file A. Therefore, the system pulls back UIAbility instance 2 and focuses it without creating a new instance.
......@@ -12,7 +12,7 @@
## Types of Want
- **Explicit Want**: If **abilityName** and **bundleName** are specified in the **want** parameter when starting an an application component, explicit Want is used.
- **Explicit Want**: If **abilityName** and **bundleName** are specified in the **want** parameter when starting an application component, explicit Want is used.
Explicit Want is usually used to start a known target application component in the same application. The target application component is started by specifying **bundleName** of the application where the target application component is located and **abilityName** in the **Want** object. When there is an explicit object to process the request, explicit Want is a simple and effective way to start the target application component.
......@@ -24,7 +24,7 @@
}
```
- **Implicit Want**: If **abilityName** is not specified in the **want** parameter when starting the an application component, implicit Want is used.
- **Implicit Want**: If **abilityName** is not specified in the **want** parameter when starting an application component, implicit Want is used.
Implicit Want can be used when the object used to process the request is unclear and the current application wants to use a capability (defined by the [skills tag](../quick-start/module-configuration-file.md#skills)) provided by another application. The system matches all applications that declare to support the capability. For example, for a link open request, the system matches all applications that support the request and provides the available ones for users to select.
......@@ -47,6 +47,7 @@
> - An application component that meets the conditions is matched. That application component is started.
> - Multiple application components that meet the conditions are matched. A dialog box is displayed for users to select one of them.
>
> - If the **want** parameter passed does not contain **abilityName** or **bundleName**, the ServiceExtensionAbility components of all applications cannot be started through implicit Want.
> - In the scenario for starting the ServiceExtensionAbility component:
> - If the **want** parameter passed in contains **abilityName**, the ServiceExtensionAbility component cannot be started through implicit Want.
>
> - If the **want** parameter passed contains **bundleName**, the **startServiceExtensionAbility()** method can be used to implicitly start ServiceExtensionAbility. By default, ServiceExtensionAbility with the highest priority is returned. If all the matching ServiceExtensionAbility components have the same priority, the first ServiceExtensionAbility is returned.
> - If the **want** parameter passed in contains **bundleName**, the **startServiceExtensionAbility()** method can be used to implicitly start the ServiceExtensionAbility component. By default, the ServiceExtensionAbility component with the highest priority is returned. If all the matching ServiceExtensionAbility components have the same priority, the first ServiceExtensionAbility component is returned.
......@@ -85,7 +85,7 @@ The **FormBindingData** class has the following APIs. For details, see [FormBind
| API| Description|
| -------- | -------- |
| createFormBindingData(obj?: Object \ string): FormBindingData| | Creates a **FormBindingData** object.|
| createFormBindingData(obj?:&nbsp;Object&nbsp;\|&nbsp;string):&nbsp;FormBindingData | Creates a **FormBindingData** object. |
## How to Develop
......@@ -327,9 +327,11 @@ For details about how to implement persistent data storage, see [Application Dat
The **Want** object passed in by the widget host to the widget provider contains a flag that specifies whether the requested widget is normal or temporary.
- Normal widget: a widget persistently used by the widget host
- Normal widget: a widget persistently used by the widget host, for example, a widget added to the home screen.
- Temporary widget: a widget temporarily used by the widget host
- Temporary widget: a widget temporarily used by the widget host, for example, the widget displayed when you swipe up on a widget application.
Converting a temporary widget to a normal one: After you swipe up on a widget application, a temporary widget is displayed. If you touch the pin button on the widget, it is displayed as a normal widget on the home screen.
Data of a temporary widget will be deleted on the Widget Manager if the widget framework is killed and restarted. The widget provider, however, is not notified of the deletion and still keeps the data. Therefore, the widget provider needs to clear the data of temporary widgets proactively if the data has been kept for a long period of time. If the widget host has converted a temporary widget into a normal one, the widget provider should change the widget data from temporary storage to persistent storage. Otherwise, the widget data may be deleted by mistake.
......
......@@ -15,6 +15,7 @@ If a task does not need to occupy a background thread for a long time (3 minutes
1. Implement the logic of image processing.
2. Segment the data, and initiate associated task scheduling through task groups.
Create a [task group](../reference/apis/js-apis-taskpool.md#taskgroup10), call [addTask()](../reference/apis/js-apis-taskpool.md#addtask10) to add tasks, call [execute()](../reference/apis/js-apis-taskpool.md#taskpoolexecute10) to execute the tasks in the task group, and set [a high priority](../reference/apis/js-apis-taskpool.md#priority) for the task group. After all the tasks in the task group are complete, the histogram processing result is returned simultaneously.
3. Summarize and process the result arrays.
......@@ -78,7 +79,7 @@ The following uses the training of a region-specific house price prediction mode
![newWorker](figures/newWorker.png)
2. In the main thread, call [ThreadWorker()](../reference/apis/js-apis-worker.md#threadworker9) to create a **Worker** object. The calling thread is the host thread.
2. In the main thread, call [constructor()](../reference/apis/js-apis-worker.md#constructor9) of **ThreadWorker** to create a **Worker** object. The calling thread is the host thread.
```js
import worker from '@ohos.worker';
......@@ -167,24 +168,22 @@ The following uses the training of a region-specific house price prediction mode
6. After the task is completed in the worker thread, destroy the worker thread. The worker thread can be destroyed by itself or the host thread. Then, call [onexit()](../reference/apis/js-apis-worker.md#onexit9) in the host thread to define the processing logic after the worker thread is destroyed.
```js
// After the worker thread is destroyed, execute the onexit() callback.
workerInstance.onexit = function() {
console.info("main thread terminate");
}
```
In the host thread, call [terminate()](../reference/apis/js-apis-worker.md#terminate9) to destroy the worker thread and stop the worker thread from receiving messages.
Method 1: In the host thread, call [terminate()](../reference/apis/js-apis-worker.md#terminate9) to destroy the worker thread and stop the worker thread from receiving messages.
```js
// Destroy the worker thread.
// Destroy the worker thread.
workerInstance.terminate();
```
In the worker thread, call [close()](../reference/apis/js-apis-worker.md#close9) to destroy the worker thread and stop the worker thread from receiving messages.
Method 2: In the worker thread, call [close()](../reference/apis/js-apis-worker.md#close9) to destroy the worker thread and stop the worker thread from receiving messages.
```js
// Destroy the worker thread.
workerPort.close();
......
......@@ -44,14 +44,14 @@ The APIs provided by **Vector** are deprecated since API version 9. You are advi
| Accessing elements| Use **vec\[index]** to obtain the value at a given position (specified by **index**).|
| Accessing elements| Use **get(index: number)** to obtain the element at a given position (specified by **index**).|
| Accessing elements| Use **getLastElement()** to obtain the last element in this container.|
| Accessing elements| Use **getlndexOf(element: T)** to obtain the index of the first occurrence of the specified element.|
| Accessing elements| Use **getLastlndexOf(element: T)** to obtain the index of the last occurrence of the specified element.|
| Accessing elements| Use **getIndexOf(element: T)** to obtain the index of the first occurrence of the specified element.|
| Accessing elements| Use **getLastIndexOf(element: T)** to obtain the index of the last occurrence of the specified element.|
| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, Vector?: Vector&lt;T&gt;) =&gt; void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;T&gt;** for data access.|
| Modifying elements| Use **vec\[index]=xxx** to change the value at a given position (specified by **index**).|
| Modifying elements| Use **set(index: number, element: T)** to replace an element at a given position (specified by **index**) with a given element.|
| Modifying elements| Use **setLength(newSize: number)** to set the size of this container.|
| Deleting elements| Use **removeBylndex(index: number)** to remove the value at a given position (specified by **index**).|
| Deleting elements| Use **removeByIndex(index: number)** to remove the value at a given position (specified by **index**).|
| Deleting elements| Use **remove(element: T)** to remove the first occurrence of the specified element.|
| Deleting elements| Use **removeByRange(fromIndex: number, toIndex: number)** to remove all of the elements within a range.|
......@@ -74,14 +74,14 @@ You are advised to use **List** for frequent insertion and removal operations.
| Accessing elements| Use **get(index: number)** to obtain the element at a given position (specified by **index**).|
| Accessing elements| Use **getFirst()** to obtain the first element in this container.|
| Accessing elements| Use **getLast()** to obtain the last element in this container.|
| Accessing elements| Use **getlndexOf(element: T)** to obtain the index of the first occurrence of the specified element.|
| Accessing elements| Use **getLastlndexOf(element: T)** to obtain the index of the last occurrence of the specified element.|
| Accessing elements| Use **getIndexOf(element: T)** to obtain the index of the first occurrence of the specified element.|
| Accessing elements| Use **getLastIndexOf(element: T)** to obtain the index of the last occurrence of the specified element.|
| Accessing elements| Use **forEach(callbackfn: (value: T, index?: number, list?: List&lt;T&gt;)=&gt; void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;T&gt;** for data access.|
| Modifying elements| Use **list\[index] = xxx** to change the value at a given position (specified by **index**).|
| Modifying elements| Use **set(index: number, element: T)** to replace an element at a given position (specified by **index**) with a given element.|
| Modifying elements| Use **replaceAllElements(callbackFn:(value: T,index?: number,list?: List&lt;T&gt;)=&gt;T,thisArg?: Object)** to replace all elements in this container with new elements.|
| Deleting elements| Use **removeBylndex(index: number)** to remove the value at a given position (specified by **index**).|
| Deleting elements| Use **removeByIndex(index: number)** to remove the value at a given position (specified by **index**).|
| Deleting elements| Use **remove(element: T)** to remove the first occurrence of the specified element.|
......@@ -105,13 +105,13 @@ You are advised to use **LinkedList** for frequent insertion and removal operati
| Accessing elements| Use **get(index: number)** to obtain the element at a given position (specified by **index**).|
| Accessing elements| Use **getFirst()** to obtain the first element in this container.|
| Accessing elements| Use **getLast()** to obtain the last element in this container.|
| Accessing elements| Use **getlndexOf(element: T)** to obtain the index of the first occurrence of the specified element.|
| Accessing elements| Use **getLastlndexOf(element: T)** to obtain the index of the last occurrence of the specified element.|
| Accessing elements| Use **getIndexOf(element: T)** to obtain the index of the first occurrence of the specified element.|
| Accessing elements| Use **getLastIndexOf(element: T)** to obtain the index of the last occurrence of the specified element.|
| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, list?: LinkedList&lt;T&gt;) =&gt; void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;T&gt;** for data access.|
| Modifying elements| Use **list\[index]=xxx** to change the value at a given position (specified by **index**).|
| Modifying elements| Use **set(index: number, element: T)** to replace an element at a given position (specified by **index**) with a given element.|
| Deleting elements| Use **removeBylndex(index: number)** to remove the value at a given position (specified by **index**).|
| Deleting elements| Use **removeByIndex(index: number)** to remove the value at a given position (specified by **index**).|
| Deleting elements| Use **remove(element: T)** to remove the first occurrence of the specified element.|
......
......@@ -12,7 +12,7 @@ Due to the memory isolation feature of the actor model, cross-thread serializati
## Data Transfer Objects
Data objects that can be transferred are classified into three types: [common objects](#common-objects), [transferable objects](#transferable-objects), and [shared objects](#shared-objects).
Data objects that can be transferred are classified into the following types: [common objects](#common-objects), [transferable objects](#transferable-objects), [shared objects](#shared-objects), and [native binding objects](#native-binding-objects).
### Common Objects
......@@ -24,7 +24,7 @@ The following object types are supported: basic types except Symbol, Date, Strin
### Transferable Objects
Transferable objects are serialized through address transfer. It transfers the ownership of an object of the ArrayBuffer type object, rather than the content in it. After the ownership is transferred, the object becomes unavailable in the sender and can be used only in the receiver.
Transferable objects are serialized through address transfer. It transfers the ownership of an object of the ArrayBuffer type, rather than the content in it. After the ownership is transferred, the object becomes unavailable in the sender and can be used only in the receiver.
```js
......@@ -47,6 +47,15 @@ If multiple operations are simultaneously performed to modify data stored in an
let sharedBuffer = new SharedArrayBuffer(1024);
```
### Native Binding Objects
Native binding objects are provided by the system. They are bound to underlying system services and enables direct access to these services.
Currently, native bound objects that support serialization include [Context](../application-models/application-context-stage.md) and [RemoteObject](../reference/apis/js-apis-rpc.md#remoteobject).
The **Context** object provides the context information about an application component. It provides a way to access system services and resources so that the application component can interact with the system. For details about how to obtain context information, see [Context (Stage Model)](../application-models/application-context-stage.md).
The **RemoteObject** object implements remote communication. It transfers the reference of an object between processes so that these processes can share the status and methods of the object. The service provider must inherit this class. For details about how to create a **RemoteObject** object, see [RemoteObject](../reference/apis/js-apis-rpc.md#remoteobject).
## TaskPool and Worker
......
......@@ -52,9 +52,9 @@ You are advised to use **HashSet** when you need a set that has only unique elem
| Adding elements| Use **add(value: T)** to add a value to this container.|
| Accessing elements| Use **values()** to return an iterator that contains all the values in this container.|
| Accessing elements| Use **entries()** to return an iterator that contains all the elements in this container.|
| Accessing elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: HashSet<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: HashSet\<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;T&gt;** for data access.|
| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: HashSet<T>) => void, thisArg?: Object)** to change a value in this container.|
| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: HashSet\<T>) => void, thisArg?: Object)** to change a value in this container.|
| Deleting elements| Use **remove(value: T)** to remove a value.|
| Deleting elements| Use **clear()** to clear this container.|
......@@ -109,9 +109,9 @@ You are advised to use **TreeSet** when you need to store data in sorted order.
| Accessing elements| Use **entries()** to return an iterator that contains all the elements in this container.|
| Accessing elements| Use **getFirstValue()** to obtain the first value in this container.|
| Accessing elements| Use **getLastValue()** to obtain the last value in this container.|
| Accessing elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: TreeSet<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: TreeSet\<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;T&gt;** for data access.|
| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: TreeSet<T>) => void, thisArg?: Object)** to change a value in this container.|
| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: TreeSet\<T>) => void, thisArg?: Object)** to change a value in this container.|
| Deleting elements| Use **remove(value: T)** to remove a value.|
| Deleting elements| Use **clear()** to clear this container.|
......@@ -169,9 +169,9 @@ You are advised to use **LightWeightSet** when you need a set that has only uniq
| Accessing elements| Use **values()** to return an iterator that contains all the values in this container.|
| Accessing elements| Use **entries()** to return an iterator that contains all the elements in this container.|
| Accessing elements| Use **getValueAt(index: number)** to obtain the value of an element at a given position (specified by **index**).|
| Accessing elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: LightWeightSet<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: LightWeightSet\<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;T&gt;** for data access.|
| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: LightWeightSet<T>) => void, thisArg?: Object)** to change a value in this container.|
| Modifying elements| Use **forEach(callbackFn: (value?: T, key?: T, set?: LightWeightSet\<T>) => void, thisArg?: Object)** to change a value in this container.|
| Deleting elements| Use **remove(key: K)** to remove an element with the specified key.|
| Deleting elements| Use **removeAt(index: number)** to remove an element at a given position (specified by **index**).|
| Deleting elements| Use **clear()** to clear this container.|
......@@ -197,10 +197,10 @@ You are advised to use PlainArray when you need to store KV pairs whose keys are
| Accessing elements| Use **getIndexOfValue(value: T)** to obtain the index of the specified value.|
| Accessing elements| Use **getKeyAt(index: number)** to obtain the key of an element at a given position (specified by **index**).|
| Accessing elements| Use **getValueAt(index: number)** to obtain the value of an element at a given position (specified by **index**).|
| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, PlainArray?: PlainArray<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **forEach(callbackFn: (value: T, index?: number, PlainArray?: PlainArray\<T>) => void, thisArg?: Object)** to traverse the elements in this container.|
| Accessing elements| Use **\[Symbol.iterator]():IterableIterator&lt;[number, T]&gt;** for data access.|
| Modifying elements| Use **setValueAt(index:number, value: T)** to change the value of an element at a given position (specified by **index**).|
| Modifying elements| Use **forEach(callbackFn: (value: T, index?: number, PlainArray?: PlainArray<T>) => void, thisArg?: Object)** to modify an element in this container.|
| Modifying elements| Use **forEach(callbackFn: (value: T, index?: number, PlainArray?: PlainArray\<T>) => void, thisArg?: Object)** to modify an element in this container.|
| Deleting elements| Use **remove(key: number)** to remove an element with the specified key.|
| Deleting elements| Use **removeAt(index: number)** to remove an element at a given position (specified by **index**).|
| Deleting elements| Use **removeRangeFrom(index: number, size: number)** to remove elements in a specified range.|
......
......@@ -4,7 +4,7 @@
Data transferred in XML format must be parsed in actual use. Generally, three types of elements need to be parsed, as described in [Parsing XML Tags and Tag Values](#parsing-xml-tags-and-tag-values), [Parsing XML Attributes and Attribute Values](#parsing-xml-attributes-and-attribute-values), and [Parsing XML Event Types and Element Depths](#parsing-xml-event-types-and-element-depths).
The **xml** module provides the **XmlPullParser** class to parse XML files. The input is an object of the ArrayBufffer or DataView type containing XML text, and the output is the parsed information.
The **xml** module provides the **XmlPullParser** class to parse XML files. The input is an object of the ArrayBuffer or DataView type containing XML text, and the output is the parsed information.
**Table 1** XML parsing options
......
......@@ -9,6 +9,8 @@
- [Ethernet Connection](net-ethernet.md)
- [Network Connection Management](net-connection-manager.md)
- [mDNS Management](net-mdns.md)
- [Traffic Management](net-statistics.md)
- [VPN Management](net-vpn.md)
- IPC & RPC
- [IPC & RPC Overview](ipc-rpc-overview.md)
- [IPC & RPC Development](ipc-rpc-development-guideline.md)
......
# HTTP Data Request
## When to Use
## Overview
An application can initiate a data request over HTTP. Common HTTP methods include **GET**, **POST**, **OPTIONS**, **HEAD**, **PUT**, **DELETE**, **TRACE**, and **CONNECT**.
......@@ -18,7 +18,7 @@ The following table provides only a simple description of the related APIs. For
| ----------------------------------------- | ----------------------------------- |
| createHttp() | Creates an HTTP request. |
| request() | Initiates an HTTP request to a given URL. |
| request2()<sup>10+</sup> | Initiates an HTTP network request based on the URL and returns a streaming response.|
| requestInStream()<sup>10+</sup> | Initiates an HTTP network request to a given URL and returns a streaming response.|
| destroy() | Destroys an HTTP request. |
| on(type: 'headersReceive') | Registers an observer for HTTP Response Header events. |
| off(type: 'headersReceive') | Unregisters the observer for HTTP Response Header events.|
......@@ -27,8 +27,8 @@ The following table provides only a simple description of the related APIs. For
| off\('dataReceive'\)<sup>10+</sup> | Unregisters the observer for events indicating receiving of HTTP streaming responses. |
| on\('dataEnd'\)<sup>10+</sup> | Registers an observer for events indicating completion of receiving HTTP streaming responses. |
| off\('dataEnd'\)<sup>10+</sup> | Unregisters the observer for events indicating completion of receiving HTTP streaming responses.|
| on\('dataProgress'\)<sup>10+</sup> | Registers an observer for events indicating progress of receiving HTTP streaming responses. |
| off\('dataProgress'\)<sup>10+</sup> | Unregisters the observer for events indicating progress of receiving HTTP streaming responses.|
| on\('dataReceiveProgress'\)<sup>10+</sup> | Registers an observer for events indicating progress of receiving HTTP streaming responses. |
| off\('dataReceiveProgress'\)<sup>10+</sup> | Unregisters the observer for events indicating progress of receiving HTTP streaming responses.|
## How to Develop request APIs
......@@ -53,6 +53,7 @@ httpRequest.on('headersReceive', (header) => {
});
httpRequest.request(
// Customize EXAMPLE_URL in extraData on your own. It is up to you whether to add parameters to the URL.
"EXAMPLE_URL",
{
method: http.RequestMethod.POST, // Optional. The default value is http.RequestMethod.GET.
// You can add header fields based on service requirements.
......@@ -81,7 +82,7 @@ httpRequest.request(
// Call the destroy() method to release resources after HttpRequest is complete.
httpRequest.destroy();
} else {
console.info('error:' + JSON.stringify(err));
console.error('error:' + JSON.stringify(err));
// Unsubscribe from HTTP Response Header events.
httpRequest.off('headersReceive');
// Call the destroy() method to release resources after HttpRequest is complete.
......@@ -91,12 +92,12 @@ httpRequest.request(
);
```
## How to Develop request2 APIs
## How to Develop requestInStream APIs
1. Import the **http** namespace from **@ohos.net.http.d.ts**.
2. Call **createHttp()** to create an **HttpRequest** object.
3. Depending on your need, call **on()** of the **HttpRequest** object to subscribe to HTTP response header events as well as events indicating receiving of HTTP streaming responses, progress of receiving HTTP streaming responses, and completion of receiving HTTP streaming responses.
4. Call **request2()** to initiate a network request. You need to pass in the URL and optional parameters of the HTTP request.
4. Call **requestInStream()** to initiate a network request. You need to pass in the URL and optional parameters of the HTTP request.
5. Parse the returned response code as needed.
6. Call **off()** of the **HttpRequest** object to unsubscribe from the related events.
7. Call **httpRequest.destroy()** to release resources after the request is processed.
......@@ -122,11 +123,11 @@ httpRequest.on('dataEnd', () => {
console.info('No more data in response, data receive end');
});
// Subscribe to events indicating progress of receiving HTTP streaming responses.
httpRequest.on('dataProgress', (data) => {
console.log("dataProgress receiveSize:" + data.receiveSize + ", totalSize:" + data.totalSize);
httpRequest.on('dataReceiveProgress', (data) => {
console.log("dataReceiveProgress receiveSize:" + data.receiveSize + ", totalSize:" + data.totalSize);
});
httpRequest.request2(
httpRequest.requestInStream(
// Customize EXAMPLE_URL in extraData on your own. It is up to you whether to add parameters to the URL.
"EXAMPLE_URL",
{
......@@ -146,14 +147,14 @@ httpRequest.request2(
readTimeout: 60000, // Optional. The default value is 60000, in ms. If a large amount of data needs to be transmitted, you are advised to set this parameter to a larger value to ensure normal data transmission.
usingProtocol: http.HttpProtocol.HTTP1_1, // Optional. The default protocol type is automatically specified by the system.
}, (err, data) => {
console.info('error:' + JSON.stringify(err));
console.error('error:' + JSON.stringify(err));
console.info('ResponseCode :' + JSON.stringify(data));
// Unsubscribe from HTTP Response Header events.
httpRequest.off('headersReceive');
// Unregister the observer for events indicating receiving of HTTP streaming responses.
httpRequest.off('dataReceive');
// Unregister the observer for events indicating progress of receiving HTTP streaming responses.
httpRequest.off('dataProgress');
httpRequest.off('dataReceiveProgress');
// Unregister the observer for events indicating completion of receiving HTTP streaming responses.
httpRequest.off('dataEnd');
// Call the destroy() method to release resources after HttpRequest is complete.
......@@ -161,10 +162,3 @@ httpRequest.request2(
}
);
```
## Samples
The following sample is provided to help you better understand how to develop the HTTP data request feature:
- [`Http`: Data Request (ArkTS) (API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Http)
- [HTTP Communication (ArkTS) (API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/SmartChatEtsOH)
# IPC & RPC Development Guidelines
## When to Use
## Overview
IPC/RPC enables a proxy and a stub that run on different processes to communicate with each other, regardless of whether they run on the same or different devices.
......
# Network Connection Management
## Introduction
## Overview
The Network Connection Management module provides basic network management capabilities, including management of Wi-Fi/cellular/Ethernet connection priorities, network quality evaluation, subscription to network connection status changes, query of network connection information, and DNS resolution.
> **NOTE**
>
> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [sms API Reference](../reference/apis/js-apis-net-connection.md).
## Basic Concepts
......@@ -107,7 +108,7 @@ conn.on('netAvailable', (data => {
// Listen to network status change events. If the network is unavailable, an on_netUnavailable event is returned.
conn.on('netUnavailable', (data => {
console.log("net is unavailable, netId is " + data.netId);
console.log("net is unavailable, data is " + JSON.stringify(data));
}));
// Register an observer for network status changes.
......
# Ethernet Connection
## Introduction
## Overview
The Ethernet Connection module allows a device to access the Internet through a network cable. After a device is connected to the Ethernet through a network cable, the device can obtain a series of network attributes, such as the dynamically allocated IP address, subnet mask, gateway, and DNS. You can manually configure and obtain the network attributes of the device in static mode.
> **NOTE**
>
> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [sms API Reference](../reference/apis/js-apis-net-ethernet.md).
## **Constraints**
......
# MDNS Management
## Introduction
## Overview
Multicast DNS (mDNS) provides functions such as adding, removing, discovering, and resolving local services on a LAN.
- Local service: a service provider on a LAN, for example, a printer or scanner.
......
# Network Sharing
## Introduction
## Overview
The Network Sharing module allows you to share your device's Internet connection with other connected devices by means of Wi-Fi hotspot, Bluetooth, and USB sharing. It also allows you to query the network sharing state and shared mobile data volume.
> **NOTE**
>
> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [sms API Reference](../reference/apis/js-apis-net-sharing.md).
## Basic Concepts
......
# Traffic Management
## Introduction
## Overview
The traffic management module allows you to query real-time or historical data traffic by the specified network interface card (NIC) or user ID (UID).
......@@ -11,6 +11,7 @@ Its functions include:
- Subscribing to traffic change events by NIC or UID
> **NOTE**
>
> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [Traffic Management](../reference/apis/js-apis-net-statistics.md).
The following describes the development procedure specific to each application scenario.
......
# VPN Management
## Overview
A virtual private network (VPN) is a dedicated network established on a public network. On a VPN, the connection between any two nodes does not have an end-to-end physical link required by the traditional private network. Instead, user data is transmitted over a logical link because a VPN is a logical network deployed over the network platform (such as the Internet) provided by the public network service provider.
> **NOTE**
>
> To maximize the application running efficiency, most API calls are called asynchronously in callback or promise mode. The following code examples use the callback mode. For details about the APIs, see [Traffic Management](../reference/apis/js-apis-net-vpn.md).
The following describes the development procedure specific to each application scenario.
## Available APIs
For the complete list of APIs and example code, see [VPN Management](../reference/apis/js-apis-net-vpn.md).
| Type| API| Description|
| ---- | ---- | ---- |
| ohos.net.vpn | setUp(config: VpnConfig, callback: AsyncCallback\<number\>): void | Establishes a VPN. This API uses an asynchronous callback to return the result.|
| ohos.net.vpn | protect(socketFd: number, callback: AsyncCallback\<void\>): void | Enables VPN tunnel protection. This API uses an asynchronous callback to return the result.|
| ohos.net.vpn | destroy(callback: AsyncCallback\<void\>): void | Destroys a VPN. This API uses an asynchronous callback to return the result.|
## Starting a VPN
1. Establish a VPN tunnel. The following uses the UDP tunnel as an example.
2. Enable protection for the UDP tunnel.
3. Establish a VPN.
4. Process data of the virtual network interface card (vNIC), such as reading or writing data.
5. Destroy the VPN.
This example shows how to develop an application using native C++ code. For details, see [Simple Native C++ Example (ArkTS) (API9)] (https://gitee.com/openharmony/codelabs/tree/master/NativeAPI/NativeTemplateDemo).
The sample application consists of two parts: JS code and C++ code.
## JS Code
The JS code is used to implement the service logic, such as creating a tunnel, establishing a VPN, enabling VPN protection, and destroying a VPN.
```js
import hilog from '@ohos.hilog';
import vpn from '@ohos.net.vpn';
import UIAbility from '@ohos.app.ability.UIAbility';
import vpn_client from "libvpn_client.so"
class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage) {
globalThis.context = this.context;
}
}
let TunnelFd = -1
let VpnConnection = vpn.createVpnConnection(globalThis.context)
@Entry
@Component
struct Index {
@State message: string = 'Test VPN'
//1. Establish a VPN tunnel. The following uses the UDP tunnel as an example.
CreateTunnel() {
TunnelFd = vpn_client.udpConnect("192.168.43.208", 8888)
}
// 2. Enable protection for the UDP tunnel.
Protect() {
VpnConnection.protect(TunnelFd).then(function () {
console.info("vpn Protect Success.")
}).catch(function (err) {
console.info("vpn Protect Failed " + JSON.stringify(err))
})
}
SetupVpn() {
let config = {
addresses: [{
address: {
address: "10.0.0.5",
family: 1
},
prefixLength: 24,
}],
routes: [],
mtu: 1400,
dnsAddresses: [
"114.114.114.114"
],
acceptedApplications: [],
refusedApplications: []
}
try {
// 3. Create a VPN.
VpnConnection.setUp(config, (error, data) => {
console.info("tunfd: " + JSON.stringify(data));
// 4. Process data of the virtual vNIC, such as reading or writing data.
vpn_client.startVpn(data, TunnelFd)
})
} catch (error) {
console.info("vpn setUp fail " + JSON.stringify(error));
}
}
// 5. Destroy the VPN.
Destroy() {
vpn_client.stopVpn(TunnelFd)
VpnConnection.destroy().then(function () {
console.info("vpn Destroy Success.")
}).catch(function (err) {
console.info("vpn Destroy Failed " + JSON.stringify(err))
})
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
console.info("vpn Client")
})
Button('CreateTunnel').onClick(() => {
this.CreateTunnel()
}).fontSize(50)
Button('Protect').onClick(() => {
this.Protect()
}).fontSize(50)
Button('SetupVpn').onClick(() => {
this.SetupVpn()
}).fontSize(50)
Button('Destroy').onClick(() => {
this.Destroy()
}).fontSize(50)
}
.width('100%')
}
.height('100%')
}
}
```
## C++ Code
The C++ code is used for underlying service implementation, such as UDP tunnel client implementation and vNIC data read and write.
```c++
#include "napi/native_api.h"
#include "hilog/log.h"
#include <cstring>
#include <thread>
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <thread>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 2048
#define VPN_LOG_TAG "NetMgrVpn"
#define VPN_LOG_DOMAIN 0x15b0
#define MAKE_FILE_NAME (strrchr(__FILE__, '/') + 1)
#define NETMANAGER_VPN_LOGE(fmt, ...) \
OH_LOG_Print(LOG_APP, LOG_ERROR, VPN_LOG_DOMAIN, VPN_LOG_TAG, "vpn [%{public}s %{public}d] " fmt, MAKE_FILE_NAME, \
__LINE__, ##__VA_ARGS__)
#define NETMANAGER_VPN_LOGI(fmt, ...) \
OH_LOG_Print(LOG_APP, LOG_INFO, VPN_LOG_DOMAIN, VPN_LOG_TAG, "vpn [%{public}s %{public}d] " fmt, MAKE_FILE_NAME, \
__LINE__, ##__VA_ARGS__)
#define NETMANAGER_VPN_LOGD(fmt, ...) \
OH_LOG_Print(LOG_APP, LOG_DEBUG, VPN_LOG_DOMAIN, VPN_LOG_TAG, "vpn [%{public}s %{public}d] " fmt, MAKE_FILE_NAME, \
__LINE__, ##__VA_ARGS__)
struct FdInfo {
int32_t tunFd = 0;
int32_t tunnelFd = 0;
struct sockaddr_in serverAddr;
};
static FdInfo fdInfo;
static bool threadRunF = false;
static std::thread threadt1;
static std::thread threadt2;
// Obtain the IP address of the UDP server.
static constexpr const int MAX_STRING_LENGTH = 1024;
std::string GetStringFromValueUtf8(napi_env env, napi_value value) {
std::string result;
char str[MAX_STRING_LENGTH] = {0};
size_t length = 0;
napi_get_value_string_utf8(env, value, str, MAX_STRING_LENGTH, &length);
if (length > 0) {
return result.append(str, length);
}
return result;
}
void HandleReadTunfd(FdInfo fdInfo) {
uint8_t buffer[BUFFER_SIZE] = {0};
while (threadRunF) {
int ret = read(fdInfo.tunFd, buffer, sizeof(buffer));
if (ret <= 0) {
if (errno != 11) {
NETMANAGER_VPN_LOGE("read tun device error: %{public}d, tunfd: %{public}d", errno, fdInfo.tunFd);
}
continue;
}
// Read data from the vNIC and send the data to the UDP server through the UDP tunnel.
NETMANAGER_VPN_LOGD("buffer: %{public}s, len: %{public}d", buffer, ret);
ret = sendto(fdInfo.tunnelFd, buffer, ret, 0, (struct sockaddr *)&fdInfo.serverAddr, sizeof(fdInfo.serverAddr));
if (ret <= 0) {
NETMANAGER_VPN_LOGE("send to server[%{public}s:%{public}d] failed, ret: %{public}d, error: %{public}s",
inet_ntoa(fdInfo.serverAddr.sin_addr), ntohs(fdInfo.serverAddr.sin_port), ret,
strerror(errno));
continue;
}
}
}
void HandleTcpReceived(FdInfo fdInfo) {
int addrlen = sizeof(struct sockaddr_in);
uint8_t buffer[BUFFER_SIZE] = {0};
while (threadRunF) {
int length = recvfrom(fdInfo.tunnelFd, buffer, sizeof(buffer), 0, (struct sockaddr *)&fdInfo.serverAddr,
(socklen_t *)&addrlen);
if (length < 0) {
if (errno != 11) {
NETMANAGER_VPN_LOGE("read tun device error: %{public}d, tunnelfd: %{public}d", errno, fdInfo.tunnelFd);
}
continue;
}
// Receive data from the UDP server and write the data to the vNIC.
NETMANAGER_VPN_LOGD("from [%{public}s:%{public}d] data: %{public}s, len: %{public}d",
inet_ntoa(fdInfo.serverAddr.sin_addr), ntohs(fdInfo.serverAddr.sin_port), buffer, length);
int ret = write(fdInfo.tunFd, buffer, length);
if (ret <= 0) {
NETMANAGER_VPN_LOGE("error Write To Tunfd, errno: %{public}d", errno);
}
}
}
static napi_value UdpConnect(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
int32_t port = 0;
napi_get_value_int32(env, args[1], &port);
std::string ipAddr = GetStringFromValueUtf8(env, args[0]);
NETMANAGER_VPN_LOGI("ip: %{public}s port: %{public}d", ipAddr.c_str(), port);
// Establish a UDP tunnel.
int32_t sockFd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockFd == -1) {
NETMANAGER_VPN_LOGE("socket() error");
return 0;
}
struct timeval timeout = {1, 0};
setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
memset(&fdInfo.serverAddr, 0, sizeof(fdInfo.serverAddr));
fdInfo.serverAddr.sin_family = AF_INET;
fdInfo.serverAddr.sin_addr.s_addr = inet_addr(ipAddr.c_str()); // server's IP addr
fdInfo.serverAddr.sin_port = htons(port); // port
NETMANAGER_VPN_LOGI("Connection successful");
napi_value tunnelFd;
napi_create_int32(env, sockFd, &tunnelFd);
return tunnelFd;
}
static napi_value StartVpn(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
napi_get_value_int32(env, args[0], &fdInfo.tunFd);
napi_get_value_int32(env, args[1], &fdInfo.tunnelFd);
if (threadRunF) {
threadRunF = false;
threadt1.join();
threadt2.join();
}
// Start two threads. One is used to read data from the vNIC, and the other is used to receive data from the server.
threadRunF = true;
std::thread tt1(HandleReadTunfd, fdInfo);
std::thread tt2(HandleTcpReceived, fdInfo);
threadt1 = std::move(tt1);
threadt2 = std::move(tt2);
NETMANAGER_VPN_LOGI("StartVpn successful");
napi_value retValue;
napi_create_int32(env, 0, &retValue);
return retValue;
}
static napi_value StopVpn(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
int32_t tunnelFd;
napi_get_value_int32(env, args[0], &tunnelFd);
if (tunnelFd) {
close(tunnelFd);
tunnelFd = 0;
}
// Stop the two threads.
if (threadRunF) {
threadRunF = false;
threadt1.join();
threadt2.join();
}
NETMANAGER_VPN_LOGI("StopVpn successful");
napi_value retValue;
napi_create_int32(env, 0, &retValue);
return retValue;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"udpConnect", nullptr, UdpConnect, nullptr, nullptr, nullptr, napi_default, nullptr},
{"startVpn", nullptr, StartVpn, nullptr, nullptr, nullptr, napi_default, nullptr},
{"stopVpn", nullptr, StopVpn, nullptr, nullptr, nullptr, napi_default, nullptr},
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void *)0),
.reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) {
napi_module_register(&demoModule);
}
```
# Socket Connection
## Introduction
## Overview
The Socket Connection module allows an application to transmit data over a socket connection through the TCP, UDP, or TLS protocol.
......
# Subscribing to State Changes of a Remote Object
## Overview
IPC/RPC allows you to subscribe to the state changes of a remote stub object. When the remote stub object dies, a death notification will be sent to your local proxy object. Such subscription and unsubscription are controlled by APIs. To be specific, you need to implement the **DeathRecipient** interface and the **onRemoteDied** API to clear resources. This callback is invoked when the process accommodating the remote stub object dies, or the device accommodating the remote stub object leaves the network. It is worth noting that these APIs should be called in the following order: The proxy object must first subscribe to death notifications of the stub object. If the stub object is in the normal state, the proxy object can cancel the subscription as required. If the process of the stub object exits or the device hosting the stub object goes offline, subsequent operations customized by the proxy object will be automatically triggered.
## When to Use
......
# WebSocket Connection
## When to Use
## Overview
You can use WebSocket to establish a bidirectional connection between a server and a client. Before doing this, you need to use the **createWebSocket()** API to create a **WebSocket** object and then use the **connect()** API to connect to the server. If the connection is successful, the client will receive a callback of the **open** event. Then, the client can communicate with the server using the **send()** API. When the server sends a message to the client, the client will receive a callback of the **message** event. If the client no longer needs this connection, it can call the **close()** API to disconnect from the server. Then, the client will receive a callback of the **close** event.
......
......@@ -68,7 +68,7 @@ The following table lists the APIs used for persisting user preference data. For
return;
}
console.info('Succeeded in getting preferences.');
// Perform related data operations.
// Before performing related data operations, obtain a Preferences instance.
})
} catch (err) {
console.error(`Failed to get preferences. Code:${err.code},message:${err.message}`);
......@@ -93,7 +93,7 @@ The following table lists the APIs used for persisting user preference data. For
return;
}
console.info('Succeeded in getting preferences.');
// Perform related data operations.
// Before performing related data operations, obtain a Preferences instance.
})
} catch (err) {
console.error(`Failed to get preferences. Code is ${err.code},message:${err.message}`);
......@@ -220,4 +220,4 @@ The following table lists the APIs used for persisting user preference data. For
} catch (err) {
console.error(`Failed to delete preferences. Code:${err.code}, message:${err.message}`);
}
```
```
\ No newline at end of file
......@@ -50,7 +50,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
## How to Develop
1. Obtain an **RdbStore** instance.<br> Example:
1. Obtain an **RdbStore** instance.<br>Example:
Stage model:
......@@ -97,7 +97,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
store.version = 3;
}
// Perform operations such as adding, deleting, modifying, and querying data in the RDB store.
// Before performing data operations on the database, obtain an RdbStore instance.
});
}
......@@ -151,7 +151,7 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
store.version = 3;
}
// Perform operations such as adding, deleting, modifying, and querying data in the RDB store.
// Before performing data operations on the database, obtain an RdbStore instance.
});
```
......@@ -256,7 +256,9 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
5. Delete the RDB store.
Use **deleteRdbStore()** to delete the RDB store and related database files.
Use **deleteRdbStore()** to delete the RDB store and related database files.
Example:
> **NOTE**
>
......@@ -299,4 +301,4 @@ The following table lists the APIs used for RDB data persistence. Most of the AP
store = null;
console.info('Succeeded in deleting RdbStore.');
});
```
```
\ No newline at end of file
......@@ -171,7 +171,7 @@ The following uses a single KV store as an example to describe how to implement
return;
}
console.info('Succeeded in getting KVStore.');
// Perform related data operations.
// Before performing related data operations, obtain a KV store instance.
});
} catch (e) {
console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);
......@@ -275,4 +275,4 @@ The following uses a single KV store as an example to describe how to implement
}
}
});
```
```
\ No newline at end of file
# DFX
- [Development of Application Event Logging](hiappevent-guidelines.md)
- [Development of Performance Tracing](hitracemeter-guidelines.md)
- [Development of Distributed Call Chain Tracing](hitracechain-guidelines.md)
- [HiLog Development (Native)](hilog-guidelines.md)
- Performance Tracing
......
# Application Freeze (appfreeze) Log Analysis
## Introduction
## Overview
Application freeze (appfreeze) means that an application does not respond to user operations (for example, clicking) within a given period of time. OpenHarmony provides a mechanism for detecting appfreeze faults and generates appfreeze logs for fault analysis.
......
# Application Recovery Development
## When to Use
## Overview
During application running, some unexpected behaviors are inevitable. For example, unprocessed exceptions and errors are thrown, and the call or running constraints of the recovery framework are violated.
......@@ -99,9 +99,12 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant'
- Define and register the [ErrorObserver](../reference/apis/js-apis-inner-application-errorObserver.md) callback. For details about its usage, see [errorManager](../reference/apis/js-apis-app-ability-errorManager.md).
```ts
var registerId = -1;
var callback = {
onUnhandledException(errMsg) {
export let abilityWant : Want // file1
import * as G form "../file1"
let registerId = -1;
let callback: Callback = {
onUnhandledException(errMsg: string): void {
console.log(errMsg);
appRecovery.saveAppState();
appRecovery.restartApp();
......@@ -112,7 +115,7 @@ import AbilityConstant from '@ohos.app.ability.AbilityConstant'
// Main window is created, set main page for this ability
console.log("[Demo] MainAbility onWindowStageCreate")
globalThis.registerObserver = (() => {
G.registerObserver = (() => {
registerId = errorManager.on('error', callback);
})
......@@ -138,13 +141,16 @@ After the callback triggers **appRecovery.saveAppState()**, **onSaveState(state,
After the callback triggers **appRecovery.restartApp()**, the application is restarted. After the restart, **onCreate(want, launchParam)** of **MainAbility** is called, and the saved data is in **parameters** of **want**.
```ts
export let abilityWant : Want // file1
import * as GlobalWant form "../file1"
storage: LocalStorage
onCreate(want, launchParam) {
console.log("[Demo] MainAbility onCreate")
globalThis.abilityWant = want;
GlobalWant.abilityWant = want;
if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
this.storage = new LocalStorage();
let recoveryData = want.parameters["myData"];
let recoveryData: string = want.parameters["myData"];
this.storage.setOrCreate("myData", recoveryData);
this.context.restoreWindowStage(this.storage);
}
......@@ -154,12 +160,15 @@ onCreate(want, launchParam) {
- Unregister the **ErrorObserver** callback.
```ts
export let abilityWant : Want // file1
import * as G form "../file1"
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
console.log("[Demo] MainAbility onWindowStageDestroy")
globalThis.unRegisterObserver = (() => {
errorManager.off('error', registerId, (err) => {
G.unRegisterObserver = (() => {
errorManager.off(type: 'error', registerId: number, (err:Error) => {
console.error("[Demo] err:", err);
});
})
......@@ -171,20 +180,22 @@ onWindowStageDestroy() {
This is triggered by the recovery framework. You do not need to register an **ErrorObserver** callback. You only need to implement **onSaveState** for application state saving and **onCreate** for data restore.
```ts
export let abilityWant : Want // file1
import * as GlobalWant form "../file1"
export default class MainAbility extends Ability {
storage: LocalStorage
onCreate(want, launchParam) {
onCreate(want: Want, launchParam:AbilityConstant.LaunchParam):void {
console.log("[Demo] MainAbility onCreate")
globalThis.abilityWant = want;
GlobalWant.abilityWant = want;
if (launchParam.launchReason == AbilityConstant.LaunchReason.APP_RECOVERY) {
this.storage = new LocalStorage();
let recoveryData = want.parameters["myData"];
this.storage.setOrCreate("myData", recoveryData);
let recoveryData: string = want.parameters["myData"];
this.storage.setOrCreate<string>("myData", recoveryData);
this.context.restoreWindowStage(this.storage);
}
}
onSaveState(state, wantParams) {
onSaveState(state: AbilityConstant.StateType, wantParams: { [key: string]: Object }) : AbilityConstant.OnSaveResult{
// Ability has called to save app data
console.log("[Demo] MainAbility onSaveState")
wantParams["myData"] = "my1234567";
......
# cppcrash Log Analysis
# Process Crash (cppcrash) Log Analysis
## Introduction
## Overview
A process crash refers to a C/C++ runtime crash. The FaultLogger module of OpenHarmony provides capabilities such as process crash detection, log collection, log storage, and log reporting, helping you to locate faults more effectively.
......@@ -23,7 +23,7 @@ Process crash detection is implemented based on the Linux signal mechanism. Curr
## Crash Log Collection
Process crash log is the fault log managed together with the app freeze and JS application crash logs by the FaultLogger module. You can collect process crash logs in any of the following ways:
Process crash log is a type of fault logs managed together with the app freeze and JS application crash logs by the FaultLogger module. You can collect process crash logs in any of the following ways:
### Collecting Logs by Using Shell
......@@ -72,17 +72,14 @@ Thread name:crasher <- Abnormal thread
### Locating Faults Through Logs
1. Determine the faulty module and fault type based on fault logs.
Generally, you can identify the faulty module based on the crash process name and identify the crash cause based on the signal. Besides, you can restore the function call chain of the crash stack based on the method name in the stack.
In the example, **SIGSEGV** is thrown by the Linux kernel because of access to an invalid memory address. The problem occurs in the **TriggerSegmentFaultException** function.
In most scenarios, a crash is caused by the top layer of the crash stack, such as null pointer access and proactive program abort.
- Determine the faulty module and fault type based on fault logs.
Generally, you can identify the faulty module based on the crash process name and identify the crash cause based on the signal. Besides, you can restore the function call chain of the crash stack based on the method name in the stack.\
In the example, **SIGSEGV** is thrown by the Linux kernel because of access to an invalid memory address. The problem occurs in the **TriggerSegmentFaultException** function.\
In most scenarios, a crash is caused by the top layer of the crash stack, such as null pointer access and proactive program abort.\
If the cause cannot be located through the call stack, you need to check for other faults, for example, memory corruption or stack overflow.
2. Use the addr2line tool of Linux to parse the code line number to restore the call stack at the time of process crash.
- Use the addr2line tool of Linux to parse the code line number to restore the call stack at the time of process crash.
When using the addr2line tool to parse the code line number of the crash stack, make sure that binary files with debugging information is used. Generally, such files are generated during version build or application build.
......@@ -94,17 +91,17 @@ Thread name:crasher <- Abnormal thread
\code root directory\out\product\exe.unstripped
```
You can run `apt-get install addr2line` to install the addr2line tool on Linux.
You can run `apt-get install addr2line` to install the addr2line tool on Linux.\
On On DevEco Studio, you can also use the llvm-addr2line tool archived in the SDK to parse code line numbers. The usage method is the same.
The following example shows how to use the addr2line tool to parse the code line number based on the offset address:
The following example shows how to use the addr2line tool to parse the code line number based on the offset address.
**[product name]** indicates the device name.
```
root:~/OpenHarmony/out/rk3568/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -e crasher 0000332c
root:~/OpenHarmony/out/[product name]/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -e crasher 0000332c
base/hiviewdfx/faultloggerd/tools/crasher/dfx_crasher.c:57
```
In this example, the crash is caused by assignment of a value to an unwritable area. It is in code line 57 in the **dfx_crasher.c** file. You can modify it to avoid the crash.
In this example, the crash is caused by assignment of a value to an unwritable area. It is in code line 57 in the **dfx_crasher.c** file. You can modify it to avoid the crash.\
If the obtained code line number is seemingly incorrect, you can fine-tune the address (for example, subtract the address by 1) or disable some compilation optimization items. It is known that the obtained code line number may be incorrect when Link Time Optimization (LTO) is enabled.
# Development of Error Manager
## When to Use
## Overview
If coding specification issues or errors exist in the code of an application, the application may encounter unexpected errors, for example, uncaught exceptions or application lifecycle timeouts, while it is running. In such a case, the application may exit unexpectedly. Error logs, however, are usually stored on users' local storage, making it inconvenient to locate faults. With the APIs provided by the **errorManager** module, your application will be able to report related errors and logs to your service platform for fault locating before it exits.
......
# Development of Application Event Logging
## Introduction
## Overview
A traditional log system aggregates log information generated by all applications running on the entire device, making it difficult to identify key information in the log. Therefore, an effective logging mechanism is needed to evaluate mission-critical information, for example, number of visits, number of daily active users, user operation habits, and key factors that affect application usage.
......
# HiLog Development (Native)
## Introduction
## Overview
HiLog is the log system of OpenHarmony that provides logging for the system framework, services, and applications to record information on user operations and system running status.
......
# Development of Distributed Call Chain Tracing
## Introduction
## Overview
The hiTraceChain module provides APIs to implement call chain tracing throughout a service process. This can help you quickly obtain the run log for the call chain of a specified service process and locate faults in inter-device, inter-process, or inter-thread communications.
......
# Development of Performance Tracing (ArkTS)
## Introduction
## Overview
hiTraceMeter provides APIs for system performance tracing. You can call the APIs provided by the hiTraceMeter module in your own service logic to effectively track service processes and check the system performance.
......@@ -21,7 +21,7 @@ hiTraceMeter provides APIs for system performance tracing. You can call the APIs
## Available APIs
The performance tracing APIs are provided by the **hiTraceMeter** module. For details, see [API Reference](../reference/apis/js-apis-hitracemeter.md).
The performance tracing APIs are provided by the **hiTraceMeter** module. For details, see [API Reference]( ../reference/apis/js-apis-hitracemeter.md).
**APIs for performance tracing**
......@@ -35,60 +35,16 @@ The performance tracing APIs are provided by the **hiTraceMeter** module. For de
In this example, distributed call chain tracing begins when the application startup execution page is loaded and stops when the service usage is completed.
1. Create a JS application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **js** > **default** > **pages** > **index**, and double-click **index.js**. Add the code to implement performance tracing upon page loading. The sample code is as follows:
```js
import hiTraceMeter from '@ohos.hiTraceMeter'
export default {
data: {
title: ""
},
onInit() {
this.title = this.$t('strings.world');
// Start trace tasks with the same name concurrently.
hiTraceMeter.startTrace("business", 1);
// Keep the service process running.
console.log(`business running`);
hiTraceMeter.startTrace("business", 2); // Start the second trace task with the same name while the first task is still running. The tasks are running concurrently and therefore their taskId must be different.
// Keep the service process running.
console.log(`business running`);
hiTraceMeter.finishTrace("business", 1);
// Keep the service process running.
console.log(`business running`);
hiTraceMeter.finishTrace("business", 2);
// Start trace tasks with the same name in serial mode.
hiTraceMeter.startTrace("business", 1);
// Keep the service process running.
console.log(`business running`);
hiTraceMeter.finishTrace("business", 1); // End the first trace task.
// Keep the service process running.
console.log(`business running`);
hiTraceMeter.startTrace("business", 1); // Start the second trace task with the same name in serial mode.
// Keep the service process running.
console.log(`business running`);
let traceCount = 3;
hiTraceMeter.traceByValue("myTestCount", traceCount);
traceCount = 4;
hiTraceMeter.traceByValue("myTestCount", traceCount);
hiTraceMeter.finishTrace("business", 1);
}
}
```
2. Create an ArkTs application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **ets** > **pages** > **index**, and double-click **index.js**. Add the code to implement performance tracing upon page loading. For example, if the name of the trace task is **HITRACE\_TAG\_APP**, the sample code is as follows:
1. Create an ArkTS application project. In the displayed **Project** window, choose **entry** > **src** > **main** > **ets** > **pages** > **index**, and double-click **index.js**. Add the code to implement performance tracing upon page loading. For example, if the name of the trace task is **HITRACE\_TAG\_APP**, the sample code is as follows:
```ts
import hitrace from '@ohos.hiTraceMeter';
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Row() {
Column() {
......@@ -97,7 +53,7 @@ In this example, distributed call chain tracing begins when the application star
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.message = 'Hello ArkUI';
// Start trace tasks with the same name concurrently.
hitrace.startTrace("HITRACE_TAG_APP", 1001);
// Keep the service process running.
......@@ -107,7 +63,7 @@ In this example, distributed call chain tracing begins when the application star
hitrace.startTrace("HITRACE_TAG_APP", 1002);
// Keep the service process running.
console.log(`HITRACE_TAG_APP running`);
hitrace.finishTrace("HITRACE_TAG_APP", 1001);
hitrace.finishTrace("HITRACE_TAG_APP", 1002);
......@@ -143,7 +99,7 @@ In this example, distributed call chain tracing begins when the application star
```
3. Click the run button on the application page. Then, run the following commands in sequence in shell:
```shell
hdc shell
hitrace --trace_begin app
......
# Development of Performance Tracing (Native)
## Introduction
## Overview
hiTraceMeter provides APIs for system performance tracing. You can call the APIs provided by the hiTraceMeter module in your own service logic to effectively track service processes and check the system performance.
> **NOTE**
......
......@@ -217,7 +217,7 @@ Use **Context.cacheDir** to obtain the cache directory of the application.
**Reference**
[Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths)
[cacheDir](../application-models/application-context-stage.md#obtaining-application-file-paths)
## In which JS file is the service widget lifecycle callback invoked?
......@@ -282,7 +282,7 @@ Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
**Solution**
Refer to the code snippet below:
Refer to the code snippet below:
```
let want = {
......@@ -472,7 +472,7 @@ To start a continuous task in the background, you must configure the permission
[Continuous Task Permission](../security/permission-list.md#ohospermissionkeep_background_running)
[Continuous Task Development](../task-management/continuous-task.md#stage-model)
[Continuous Task](../task-management/continuous-task.md)
## How do FA widgets exchange data?
......
......@@ -36,10 +36,11 @@ You can use [attribute animation](../reference/arkui-ts/ts-animatorproperty.md)
Applicable to: OpenHarmony 3.2 Beta 5 (API version 9)
**Solution**
**Solution**
- Add **focusable\(true\)** to the list item to enable it to obtain focus.
Use either of the following:
- Add **focusable\(true\)** to the list item to enable it to obtain focus.
- Nest a focusable component, for example, **\<Button>**, at the outer layer of each item.
## Why is the click event not triggered for the focused component upon the press of the Enter key after keyboard navigation?
......@@ -139,6 +140,8 @@ Currently, the menu is displayed when the bound component is clicked or long pre
Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
**Solution**
Set the **focusable** attribute of the **\<TextInput>** component to **false**. In this way, the component is not focusable and therefore will not bring up the keyboard.
## How do I implement the slide up and slide down effect for page transition?
......@@ -199,7 +202,7 @@ Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
**Symptom**
Custom components A and B need to deliver the following effects: When custom component A, displayed at the bottom of the screen by default, is touched, it is hidden, and custom component B slides in from the bottom. When custom component B is touched, it is hidden, and custom component A slides in from the bottom.
Custom components A and B need to deliver the following effects: When custom component A, displayed at the bottom of the screen by default, is touched, it is hidden, and custom component B slides in from the bottom; when custom component B is touched, it is hidden, and custom component A slides in from the bottom.
**Solution**
......@@ -266,4 +269,4 @@ struct ComponentChild2 {
**Reference**
[Transition Animation Within the Component](../ui/arkts-enter-exit-transition.md)
[Enter/Exit Transition](../ui/arkts-enter-exit-transition.md)
......@@ -21,42 +21,6 @@ try {
}
```
## How do I hide the status bar to get the immersive effect?
Applicable to: OpenHarmony 3.2 Beta5 (API version 9)
**Solution**
1. Use **onWindowStageCreate** to obtain a **windowClass** object.
```
onWindowStageCreate(windowStage) {
// When the main window is created, set the main page for this ability.
console.log("[Demo] MainAbility onWindowStageCreate")
windowStage.getMainWindow((err, data) => {
if (err.code) {
console.error('Failed to obtain the main window.')
return;
}
// Obtain a windowClass object.
globalThis.windowClass = data;
})
}
```
2. Enable the full-screen mode for the window and hide the status bar.
```
globalThis.windowClass.setFullScreen(isFullScreen, (err, data) => {
if (err.code) {
console.error('Failed to enable the full-screen mode. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in enabling the full-screen mode. Data: ' + JSON.stringify(data));
});
```
## How do I obtain the window width and height?
Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model)
......
......@@ -98,7 +98,7 @@ Music cannot be played in the background.
**Reference**
[Continuous Task Development](../task-management/continuous-task.md)
[Continuous Task](../task-management/continuous-task.md)
[AVSession Development](../media/using-avsession-developer.md)
......@@ -197,4 +197,4 @@ CameraStatus: Enumerates the camera statuses.
**Reference**
[CameraStatus](../reference/apis/js-apis-camera.md#oncamerastatus)
\ No newline at end of file
[CameraStatus](../reference/apis/js-apis-camera.md#oncamerastatus)
# File Management
- [File Management Overview](file-management-overview.md)
- Application File
- Application Files
- [Application File Overview](app-file-overview.md)
- [Application Sandbox Directory](app-sandbox-directory.md)
- Application File Access and Management
- [Accessing Application Files](app-file-access.md)
- [Uploading and Downloading Application Files](app-file-upload-download.md)
- [Obtaining Application and File System Space Statistics](app-fs-space-statistics.md)
- [Sending Files to an Application Sandbox](send-file-to-app-sandbox.md)
- [Pushing Files to an Application Sandbox](send-file-to-app-sandbox.md)
- [Sharing an Application File](share-app-file.md)
- Application Data Backup and Restoration
- [Application Data Backup and Restoration Overview](app-file-backup-overview.md)
- [Backing Up and Restoring Application Access Data](app-file-backup-extension.md)
- [Backing Up and Restoring Application-triggered Data (for System Applications Only)](app-file-backup.md)
- User File
- [Backup and Restoration Accessed by Applications](app-file-backup-extension.md)
- [Backup and Restoration Triggered by System Applications](app-file-backup.md)
- User Files
- [User File Overview](user-file-overview.md)
- Selecting and Saving User Files (FilePicker)
- [Selecting User Files](select-user-file.md)
- [Saving User Files](save-user-file.md)
- Album Management (photoAccessHelper)
- [photoAccessHelper Overview](photoAccessHelper-overview.md)
- [Media Asset (Image and video) Management](photoAccessHelper-resource-guidelines.md)
- [User Album Management](photoAccessHelper-userAlbum-guidelines.md)
- [System Album Management](photoAccessHelper-systemAlbum-guidelines.md)
- [Media Asset Change Notification Management](photoAccessHelper-notify-guidelines.md)
- [Developing a FileManager Application (for System Applications Only)](dev-user-file-manager.md)
- [Managing Media Assets (Images and Videos)](photoAccessHelper-resource-guidelines.md)
- [Managing User Albums](photoAccessHelper-userAlbum-guidelines.md)
- [Managing System Albums](photoAccessHelper-systemAlbum-guidelines.md)
- [Managing Media Asset Change Notifications](photoAccessHelper-notify-guidelines.md)
- [Developing a File Manager Application (for System Applications Only)](dev-user-file-manager.md)
- [Managing External Storage Devices (for System Applications Only)](manage-external-storage.md)
- Distributed File System
- [Distributed File System Overview](distributed-fs-overview.md)
......
# Accessing Application Files
This topic describes how to view, create, read, write, delete, move, or copy a file in the application file directory and obtain the file information.
This topic describes how to enable an application to view, create, read, write, delete, move, or copy an application and obtain file information.
## Available APIs
You can use [ohos.file.fs](../reference/apis/js-apis-file-fs.md) to implement the application file access capabilities. The following table describes the APIs.
You can use [ohos.file.fs](../reference/apis/js-apis-file-fs.md) to implement access to application files. The following table describes the APIs.
**Table 1** APIs for basic application file operations
| API| Description| Type| Synchronous Programming| Asynchronous Programming|
| API| Description| Type| Synchronous Programming| Asynchronous Programming|
| -------- | -------- | -------- | -------- | -------- |
| access | Checks whether a file exists.| Method| √ | √ |
| close | Closes a file.| Method| √ | √ |
| copyFile | Copies a file.| Method| √ | √ |
| createStream | Creates a stream based on the specified file path.| Method| √ | √ |
| listFile | Lists all files in a directory.| Method| √ | √ |
| mkdir | Creates a directory.| Method| √ | √ |
| moveFile | Moves a file.| Method| √ | √ |
| open | Opens a file.| Method| √ | √ |
| read | Reads data from a file.| Method| √ | √ |
| rename | Renames a file or folder.| Method| √ | √ |
| rmdir | Deletes a directory.| Method| √ | √ |
| stat | Obtains detailed file information.| Method| √ | √ |
| unlink | Deletes a single file.| Method| √ | √ |
| write | Writes data to a file.| Method| √ | √ |
| Stream.close | Closes a stream.| Method| √ | √ |
| Stream.flush | Flushes all data from this stream.| Method| √ | √ |
| Stream.write | Writes data to a stream.| Method| √ | √ |
| Stream.read | Reads data from a stream.| Method| √ | √ |
| File.fd | Defines a file descriptor.| Attribute| √ | × |
| OpenMode | Defines the mode for opening a file.| Attribute| √ | × |
| Filter | Defines the options for setting the file filter.| Type| × | × |
| access | Checks whether a file exists.| Method| √ | √ |
| close | Closes a file.| Method| √ | √ |
| copyFile | Copies a file.| Method| √ | √ |
| createStream | Creates a stream based on the specified file path.| Method| √ | √ |
| listFile | Lists all files in a directory.| Method| √ | √ |
| mkdir | Creates a directory.| Method| √ | √ |
| moveFile | Moves a file.| Method| √ | √ |
| open | Opens a file.| Method| √ | √ |
| read | Reads data from a file.| Method| √ | √ |
| rename | Renames a file or folder.| Method| √ | √ |
| rmdir | Deletes a directory.| Method| √ | √ |
| stat | Obtains detailed file information.| Method| √ | √ |
| unlink | Deletes a single file.| Method| √ | √ |
| write | Writes data to a file.| Method| √ | √ |
| Stream.close | Closes a stream.| Method| √ | √ |
| Stream.flush | Flushes all data from this stream.| Method| √ | √ |
| Stream.write | Writes data to a stream.| Method| √ | √ |
| Stream.read | Reads data from a stream.| Method| √ | √ |
| File.fd | Defines a file descriptor.| Attribute| √ | × |
| OpenMode | Defines the mode for opening a file.| Attribute| √ | × |
| Filter | Defines the options for setting the file filter.| Type| × | × |
## Development Example
Obtain the [application file path](../application-models/application-context-stage.md#obtaining-the-application-development-path). The following example shows how to obtain a HAP file path using **UIAbilityContext**. For details about how to obtain **UIAbilityContext**, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
First, obtain the [application file path](../application-models/application-context-stage.md#obtaining-application-file-paths). The following example shows how to obtain a HAP file path using **UIAbilityContext**. For details about how to obtain **UIAbilityContext**, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
The following describes common file operations.
Then, perform common file operations.
### Creating, Reading, and Writing a File
......@@ -68,8 +68,8 @@ function createFile() {
### Copying Data to Another File
The following example demonstrates how to write the data read from a file to another file.
The following example demonstrates how to read data from a file and write it to another file.
```ts
// pages/xxx.ets
import fs from '@ohos.file.fs';
......@@ -101,12 +101,12 @@ function readWriteFile() {
> **NOTE**
>
> When using **read()** or **write()**, pay attention to the optional parameter **offset**. For a file that has been read or written, the offset pointer is at the end position of the last read or write operation by default.
> When using **read()** or **write()**, pay attention to the optional parameter **offset**. For a file that has been read or written, **offset** points to the end position of the last read or write operation by default.
### Reading and Writing Files in a Stream
The following example demonstrates how to read and write file data using a stream.
```ts
// pages/xxx.ets
import fs from '@ohos.file.fs';
......@@ -138,12 +138,14 @@ async function readWriteFileWithStream() {
```
> **NOTE**
>
> Close the stream that is no longer used in a timely manner. <br>Comply with the related programming specifications for **Stream** APIs in asynchronous mode and avoid mixed use of the APIs in synchronous mode and asynchronous mode. <br>The **Stream** APIs do not support concurrent read and write operations.
>
> - Close the stream that is no longer used in a timely manner.
> - Comply with the programming specifications for **Stream** APIs in asynchronous mode and avoid mixed use of the APIs in synchronous mode and asynchronous mode.
> - The **Stream** APIs do not support concurrent read and write operations.
### Listing Files
The following example demonstrates how to list files.
The following example demonstrates how to list files that meet the specified conditions.
```ts
// List files.
......@@ -162,7 +164,7 @@ let options = {
suffix: ['.png', '.jpg', '.txt'], // The filename extension can be '.png', '.jpg', or '.txt'.
displayName: ['test%'], // The filename starts with 'test'.
fileSizeOver: 0, // The file size is greater than or equal to 0.
lastModifiedAfter: new Date(0).getTime(), // The latest modification time of the file is later than January 1, 1970.
lastModifiedAfter: new Date(0).getTime(), // The latest modification time of the file is later than January 1, 1970.
},
}
let files = fs.listFileSync(filesDir, options);
......
# Backing Up and Restoring Application Access Data
# Backup and Restoration Accessed by Applications
You can use BackupExtensionAbility to implement backup and restoration of application access data.
You can use BackupExtensionAbility to enable an application to access the backup and restoration framework.
BackupExtensionAbility is a class derived from the [ExtensionAbility](../application-models/extensionability-overview.md) component in [Stage Model](../../application-dev/application-models/stage-model-development-overview.md). You can modify the configuration file to customize the behavior of the backup and restoration framework, including whether backup and restoration are allowed and which files are backed up.
BackupExtensionAbility is a class derived from the [ExtensionAbility](../application-models/extensionability-overview.md) component in [Stage Model](../../application-dev/application-models/stage-model-development-overview.md). You can modify the configuration file to customize the backup and restoration framework behavior, including whether to allow backup and restoration and specifying the files to be backed up.
## Constraints
- The paths of all files and directories to be backed up cannot exceed 4095 bytes. Otherwise, undefined behavior may occur.
- If a directory needs to be backed up, the application process must have the permission to read the directory and all its subdirectories (**r** in DAC). Otherwise, the backup fails.
- If a file needs to be backed up, the application process must have the permission to search for its grandparent directory of the file (**x** in DAC). Otherwise, the backup fails.
- If a file needs to be backed up, the application process must have the permission to retrieve the grandparent directory of the file (**x** in DAC). Otherwise, the backup fails.
## How to Develop
1. Add the **extensionAbilities** configuration in the application's **module.json5** file.
1. Add **extensionAbilities** to the application's **module.json5** file.
Add **extensionAbilities**, set **type** to **backup**, and add **name: ohos.extension.backup** to **[metadata]**(../../application-dev/reference/apis/js-apis-bundleManager-metadata.md).
Add the **extensionAbilities** field, set **type** to **backup**, and add a record with **name** of **ohos. extension. backup** to **[metadata](../../application-dev/reference/apis/js-apis-bundleManager-metadata.md)**.
BackupExtensionAbility configuration example:
......@@ -40,7 +40,7 @@ BackupExtensionAbility is a class derived from the [ExtensionAbility](../applica
2. Add a metadata resource configuration file.
The metadata resource configuration file defines the files to be transferred during backup and restoration. The file name must be the same as the value of **resource** under **metadata** in the **module.json5** file. This file is stored in the **Profile** folder.
The metadata resource configuration file defines the files to be transferred during the backup and restoration process. The file is located in the **Profile** folder, and the file name must be the same as the value of **resource** under **metadata** in the **module.json5** file.
Metadata resource configuration file example:
......@@ -61,8 +61,8 @@ BackupExtensionAbility is a class derived from the [ExtensionAbility](../applica
| Name | Type | Mandatory| Description |
| -------------------- | ---------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| allowToBackupRestore | Boolean | Yes | Whether to allow backup and restoration. The default value is **false**. |
| includes | String array| No | Files and directories to be backed up in the application sandbox.<br>Each item in the array is a pattern string, which can contain shell-style wildcards such as *****, **?**, and **[**.<br>The pattern string that does not start with a slash (/) indicates a relative path relative to the root path.<br>If **includes** is configured, the backup and restoration framework uses the pattern strings configured. Otherwise, the backup and restoration framework uses the **includes** default value (see the following code segment).|
| excludes | String array| No | Exception items in **includes** that do not need to be backed up. The value is in the same format as **includes**.<br>If **excludes** is configured, the backup and restoration framework uses the pattern strings configured. Otherwise, the backup and restoration framework uses an empty array as the default value. |
| includes | String array| No | Files and directories to be backed up in the application sandbox.<br>Each item in the array is a pattern string, which can contain shell-style wildcards such as (`*`, `?`, `[`).<br>The pattern string that does not start with a slash (/) indicates a relative path.<br>If **includes** is configured, the backup and restoration framework uses the pattern strings configured. Otherwise, the backup and restoration framework uses the **includes** default value (see the following code segment).|
| excludes | String array| No | Items in **includes** that do not need to be backed up. The value is in the same format as **includes**.<br>If **excludes** is configured, the backup and restoration framework uses the pattern strings configured. Otherwise, the backup and restoration framework uses an empty array as the default value. |
**includes** default value:
......@@ -77,4 +77,4 @@ BackupExtensionAbility is a class derived from the [ExtensionAbility](../applica
"data/storage/el2/base/haps/*/preferences/",
]
}
```
```
\ No newline at end of file
# Application Data Backup and Restoration Overview
Application data, such as the configuration and service data, is generated when an application is used. To ensure that user data will not be lost due to operations, such as application updates and hopping, applications need to access data backup and restoration.
Application data, such as the configuration and service data, is generated when an application is used. To prevent user data against loss due to operations such as application updates and hopping, the application data needs to be backed up and restored.
Before development, you need to understand the ExtensionAbility component. For details, see [ExtensionAbility Component Overview](../application-models/extensionability-overview.md).
Before development, you need to understand the [ExtensionAbility](../application-models/extensionability-overview.md) component.
BackupExtensionAbility is a class derived from ExtensionAbility in the stage model. It provides the capabilities of backing up and restoring application data. It is an extended component without the UI. It runs when a backup or restoration task starts and exits when the task is complete.
Derived from ExtensionAbility in the stage model, BackupExtensionAbility provides the capabilities of backing up and restoring application data. It is an extended component without the UI. It runs when a backup or restoration task starts and exits when the task is complete.
The implementation includes the following:
- [Backup and restoration of application access data](app-file-backup-extension.md): All applications can access data backup and restoration. After accessed, the application can modify the configuration file to customize the behavior of the backup and restoration framework, including whether to allow backup and restoration and specifying the data to be backed up.
- [Backup and restoration accessed by applications](app-file-backup-extension.md): All applications can access the data backup and restoration framework. You can customize the backup and restoration framework behavior for the application, including whether to allow backup and restoration and specifying the data to be backed up, by modifying the application configuration file.
Applications can perform backup and restoration configurations, but not trigger data backup and restoration.
The application itself cannot trigger data backup and restoration.
- [Backup and restoration of application-triggered data](app-file-backup.md): Only system applications can trigger data backup and restoration. After data backup or restoration is triggered, the backup and restoration framework checks whether each application has accessed data backup and restoration. If yes, the backup and restore framework backs up or restores data based on the application's configuration file.
- [Backup and restoration triggered by system applications](app-file-backup.md): Only system applications can trigger data backup and restoration. After data backup or restoration is triggered, the backup and restoration framework locates the applications that have accessed the data backup and restoration framework and backs up or restores data based on the application's configuration file.
# Backing Up and Restoring Application-triggered Data (for System Applications Only)
# Backup and Restoration Triggered by System Applications
The backup and restoration module provides a complete data backup and restoration solution for application data, user data, and system services on devices. You can implement data backup or restoration for applications by performing the following operations:
The backup and restoration framework provides a complete data backup and restoration solution for application data, user data, and system services on devices. You can follow the procedure below to enable an application to trigger data backup or restoration:
- [Obtaining the capability file](#obtaining-the-capability-file): Obtain the capability file of all applications of the system user. The capability file is indispensable for data backup and restoration.
- [Obtain capability files](#obtaining-capability-files): Obtain capability files of all applications of the user in the system. The capability files are indispensable for data backup and restoration.
- [Backing up application data](#backing-up-application-data): Select the application data to be backed up based on the application information provided by the capability file, and back up the data.
- [Back up application data](#backing-up-application-data): Back up the application data based on the application information in the capability files.
- [Restoring application data](#restoring-application-data): Select the application data to be restored based on the application information provided in the capability file and restore the data.
- [Restore application data](#restoring-application-data): Restore the application data based on the application information in the capability files.
- [Installing the application during data restoration](#installing-the-application-during-data-restoration): Install the application if the application has not been installed. As an extended function of application data restoration, this function allows the application to be installed on the device before data restoration.
- [Install the application during data restoration](#installing-the-application-during-data-restoration): Install the application if the application with data to be restored has not been installed. As an extended function of application data restoration, this function allows the application to be installed on the device before data restoration.
## How to Develop
......@@ -16,7 +16,7 @@ For details about the APIs to be used, see [Backup and Restoration](../reference
Before using the APIs, you need to:
1. Apply for the ohos.permission.BACKUP permission. For details, see [Apply for permissions](../security/accesstoken-guidelines.md).
1. Apply for the **ohos.permission.BACKUP** permission. For details, see [Apply for Permissions](../security/accesstoken-guidelines.md).
2. Import **@ohos.file.backup**.
......@@ -24,13 +24,13 @@ Before using the APIs, you need to:
import backup from '@ohos.file.backup';
```
## Obtaining the Capability File
## Obtaining Capability Files
Obtain the application capability file of the current system user. This file is indispensable for application data backup and restoration.
Obtain capability files of all applications of the current user. The capability files are indispensable for application data backup and restoration.
This file contains the device type and version and basic application information, such as the application name, application data size, application version, whether to allow backup and restoration, and whether to install the application during restoration.
The capability file of an application contains the device type, device version, and basic application information, such as the application name, application size, application version, whether to allow backup and restoration, and whether to install the application during restoration.
Use **backup.getLocalCapabilities()** to obtain the capability file.
Use **backup.getLocalCapabilities()** to obtain capability files.
```js
import fs from '@ohos.file.fs';
......@@ -79,9 +79,9 @@ Use **backup.getLocalCapabilities()** to obtain the capability file.
## Backing Up Application Data
You need to select the application data to be backed up based on the application information provided by the capability file.
You can select the application data to be backed up based on the application information in the capability files.
The Backup & Restore service packages the application data into a file. The file handle is returned by the [onFileReady](../reference/apis/js-apis-file-backup.md#onfileready) callback registered when the instance is created.
The Backup & Restore service packages the application data to be backed up. The package file handle is returned by the [onFileReady](../reference/apis/js-apis-file-backup.md#onfileready) callback registered when the **SessionBackup** instance is created.
You can save the file to a local directory as required.
......@@ -152,9 +152,9 @@ You can save the file to a local directory as required.
## Restoring Application Data
You can select the application data to be restored based on the application information provided by the capability file.
You can select the application data to be restored based on the application information in the capability files.
During the restoration, the Backup and Restore service returns the file handle of the application data to be restored in the [onFileReady](../reference/apis/js-apis-file-backup.md#onfileready) callback registered when the instance is created based on the [getFileHandle](../reference/apis/js-apis-file-backup.md#getfilehandle) called. Then, the data to be restored is written to the file handle based on the [uri](../reference/apis/js-apis-file-backup.md#filemeta) returned. After the data is written, use [publishFile()](../reference/apis/js-apis-file-backup.md#publishfile) to notify the service that the data write is complete.
The Backup and Restore service returns the file handle of the application data to be restored in the [onFileReady](../reference/apis/js-apis-file-backup.md#onfileready) callback registered when the **SessionRestore** instance is created. The file handle is obtained by [getFileHandle](../reference/apis/js-apis-file-backup.md#getfilehandle). Then, the data to be restored is written to the file handle based on the [uri](../reference/apis/js-apis-file-backup.md#filemeta) returned. After the data is written, use [publishFile()](../reference/apis/js-apis-file-backup.md#publishfile) to notify the service that the data write is complete.
When all the data of the application is ready, the service starts to restore the application data.
......@@ -184,7 +184,7 @@ When all the data of the application is ready, the service starts to restore the
}
fs.copyFileSync(bundlePath, file.fd);
fs.closeSync(file.fd);
// After the data is transferred, notify the server that the file is ready.
// After the data is transferred, notify the server that the files are ready.
publishFile(file);
console.info('onFileReady success');
},
......@@ -220,11 +220,11 @@ When all the data of the application is ready, the service starts to restore the
"com.example.hiworld",
]
// You can obtain the capability file based on actual situation. The following is an example only.
// You can also construct a capability file as required.
// You can also construct capability files as required.
let fileData = await backup.getLocalCapabilities();
await g_session.appendBundles(fileData.fd, backupApps);
console.info('appendBundles success');
// After the application to be restored is added, call getFileHandle() to obtain the handle of the application file to be restored based on the application name.
// After the applications to be restored are added, call getFileHandle() to obtain the handles of the application files to be restored based on the application name.
// The number of application data files to be restored varies depending on the number of backup files. The following is only an example.
await g_session.getFileHandle({
bundleName: restoreApps[0],
......@@ -240,11 +240,11 @@ When all the data of the application is ready, the service starts to restore the
## Installing the Application During Data Restoration
You can enable the application to be installed before application data restoration. To achieve this purpose, the value of **needToInstall** in **bundleInfos** in the [capability file](#obtaining-the-capability-file) must be **true**.
If the application has not been installed, you can install the application and then restore the application data. To achieve this purpose, the value of **needToInstall** in **bundleInfos** in the [capability file](#obtaining-capability-files) must be **true**.
> **NOTE**
> - [Application data backup](#backing-up-application-data) does not support backup of the application installation package. Therefore, you need to obtain the application installation package.
> - To obtain the file handle of the application installation package, call [getFileHandle()](../reference/apis/js-apis-file-backup.md#getfilehandle) with **FileMeta.uri** set to **/data/storage/el2/restore/bundle.hap**. The file handle of the application installation package is returned through the **onFileReady()** callback registered when the instance is created. The returned **File.uri** is **data/storage/el2/restore/bundle.hap**.
> - To obtain the file handle of an application installation package, call [getFileHandle()](../reference/apis/js-apis-file-backup.md#getfilehandle) with **FileMeta.uri** set to **/data/storage/el2/restore/bundle.hap**. The file handle of the application installation package is returned through the **onFileReady()** callback registered when the instance is created. The returned **File.uri** is **data/storage/el2/restore/bundle.hap**.
**Example**
......@@ -277,7 +277,7 @@ You can enable the application to be installed before application data restorati
}
fs.copyFileSync(bundlePath, file.fd);
fs.closeSync(file.fd);
// After the data is transferred, notify the server that the file is ready.
// After the data is transferred, notify the server that the files are ready.
publishFile(file);
console.info('onFileReady success');
},
......
......@@ -4,8 +4,8 @@ Application files are files of an application, including the application's insta
- The data used and saved by an application is stored in files, key-value (KV) pairs, and databases in a dedicated directory on a device. This directory is called application file directory, and the files in the directory are application files.
- The directories visible to an application include the application file directory and a directory containing the minimum system files required for the running of the application. These two directories constitute an [application sandbox directory](app-sandbox-directory.md). That means, the application file directory is a subset of the application sandbox directory.
- The directories visible to an application include the application file directory and a directory containing the minimum system files required for the running of the application. These two directories constitute an [application sandbox directory](app-sandbox-directory.md). That is, the application file directory is a subset of the application sandbox directory.
- The system files and directories are read-only for the application. The application can only save files to sub-directories in the [application file directory](app-sandbox-directory.md#application-file-directory-and-application-file-path) based on certain rules.
The following topics describe the application sandbox, application file directories, and how to access, manage, and share application files.
The following topics describe the application sandbox, application file directories, and how to access, manage, and share application files.
\ No newline at end of file
# Uploading and Downloading an Application File
This topic describes how to upload an application file to a network server and download a network resource file from a network server to a local application directory.
This topic describes how to enable an application to upload an application file to a network server and download a network resource file from a network server to a local application directory.
## Uploading an Application File
......@@ -10,7 +10,7 @@ You can use [ohos.request](../reference/apis/js-apis-request.md) **uploadFile()*
>
> Currently, only the files in the **cache/** directories (**cacheDir**) can be uploaded.
>
> <br>The **ohos.permission.INTERNET** permission is required for using **ohos.request**. For details about how to apply for a permission, see [Applying for Permissions](../security/accesstoken-guidelines.md).
> The **ohos.permission.INTERNET** permission is required for using **ohos.request**. For details about how to apply for a permission, see [Applying for Permissions](../security/accesstoken-guidelines.md).
The following example demonstrates how to upload a file in the **cache** directory of an application to a network server.
......@@ -62,13 +62,13 @@ try {
## Downloading a Network Resource File to the Application File Directory
You can use [ohos.request](../reference/apis/js-apis-request.md) **downloadFile()** to download network resource files to a local application directory. You can use the ([ohos.file.fs](../reference/apis/js-apis-file-fs.md) APIs to access the downloaded files. For details, see [Accessing Application Files](app-file-access.md). The system service proxy implements the download.
You can use [ohos.request](../reference/apis/js-apis-request.md) **downloadFile()** to download network resource files to a local application directory. You can use the [ohos.file.fs](../reference/apis/js-apis-file-fs.md) APIs to access the downloaded files in the same way as [accessing application files](app-file-access.md). The system service proxy implements the download.
> **NOTE**
>
> Currently, network resource files can be downloaded only to an application file directory.
>
> <br>The **ohos.permission.INTERNET** permission is required for using **ohos.request**. For details about how to apply for a permission, see [Applying for Permissions](../security/accesstoken-guidelines.md).
> The **ohos.permission.INTERNET** permission is required for using **ohos.request**. For details about how to apply for a permission, see [Applying for Permissions](../security/accesstoken-guidelines.md).
The following example demonstrates how to download a network resource file to a local application file directory.
......
......@@ -10,22 +10,22 @@ For details about the APIs, see [ohos.file.statvfs](../reference/apis/js-apis-fi
| Module| API| Description|
| -------- | -------- | -------- |
| \@ohos.file.storageStatistics | getCurrentBundleStats | Obtains the storage space of the current application, in bytes.|
| \@ohos.file.statvfs | getFreeSize | Obtains the free space of a file system, in bytes.|
| \@ohos.file.statvfs | getTotalSize | Obtains the total space of a file system, in bytes.|
| \@ohos.file.storageStatistics | getCurrentBundleStats | Obtains the storage space of the current application, in bytes.|
| \@ohos.file.statvfs | getFreeSize | Obtains the free space of a file system, in bytes.|
| \@ohos.file.statvfs | getTotalSize | Obtains the total space of a file system, in bytes.|
**Table 2** Attributes for application space statistics
| BundleStats Attribute| Description| Directory for Statistics|
| BundleStats Attribute| Description| Directory for Statistics|
| -------- | -------- | -------- |
| appSize | Size of the application installation files, in bytes.| Application installation file directory:<br>**/data/storage/el1/bundle **|
| cacheSize | Size of the application cache files, in bytes.| Application cache file directories:<br>**/data/storage/el1/base/cache**<br>**/data/storage/el1/base/haps/entry/cache**<br>**/data/storage/el2/base/cache**<br>**/data/storage/el2/base/haps/entry/cache **|
| dataSize | Size of the application files (excluding the application installation files and cache files), in bytes.| The application files include local files, distributed files, and database files.<br>- Local application file directories (parent directories of the **cache** directories):<br>**/data/storage/el1/base**<br>**/data/storage/el2/base**<br>- Distributed application directory:<br>/data/storage/el2/distributedfiles<br>- Database directories:<br>**/data/storage/el1/database**<br>**/data/storage/el2/database **|
| appSize | Size of the application installation files, in bytes.| /data/storage/el1/bundle |
| cacheSize | Size of the application cache files, in bytes.| /data/storage/el1/base/cache<br>/data/storage/el1/base/haps/entry/cache<br>/data/storage/el2/base/cache<br>/data/storage/el2/base/haps/entry/cache |
| dataSize | Size of the application files (excluding the application installation files and cache files), in bytes.| The application files include local files, distributed files, and database files.<br>- Local application file directories (parent directories of the **cache** directories):<br>**/data/storage/el1/base**<br>**/data/storage/el2/base**<br>- Distributed application directory: **/data/storage/el2/distributedfiles**<br>- Database directories:<br>**/data/storage/el1/database**<br>**/data/storage/el2/database** |
## Development Example
- Obtain the free space of **/data** of the file system.
```ts
import statvfs from '@ohos.file.statvfs';
......@@ -40,7 +40,7 @@ For details about the APIs, see [ohos.file.statvfs](../reference/apis/js-apis-fi
```
- Obtain the space occupied by the current application.
```ts
import storageStatistics from "@ohos.file.storageStatistics";
......
# Application Sandbox Directory
The application sandbox is an isolation mechanism to prevent data from being accessed through path traversal. This mechanism allows only the application sandbox directory visible to an application.
The application sandbox is an isolation mechanism used to prevent malicious data access through path traversal. With this mechanism, only the application sandbox directory is visible to an application.
- The system maps a dedicated application sandbox directory in the internal storage space for each application. The directory is a collection of the [application file directory](app-file-overview.md) and a directory containing the minimum system files required during application's runtime.
- The system has a dedicated application sandbox directory in the internal storage to map the directory of each application. The application sandbox directory holds [application files](app-file-overview.md) and the minimum system files required for running of the application.
- The application sandbox specifies the minimum range of data visible to each application. In the application sandbox directory, an application can access only its own application files and the system files required for its running. The application cannot access files of other applications. The security of application files is protected in this way.
- The application sandbox specifies the minimum data range visible to each application. In the application sandbox directory, an application can access only its own application files and the system files required for its running. The application cannot access files of other applications. This ensures application file security.
- In each application sandbox directory, the application can save and process its own application files in the [application file directory](app-file-overview.md), and can only read the system files and directories. The application can access [user files](user-file-overview.md) by using specific APIs only with authorization from the user.
- In each application sandbox directory, the application can save and process its application files in the [application file directory](app-file-overview.md), and can only read the system files and directories. To access [user files](user-file-overview.md), the application need to call specific APIs and have authorization from the user.
The following figure illustrates the file access scope and modes for an application in an application sandbox.
The following figure illustrates the file access mechanism in an application sandbox.
**Figure 1** File access mechanism in an application sandbox
**Figure 1** File access in an application sandbox
![Application sandbox file access relationship](figures/application-sandbox-file-access-relationship.png)
## Application Sandbox Directory and Application Sandbox Path
With the application sandbox mechanism, an application cannot learn the location and existence of other applications' directories and user file directories. In addition, all the application directories visible to an application are isolated by permission and namespace to form an independent directory view and shield the real (physical) paths.
With the application sandbox mechanism, an application is not aware of the existence and location of other applications' directories and user file directories. Even the application directories visible to an application are isolated by permission and namespace to form an independent directory view and shield the real (physical) paths.
- As shown in the following figure, the sandbox mechanism minimizes the number of directories and files visible to a common application (third-party application). The directories and file paths visible to a common application are different from those visible to a system process. The path of a file or folder in the application sandbox directory visible to a common application is called the application sandbox path.
- As shown in the following figure, the sandbox mechanism minimizes the number of directories and files visible to a common application (third-party application). In addition, the directories and file paths visible to a common application are different from those visible to a system process. The path of a file or folder in the application sandbox directory visible to a common application is called the application sandbox path.
- You can view the real application paths (the directory view visible to a system process) in the HDC shell environment. For details about the mappings between the application sandbox paths and real application paths, see [Mappings Between Application Sandbox Paths and Physical Paths](send-file-to-app-sandbox.md#mappings-between-application-sandbox-paths-and-physical-paths).
- The application sandbox paths and physical paths are not in one-to-one mappings. The application sandbox paths are always less than the physical paths. You may not obtain the application sandbox path based on a physical path in certain cases, but you can obtain the physical path based on an application sandbox path.
**Figure 2** Different directory views to processes and applications
**Figure 2** Different directory views to processes and applications
![Application sandbox path](figures/application-sandbox-path.png)
## Application File Directory and Application File Path
......@@ -32,31 +34,33 @@ The application sandbox directory includes application file directories and syst
The system file directories visible to an application are preset by OpenHarmony.
The following figure shows the application file directories. The path of a file or a folder in the application file directory is called the application file path. The file paths in the application file directory have different attributes and characteristics.
The following figure shows the application file directories. The path of a file or a folder in the application file directory is called the application file path. The sub-directories in the application file directory have different attributes.
**Figure 3** Application file directory structure
**Figure 3** Application file directory structure
![Application file directory structure](figures/application-file-directory-structure.png)
1. Level 1 directory **data/**: indicates the application file directory.
1. Level 1 directory **data/** indicates the application file directory.
2. Level 2 directory **storage/**: indicates a directory for persistent files of the application.
2. Level 2 directory **storage/** indicates a directory for persistent files of the application.
3. Level 3 directories **el1/** and **el2/**: indicate directories for files of different encryption levels (els).
3. Level 3 directories **el1/** and **el2/** indicate directories for files of different encryption levels (els).
- **el1**: directory for the data that can be accessed once the device starts. This directory contains device-focused files.
- **el2**: directory for the data that can be accessed only after at lease one successful unlocking operation (by PIN, fingerprint, or facial authentication, or password-free sign-in) upon the start of the device. This directory contains user-focused files.<br>
Unless otherwise required, application data is placed in the **el2** directory for security purposes. However, the data that needs to be accessed before the screen is unlocked (such as the clock, alarm, and wallpaper data) can be placed in the **el1** directory. For details about how to switch to and modify the **el** directories, see [Obtaining and Modifying el Directories](../application-models/application-context-stage.md#obtaining-and-modifying-encryption-levels).
- **el2**: directory for the data that can be accessed only after at lease one successful unlock operation (by PIN, fingerprint, or facial authentication, or password-free sign-in) upon the start of the device. This directory contains user-focused files.
Unless otherwise required, application data is placed in the **el2** directory for security purposes. However, the data that needs to be accessed before the screen is unlocked (such as the clock, alarm, and wallpaper data) can be placed in the **el1** directory. For details about the operations on **el** directories, see [Obtaining and Modifying el Directories](../application-models/application-context-stage.md#obtaining-and-modifying-encryption-levels).
4. Level 4 and level 5 directories:
The application's global data is stored in the **files**, **cache**, **preferences**, **temp**, and **distributedfiles** folders in **base**. You can use **ApplicationContext** to obtain the application file paths of these folders.
You can use **UIAbilityContext**, **AbilityStageContext**, and **ExtensionContext** to obtain application file paths related to the OpenHarmony Ability Package (HAP). When the HAP is uninstalled, the files stored in these directories are automatically deleted, without affecting the files in app-level directories. An application in the development state contains one or more HAPs. For details, see [Application Package Structure in Stage Mode](../quick-start/application-package-structure-stage.md).
You can use **UIAbilityContext**, **AbilityStageContext**, and **ExtensionContext** to obtain application file paths related to the OpenHarmony Ability Package (HAP). When the HAP is uninstalled, the files stored in these directories are automatically deleted, without affecting the files in app-level directories. An application in the development state has one or more HAPs. For details, see [Application Package Structure in Stage Mode](../quick-start/application-package-structure-stage.md).
For details about how to obtain the context and application file paths, see [Context (Stage Model)](../application-models/application-context-stage.md).
> **NOTE**
>
> - Do not directly use file paths made up by level 1 to level 4 directory names. Incompatibility problems may occur if the directory names are changed in later versions.
> - Use **Context** to obtain application file paths, which include but are not limited to the directories highlighted in green in **Figure 3**.
> - Do not use file paths made up by level 1 to level 4 directory names. Incompatibility problems may occur if the directory names are changed in later versions.
> - Use **Context** to obtain the application file paths, including but are not limited to the directories highlighted in green in **Figure 3**.
The following table describes the application file paths and lifecycle.
......@@ -64,7 +68,7 @@ The following figure shows the application file directories. The path of a file
| Folder| Context Attribute Name| Type| Description|
| -------- | -------- | -------- | -------- |
| bundle | bundleCodeDir | Installation file directory| Directory for saving the HAPs of the application after an application is installed.<br>This directory is cleared when the application is uninstalled.<br> Do not access resource files by concatenating paths. Use [@ohos.resourceManager](../reference/apis/js-apis-resource-manager.md) instead. |
| bundle | bundleCodeDir | Installation file directory| Directory for saving the HAPs after an application is installed.<br>This directory is cleared when the application is uninstalled.<br> Do not access resource files using concatenated paths. Use [@ohos.resourceManager](../reference/apis/js-apis-resource-manager.md) instead.|
| base | NA | Directory for local device files| Directory for saving the application's persistent data on the device. Subdirectories include **files/**, **cache/**, **temp/**, and **haps/**.<br>This directory is cleared when the application is uninstalled.|
| database | databaseDir | Database directory| Directory in **el1** for saving the files operated by the distributed database service.<br>This directory is cleared when the application is uninstalled.|
| distributedfiles | distributedFilesDir | Distributed file directory| Directory in **el2** for saving the application files that can be directly accessed across devices.<br>This directory is cleared when the application is uninstalled.|
......@@ -73,7 +77,7 @@ The following figure shows the application file directories. The path of a file
| preferences | preferencesDir | Preferences file directory| Directory for saving common application configuration and user preference data managed by using database APIs.<br>This directory is cleared when the application is uninstalled. For details, see [Persisting Preferences Data](../database/data-persistence-by-preferences.md).|
| temp | tempDir | Temporary file directory| Directory for saving the files generated and required during the application's runtime on the device. <br>This directory is cleared when the application exits.|
The application file paths are used in the following scenarios:
The application scenarios of the application file directories are as follows:
- Installation file directory<br>
Used to store the code resource data of the application, including the HAPs of the application, reusable library files, and plug-ins. The code stored in this directory can be dynamically loaded.
......@@ -83,9 +87,9 @@ The following figure shows the application file directories. The path of a file
Used to store the application's data used for distributed scenarios, including file sharing, file backup, and file processing across devices. The data stored in this directory enables the application to run smoothly on multiple devices.
- Application file directory<br>
Used to store private data of the application, including persistent files, images, media files, and log files. The data is stored in this directory to ensure privacy, security, and permanent validity.
- Cached application file directory<br>
- Cache application file directory<br>
Used to store cached data of the application, including offline data, cached images, database backup, and temporary files. Data stored in this directory may be automatically deleted by the system. Therefore, do not store important data in this directory.
- Preferences file directory<br>
Used to store application preferences data, including preference files and configuration files. This directory applied to storing only a small amount of data.
- Temporary file directory<br>
Used to store temporarily generated data of an application, including cached database data and images, temporary log files, downloaded application installation package files. The data stored in this directory is deleted after being used.
Used to store temporarily generated data of an application, including cached database data and images, temporary log files, downloaded application installation package. The data stored in this directory is deleted after being used.
\ No newline at end of file
# Developing a FileManager Application (for System Applications Only)
# Developing a File Manager Application (for System Applications Only)
OpenHarmony is prebuilt with the **FileManager** application. You can also develop your own **FileManager** as required.
OpenHarmony is prebuilt with the **FileManager** application. You can also develop your own file manager application as required.
## Available APIs
For details about the APIs, see [User File Access and Management](../reference/apis/js-apis-fileAccess.md).
For details about the APIs used to develop a file manager application, see [User File Access and Management](../reference/apis/js-apis-fileAccess.md).
## How to Develop
1. Configure the permissions required and import dependent modules.
1. Apply for permissions required.<br>
Apply for the **ohos.permission.FILE_ACCESS_MANAGER** and **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** permissions. For details, see [Applying for Permissions](../security/accesstoken-guidelines.md).
> **NOTE**
>
> **ohos.permission.FILE_ACCESS_MANAGER** is required for using the user file access framework APIs.
> **ohos.permission.FILE_ACCESS_MANAGER** allows your application to use the user file access framework APIs.
>
> **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** is required for querying information about file management server applications supported by the system.
> **ohos.permission.GET_BUNDLE_INFO_PRIVILEGED** allows your application to obtain information about file management server applications supported by the system.
2. Import the dependent modules.
2. Import dependent modules.
```ts
import fileAccess from '@ohos.file.fileAccess';
......@@ -26,8 +26,8 @@ For details about the APIs, see [User File Access and Management](../reference/a
The **fileAccess** module provides APIs for basic file operations, and the **fileExtensionInfo** module provides key structs for application development.
3. Query device information.
You can obtain attributes of one or all devices managed by the file management server in the current system. You can also filter devices as required.
3. Query device information.<br>
You can obtain attributes of the devices managed by one or all file management servers in the system. You can also filter devices as required.
In the user file access framework, **RootInfo** indicates the attribute information of a device. For example, obtain **RootInfo** of all devices.
......@@ -68,19 +68,19 @@ For details about the APIs, see [User File Access and Management](../reference/a
```
4. View directories.
In the user file access framework, **FileInfo** indicates basic information about a file (directory). You can use **listfile()** to traverse all files (directories) of the next level to obtain a **FileIterator** object or use **scanfile()** to filter the specified directories and obtain the **FileIterator** object that meets the conditions.
In the user file access framework, **FileInfo** indicates basic information about a file (directory). You can use **listfile()** to obtain a **FileIterator** object that traverses all files (directories) of the next level or use **scanfile()** to obtain a **FileIterator** object that meets the specified conditions.
Currently, **listfile()** and **scanfile()** can be called by the **RootInfo** object to traverse lower-level files or filter the entire directory tree. In addition, **listfile()** and **scanfile()** can be called by the **FileInfo** object to traverse lower-level files or filter specified directories.
Currently, **listfile()** and **scanfile()** can be called by the **RootInfo** object to traverse the next-level files or filter the entire directory tree. In addition, **listfile()** and **scanfile()** can be called by the **FileInfo** object to traverse the next-level files or filter the specified directories.
```ts
// Start from the root directory.
let rootInfo = rootinfos[0];
let fileInfos = [];
let isDone = false;
let filter = {suffix: [".txt", ".jpg", ".xlsx"]}; // Set filter criteria.
let filter = {suffix: [".txt", ".jpg", ".xlsx"]}; // Set filter criteria.
try {
let fileIterator = rootInfo.listFile(); // Traverse the root directory of rootinfos[0] and return an iterator object.
// let fileIterator = rootInfo.scanFile(filter); // Filter the file information of device rootinfos[0] that meets the specified conditions and return an iteration object.
// let fileIterator = rootInfo.scanFile(filter); // Filter device rootinfos[0] files that meet the specified conditions and return an iteration object.
if (!fileIterator) {
console.error("listFile interface returns an undefined object");
return;
......@@ -97,12 +97,12 @@ For details about the APIs, see [User File Access and Management](../reference/a
}
// Start from the specified directory.
let fileInfoDir = fileInfos[0]; // fileInfoDir indicates information about a directory.
let fileInfoDir = fileInfos[0]; // fileInfoDir indicates information about a directory.
let subFileInfos = [];
let isDone = false;
let filter = {suffix: [".txt", ".jpg", ".xlsx"]}; // Set filter criteria.
let filter = {suffix: [".txt", ".jpg", ".xlsx"]}; // Set filter criteria.
try {
let fileIterator = fileInfoDir.listFile(); // Traverse files in the specified directory and return an iterator object.
let fileIterator = fileInfoDir.listFile(); // Traverse files in the specified directory and return an iterator object.
// let fileIterator = rootInfo.scanFile(filter); // Filter the files in the specified directory and return an iterator object.
if (!fileIterator) {
console.error("listFile interface returns an undefined object");
......
# Distributed File System Overview
OpenHarmony distributed file system (hmdfs) provides cross-device file access capabilities applicable to the following scenarios:
OpenHarmony distributed file system (hmdfs) provides cross-device file access capabilities in the following scenarios:
- The user can use the editing software on one device to edit the files on another device.
- The user uses the editing software on one device to edit the files on another device.
- Music stored on a tablet can be directly viewed and played by a in-car system.
- Music stored on a tablet can be directly viewed and played by an in-car system.
- The user can use a tablet to view the photos taken by another device.
- The user uses a tablet to view the photos taken by another device.
The hmdfs provides a globally consistent access view for each device dynamically connected to a network via DSoftBus and allows you to implement high-performance read and write operations on files with low latency by using basic file system APIs.
......@@ -16,13 +16,13 @@ The hmdfs provides a globally consistent access view for each device dynamically
- distributedfile_daemon: listens for device online status, establishes links over DSoftBus, and applies data transfer policies based on the security level of the device.
- hmdfs: implements a network file system in the kernel, providing cache management, file access, metadata management, and conflict management.
- Buffer management
- After devices are connected to form a Virtual Device, hmdfs provides file access capabilities, but does not proactively transmit or copy files. Active copy is required when an application needs to save data to a local directory.
- hmdfs: implements a network file system in the kernel and provides cache management, file access, metadata management, and conflict management.
- Cache management
- After devices are connected to form a Virtual Device, the hmdfs provides file access capabilities, but does not proactively transmit or copy files. Active copy is required when an application needs to save data to a local directory.
- The hmdfs ensures close-to-open cache consistency, which allows data to flushed when a client closes a file. Then, the latest data can be read when the file is opened on any other client. The hmdfs does not ensure real-time consistency of the file content.
- If data written at the peer end has not been flushed to the local end in a timely manner due to network problems, the file system flushes the data to the local end upon the next network access. However, if the data has been modified on the remote end, only the latest data can be flushed.
- If data written at the remote end has not been flushed to the local end in a timely manner due to network problems, the file system flushes the data to the local end upon the next network access. However, if the data has been modified on the remote end, only the latest data can be flushed.
- File access
- OpenHarmony provides the same interface, [ohos.file.fs](../reference/apis/js-apis-file-fs.md), for accessing files in the local and distributed file systems.
- OpenHarmony provides the unified [ohos.file.fs](../reference/apis/js-apis-file-fs.md) for accessing files in the local and distributed file systems.
- The files in the local file system are accessed in overlay mode.
- The files on another device are accessed over a synchronous network.
> **NOTE**
......@@ -31,9 +31,9 @@ The hmdfs provides a globally consistent access view for each device dynamically
- Metadata management
- In distributed networking, when a file is created, deleted, or modified on a client, the latest file can be viewed on another client. The speed varies depending on the network status.
- If a device goes offline, its data is no longer visible to other devices. However, due to the delay in sensing the device offline, the files of some offline devices may also be visible to other devices. Therefore, you need to consider the network delay in application development.
- Conflict Handling
- If a file on the local end and a file on the remote end have the same name, the file on the remote end will be renamed.
- If multiple remote devices have files of the same name, the name of the file with the smallest device access ID is retained and the files on other devices will be renamed.
- In the networking scenario, the directory tree has remote files. If "duplicate file name" is displayed when a file is created,
- the conflict file is renamed "_conflict_dev_ID". The ID automatically increases from 1.
- If a local directory has the same name as a remote directory, "_remote_directory" will be added to the end of the peer directory.
- Conflict management
- If a file name conflict occurs on the local and remote devices, the file on the remote device is renamed.
- If a file name conflict occurs between multiple remote devices, the name of the file with the smallest device access ID is retained and the files on other devices are renamed.
- If the directory tree already has remote files in networking scenario, a file with duplicate file name cannot be created successfully.
- The conflict files are renamed in "_conflict_dev_ID" format. The IDs automatically increment from 1.
- If a local directory and a remote directory have the same name, it does not yield a conflict. If the two directories have files with the same name, "_remote_directory" is added to the end of the remote directory.
# Accessing Files Across Devices
# Access Files Across Devices
The distributed file system provides cross-device file access capabilities for applications. For the same application installed on multiple devices, you can implement read and write of the files in the application's distributed directory (**/data/storage/el2/distributedfiles/**) across devices by using [ohos.file.fs](app-file-access.md). For example, device A and device B are installed with the same application. After device A and device B are connected to form a Virtual Device, the application on device A can access the files of the same application on Device B. What you need to do is place the files to the distributed directory.
The distributed file system provides cross-device file access capabilities for applications. For the same application installed on multiple devices that form a Super Device, you can use [ohos.file.fs](app-file-access.md) APIs to implement read and write of the files in the application's distributed directory (**/data/storage/el2/distributedfiles/**).
## How to Develop
For example, device A and device B are installed with the same application. After device A and device B are connected to form a Super Device, the application on device A can access the files in the distributed directory of the same application on Device B.
1. Complete distributed networking for the devices.
Connect the devices to a LAN, and complete authentication of the devices. The devices must have the same account number.
## How to Develop
1. Connect the devices to form a Super Device.
Connect the devices to a LAN, and complete authentication of the devices. The devices must have the same account number.
2. Implement cross-device access to the files of the same application.
Place the files in the **distributedfiles/** directory of the application sandbox to implement access from difference devices.
For example, create a test file in the **distributedfiles/** directory on device A and write data to the file. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
For example, create a file in the **distributedfiles/** directory on device A and write data to the file. For details about how to obtain the application context, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
```ts
import fs from '@ohos.file.fs';
......
......@@ -2,23 +2,23 @@
The data in an operating system (OS) can be classified into the following types based on the data structure:
- Structured data: data that can be defined in a unified data model. The structured data is generally stored in a database. In application development, the management of structured data is implemented by the [data management module](../database/data-mgmt-overview.md).
- Structured data: data that can be defined in a unified data model and is generally stored in a database. In OpenHarmony application development, the management of structured data is implemented by the [data management module](../database/data-mgmt-overview.md).
- Unstructured data: data that does not conform to any predefined data structure or model and cannot be easily presented in two-dimensional database tables. Unstructured data includes files in a variety of formats, such as documents, images, videos, and audio clips. In application development, the management of unstructured data is implemented by the file management module, which will be elaborated in this document.
- Unstructured data: data that does not conform to any predefined data structure or model and cannot be easily presented in two-dimensional database tables. Unstructured data includes files in a variety of formats, such as documents, images, videos, and audio clips. In OpenHarmony application development, the management of unstructured data is implemented by the file management module, which will be elaborated in this document.
In the file management module, the files can be classified into the following types based on the file owner:
- [Application files](app-file-overview.md): files of an application, including the application's installation files, resource files, and cached files.
- [Application files](app-file-overview.md): files of an application, including the installation files, resource files, and cache files of the application.
- [User files](user-file-overview.md): files of a user who logs in to the device, including the user's images, video and audio clips, and documents.
- [User files](user-file-overview.md): files of a user who has logged in to the device. User files include the user's images, video and audio clips, and documents.
- System files: files irrelevant to applications and users, including public libraries, device files, and system resource files. System files do not need to be managed by developers and are not described in this document.
- System files: files irrelevant to applications and users. System files include public libraries, device files, and system resource files. The system files do not need to be managed by developers and are not described in this document.
The file systems can be classified into the following types based on the file storage location (data source location):
- Local file system: provides capabilities for accessing the files stored on a local device or its external storage devices (such as USB flash drives and removable hard drives). The local file system is the most basic file system and is not described in this document.
- Local file system: allows access to the files stored on a device and its external storage devices (such as USB flash drives and removable hard drives). The local file system is the most basic file system and is not described in this document.
- [Distributed file system](distributed-fs-overview.md): provides capabilities for accessing files across devices, which are connected through a computer network.
- [Distributed file system](distributed-fs-overview.md): allows access to files across devices, which include not only the local device and its external storage devices, but also the devices connected over a computer network.
**Figure 1** Files in an OS
......
# Managing External Storage Devices (for System Applications Only)
External storage devices are pluggable. OpenHarmony provides the functions of listening for the device insertion and removal events and mounting/unmounting an external storage device.
Because external storage devices are pluggable, OpenHarmony provides functions for listening for the device insertion/removal events and mounting/unmounting an external storage device.
External storage devices are managed by the StorageManager and StorageDaemon services. StorageDaemon implements the underlying listening and mount/unmount functions. StorageManager provides status change notifications, query, and management capabilities for system applications.
External storage devices are managed by the StorageManager and StorageDaemon services. StorageDaemon implements underlying listening and mount/unmount functions. StorageManager provides status change notifications and query and management of external storage devices for system applications.
**Figure 1** External storage device management
......@@ -10,12 +10,12 @@ External storage devices are managed by the StorageManager and StorageDaemon ser
- When an external storage device is inserted, the StorageDaemon process obtains an insertion event over netlink and creates a disk device and volume. The created volume is in the **UNMOUNTED** state.
- Then, the StorageDaemon process checks the volume. During the check process, the volume is in the **CHECKING** state.
- Then, the StorageDaemon process checks the volume. The volume transits to the **CHECKING** state.
- The StorageDaemon process mounts the volume if the check is successful. If the mount operation is successful, the volume state changes to **MOUNTED** and StorageManager is instructed to send the COMMON_EVENT_VOLUME_MOUNTED broadcast.
- If the check fails, the volume state changes to **UNMOUNTED**.
- For a volume in the **MOUNTED** state:
- If the device is directly removed, the volume information will be deleted and COMMON_EVENT_VOLUME_BAD_REMOVAL is broadcast.
- If the device is directly removed, the volume information is deleted and COMMON_EVENT_VOLUME_BAD_REMOVAL is broadcast.
- If the user chooses **Eject device**, the volume state changes to **EJECTING** and the COMMON_EVENT_VOLUME_EJECT is broadcast. After StorageDaemon unmounts the volume, the volume state changes to **UNMOUNTED** and COMMON_EVENT_VOLUME_UNMOUNTED is broadcast.
- For a volume in the **UNMOUNTED** state, removing the device will delete the volume information and broadcast COMMON_EVENT_VOLUME_REMOVED.
......@@ -38,13 +38,13 @@ The following table describes the broadcast related parameters.
## How to Develop
Subscribe to broadcast events to notify the insertion and removal of external storage devices. The volumes can be queried and managed based on the volume information obtained from the broadcast.
You can subscribe to broadcast events to observe the insertion and removal of external storage devices, and query or manage volumes based on the volume information obtained from the broadcast.
1. Apply for permissions.
1. Apply for permissions.<br>
Apply for the **ohos.permission.STORAGE_MANAGER** permission for subscribing to volume broadcast events. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file).
2. Subscribe to broadcast events.
Subscribe to the following events:
2. Subscribe to broadcast events.<br>
You can subscribe to the following events:
- "usual.event.data.VOLUME_REMOVED": The device is removed.
- "usual.event.data.VOLUME_UNMOUNTED": The volume is unmounted.
......@@ -68,7 +68,7 @@ Subscribe to broadcast events to notify the insertion and removal of external st
let subscriber = await CommonEvent.createSubscriber(subscribeInfo);
```
3. Obtain the volume information from the broadcast.
3. Obtain volume information from the broadcast.
```ts
CommonEvent.subscribe(subscriber, function (err, data) {
......
# Media Asset (Image, Video, and Album) Change Notification Management
# Managing Media Asset Change Notifications
The **photoAccessHelper** module provides APIs for listening for media asset changes.
The **photoAccessHelper** module provides APIs for listening for media asset (image, video, and album) changes.
> **NOTE**
>
> Before you start, refer to [photoAccessHelper Overview](photoAccessHelper-overview.md) to learn how to obtain a **photoAccessHelper** instance and apply for permissions required.
> By default, the **photoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **photoAccessHelper** instance is not added, an error indicating that **photoAccessHelper** is not defined is reported.
> Before you start, you need to obtain a **PhotoAccessHelper** instance and apply for required permissions. For details, see [photoAccessHelper Overview](photoAccessHelper-overview.md).<br>
> By default, the **PhotoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **PhotoAccessHelper** instance is not added, an error indicating that **photoAccessHelper** is not defined is reported.
The APIs related to media asset change notifications can be called asynchronously only in callback mode. This topic describes how to use some APIs. For more information about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
Unless otherwise specified, all the media assets to be obtained in this document exist in the database. If no media asset is obtained when the sample code is executed, check whether the media assets exist in the database.
......@@ -16,14 +16,14 @@ Use [registerChange](../reference/apis/js-apis-photoAccessHelper.md#registerchan
### Registering a Listener for a File Asset
Registers a listener for the specified file asset. When the observed file asset changes, the listener callback will be invoked to return the change.
Register a listener for the specified file asset. When the observed file asset changes, the listener callback will be invoked to return the change.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Register a listener for an image. When the image is favorited, the listener callback will be invoked.
Example: Listener for changes of an image. When the image is favorited, the listener callback will be invoked.
**How to Develop**
......@@ -60,18 +60,18 @@ try {
### Registering a Listener for an Album
Registers a listener for an album. When the observed album changes, the listener callback will be invoked to return the change.
Register a listener for an album. When the observed album changes, the listener callback will be invoked to return the change.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Register a listener for a user album. When the album is renamed, the listener callback will be invoked.
Example: Listener for a user album. When the album is renamed, the listener callback will be invoked.
**How to Develop**
1. [Obtain the user album](photoAccessHelper-userAlbum-guidelines.md#obtaining-a-use-album].
1. [Obtain a user album](photoAccessHelper-userAlbum-guidelines.md#obtaining-a-user-album).
2. Register a listener for the user album.
3. Rename the user album.
......@@ -106,24 +106,30 @@ try {
## Fuzzy Listening
You can set **forChildUris** to **true** to register fuzzy listening. When **uri** is an album URI, the value **true** of **forChildUris** listens for the changes of the files in the album, and the value **false** listens for only the changes of the album itself. <br>If **uri** is the URI of a **fileAsset**, there is no difference between **true** and **false** for **forChildUris**.<br>If **uri** is **DefaultChangeUri**, **forChildUris** must be set to **true**. If **forChildUris** is **false**, the URI cannot be found and no message can be received.
You can set **forChildUris** to **true** to enable fuzzy listening.
### Registering a Listener for All FileAssets
If **uri** is an album URI, the value **true** of **forChildUris** enables listening for the changes of the files in the album, and the value **false** enables listening for only the changes of the album itself.
Register listening for all FileAssets. When an observed FileAsset changes, the listener callback will be invoked.
If **uri** is the URI of a file asset, there is no difference between **true** and **false** for **forChildUris**.
If **uri** is **DefaultChangeUri**, **forChildUris** must be set to **true**. If **forChildUris** is **false**, the URI cannot be found and no notification can be received.
### Registering a Listener for All File Assets
Register listening for all file assets. When an observed file asset changes, the listener callback will be invoked.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Register a listener for all FileAssets. When an observed FileAsset is favorited, the listener callback will be invoked.
Example: Register a listener for all file assets. When an observed file asset is favorited, the listener callback will be invoked.
**How to Develop**
1. Register a listener for all FileAssets.
1. Register a listener for all file assets.
2. [Obtain a media asset](photoAccessHelper-resource-guidelines.md#obtaining-the-specified-media-assets).
3. Add the media asset obtained to **Favorites**.
3. Add the obtained media asset to **Favorites**.
```ts
import dataSharePredicates from '@ohos.data.dataSharePredicates';
......@@ -150,22 +156,22 @@ try {
}
```
## Unregistering the Listening for a URI
## Unregistering Listening for a URI
Use [unRegisterChange](../reference/apis/js-apis-photoAccessHelper.md#unregisterchange) to unregister the listening for the specified URI. Multiple listeners can be registered for a URI. If multiple listener callbacks exist, you can unregister a listener callback registered. If callback is not specified, all listeners of the URI will be unregistered.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Unregister the listening for an image. After that, the corresponding listener callback is not triggered when the image favorites status is changed.
Example: Unregister listening for an image. After that, the unregistered listener callback will not be invoked when the image favorite status is changed.
**How to Develop**
1. [Obtain a media asset](photoAccessHelper-resource-guidelines.md#obtaining-the-specified-media-assets).
2. Unregister the listening for the URI of the media asset obtained.
3. Add the media asset obtained to **Favorites**.
2. Unregister listening for the URI of the media asset obtained.
3. Add the obtained media asset to **Favorites**.
```ts
import dataSharePredicates from '@ohos.data.dataSharePredicates';
......
# PhotoAccessHelper Overview
**PhotoAccessHelper** provides album management capabilities, including creating and accessing an album and accessing and modifying media data in albums. You can use the APIs provided by **PhotoAccessHelper** to manage:
**PhotoAccessHelper** provides album management capabilities, including creating and accessing an album and accessing and modifying media data in albums. You can use the APIs provided by **PhotoAccessHelper** to:
- [Media assets (images and videos)](photoAccessHelper-resource-guidelines.md), including:
- [Manage media assets (images and videos)](photoAccessHelper-resource-guidelines.md), including:
- Obtaining the specified media assets.
- Obtaining an image or video thumbnail.
- Obtaining image and video thumbnails.
- Creating a media asset.
- Renaming a media asset.
- Moving a media asset to the trash.
- [User Albums](photoAccessHelper-userAlbum-guidelines.md), including:
- [Manage user albums](photoAccessHelper-userAlbum-guidelines.md), including:
- Creating a user album.
- Obtaining a user album.
- Renaming a user album.
......@@ -16,39 +16,38 @@
- Obtaining images and videos from a user album.
- Removing images and videos from a user album.
- Deleting a user album.
- [System albums](photoAccessHelper-systemAlbum-guidelines.md), including:
- [Manage system albums](photoAccessHelper-systemAlbum-guidelines.md), including:
- Favorites
- Video album
- Screenshot album
- [Media asset (image, video, and album) change notifications](photoAccessHelper-notify-guidelines.md), including:
- Registering listening for a specified URI.
- Unregistering the listening for a specified URI.
- Videos
- Screenshots
- [Manage media asset (image, video, and album) change notifications](photoAccessHelper-notify-guidelines.md), including:
- Registering listening for the specified URI.
- Unregistering the listening for the specified URI.
> **NOTE**
>
> The **PhotoAccessHelper** development guides apply only to API version 10 based on the stage model.
> This development guide applies only to API version 10 based on the stage model.
An application needs to obtain a **photoAccessHelper** instance before accessing and modifying the media data in an album. User personal data is involved in the **photoAccessHelper** module. Therefore, the application needs to apply for the related read and write permissions. Unless otherwise specified, the APIs of the **photoAccessHelper** module apply to **pages/index.ets** of the project or other customized .ets files by default.
An application needs to obtain a **PhotoAccessHelper** instance before accessing and modifying the media data in an album. User personal data is involved in the **photoAccessHelper** module. Therefore, the application needs to apply for the related read and write permissions. Unless otherwise specified, the APIs of the **photoAccessHelper** module are used in **pages/index.ets** of the project or other customized .ets files by default.
Before using the **PhotoAccessHelper** APIs, you need to:
- [Obtain a **photoAccessHelper** instance.](#obtaining-a-photoaccesshelper-instance)
- [Apply for permissions.](#applying-for-permissions)
- [Obtain a **PhotoAccessHelper** instance](#obtaining-a-photoaccesshelper-instance).
- [Apply for permissions](#applying-for-permissions).
## Obtaining a photoAccessHelper Instance
## Obtaining a PhotoAccessHelper Instance
The application needs to call [getPhotoAccessHelper](../reference/apis/js-apis-photoAccessHelper.md#photoaccesshelpergetphotoaccesshelper) to obtain a **photoAccessHelper** instance based on the application context. The instance obtained can be used to access or modify the media data (such as image and videos) in an album.
The application needs to call [getPhotoAccessHelper](../reference/apis/js-apis-photoAccessHelper.md#photoaccesshelpergetphotoaccesshelper) to obtain a **PhotoAccessHelper** instance based on the application context. The instance obtained can be used to access or modify the media data (such as images and videos) in an album.
**How to Develop**
1. Import the **photoAccessHelper** module.
2. Use **getContext** to obtain the application context.
3. Obtain a **photoAccessHelper** instance.
3. Obtain a **PhotoAccessHelper** instance.
```ts
import photoAccessHelper from '@ohos.file.photoAccessHelper';
// The phAccessHelper instance obtained here is a global object. By default, the object obtained here is used in subsequent operations. If the code is not added, an undefined error will be reported.
// The phAccessHelper instance obtained here is a global object. By default, the object obtained here is used in subsequent operations in this document. If an undefined error is reported, add the code snippet here.
const context = getContext(this);
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
```
......@@ -59,16 +58,16 @@ Before applying for permission, ensure that the [basic principles for permission
| Permission | Description | Authorization Mode |
| ------------------------------ | ------------------------------------------ | ---------- |
| ohos.permission.READ_IMAGEVIDEO | Allows an app to read image and video file information from a user's external storage.| user_grant |
| ohos.permission.WRITE_IMAGEVIDEO | Allows an app to read and write image and video file information on a user's external storage.| user_grant |
| ohos.permission.READ_IMAGEVIDEO | Allows an application to read image and video file information from a user's external storage.| user_grant |
| ohos.permission.WRITE_IMAGEVIDEO | Allows an application to read and write image and video file information on a user's external storage.| user_grant |
The required permissions must be authorized by the user (user_grant). You need to add the permissions in the **module.json5** file, and use [abilityAccessCtrl.requestPermissionsFromUser](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9) to check whether the required permissions are granted by the user. If yes, the application can access the data. Otherwise, a dialog box will be displayed to request user authorization.
The required permissions must be authorized by the user (user_grant). After adding the permissions in the **module.json5** file, use [abilityAccessCtrl.requestPermissionsFromUser](../reference/apis/js-apis-abilityAccessCtrl.md#requestpermissionsfromuser9) to check whether the required permissions are granted by the user. If yes, the application can access the data. Otherwise, a dialog box will be displayed to request user authorization.
> **NOTE**<br>Even if the user has granted the permission, the permission will still be checked before an API protected by the permission is called. The permission granted status should not be persisted, because the user can revoke the permission through the system application **Settings**.
**How to Develop**
1. Declare the permissions in the **module.json5** file.<br>Add **requestPermissions** under **module** in the file, and add the required permissions. For details, see [Applying for Permissions](../security/accesstoken-guidelines.md).
1. Declare the required permissions in the **module.json5** file.<br>Add **requestPermissions** under **module** in the file, and add the required permissions. For details, see [Applying for Permissions](../security/accesstoken-guidelines.md).
```json
{
......@@ -99,7 +98,7 @@ The required permissions must be authorized by the user (user_grant). You need t
}
```
2. Call **requestPermissionsFromUser** in the **onWindowStageCreate** callback of **Ability.ts** to check for the required permissions. If the permissions are not granted, display a dialog box to request user authorization dynamically.
2. Call **requestPermissionsFromUser** in the **onWindowStageCreate** callback of **Ability.ts** to check the required permissions. If the permissions are not granted, display a dialog box to request user authorization dynamically.
```ts
import UIAbility from '@ohos.app.ability.UIAbility';
......
# Media Asset Management
# Managing Media Assets
Applications can call **photoAccessHelper** APIs to manage media assets (images and videos).
> **NOTE**
>
> Before you start, refer to [photoAccessHelper Overview](photoAccessHelper-overview.md) to learn how to obtain a **photoAccessHelper** instance and apply for permissions required.
> By default, the **photoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **photoAccessHelper** instance is not added, an error indicating that **photoAccessHelper** is not defined is reported.
> Before you start, you need to obtain a **PhotoAccessHelper** instance and apply for required permissions. For details, see [photoAccessHelper Overview](photoAccessHelper-overview.md).<br>
> By default, the **PhotoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **PhotoAccessHelper** instance is not added, an error indicating that **photoAccessHelper** is not defined is reported.
To ensure application running efficiency, most **PhotoAccessHelper** calls are asynchronous in callback or promise mode. The following code samples use promise-based APIs. For details about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
To ensure application running efficiency, most **photoAccessHelper** APIs are asynchronously implemented in callback or promise mode. The following code samples use promise-based APIs. For details about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
## Obtaining the Specified Media Assets
You can query media assets by media type, date, or album name.
You can obtain media assets by media type, date, or album name.
Use [PhotoAccessHelper.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets) with the [FetchOptions](../reference/apis/js-apis-photoAccessHelper.md#fetchoptions) object to specify search criteria. Unless otherwise specified, all the media assets to be obtained in this document exist in the database. If no media asset is obtained when the sample code is executed, check whether the media assets exist in the database.
......@@ -19,7 +19,7 @@ To obtain the object at the specified position (for example, the first, the last
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
- The [dataSharePredicates](../reference/apis/js-apis-data-dataSharePredicates.md) module is imported.
......@@ -29,7 +29,7 @@ Example: Obtain the image **test.jpg**.
**How to Develop**
Create a **FetchOptions** object and specify **test.jpg**.
1. Create a **FetchOptions** object and specify **test.jpg**.
```ts
import dataSharePredicates from '@ohos.data.dataSharePredicates';
......@@ -42,7 +42,7 @@ let fetchOptions = {
};
```
Call **PhotoAccessHelper.getAssets** to obtain image assets.
2. Call **PhotoAccessHelper.getAssets** to obtain image assets.
```ts
try {
......@@ -55,7 +55,7 @@ try {
}
```
### Obtaining an Image or Video Asset by URI
### Obtaining an Image or Video by URI
Example: Obtain the image with the file URI **file://media/Photo/1**.
......@@ -86,7 +86,7 @@ try {
### Obtaining Images or Videos by Time
Example: Obtain the media assets added from 2022-06-01 to 2023-06-01.
Example: Obtain the media assets added between 2022-06-01 and 2023-06-01.
```ts
import dataSharePredicates from '@ohos.data.dataSharePredicates';
......@@ -96,7 +96,7 @@ let startTime = Date.parse(new Date('2022-06-01').toString()) / 1000; // The val
let endTime = Date.parse(new Date('2023-06-01').toString()) / 1000; // The value of the end time is the number of seconds elapsed since the Epoch time.
let date_added = photoAccessHelper.PhotoKeys.DATE_ADDED;
predicates.between(date_added, startTime, endTime);
predicates.orderByDesc(date_added); // The query results are sorted in descending order.
predicates.orderByDesc(date_added); // Sort the obtained records in descending order.
let fetchOptions = {
fetchColumns: [date_added], // The date_added attribute is not a default option and needs to be added.
predicates: predicates
......@@ -123,7 +123,7 @@ Use [FileAsset.getThumbnail](../reference/apis/js-apis-photoAccessHelper.md#gett
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
- The [dataSharePredicates](../reference/apis/js-apis-data-dataSharePredicates.md) module is imported.
......@@ -169,10 +169,10 @@ Use [createAsset](../reference/apis/js-apis-photoAccessHelper.md#createasset) to
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.WRITE_IMAGEVIDEO** permission.
### Creating an Image or Video Asset
### Creating an Image or Video
Example: Create an image asset.
......@@ -197,15 +197,15 @@ try {
## Renaming a Media Asset
Before renaming a file, use [FetchResult](../reference/apis/js-apis-photoAccessHelper.md#fetchresult) to obtain the file.
Set the **FileAsset.displayName** attribute to modify the file name (including the file name extension) displayed.
After the modification, use [FileAsset.commitModify](../reference/apis/js-apis-photoAccessHelper.md#commitmodify) to update the modification to the database.
Before renaming a file, use [FetchResult](../reference/apis/js-apis-photoAccessHelper.md#fetchresult) to obtain the file.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.WRITE_IMAGEVIDEO** and **ohos.permission.READ_IMAGEVIDEO** permissions.
Example: Rename the first file in the obtained image assets.
......@@ -246,11 +246,11 @@ try {
You can use [deleteAssets](../reference/apis/js-apis-photoAccessHelper.md#deleteassets) to move files to the trash.
The files moved to the trash will be retained for 30 days, and deleted permanently after 30 days. Before a file is deleted permanently from the trash, the user can restore it using the system application **File Manager** or **Gallery**.
The files moved to the trash will be retained for 30 days, and deleted permanently after 30 days. Before a file is deleted permanently from the trash, the user can restore it using the system application **FileManager** or **Gallery**.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.WRITE_IMAGEVIDEO** and **ohos.permission.READ_IMAGEVIDEO** permissions.
Example: Move the first file in the result set to the trash.
......
# System Album Management
# Managing System Albums
The **photoAccessHelper** module provides APIs for managing system albums, including the **Favorites**, video album, and screenshot album.
The **photoAccessHelper** module provides APIs for managing system albums, including the **Favorites**, **Videos**, **Screenshots**.
> **NOTE**
>
> Before you start, refer to [photoAccessHelper Overview](photoAccessHelper-overview.md) to learn how to obtain a **photoAccessHelper** instance and apply for permissions required.
> By default, the **PhotoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **PhotoAccessHelper** APIs are used. If the code for obtaining the **PhotoAccessHelper** instance is not added, an error indicating that **PhotoAccessHelper** is not defined is reported.
> Before you start, you need to obtain a **PhotoAccessHelper** instance and apply for required permissions. For details, see [photoAccessHelper Overview](photoAccessHelper-overview.md).<br>
> By default, the **PhotoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **PhotoAccessHelper** instance is not added, an error indicating that **PhotoAccessHelper** is not defined is reported.
To ensure application running efficiency, most **photoAccessHelper** calls are asynchronous in callback or promise mode. The following code samples use promise-based APIs. For details about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
To ensure application running efficiency, most **photoAccessHelper** APIs are asynchronously implemented in callback or promise mode. The following code samples use promise-based APIs. For details about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
Unless otherwise specified, all the media assets to be obtained in this document exist in the database. If no media asset is obtained when the sample code is executed, check whether the media assets exist in the database.
## Favorites
The **Favorites** is a system album. When you favorite a photo or video, the photo or video is added to **Favorites**. When you favorite a photo or video, the photo or video is removed from **Favorites**.
**Favorites** is a system album. Favoriting a photo or video adds the photo or video to **Favorites**; unfavoriting a photo or video removes the photo or video from **Favorites**.
### Obtaining a Favorites Object
......@@ -20,7 +20,7 @@ Use [getAlbums](../reference/apis/js-apis-photoAccessHelper.md#getalbums) to obt
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
**How to Develop**
......@@ -41,11 +41,11 @@ try {
### Favoriting an Image or Video
Use [setFavorite](../reference/apis/js-apis-photoAccessHelper.md#setfavorite) to add images or videos to **Favorites**.
Use [setFavorite](../reference/apis/js-apis-photoAccessHelper.md#setfavorite) to add an image or video to **Favorites**.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Favorite an image.
......@@ -54,7 +54,7 @@ Example: Favorite an image.
1. [Obtain media assets](photoAccessHelper-resource-guidelines.md#obtaining-the-specified-media-assets).
2. Set **favoriteState** to **true** to favorite the image.
3. Use **FileAsset.setFavorite** to add the image to **Favorites**.
3. Call **FileAsset.setFavorite** to add the image to **Favorites**.
```ts
import dataSharePredicates from '@ohos.data.dataSharePredicates';
......@@ -83,7 +83,7 @@ try {
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
Example: Obtain an image from **Favorites**.
......@@ -121,20 +121,20 @@ try {
### Unfavoriting an Image or Video
Use [setFavorite](../reference/apis/js-apis-photoAccessHelper.md#setfavorite) to remove an image or video from **Favorites**.
Use [setFavorite](../reference/apis/js-apis-photoAccessHelper.md#setfavorite) to remove images or videos from **Favorites**.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Unfavorite an image.
**How to Develop**
1. [Obtain the image and videos in **Favorites**](#obtaining-images-and-videos-in-favorites).
1. [Obtain the images and videos in **Favorites**](#obtaining-images-and-videos-in-favorites).
2. Set **favoriteState** to **false**.
3. Use **FileAsset.setFavorite** to remove the image from **Favorites**.
3. Call **FileAsset.setFavorite** to unfavorite an image or video.
```ts
......@@ -163,9 +163,9 @@ try {
}
```
## Video Album
## Videos
The video album is a system album. The media assets of the video type in user files are automatically added to the video album.
**Videos** is a system album that holds media assets of the video type in user files.
### Obtaining a Video Album Object
......@@ -173,7 +173,7 @@ Use [getAlbums](../reference/apis/js-apis-photoAccessHelper.md#getalbums) to obt
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
**How to Develop**
......@@ -192,16 +192,16 @@ try {
}
```
### Obtaining Videos from the Video Album
### Obtaining a Video from Videos
[Obtain a video album object](#obtaining-a-video-album-object). Use [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain video assets in the video album.
[Obtain a video album object](#obtaining-a-video-album-object), and use [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain video assets in **Videos**.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
Example: Obtain a video in the video album.
Example: Obtain a video in **Videos**.
**How to Develop**
......@@ -234,17 +234,17 @@ try {
}
```
## Screenshot Album
## Screenshots
The screenshot album is a system album. The user's screenshots and screen recording files are automatically added to this album.
**Screenshots** is a system album that holds user's screenshots and screen recording files.
### Obtaining a Screenshot Album Object
Use [getAlbums](../reference/apis/js-apis-photoAccessHelper.md#getalbums) to obtain a screenshot album.
Use [getAlbums](../reference/apis/js-apis-photoAccessHelper.md#getalbums) to obtain a screenshot album object.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
**How to Develop**
......@@ -263,16 +263,16 @@ try {
}
```
### Obtaining Media Assets in the Screenshot Album
### Obtaining Media Assets in Screenshots
[Obtain a screenshot album object](#obtaining-a-screenshot-album-object), and call [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain the media assets in the album.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
Example: Obtain a media asset from the screenshot album.
Example: Obtain a media asset from **Screenshots**.
**How to Develop**
......
# User Album Management
# Managing User Albums
The **photoAccessHelper** module provides APIs for user album management, including creating or deleting a user album, adding images and videos to a user album, and deleting image and videos from a user album.
> **NOTE**
>
> Before you start, refer to [photoAccessHelper Overview](photoAccessHelper-overview.md) to learn how to obtain a **photoAccessHelper** instance and apply for permissions required.
> By default, the **photoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **photoAccessHelper** instance is not added, an error indicating that **photoAccessHelper** is not defined is reported.
> Before you start, you need to obtain a **PhotoAccessHelper** instance and apply for required permissions. For details, see [photoAccessHelper Overview](photoAccessHelper-overview.md).<br>
> By default, the **PhotoAccessHelper** instance obtained in [photoAccessHelper Overview](photoAccessHelper-overview.md) is used when **photoAccessHelper** APIs are used. If the code for obtaining the **PhotoAccessHelper** instance is not added, an error indicating that **photoAccessHelper** is not defined is reported.
To ensure application running efficiency, most **PhotoAccessHelper** calls are asynchronous in callback or promise mode. The following code samples use promise-based APIs. For details about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
To ensure application running efficiency, most **photoAccessHelper** APIs are asynchronously implemented in callback or promise mode. The following code samples use promise-based APIs. For details about the APIs, see [Album Management](../reference/apis/js-apis-photoAccessHelper.md).
Unless otherwise specified, all the media assets to be obtained in this document exist in the database. If no media asset is obtained when the sample code is executed, check whether the media assets exist in the database.
## Creating a User Album
......@@ -23,14 +23,14 @@ The album name must meet the following requirements:
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.WRITE_IMAGEVIDEO** permission.
Example: Create a user album.
**How to Develop**
1. Set the name of the album to create.
1. Set the name of the album.
2. Use **createAlbum** to create an album.
```ts
......@@ -49,10 +49,10 @@ Use [getAlbums](../reference/apis/js-apis-photoAccessHelper.md#getalbums) to obt
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** permission.
Example: Obtain a user album named **albumName**.
Example: Obtain the user album named **albumName**.
**How to Develop**
......@@ -83,17 +83,15 @@ try {
## Renaming a User Album
Modify the **Albums.albumName** attribute of the album,
Modify the **Albums.albumName** attribute of the album, and use [Album.commitModify](../reference/apis/js-apis-photoAccessHelper.md#commitmodify-2) to update the modification to the database.
and use [Album.commitModify](../reference/apis/js-apis-photoAccessHelper.md#commitmodify-2) to update the modification to the database.
Before renaming a user album, you need to obtain an album object. You can use the [FetchResult](../reference/apis/js-apis-photoAccessHelper.md#fetchresult) APIs to obtain the user album of the corresponding location.
Before renaming a user album, you need to obtain an album object. You can use the [FetchResult](../reference/apis/js-apis-photoAccessHelper.md#fetchresult) APIs to obtain the user album of the specified location.
The new user album names must also comply with the user name requirements in [Creating a User Album](#creating-a-user-album).
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Rename an album named **albumName**.
......@@ -104,7 +102,7 @@ Example: Rename an album named **albumName**.
2. Call **getAlbums** to obtain user albums.
3. Call [FetchResult.getFirstObject](../reference/apis/js-apis-photoAccessHelper.md#getfirstobject) to obtain the first user album.
4. Set a new album name.
5. Call **Album.commitModify** to update the modified album attributes to the database.
5. Call **Album.commitModify** to update the new album name to the database.
```ts
import dataSharePredicates from '@ohos.data.dataSharePredicates';
......@@ -129,16 +127,16 @@ try {
}
```
## Adding Images and Videos to a User Album
## Adding Images or Videos to a User Album
[Obtain a user album](#obtaining-a-user-album) and the array of the images or videos to be added to the album, and then call [Album.addAssets](../reference/apis/js-apis-photoAccessHelper.md#addassets) to add the images or videos to the user album.
[Obtain the user album](#obtaining-a-user-album) and the images or videos to be added to the album, and then call [Album.addAssets](../reference/apis/js-apis-photoAccessHelper.md#addassets) to add the images or videos to the user album.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Add an image to the album named **albumName**.
Example: Add an image to the album **albumName**.
**How to Develop**
......@@ -184,14 +182,14 @@ try {
## Obtaining Images and Videos in a User Album
[Obtain the user album](#obtaining-a-user-album) object, and call [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain the media assets in the user album.
[Obtain the user album](#obtaining-a-user-album), and call [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain the media assets in the user album.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Obtain an image in a user album named **albumName**.
Example: Obtain an image in the user album **albumName**.
**How to Develop**
......@@ -235,13 +233,13 @@ try {
## Removing Images and Videos from a User Album
[Obtain the user album](#obtaining-a-user-album) object, and call [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain the media assets in the user album.
[Obtain the user album](#obtaining-a-user-album), and call [Album.getAssets](../reference/apis/js-apis-photoAccessHelper.md#getassets-2) to obtain the media assets in the user album.
Use [Album.removeAssets](../reference/apis/js-apis-photoAccessHelper.md#removeassets) to remove the specified images.
Use [Album.removeAssets](../reference/apis/js-apis-photoAccessHelper.md#removeassets) to remove the specified media assets.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Remove an image from the album named **albumName**.
......@@ -290,11 +288,11 @@ try {
## Deleting a User Album
[Obtain the user album](#obtaining-a-user-album) object, and call [deleteAlbums](../reference/apis/js-apis-photoAccessHelper.md#deletealbums) to delete the user album.
[Obtain the user album](##obtaining-a-user-album), and call [deleteAlbums](../reference/apis/js-apis-photoAccessHelper.md#deletealbums) to delete the user album.
**Prerequisites**
- A **photoAccessHelper** instance is obtained.
- A **PhotoAccessHelper** instance is obtained.
- The application has the **ohos.permission.READ_IMAGEVIDEO** and **ohos.permission.WRITE_IMAGEVIDEO** permissions.
Example: Delete a user album named **albumName**.
......
......@@ -2,9 +2,9 @@
When a user needs to download a file from the network to a local directory or save a user file into another directory, use **FilePicker** to save the file.
The operations for saving images, audio or video clips, and documents are similar. Call **save()** of the corresponding picker instance and pass in **saveOptions**. No permission is required if **FilePicker** is used to access files.
The operations for saving images, audio or video clips, and documents are similar. Call **save()** of the corresponding picker instance and pass in **saveOptions**. No permission is required if your application uses **FilePicker** to access files.
The **save()** method saves the file in the file manager, not in the Gallery.
The **save()** method saves files in the file manager, not in **Gallery**.
## Saving Images or Video Files
......@@ -53,9 +53,9 @@ For example, select an image from **Gallery** and save it to the file manager.
}
```
3. Create a **photoViewPicker** instance and call [save()](../reference/apis/js-apis-file-picker.md#save) to open the **FilePicker** page to save the image. After the user selects the target folder, the file saving operation is complete. After the image is saved successfully, the URI of the saved image is returned.
3. Create a **photoViewPicker** instance and call [save()](../reference/apis/js-apis-file-picker.md#save) to open the **FilePicker** page to save the image. After the user selects the destination folder, the image is saved and the URI of the saved image is returned.
The permission on the URI returned by **save()** is read/write. Further operations can be performed based on the URI in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
The permission on the URI returned by **save()** is read/write. Further operations on the file can be performed based on the URI in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
```ts
let uri:string;
......@@ -81,9 +81,9 @@ For example, select an image from **Gallery** and save it to the file manager.
}
```
4. Use a button to trigger invocation of other functions. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_WRITE**.
4. After the UI is returned from the **FilePicker** page, use a button to trigger API calling. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_WRITE**.
Use [fs.write](../reference/apis/js-apis-file-fs.md#fswrite) to edit and modify the file based on the FD. After the modification is complete, close the FD.
Then, use [fs.write](../reference/apis/js-apis-file-fs.md#fswrite) to modify the file based on the FD, and close the FD after the modification is complete.
```ts
async writeOnly(uri) {
......@@ -100,7 +100,7 @@ For example, select an image from **Gallery** and save it to the file manager.
## Saving Documents
1. Import the **picker** module and **fs** module.
1. Import the **picker** and **fs** modules.
```ts
import picker from '@ohos.file.picker';
......@@ -111,12 +111,12 @@ For example, select an image from **Gallery** and save it to the file manager.
```ts
const documentSaveOptions = new picker.DocumentSaveOptions(); // Create a documentSaveOptions instance.
documentSaveOptions.newFileNames = ["DocumentViewPicker01.txt"]; // (Optional) Set the names of the documents to save.
documentSaveOptions.newFileNames = ["DocumentViewPicker01.txt"]; // (Optional) Set the name of the document to save.
```
3. Create a **documentViewPicker** instance, and call [save()](../reference/apis/js-apis-file-picker.md#save-3) to open the **FilePicker** page to save the documents. After the user selects the target folder, the file saving operation is complete. After the files are saved successfully, the URIs of the files saved are returned.
3. Create a **documentViewPicker** instance, and call [save()](../reference/apis/js-apis-file-picker.md#save-3) to open the **FilePicker** page to save the document. After the user selects the destination folder, the document is saved and the URI of the document saved is returned.
The permission on the URIs returned by **save()** is read/write. Further file operations can be performed based on the URIs in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
The permission on the URI returned by **save()** is read/write. Further operations on the file can be performed based on the URI in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
```ts
let uri = null;
......@@ -129,14 +129,14 @@ For example, select an image from **Gallery** and save it to the file manager.
})
```
4. Use a button to trigger invocation of other functions. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_WRITE**.
4. After the UI is returned from the **FilePicker** page, use a button to trigger API calling. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_WRITE**.
```ts
let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
console.info('file fd: ' + file.fd);
```
5. Use [fs.writeSync()](../reference/apis/js-apis-file-fs.md#writesync) to edit the file based on the FD, and then close the FD.
5. Use [fs.writeSync()](../reference/apis/js-apis-file-fs.md#writesync) to edit the document based on the FD, and then close the FD.
```ts
let writeLen = fs.writeSync(file.fd, 'hello, world');
......@@ -146,7 +146,7 @@ For example, select an image from **Gallery** and save it to the file manager.
## Saving Audio Files
1. Import the **picker** module and **fs** module.
1. Import the **picker** and **fs** modules.
```ts
import picker from '@ohos.file.picker';
......@@ -157,12 +157,12 @@ For example, select an image from **Gallery** and save it to the file manager.
```ts
const audioSaveOptions = new picker.AudioSaveOptions(); // Create an audioSaveOptions instance.
audioSaveOptions.newFileNames = ['AudioViewPicker01.mp3']; // (Optional) Set the names of the files to save.
audioSaveOptions.newFileNames = ['AudioViewPicker01.mp3']; // (Optional) Set the name of the audio file to save.
```
3. Create an **audioViewPicker** instance, and call [save()](../reference/apis/js-apis-file-picker.md#save-6) to open the **FilePicker** page to save the files. After the user selects the target folder, the file saving operation is complete. After the files are saved successfully, the URIs of the files saved are returned.
3. Create an **audioViewPicker** instance, and call [save()](../reference/apis/js-apis-file-picker.md#save-6) to open the **FilePicker** page to save the file. After the user selects the destination folder, the audio file is saved and the URI of the file saved is returned.
The permission on the URIs returned by **save()** is read/write. Further file operations can be performed based on the URIs in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
The permission on the URI returned by **save()** is read/write. Further operations on the file can be performed based on the URI in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
```ts
let uri = null;
......@@ -175,7 +175,7 @@ For example, select an image from **Gallery** and save it to the file manager.
})
```
4. Use a button to trigger invocation of other functions. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_WRITE**.
4. After the UI is returned from the **FilePicker** page, use a button to trigger API calling. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_WRITE**.
```ts
let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
......
# Selecting User Files
If your application needs to support share and saving of user files (such as images and videos), you can use OpenHarmony [FilePicker](../reference/apis/js-apis-file-picker.md) to implement selection and saving of user files.
If your application needs to support share and saving of user files (such as images and videos), you can use OpenHarmony [FilePicker](../reference/apis/js-apis-file-picker.md) to implement selection and saving of user files. No permission is required if your application uses **FilePicker** to access files.
The **FilePicker** provides the following interfaces by file type:
- [**PhotoViewPicker**](../reference/apis/js-apis-file-picker.md#photoviewpicker): used to select and save images or video files.
- [PhotoViewPicker](../reference/apis/js-apis-file-picker.md#photoviewpicker): used to select and save images or video files.
- [**DocumentViewPicker**](../reference/apis/js-apis-file-picker.md#documentviewpicker): used to select and save documents.
- [DocumentViewPicker](../reference/apis/js-apis-file-picker.md#documentviewpicker): used to select and save documents.
- [**AudioViewPicker**](../reference/apis/js-apis-file-picker.md#audioviewpicker): used to select and save audio files.
- [AudioViewPicker](../reference/apis/js-apis-file-picker.md#audioviewpicker): used to select and save audio files.
## Selecting Images or Video Files
1. Import the **picker** module and **fs** module.
1. Import the **picker** and **fs** modules.
```ts
import picker from '@ohos.file.picker';
......@@ -25,8 +25,8 @@ The **FilePicker** provides the following interfaces by file type:
const photoSelectOptions = new picker.PhotoSelectOptions();
```
3. Set the file type and the maximum number of media files to select.
For example, select a maximum of five images. For details about the media file type, see [PhotoViewMIMETypes](../reference/apis/js-apis-file-picker.md#photoviewmimetypes).
3. Set the file type and the maximum number of media files to select.<br>
For example, select a maximum of five images. For details about the media file types, see [PhotoViewMIMETypes](../reference/apis/js-apis-file-picker.md#photoviewmimetypes).
```ts
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // Select images.
......@@ -48,14 +48,14 @@ The **FilePicker** provides the following interfaces by file type:
})
```
5. Use a button to trigger invocation of other functions. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_ONLY**.
5. After the UI is returned from the **FilePicker** page, use a button to trigger API calling. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the file descriptor (FD). Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_ONLY**.
```ts
let file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
console.info('file fd: ' + file.fd);
```
6. Use [fs.readSync()](../reference/apis/js-apis-file-fs.md#readsync) to read the file data based on the FD. After the data is read, close the FD.
6. Use [fs.readSync()](../reference/apis/js-apis-file-fs.md#readsync) to read the file based on the FD. After the data is read, close the FD.
```ts
let buffer = new ArrayBuffer(4096);
......@@ -66,7 +66,7 @@ The **FilePicker** provides the following interfaces by file type:
## Selecting Documents
1. Import the **picker** module and **fs** module.
1. Import the **picker** and **fs** modules.
```ts
import picker from '@ohos.file.picker';
......@@ -83,7 +83,7 @@ The **FilePicker** provides the following interfaces by file type:
The permission on the URIs returned by **select()** is read-only. Further file operations can be performed based on the URIs in the result set. Note that the URI cannot be directly used in the **picker** callback to open a file. You need to define a global variable to save the URI and use a button to trigger file opening.
For example, you can use [file management APIs](../reference/apis/js-apis-file-fs.md) to obtain file attribute information, such as the file size, access time, and last modification time, based on the URI. If you need to obtain the file name, use [startAbilityForResult](../../application-dev/application-models/uiability-intra-device-interaction.md).
For example, you can use [file management APIs](../reference/apis/js-apis-file-fs.md) to obtain file attributes, such as the file size, access time, and last modification time, based on the URI. If you need to obtain the file name, use [startAbilityForResult](../../application-dev/application-models/uiability-intra-device-interaction.md).
> **NOTE**
>
......@@ -102,7 +102,7 @@ The **FilePicker** provides the following interfaces by file type:
> **NOTE**
>
> Currently, **DocumentSelectOptions** does not provide the method for obtaining the file name. To obtain the file name, use **startAbilityForResult()**.
> Currently, **DocumentSelectOptions** cannot be used to obtain the file name. To obtain the file name, use **startAbilityForResult()**.
```ts
let config = {
......@@ -126,14 +126,14 @@ The **FilePicker** provides the following interfaces by file type:
}
```
4. Use a button to trigger invocation of other functions. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_ONLY**.
4. After the UI is returned from the **FilePicker** page, use a button to trigger API calling. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_ONLY**.
```ts
let file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
console.info('file fd: ' + file.fd);
```
5. Use [fs.readSync()](../reference/apis/js-apis-file-fs.md#readsync) to read the file data based on the FD. After the data is read, close the FD.
5. Use [fs.readSync()](../reference/apis/js-apis-file-fs.md#readsync) to read the file based on the FD. After the data is read, close the FD.
```ts
let buffer = new ArrayBuffer(4096);
......@@ -143,9 +143,9 @@ The **FilePicker** provides the following interfaces by file type:
```
## Selecting an Audio File
## Selecting Audio Files
1. Import the **picker** module and **fs** module.
1. Import the **picker** and **fs** modules.
```ts
import picker from '@ohos.file.picker';
......@@ -179,14 +179,14 @@ The **FilePicker** provides the following interfaces by file type:
})
```
4. Use a button to trigger invocation of other functions. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_ONLY**.
4. After the UI is returned from the **FilePicker** page, use a button to trigger API calling. Use [fs.openSync()](../reference/apis/js-apis-file-fs.md#fsopensync) to open the file based on the URI and obtain the FD. Note that the **mode** parameter of **fs.openSync()** must be **fs.OpenMode.READ_ONLY**.
```ts
let file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
console.info('file fd: ' + file.fd);
```
5. Use [fs.readSync()](../reference/apis/js-apis-file-fs.md#readsync) to read the file data based on the FD. After the data is read, close the FD.
5. Use [fs.readSync()](../reference/apis/js-apis-file-fs.md#readsync) to read the file based on the FD. After the data is read, close the FD.
```ts
let buffer = new ArrayBuffer(4096);
......
# Sending Files to an Application Sandbox
# Pushing Files to an Application Sandbox
During the development and debugging process of an application, you may need to place some files to the application sandbox for intra-application access or for testing purposes. In this case, you can use either of the following methods:
During the development and debugging process of an application, you may need to push files to the application sandbox for intra-application access or for testing purposes. In this case, you can use either of the following methods:
1. Use DevEco Studio to place the files to the application installation directory. For details, see [Application Installation Resource Access](../quick-start/resource-categories-and-access.md# resource-access).
- Use DevEco Studio to push the files to the application installation directory. For details, see [Application Installation Resource Access](../quick-start/resource-categories-and-access.md#resource-access).
2. Use the hdc tool to send files to the application sandbox directory on the device. This section describes the second method.
- Use the hdc tool to push files to the application sandbox directory on the device. This section describes the second method.
However, the file directories visible to the debugged process in the hdc shell are different from the application sandbox directories visible to the application. You need to understand the mappings between the application sandbox directories and the physical (real) directories.
......@@ -27,15 +27,15 @@ The read and write operations performed based on the application sandbox paths v
The following uses the application bundle **com.ohos.example** as an example. If the application sandbox path is **/data/storage/el1/bundle**, the physical path is **/data/app/el1/bundle/public/<PACKAGENAME>**, that is, **/data/app/el1/bundle/public/com.ohos.example**.
Run the following command to send the file:
Run the following command to push files:
```
hdc file send ${Path of the local file to send} /data/app/el1/bundle/public/com.ohos.example/
hdc file send ${Path of the local files to send} /data/app/el1/bundle/public/com.ohos.example/
```
## Switching to the Application View
During the debugging process, if you do not have the permission or the file does not exist, you need to switch from the process view to the application view and further analyze permission and directory problems. To switch to the application view, run the following commands:
During the debugging process, if the required permission is unavailable or the file does not exist, you need to switch from the process view to the application view and further analyze permission and directory problems. To switch to the application view, run the following commands:
```
hdc shell // Switch to shell.
......
# Setting the Security Level of a Distributed File
The security capabilities vary with devices. For example, small embedded devices provide fewer security capabilities than tablets. The security requirements also vary with data. For example, personal health information and bank card information are not expected to be accessed by devices of lower security levels. OpenHarmony provides a complete set of standards for data and device classification and custom data transfer policies for different devices. For details, see [Data Security Labels and Device Security Levels](../database/access-control-by-device-and-data-level.md).
The security capabilities vary with devices. For example, small embedded devices provide fewer security capabilities than tablets. The security requirements also vary with data. For example, personal health information and bank card information are not expected to be accessed by devices of lower security levels. OpenHarmony provides a complete set of data and device classification standards and custom data transfer policies for different devices. For details, see [Access Control by Device and Data Level](../database/access-control-by-device-and-data-level.md).
## Available APIs
......@@ -8,26 +8,26 @@ For details about the APIs, see [ohos.file.securityLabel](../reference/apis/js-a
**Table 1** APIs
| API| Description| Type| Synchronous Programming| Asynchronous Programming|
| API| Description| Type| Synchronous Programming| Asynchronous Programming|
| -------- | -------- | -------- | -------- | -------- |
| setSecurityLabel | Sets a security label for a file.| Method| √ | √ |
| getSecurityLabel | Obtains the security label of a file.| Method| √ | √ |
| setSecurityLabel | Sets a security label for a file.| Method| √ | √ |
| getSecurityLabel | Obtains the security label of a file.| Method| √ | √ |
> **NOTICE**
> **NOTE**
>
> 1. In distributed networking, a device can view the files that do not match its security level but cannot access them.
> - In distributed networking, a device can view the files that do not match its security level but cannot access them.
>
> 2. The default security level of the distributed file system data is S3. Applications can set the security level of files.
> - The default security level of the distributed file system data is S3. Applications can set the security level of files.
## Development Example
Obtain the sandbox path of the file and set the data security label. For details about how to obtain the context in the example, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
Obtain the sandbox path of a file and set the data security label. For details about how to obtain the context, see [Obtaining the Context of UIAbility](../application-models/uiability-usage.md#obtaining-the-context-of-uiability).
```ts
import securityLabel from '@ohos.file.securityLabel';
//Obtain the sandbox path of the file.
// Obtain the sandbox path of the file.
let context =...; // Obtain UIAbilityContext information.
let pathDir = context.filesDir;
let filePath = pathDir + '/test.txt';
......
# Sharing an Application File
The file of an application can be shared with another application based on the file descriptor (FD) or uniform resource identifier (URI) of the file. However, if the FD of a shared file is closed, the file cannot be opened. Therefore, the file sharing based on the FD is not recommended. This section describes how to share an application file based on its URI.
An application can share its file with another application based on the file descriptor (FD) or uniform resource identifier (URI) of the file. However, if the FD of a shared file is closed, the file is no longer opened. Therefore, the FD-based file sharing is not recommended. This section describes how to share an application file based on its URI.
- You can use **wantConstant.Flags()** of the [ohos.app.ability.wantConstant](../reference/apis/js-apis-app-ability-wantConstant.md#wantconstantflags) module to share an application file in read or read/write mode based on its URI with another application. The target application can use **open()** of the [ohos.file.fs](../reference/apis/js-apis-file-fs.md#fsopen) module to open the URI and then perform read and/or write operations based on the permissions granted. Currently, OpenHarmony API version 9 supports only temporary authorization. The permission on shared file is revoked once the target application exits.
- You can use [wantConstant.Flags](../reference/apis/js-apis-app-ability-wantConstant.md#wantconstantflags) to share a single application file in read or read/write mode based on its URI with another application. The target application can use **open()** of the [ohos.file.fs](../reference/apis/js-apis-file-fs.md#fsopen) module to open the URI and then perform read and/or write operations based on the permissions granted. OpenHarmony API version 9 supports only temporary authorization. The permission on the shared file is revoked once the target application exits.
- You can also use **open()** of the ohos.file.fs module to share an application file with the specified permissions to another application based on the FD. After parsing the FD from **Want**, the target application can read and write the file by using **read()** and **write()** APIs of ohos.file.fs.
- You can also use **open()** of the ohos.file.fs module to share a single application file with the specified permissions to another application based on the FD. After parsing the FD from **Want**, the target application can read and write the file by using **read()** and **write()** APIs of ohos.file.fs.
You can use the related APIs to [share a file with another application](#sharing-a-file-with-another-application) or [use shared application files](#using-shared-files).
......@@ -12,7 +12,7 @@ You can use the related APIs to [share a file with another application](#sharing
The file URIs are in the following format:
file://&lt;bundleName&gt;/&lt;path&gt;
**file**://&lt;*bundleName*&gt;/&lt;*path*&gt;
- **file**: indicates a file URI.
......@@ -22,7 +22,7 @@ The file URIs are in the following format:
## Sharing a File with Another Application
Before sharing application files, you need to [obtain the application file path](../application-models/application-context-stage.md#obtaining-the-application-development-path).
Before sharing application files, you need to [obtain the application file path](../application-models/application-context-stage.md#obtaining-application-file-paths).
1. Obtain the application sandbox path of the file and convert it into the file URI.
......@@ -43,7 +43,7 @@ Before sharing application files, you need to [obtain the application file path]
```
2. Set the target application, with which you want to share the file, and grant permissions on the file.
Use [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to share the file with the target application. You need to pass in the URI obtained in **uri** of the **want** parameter, set the type of the file to share, set **action** to **ohos.want.action.sendData**, and set the granted permission on the file in **flags**. For details, see [Want](../reference/apis/js-apis-app-ability-want.md#attributes).
Use [startAbility()](../reference/apis/js-apis-inner-application-uiAbilityContext.md#uiabilitycontextstartability) to share the file with the target application. You need to pass in the obtained URI in **uri** of the **want** parameter, set the type of the file to share, set **action** to **ohos.want.action.sendData**, and set the granted permission on the file in **flags**. For details, see [Want](../reference/apis/js-apis-app-ability-want.md#attributes).
> **NOTE**
>
......@@ -85,7 +85,7 @@ Before sharing application files, you need to [obtain the application file path]
## Using Shared Files
In the [**module.json5** file](../quick-start/module-configuration-file.md) of the application, which wants to use the shared file, set **actions** to **ohos.want.action.sendData** to allow the application to receive files shared by another application and set **uris** to the type of the URI to receive. In the following example, the application receives only .txt files with **scheme** of **file**.
```json
{
"module": {
......@@ -115,7 +115,7 @@ In the [**module.json5** file](../quick-start/module-configuration-file.md) of t
After **UIAbility** of the application starts, the application obtains **want** information from [**onCreate()**](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityoncreate) or [**onNewWant()**](../reference/apis/js-apis-app-ability-uiAbility.md#uiabilityonnewwant).
After obtaining the URI of the shared file through **want**, the application can call **fs.open()** to open the file, and then read and write the file after obtaining the related file object.
After obtaining the URI of the shared file from **want**, the application can call **fs.open()** to open the file, and then read and write the file after obtaining the related file object.
```ts
// xxx.ets
......
# User File Overview
User files are the private images, video and audio clips, and documents of the user who logs in to the device.
User files are the private images, video and audio clips, and documents of the user who has logged in to the device.
1. User files are stored in a directory, whose owner is the user who logs in to the device.
- User files are stored in a directory, whose owner is the user who has logged in to the device.
2. User files can be stored in [built-in storage](#built-in-storage) and [external storage](#external-storage).
- User files can be stored in [built-in storage](#built-in-storage) and [external storage](#external-storage) of the device.
3. An application cannot access user files without user authorization, or the operations on user files must be performed by the user.
- An application cannot access user files without user authorization, or the operations on user files must be performed by the user.
OpenHarmony provides the [user file access framework](#user-file-access-framework) for developers to access and manage user files, which will be described in detail below.
OpenHarmony provides the [user file access framework](#user-file-access-framework) for developers to access and manage user files.
## User File Storage
### Built-in Storage
Built-in storage refers to the internal storage device (space) of a device. The built-in storage device cannot be removed. The following files can be stored in the built-in storage of a device:
Built-in storage is the internal storage device (space) of a device. The built-in storage device cannot be removed. The following files can be stored in the built-in storage of a device:
- Files owned by a user: The files belong to the user who logs in to the device. Different users who log in to a device can view only their own files.
- Files of a user: The files belong to the user who has logged in to the device. Different login users on a device can view their own files only.
These user files can be classified into the following types based on file attributes and access habits of users/applications:
- Image/Video files
The files have attributes, such as the shooting time, location, rotation angle, and file width and height information, and are stored in media file formats. The files are usually presented as media files or albums, without the specific location in the system.
- Image/Video files<br>
The files have attributes, such as the shooting time, location, rotation angle, and file width and height information, and are stored in media file formats. Generally, these files are presented as media files or albums, without the specific storage location in the system.
- Audio files
The files have attributes, such as the album, creator, and shooting duration information, and are stored in media file formats. Generally, the files are presented by file, album, or creator, without the specific location in the system.
- Audio files<br>
The files have attributes, such as the album, artist, and duration information, and are stored in media file formats. Generally, audio files are presented by file, album, or artist, without the specific storage location in the system.
- Documents
The files are stored as common files, including common text files, compressed files, and images, videos and audio clips stored as common files. These files are presented in a directory tree.
- Other files (documents)<br>
The files are stored as common files, including common text files, compressed files, and images, videos and audio clips stored as common files. Generally, these files are presented in a directory tree.
- Files shared by users: The files are stored in a directory for share and shared by multiple users.
The files in the shared directory are stored as common files and presented in a directory tree.
- Files shared by users: The files are stored in a share directory to enable access from multiple users.
The files in the share directory are stored as common files and presented in a directory tree.
### External Storage
External storage is not inside a device's main storage or memory. Common external storage devices include pluggable devices, such as SD cards and USB flash drives. Same as the files in the shared directory of the built-in storage device, the files in an external storage device can be viewed by all the users who log in to the system.
External storage is not inside a device's main storage or memory. Common external storage devices include pluggable devices, such as SD cards and USB flash drives. Same as the files in the share directory of the built-in storage device, the files in an external storage device can be viewed by all the users who has logged in to the system.
External storage devices are pluggable. OpenHarmony provides the functions of listening for the device insertion and removal events and mounting/unmounting an external storage device. For details, see [Managing External Storage Devices)](manage-external-storage.md).
External storage devices are pluggable. OpenHarmony provides listening for the device insertion/removal events and mount/unmount of an external storage device. For details, see [Managing External Storage Devices](manage-external-storage.md).
The files on external storage devices are presented as common files in a directory tree, like the documents stored in built-in storage.
The files on external storage devices are presented as common files in a directory tree, like the documents in built-in storage.
## User File Access Framework
OpenHarmony provides the user file access framework for developers to access and manage user files. This framework leverages the ExtensionAbility of OpenHarmony to provide a set of methods and interfaces for accessing user files.
**Figure 1** User file access framework
**Figure 1** User file access framework
![User file access framework](figures/user-file-access-framework.png)
- To access user files, for example, select a photo or save multiple documents, a system application or third-party application (file access client in **Figure 1**) starts the **FilePicker** application.
- The file access client (a system application or third-party application) can access user files, for example, select a photo or save multiple documents, by starting the **FilePicker** application.
- OpenHarmony is prebuilt with the **FilePicker** and **FileManager** applications.
- **FilePicker**: provides APIs for a file access client to select and save user files without any permission. For details, see [Selecting User Files](select-user-file.md).
- **FileManager**: allows users to view and modify files, and delete, rename, move, and create files or directories by using a system FileManager.
- **FilePicker**: allows a file access client to select and save user files without any permission. For details, see [Selecting User Files](select-user-file.md).
- **FileManager**: allows users to view and modify files, and delete, rename, move, and create files or directories.
You can also develop your own FilePicker or FileManager applications as required. FilePicker is a subset of FileManager. For details about how to develop a FileManager application, see [Developing a FileManager Application)](dev-user-file-manager.md).
You can also develop your own file picker or file manager applications as required. File picker is a subset of file manager. For details about how to develop a file manager application, see [Developing a File Manager Application](dev-user-file-manager.md).
- The user file access framework provides the following functional modules:
- The user file access framework consists of the following functional modules:
- **File Access Helper**: provides APIs for the **FileManager** and **FilePicker** to access user files.
- **File Access ExtensionAbility**: provides a file access framework to implement file access functions. The **File Access ExtensionAbility** consists of the following:
- **UserFileManager**: implements management of the files stored on the built-in storage.
- **ExternalFileManager**: implements management of the files stored on the external storage.
- **File Access ExtensionAbility**: implements file access via the following services:
- **UserFileManager**: implements management of the files on the built-in storage based on the File Access ExtensionAbility framework.
- **ExternalFileManager**: implements management of the files on the external storage based on the File Access ExtensionAbility framework.
......@@ -31,6 +31,7 @@
- [Developing Audio Call](audio-call-development.md)
- [Video Playback](video-playback.md)
- [Video Recording](video-recording.md)
- [Screen Capture](avscreen-capture.md)
- Audio and Video Codecs
- [Obtaining Supported Codecs](obtain-supported-codecs.md)
- [Audio Encoding](audio-encoding.md)
......@@ -61,6 +62,7 @@
- Best Practices
- [Camera Photographing Sample](camera-shooting-case.md)
- [Camera Recording Sample](camera-recording-case.md)
- [Using Performance Improvement Features (for System Applications Only)](camera-performance-improvement.md)
- Image
- [Image Overview](image-overview.md)
- [Image Decoding](image-decoding.md)
......
......@@ -28,8 +28,7 @@ Read [AudioEncoder](../reference/native-apis/_audio_encoder.md) for the API refe
Refer to the code snippet below to complete the entire audio encoding process, including creating an encoder, setting encoding parameters (such as the sampling rate, bit rate, and number of audio channels), and starting, refreshing, resetting, and destroying the encoder.
During application development, you must call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur.
During application development, you must call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur.
For details about the complete code, see [Sample](https://gitee.com/openharmony/multimedia_av_codec/blob/master/test/nativedemo/audio_demo/avcodec_audio_aac_encoder_demo.cpp).
......@@ -41,37 +40,34 @@ The figure below shows the call relationship of audio encoding.
You can create an encoder by name or MIME type.
```cpp
// Create an encoder by name.
OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
const char *name = OH_AVCapability_GetName(capability);
OH_AVCodec *audioEnc = OH_AudioEncoder_CreateByName(name);
```
```cpp
// Create an encoder by MIME type.
OH_AVCodec *audioEnc = OH_AudioEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC);
```
```cpp
// Initialize the queues.
class AEncSignal {
public:
std::mutex inMutex_;
std::mutex outMutex_;
std::mutex startMutex_;
std::condition_variable inCond_;
std::condition_variable outCond_;
std::condition_variable startCond_;
std::queue<uint32_t> inQueue_;
std::queue<uint32_t> outQueue_;
std::queue<OH_AVMemory *> inBufferQueue_;
std::queue<OH_AVMemory *> outBufferQueue_;
std::queue<OH_AVCodecBufferAttr> attrQueue_;
};
AEncSignal *signal_ = new AEncSignal();
```
```cpp
// Create an encoder by name.
OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
const char *name = OH_AVCapability_GetName(capability);
OH_AVCodec *audioEnc = OH_AudioEncoder_CreateByName(name);
```
```cpp
// Create an encoder by MIME type.
OH_AVCodec *audioEnc = OH_AudioEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC);
```
```cpp
// Initialize the queues.
class AEncSignal {
public:
std::mutex inMutex_;
std::mutex outMutex_;
std::mutex startMutex_;
std::condition_variable inCond_;
std::condition_variable outCond_;
std::condition_variable startCond_;
std::queue<uint32_t> inQueue_;
std::queue<uint32_t> outQueue_;
std::queue<OH_AVMemory *> inBufferQueue_;
std::queue<OH_AVMemory *> outBufferQueue_;
std::queue<OH_AVCodecBufferAttr> attrQueue_;
};
AEncSignal *signal_ = new AEncSignal();
```
2. Call **OH_AudioEncoder_SetCallback()** to set callback functions.
Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
......@@ -83,126 +79,122 @@ The figure below shows the call relationship of audio encoding.
You need to process the callback functions to ensure that the encoder runs properly.
```cpp
// Implement the OH_AVCodecOnError callback function.
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
(void)codec;
(void)errorCode;
(void)userData;
}
// Implement the OH_AVCodecOnStreamChanged callback function.
static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
(void)codec;
(void)format;
(void)userData;
}
// Implement the OH_AVCodecOnNeedInputData callback function.
static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
{
(void)codec;
// The input stream is sent to the InputBuffer queue.
AEncSignal *signal = static_cast<AEncSignal *>(userData);
unique_lock<mutex> lock(signal->inMutex_);
signal->inQueue_.push(index);
signal->inBufferQueue_.push(data);
signal->inCond_.notify_all();
}
// Implement the OH_AVCodecOnNewOutputData callback function.
static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
void *userData)
{
(void)codec;
// The index of the output buffer is sent to OutputQueue_.
// The encoded data is sent to the outBuffer queue.
AEncSignal *signal = static_cast<AEncSignal *>(userData);
unique_lock<mutex> lock(signal->outMutex_);
signal->outQueue_.push(index);
signal->outBufferQueue_.push(data);
if (attr) {
signal->attrQueue_.push(*attr);
}
}
OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
// Set the asynchronous callbacks.
int32_t ret = OH_AudioEncoder_SetCallback(audioEnc, cb, userData);
```
```cpp
// Implement the OH_AVCodecOnError callback function.
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
{
(void)codec;
(void)errorCode;
(void)userData;
}
// Implement the OH_AVCodecOnStreamChanged callback function.
static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
{
(void)codec;
(void)format;
(void)userData;
}
// Implement the OH_AVCodecOnNeedInputData callback function.
static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
{
(void)codec;
// The input stream is sent to the InputBuffer queue.
AEncSignal *signal = static_cast<AEncSignal *>(userData);
unique_lock<mutex> lock(signal->inMutex_);
signal->inQueue_.push(index);
signal->inBufferQueue_.push(data);
signal->inCond_.notify_all();
}
// Implement the OH_AVCodecOnNewOutputData callback function.
static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
void *userData)
{
(void)codec;
// The index of the output buffer is sent to OutputQueue_.
// The encoded data is sent to the outBuffer queue.
AEncSignal *signal = static_cast<AEncSignal *>(userData);
unique_lock<mutex> lock(signal->outMutex_);
signal->outQueue_.push(index);
signal->outBufferQueue_.push(data);
if (attr) {
signal->attrQueue_.push(*attr);
}
}
OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
// Set the asynchronous callbacks.
int32_t ret = OH_AudioEncoder_SetCallback(audioEnc, cb, userData);
```
3. Call **OH_AudioEncoder_Configure** to configure the encoder.
The following options are mandatory: sampling rate, bit rate, number of audio channels, audio channel type, and bit depth. The maximum input length is optional.
For FLAC encoding, the compliance level and sampling precision are also mandatory.
```cpp
enum AudioFormatType : int32_t {
TYPE_AAC = 0,
TYPE_FLAC = 1,
};
int32_t ret;
// (Mandatory) Configure the audio sampling rate.
constexpr uint32_t DEFAULT_SMAPLERATE = 44100;
// (Mandatory) Configure the audio bit rate.
constexpr uint32_t DEFAULT_BITRATE = 32000;
// (Mandatory) Configure the number of audio channels.
constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
// (Mandatory) Configure the audio channel type.
constexpr AudioChannelLayout CHANNEL_LAYOUT =AudioChannelLayout::STEREO;
// (Mandatory) Configure the audio bit depth. Only SAMPLE_S16LE and SAMPLE_S32LE are available for FLAC encoding.
constexpr OH_BitsPerSample SAMPLE_FORMAT =OH_BitsPerSample::SAMPLE_S32LE;
// (Mandatory) Configure the audio bit depth. Only SAMPLE_S32P is available for AAC encoding.
constexpr OH_BitsPerSample SAMPLE_AAC_FORMAT =OH_BitsPerSample::SAMPLE_S32P;
// Configure the audio compliance level. The default value is 0, and the value ranges from -2 to 2.
constexpr int32_t COMPLIANCE_LEVEL = 0;
// (Mandatory) Configure the audio sampling precision. SAMPLE_S16LE, SAMPLE_S24LE, and SAMPLE_S32LE are available.
constexpr BITS_PER_CODED_SAMPLE BITS_PER_CODED_SAMPLE =OH_BitsPerSample::SAMPLE_S24LE;
// (Optional) Configure the maximum input length.
constexpr uint32_t DEFAULT_MAX_INPUT_SIZE = 1024*DEFAULT_CHANNEL_COUNT *sizeof(float);//aac
OH_AVFormat *format = OH_AVFormat_Create();
// Set the format.
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(),DEFAULT_SMAPLERATE);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_BITRATE.data(), DEFAULT_BITRATE);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(),DEFAULT_CHANNEL_COUNT);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE.data(),DEFAULT_MAX_INPUT_SIZE);
OH_AVFormat_SetLongValue(format,MediaDescriptionKey::MD_KEY_CHANNEL_LAYOUT.data(),CHANNEL_LAYOUT);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),SAMPLE_FORMAT);
if(audioType == TYPE_AAC){
OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), SAMPLE_AAC_FORMAT);
}
if (audioType == TYPE_FLAC) {
OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_BITS_PER_CODED_SAMPLE.data(), BITS_PER_CODED_SAMPLE);
OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_COMPLIANCE_LEVEL.data(), COMPLIANCE_LEVEL);
}
// Configure the encoder.
ret = OH_AudioEncoder_Configure(audioEnc, format);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
```cpp
enum AudioFormatType : int32_t {
TYPE_AAC = 0,
TYPE_FLAC = 1,
};
int32_t ret;
// (Mandatory) Configure the audio sampling rate.
constexpr uint32_t DEFAULT_SMAPLERATE = 44100;
// (Mandatory) Configure the audio bit rate.
constexpr uint64_t DEFAULT_BITRATE = 32000;
// (Mandatory) Configure the number of audio channels.
constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
// (Mandatory) Configure the audio channel type.
constexpr AudioChannelLayout CHANNEL_LAYOUT =AudioChannelLayout::STEREO;
// (Mandatory) Configure the audio bit depth. Only SAMPLE_S16LE and SAMPLE_S32LE are available for FLAC encoding.
constexpr OH_BitsPerSample SAMPLE_FORMAT =OH_BitsPerSample::SAMPLE_S32LE;
// (Mandatory) Configure the audio bit depth. Only SAMPLE_F32P is available for AAC encoding.
constexpr OH_BitsPerSample SAMPLE_AAC_FORMAT = OH_BitsPerSample::SAMPLE_F32LE;
// Configure the audio compliance level. The default value is 0, and the value ranges from -2 to 2.
constexpr int32_t COMPLIANCE_LEVEL = 0;
// (Mandatory) Configure the audio sampling precision. SAMPLE_S16LE, SAMPLE_S24LE, and SAMPLE_S32LE are available.
constexpr BITS_PER_CODED_SAMPLE BITS_PER_CODED_SAMPLE =OH_BitsPerSample::SAMPLE_S24LE;
// (Optional) Configure the maximum input length.
constexpr uint32_t DEFAULT_MAX_INPUT_SIZE = 1024*DEFAULT_CHANNEL_COUNT *sizeof(float);//aac
OH_AVFormat *format = OH_AVFormat_Create();
// Set the format.
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(),DEFAULT_SMAPLERATE);
OH_AVFormat_SetLongValue(format,MediaDescriptionKey::MD_KEY_BITRATE.data(), DEFAULT_BITRATE);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(),DEFAULT_CHANNEL_COUNT);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE.data(),DEFAULT_MAX_INPUT_SIZE);
OH_AVFormat_SetLongValue(format,MediaDescriptionKey::MD_KEY_CHANNEL_LAYOUT.data(),CHANNEL_LAYOUT);
OH_AVFormat_SetIntValue(format,MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),SAMPLE_FORMAT);
if(audioType == TYPE_AAC){
OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(), SAMPLE_AAC_FORMAT);
}
if (audioType == TYPE_FLAC) {
OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_BITS_PER_CODED_SAMPLE.data(), BITS_PER_CODED_SAMPLE);
OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_COMPLIANCE_LEVEL.data(), COMPLIANCE_LEVEL);
}
// Configure the encoder.
ret = OH_AudioEncoder_Configure(audioEnc, format);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
4. Call **OH_AudioEncoder_Prepare()** to prepare internal resources for the encoder.
```c++
OH_AudioEncoder_Prepare(audioEnc);
```
```c++
OH_AudioEncoder_Prepare(audioEnc);
```
5. Call **OH_AudioEncoder_Start()** to start the encoder.
```c++
inputFile_ = std::make_unique<std::ifstream>();
// Open the path of the binary file to be encoded.
inputFile_->open(inputFilePath.data(), std::ios::in |std::ios::binary);
// Configure the path of the output file.
outFile_ = std::make_unique<std::ofstream>();
outFile_->open(outputFilePath.data(), std::ios::out |std::ios::binary);
// Start encoding.
ret = OH_AudioEncoder_Start(audioEnc);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
```c++
inputFile_ = std::make_unique<std::ifstream>();
// Open the path of the binary file to be encoded.
inputFile_->open(inputFilePath.data(), std::ios::in |std::ios::binary);
// Configure the path of the output file.
outFile_ = std::make_unique<std::ofstream>();
outFile_->open(outputFilePath.data(), std::ios::out |std::ios::binary);
// Start encoding.
ret = OH_AudioEncoder_Start(audioEnc);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
6. Call **OH_AudioEncoder_PushInputData()** to write the data to encode.
To indicate the End of Stream (EOS), pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag.
......@@ -213,64 +205,64 @@ The figure below shows the call relationship of audio encoding.
| Sampling Rate| FRAME_SIZE|
| :----: | :----: |
| 8000 | 576 |
| 16000 | 1152 |
| 22050 | 2304 |
| 24000 | 2304 |
| 32000 | 2304 |
| 44100 | 4608 |
| 48000 | 4608 |
| 88200 | 8192 |
| 96000 | 8192 |
| 8000 | 576 |
| 16000 | 1152 |
| 22050 | 2304 |
| 24000 | 2304 |
| 32000 | 2304 |
| 44100 | 4608 |
| 48000 | 4608 |
| 88200 | 8192 |
| 96000 | 8192 |
**NOTE**: If **FRAME_SIZE** is not set to **1024** for AAC encoding, an error code is returned. In the case of FLAC encoding, if **FRAME_SIZE** is set to a value greater than the value listed in the table for a given sampling rate, an error code is returned; if **FRAME_SIZE** is set to a value less than the value listed, the encoded file may be damaged.
```c++
constexpr int32_t FRAME_SIZE = 1024; // AAC encoding
constexpr int32_t DEFAULT_CHANNEL_COUNT =2;
constexpr int32_t INPUT_FRAME_BYTES = DEFAULT_CHANNEL_COUNT * FRAME_SIZE * sizeof(float); // AAC encoding
// Configure the buffer information.
OH_AVCodecBufferAttr info;
// Set the package size, offset, and timestamp.
info.size = pkt_->size;
info.offset = 0;
info.pts = pkt_->pts;
info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
auto buffer = signal_->inBufferQueue_.front();
if (inputFile_->eof()){
info.size = 0;
info.flags = AVCODEC_BUFFER_FLAGS_EOS;
}else{
inputFile_->read((char *)OH_AVMemory_GetAddr(buffer), INPUT_FRAME_BYTES);
}
uint32_t index = signal_->inQueue_.front();
// Send the data to the input queue for encoding. The index is the subscript of the queue.
int32_t ret = OH_AudioEncoder_PushInputData(audioEnc, index,info);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
```c++
constexpr int32_t FRAME_SIZE = 1024; // AAC encoding
constexpr int32_t DEFAULT_CHANNEL_COUNT =2;
constexpr int32_t INPUT_FRAME_BYTES = DEFAULT_CHANNEL_COUNT * FRAME_SIZE * sizeof(float); // AAC encoding
// Configure the buffer information.
OH_AVCodecBufferAttr info;
// Set the package size, offset, and timestamp.
info.size = pkt_->size;
info.offset = 0;
info.pts = pkt_->pts;
info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
auto buffer = signal_->inBufferQueue_.front();
if (inputFile_->eof()){
info.size = 0;
info.flags = AVCODEC_BUFFER_FLAGS_EOS;
}else{
inputFile_->read((char *)OH_AVMemory_GetAddr(buffer), INPUT_FRAME_BYTES);
}
uint32_t index = signal_->inQueue_.front();
// Send the data to the input queue for encoding. The index is the subscript of the queue.
int32_t ret = OH_AudioEncoder_PushInputData(audioEnc, index,info);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
7. Call **OH_AudioEncoder_FreeOutputData()** to output the encoded stream.
```c++
OH_AVCodecBufferAttr attr = signal_->attrQueue_.front();
OH_AVMemory *data = signal_->outBufferQueue_.front();
uint32_t index = signal_->outQueue_.front();
// Write the encoded data (specified by data) to the output file.
outFile_->write(reinterpret_cast<char *>(OH_AVMemory_GetAdd(data)), attr.size);
// Release the output buffer.
ret = OH_AudioEncoder_FreeOutputData(audioEnc, index);
if (ret != AV_ERR_OK) {
// Exception handling.
}
if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
cout << "decode eos" << endl;
isRunning_.store(false);
break;
}
```
```c++
OH_AVCodecBufferAttr attr = signal_->attrQueue_.front();
OH_AVMemory *data = signal_->outBufferQueue_.front();
uint32_t index = signal_->outQueue_.front();
// Write the encoded data (specified by data) to the output file.
outFile_->write(reinterpret_cast<char *>(OH_AVMemory_GetAdd(data)), attr.size);
// Release the output buffer.
ret = OH_AudioEncoder_FreeOutputData(audioEnc, index);
if (ret != AV_ERR_OK) {
// Exception handling.
}
if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
cout << "decode eos" << endl;
isRunning_.store(false);
break;
}
```
8. (Optional) Call **OH_AudioEncoder_Flush()** to refresh the encoder.
After **OH_AudioEncoder_Flush()** is called, the current encoding queue is cleared.
......@@ -282,19 +274,18 @@ The figure below shows the call relationship of audio encoding.
* The EOS of the file is reached.
* An error with **OH_AudioEncoder_IsValid** set to **true** (indicating that the execution can continue) occurs.
```c++
// Refresh the encoder.
ret = OH_AudioEncoder_Flush(audioEnc);
if (ret != AV_ERR_OK) {
// Exception handling.
}
// Start encoding again.
ret = OH_AudioEncoder_Start(audioEnc);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
```c++
// Refresh the encoder.
ret = OH_AudioEncoder_Flush(audioEnc);
if (ret != AV_ERR_OK) {
// Exception handling.
}
// Start encoding again.
ret = OH_AudioEncoder_Start(audioEnc);
if (ret != AV_ERR_OK) {
// Exception handling.
}
```
9. (Optional) Call **OH_AudioEncoder_Reset()** to reset the encoder.
After **OH_AudioEncoder_Reset()** is called, the encoder returns to the initialized state. To continue encoding, you must call **OH_AudioEncoder_Configure()** and then **OH_AudioEncoder_Start()**.
......@@ -334,4 +325,4 @@ The figure below shows the call relationship of audio encoding.
audioEnc = NULL; // The encoder cannot be destroyed repeatedly.
}
return ret;
```
```
\ No newline at end of file
# Screen Capture
Screen capture is mainly used to record the main screen.
You can call the native APIs of the **AVScreenCapture** module to record the screen and collect audio and video source data output by the device and microphone. When developing a live streaming or an office application, you can call the APIs to obtain original audio and video streams and transfer the streams to other modules for processing. In this way, the home screen can be shared during live streaming.
The **AVScreenCapture**, **Window**, and **Graphics** modules together implement the entire video capture process.
By default, the main screen is captured, and the **Graphics** module generates the screen capture frame data based on the main screen and places the data to the display data buffer queue. The screen capture framework obtains the data from the display data buffer queue for consumption processing.
## Development Guidelines
The full screen capture process involves creating an **AVScreenCapture** instance, configuring audio and video capture parameters, starting and stopping screen capture, and releasing the instance. This topic describes how to use the **AVScreenCapture** module to carry out one-time screen capture. For details about the API reference, see [AVScreenCapture](../reference/native-apis/_a_v_screen_capture.md).
After an **AVScreenCapture** instance is created, different APIs can be called to switch the AVScreenCapture to different states and trigger the required behavior. If an API is called when the AVScreenCapture is not in the given state, the system may throw an exception or generate other undefined behavior. Therefore, you are advised to check the AVScreenCapture state before triggering state transition.
### Permission Description
Before development, configure the following permissions for your application. For details about permission configuration, see [Permission Application Guide](../security/accesstoken-guidelines.md).
| Permission| Description| Authorization Mode| APL|
| ------ | ----- | --------| ------- |
| ohos.permission.CAPTURE_SCREEN | Allows an application to take screenshots.| system_grant | system_core |
| ohos.permission.MICROPHONE | Allows an application to access the microphone.<br>This permission is required only when you need to record the audio output by the microphone.| user_grant | normal |
### How to Develop
The following walks you through how to implement simple screen capture:
1. Create an **AVScreenCapture** instance, named **capture** in this example.
```c++
OH_AVScreenCapture* capture = AVScreenCapture_Create();
```
2. Set screen capture parameters.
After creating the **capture** instance, you can set the parameters required for screen capture.
```c++
OH_AudioCaptureInfo miccapinfo = {
.audioSampleRate = 16000,
.audioChannels = 2,
.audioSource = OH_MIC
};
OH_VideoCaptureInfo videocapinfo = {
.videoFrameWidth = display->GetWidth(),
.videoFrameHeight = display->Height(),
.videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA
};
OH_AudioInfo audioinfo = {
.micCapInfo = miccapinfo,
};
OH_VideoInfo videoinfo = {
.videoCapInfo = videocapinfo
};
OH_RecorderInfo recorderinfo = {
.url = name
};
OH_AVScreenCaptureConfig config = {
.captureMode = OH_CAPTURE_HOME_SCREEN,
.dataType = OH_ORIGINAL_STREAM,
.audioInfo = audioinfo,
.videoInfo = videoinfo,
.recorderInfo = recorderinfo
};
OH_AVScreenCapture_Init(capture, config);
```
3. Enable the microphone.
```c++
bool isMic = true;
OH_AVScreenCapture_SetMicrophoneEnabled(capture, isMic);
```
4. Set callback functions, which are used to listen for errors that may occur during screen capture and the generation of audio and video stream data.
```c++
OH_AVScreenCaptureCallback callback;
callback.onAudioBufferAvailable = OnAudioBufferAvailable;
callback.onVideoBufferAvailable = OnVideoBufferAvailable;
OH_AVScreenCapture_SetCallback(capture, callback);
```
5. Call **StartScreenCapture** to start screen capture.
```c++
OH_AVScreenCapture_StartScreenCapture(capture);
```
6. Call **StopScreenCapture()** to stop screen capture.
```c++
OH_AVScreenCapture_StopScreenCapture(capture_);
```
7. Call **AcquireAudioBuffer()** to obtain an audio buffer.
```c++
OH_AVScreenCapture_AcquireAudioBuffer(capture, &audiobuffer, type);
```
8. Call **AcquireVideoBuffer()** to obtain a video buffer.
```c++
OH_NativeBuffer* buffer = OH_ScreenCapture_AcquireVideoBuffer(capture, &fence, &timestamp, &damage);
```
9. Call **ReleaseAudioBuffer()** to release the audio buffer.
```c++
OH_ScreenCapture_ReleaseAudioBuffer(capture, type);
```
10. Call **ReleaseVideoBuffer()** to release the video buffer.
```c++
OH_ScreenCapture_ReleaseVideoBuffer(capture);
```
11. Call **release()** to release the instance.
```c++
OH_AVScreenCapture_Release(capture);
```
### Sample Code
Refer to the sample code below to implement screen capture using **AVScreenCapture**.
Currently, the buffer holds original streams, which can be encoded and saved in MP4 format for playback. The encoding format and file format are reserved and will be implemented in later versions.
```c++
#include "multimedia/player_framework/native_avscreen_capture.h"
#include "multimedia/player_framework/native_avscreen_capture_base.h"
#include "multimedia/player_framework/native_avscreen_capture_errors.h"
void OnError(struct OH_AVScreenCapture *capture, int32_t errorCode)
{
(void) capture;
(void) errorCode;
}
void OnAudioBufferAvailable(struct OH_AVScreenCapture *capture, bool isReady, OH_AudioCapSourceType type)
{
if (isReady) {
OH_AudioBuffer *audiobuffer = (struct OH_AudioBuffer*) malloc (sizeof(OH_AudioBuffer));
// Obtain an audio buffer.
int32_t ret = OH_AVScreenCapture_AcquireAudioBuffer(capture, &audiobuffer, type);
/* Obtain a buffer. */
(void)audiobuffer->buf;
/* Obtain the buffer size. */
(void)audiobuffer->size;
/* Obtain the timestamp of the audio buffer. */
(void)audiobuffer->timestamp;
free(audiobuffer);
audiobuffer = nullptr;
// Release the audio buffer.
int32_t ret = OH_ScreenCapture_ReleaseAudioBuffer(capture, type);
}
}
void OnVideoBufferAvailable(struct OH_ScreenCapture *capture, bool isReady)
{
if (isReady) {
int32_t fence = 0;
int64_t timestamp = 0;
struct OH_Rect damage;
// Obtain a video buffer.
OH_NativeBuffer* buffer = OH_ScreenCapture_AcquireVideoBuffer(capture, &fence, &timestamp, &damage);
void *virAddr = nullptr;
OH_NativeBuffer_Map (buffer, &virAddr); // Obtain a buffer.
OH_NativeBuffer_Config config;
OH_NativeBuffer_GetNativeBufferConfig(buffer, config); // Obtain the width, height, and format.
// Obtain the fence, timestamp, and coordinate information.
OH_NativeBuffer_UnMap (buffer); // Release the buffer.
// Release the video buffer.
int32_t ret = OH_ScreenCapture_ReleaseVideoBuffer(capture);
}
}
int main()
{
// Instantiate AVScreenCapture.
struct OH_AVScreenCapture* capture = OH_AVScreenCapture_Create(void);
// Set the callbacks.
struct OH_AVScreenCaptureCallback callback;
callback.onError = OnError;
callack.onAudioBufferAvailable = OnAudioBufferAvailable ;
callack.onVideoBufferAvailable = OnVideoBufferAvailable;
int32_t ret = OH_AVScreenCapture_SetCallback(capture, callback);
// Initialize AVScreenCapture and pass in an OH_AVScreenRecorderConfig struct.
OH_AudioCaptureInfo miccapinfo = {
.audioSampleRate = 16000,
.audioChannels = 2,
.audioSource = OH_MIC
};
OH_VideoCaptureInfo videocapinfo = {
.videoFrameWidth = 720,
.videoFrameHeight = 1280,
.videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA
};
OH_AudioInfo audioinfo = {
.micCapInfo = miccapinfo,
};
OH_VideoInfo videoinfo = {
.videoCapInfo = videocapinfo
};
OH_AVScreenCaptureConfig config = {
.captureMode = OH_CAPTURE_HOME_SCREEN,
.dataType = OH_ORIGINAL_STREAM,
.audioInfo = audioinfo,
.videoInfo = videoinfo,
.recorderInfo = recorderinfo
};
OH_AVScreenCapture_Init(capture, config);
int32_t ret = OH_AVScreenCapture_Init(capture, &config);
// Start screen capture.
int32_t ret = OH_AVScreenCapture_StartScreenCapture(capture);
// Enable the microphone.
int32_t ret = OH_ScreenCapture_SetMicrophoneEnable(capture, true);
sleep(10); // Capture the screen for 10s.
// Stop screen capture.
int32_t ret = OH_ScreenCapture_StopScreenCapture(capture);
// Release the AVScreenCapture instance.
int32_t ret = OH_ScreenCapture_Realease(capture);
return 0;
}
```
# Using Performance Improvement Features (for System Applications Only)
The camera startup performance is affected by time-consuming operations such as power-on of underlying components and initialization of the process pipeline. To improve the camera startup speed and thumbnail display speed, OpenHarmony introduces some features. The capabilities of these features are related to underlying components. You need to check whether these capabilities are supported before using them.
These features are involved in the processes of starting the camera device, configuring streams, and taking photos. This topic describes the three scenarios.
## Deferred Stream Configuration
A typical camera startup process includes starting the camera device, configuring a data stream, and starting the data stream. Before configuring the data stream, you need to obtain the surface ID of the **\<XComponent>**.
The deferred stream configuration feature decouples stream configuration and start from the surface. Before the **\<XComponent>** provides the surface for the camera application, the system configures and starts the stream. This way, the surface only needs to be available before the stream is started. This improves the startup speed and prevents the implementation of other startup optimization schemas from being affected.
![deferred-surface-scene](figures/deferred-surface-scene.png)
Before optimization: Stream configuration depends on a **Surface** object, which is available after UI loading is complete. In other words, you can create a session, configure input and output streams, and start the session only after the UI is loaded. The camera HDI is responsible for stream configuration.
After optimization: Stream configuration does not depend on the **Surface** object. UI loading and stream configuration are executed concurrently. After the parameters are prepared, you can create a session.
### Available APIs
Read [Camera](../reference/apis/js-apis-camera.md) for the API reference.
| API| Description|
| ---- | ---- |
| createDeferredPreviewOutput(profile: Profile): Promise\<PreviewOutput> | Creates a deferred **PreviewOutput** instance and adds it to the data stream instead of a common **PreviewOutput** instance during stream configuration.|
| addDeferredSurface(surfaceId: string): Promise\<void> | Adds a surface for delayed preview. This API can run after **session.commitConfig()** or **session.start()** is called.|
### Development Example
The figure below shows the recommended API call process.
![](figures/deferred-surface-sequence-diagram.png)
```js
import camera from '@ohos.multimedia.camera';
function async preview(context: Context, cameraInfo: camera.Device, previewProfile: camera.Profile, photoProfile: camera.Profile, surfaceId: string): Promise<void> {
const cameraManager: camera.CameraManager = camera.getCameraManager(context);
const cameraInput camera.CameraInput = await cameraManager.createCameraInput(cameraInfo)
const previewOutput: camera.PreviewOutput = await cameraManager.createDeferredPreviewOutput(previewProfile);
const photoOutput: camera.PhotoOutput = await cameraManager.createPhotoOutput(photoProfile);
const session: camera.CaptureSession = await this.mCameraManager.createCaptureSession();
await session.beginConfig();
await session.addInput(cameraInput);
await session.addOutput(previewOutput);
await session.addOutput(photoOutput);
await session.commitConfig();
await session.start();
await previewOutput.addDeferredSurface(surfaceId);
}
```
## Quick Thumbnail
The photographing performance depends on the algorithm processing speed. A complex algorithm chain provides better image effect while requiring longer processing time.
To improve the photographing speed perceived by end users, the quick thumbnail feature is introduced. When the user takes a photo, a thumbnail is output and reported to the camera application for display before a real image is reported.
In this way, the photographing process is optimized, which fulfills the processing requirements of the post-processing algorithm without blocking the photographing speed of the foreground.
### Available APIs
Read [Camera](../reference/apis/js-apis-camera.md) for the API reference.
| API| Description|
| ---- | ---- |
| isQuickThumbnailSupported() : boolean | Checks whether the quick thumbnail feature is supported.|
| enableQuickThumbnail(enabled:bool): void | Enables or disables the quick thumbnail feature.|
| on(type: 'quickThumbnail', callback: AsyncCallback\<image.PixelMap>): void | Listens for camera thumbnails.|
> **NOTE**
>
> - **isQuickThumbnailSupported** and **enableQuickThumbnail** must be called after **CaptureSession.addOutput** and **CaptureSession.addInput** but before **CaptureSession.commitConfig()**.
> - **on()** takes effect after **enableQuickThumbnail(true)** is called.
### Development Example
The figure below shows the recommended API call process.
![](figures/quick-thumbnail-sequence-diagram.png)
```js
import camera from '@ohos.multimedia.camera'
this.cameraManager = camera.getCameraManager(globalThis.abilityContext);
let cameras = this.cameraManager.getSupportedCameras()
// Create a CaptureSession instance.
this.captureSession = await this.cameraManager.createCaptureSession()
// Start configuration for the session.
await this.captureSession.beginConfig()
// Add a CameraInput instance to the session.
this.cameraInput = await this.cameraManager.createCameraInput(cameras[0])
await this.cameraInput.open()
await this.captureSession.addInput(this.cameraInput)
// Add a PhotoOutput instance to the session.
this.photoOutPut = await this.cameraManager.createPhotoOutput(photoProfile, surfaceId)
await this.captureSession.addOutput(this.photoOutPut)
boolean isSupported = this.photoOutPut.isQuickThumbnailSupported()
if (isSupported) {
// Enable the quick thumbnail feature.
this.photoOutPut.enableQuickThumbnail(true)
this.photoOutPut.on('quickThumbnail', (err, pixelmap) => {
if (err || pixelmap === undefined) {
Logger.error(this.tag, 'photoOutPut on thumbnail failed ')
return
}
// Display or save the PixelMap instance.
this.showOrSavePicture(pixelmap)
})
}
```
## Prelaunch
Generally, the startup of the camera application is triggered when the user touches the camera icon on the home screen. The home screen senses the touch event and instructs the application manager to start the camera application. This takes a relatively long time. After the camera application is started, the camera startup process starts. A typical camera startup process includes starting the camera device, configuring a data stream, and starting the data stream, which is also time-consuming.
The prelaunch feature triggers the action of starting the camera device before the camera application is started. In other words, when the user touches the camera icon on the home screen, the system starts the camera device. At this time, the camera application is not started yet. The figure below shows the camera application process before and after the prelaunch feature is introduced.
![prelaunch-scene](figures/prelaunch-scene.png)
### Available APIs
Read [Camera](../reference/apis/js-apis-camera.md) for the API reference.
| API| Description|
| ---- | ---- |
| isPrelaunchSupported(camera: CameraDevice) : boolean | Checks whether the camera supports prelaunch.|
| setPrelaunchConfig(prelaunchConfig: PrelaunchConfig) : void | Sets the prelaunch parameters.|
| prelaunch() : void | Prelaunches the camera. This API is called when a user clicks the system camera icon to start the camera application.|
### Development Example
The figure below shows the recommended API call process.
![](figures/prelaunch-sequence-diagram.png)
- **Home screen**
```js
import camera from '@ohos.multimedia.camera'
this.cameraManager = camera.getCameraManager(globalThis.abilityContext);
try {
this.cameraManager.prelaunch();
} catch (error) {
console.error(`catch error: Code: ${error.code}, message: ${error.message}`)
}
```
- **Camera application**
To use the prelaunch feature, the camera application must configure the **ohos.permission.CAMERA** permission.
For details about how to request and verify the permissions, see [Permission Application Guide](../security/accesstoken-guidelines.md).
```js
import camera from '@ohos.multimedia.camera'
this.cameraManager = camera.getCameraManager(globalThis.abilityContext);
let cameras = this.cameraManager.getSupportedCameras()
if(this.cameraManager.isPrelaunchSupported(cameras[0])) {
try {
this.cameraManager.setPrelaunchConfig({cameraDevice: cameras[0]});
} catch (error) {
console.error(`catch error: Code: ${error.code}, message: ${error.message}`)
}
}
```
......@@ -72,7 +72,7 @@ let AVRecorderConfig = {
audioSourceType : media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,
videoSourceType : media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV,
profile : AVRecorderProfile,
url : 'fd://', // Before passing in a file descriptor to this parameter, the file must be created by the caller and granted with the read and write permissions. Example value: eg.fd://45--file:///data/media/01.mp4.
url : 'fd://', // Before passing in a file descriptor to this parameter, the file must be created by the caller and granted with the read and write permissions. Example value: fd://45--file:///data/media/01.mp4.
rotation: 0, // The value can be 0, 90, 180, or 270. If any other value is used, prepare() reports an error.
location : { latitude : 30, longitude : 130 }
}
......
......@@ -104,7 +104,7 @@ Read [Camera](../reference/apis/js-apis-camera.md) for the API reference.
avRecorder.start().then(() => {
console.info('avRecorder start success');
}
});
```
5. Stop video recording.
......@@ -114,7 +114,7 @@ Read [Camera](../reference/apis/js-apis-camera.md) for the API reference.
```ts
videoRecorder.stop().then(() => {
console.info('stop success');
}
});
videoOutput.stop((err) => {
if (err) {
......
......@@ -90,3 +90,16 @@ The following walks you through how to implement simple playback:
```c++
OH_AudioStreamBuilder_Destroy(builder);
```
## Setting the Low Latency Mode
If the device supports the low-latency channel, you can use the low-latency mode to create a player for a higher-quality audio experience.
The development process is similar to that in the common playback scenario. The only difference is that you need to set the low delay mode by calling [OH_AudioStreamBuilder_SetLatencyMode()](../reference/native-apis/_o_h_audio.md#oh_audiostreambuilder_setlatencymode) when creating an audio stream builder.
The code snippet is as follows:
```C
OH_AudioStream_LatencyMode latencyMode = AUDIOSTREAM_LATENCY_MODE_FAST;
OH_AudioStreamBuilder_SetLatencyMode(builder, latencyMode);
```
......@@ -46,7 +46,7 @@ Read [AVPlayer](../reference/apis/js-apis-media.md#avplayer9) for the API refere
>
> The URL in the code snippet below is for reference only. You need to check the media asset validity and set the URL based on service requirements.
>
> - If local files are used for playback, ensure that the files are available and the application sandbox path is used for access. For details about how to obtain the application sandbox path, see [Obtaining the Application Development Path](../application-models/application-context-stage.md#obtaining-the-application-development-path). For details about the application sandbox and how to push files to the application sandbox, see [File Management](../file-management/app-sandbox-directory.md).
> - If local files are used for playback, ensure that the files are available and the application sandbox path is used for access. For details about how to obtain the application sandbox path, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths). For details about the application sandbox and how to push files to the application sandbox, see [File Management](../file-management/app-sandbox-directory.md).
>
> - If a network playback path is used, you must request the ohos.permission.INTERNET [permission](../security/accesstoken-guidelines.md).
>
......
......@@ -18,3 +18,6 @@
- [Purgeable Memory Development](purgeable-memory-guidelines.md)
- Device Management
- [USB DDK Development](usb-ddk-guidelines.md)
- Data Management
- [RelationalStore Development](native-relational-store-guidelines.md)
......@@ -26,6 +26,13 @@ For details about the APIs, see [native_buffer](../reference/native-apis/_o_h___
The following describes how to use the native APIs provided by **NativeBuffer** to create an **OH_NativeBuffer** instance, obtain memory properties, and map the corresponding ION memory to the process address space.
**Adding Dynamic Link Libraries**
Add the following library to **CMakeLists.txt**:
```txt
libnative_buffer.so
```
**Header File**
```c++
#include <native_buffer/native_buffer.h>
......@@ -51,14 +58,14 @@ The following describes how to use the native APIs provided by **NativeBuffer**
if (ret != 0) {
std::cout << "OH_NativeBuffer_Map Failed" << std::endl;
}
// Unmap the ION memory from the process address space when it is no longer needed.
// Unmap the ION memory from the process address space when it is no longer needed.
ret = OH_NativeBuffer_Unmap(buffer);
if (ret != 0) {
std::cout << "OH_NativeBuffer_Unmap Failed" << std::endl;
}
```
3. Obtain the memory properties.
```c++
// Obtain the properties of the OH_NativeBuffer instance.
......
......@@ -27,6 +27,17 @@ For details about the APIs, see [native_image](../reference/native-apis/_o_h___n
The following steps describe how to use the native APIs provided by **NativeImage** to create an **OH_NativeImage** instance as the consumer and update the data to a OpenGL external texture.
**Adding Dynamic Link Libraries**
Add the following libraries to **CMakeLists.txt**:
```txt
libEGL.so
libGLESv3.so
libnative_image.so
libnative_window.so
libnative_buffer.so
```
**Header File**
```c++
#include <EGL/egl.h>
......@@ -159,41 +170,48 @@ The following steps describe how to use the native APIs provided by **NativeImag
4. Write the produced content to a **NativeWindowBuffer** instance.
1. Obtain a NativeWindowBuffer instance from the NativeWindow instance.
```c++
OHNativeWindowBuffer* buffer = nullptr;
int fenceFd;
// Obtain a NativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer.
OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
BufferHandle *handle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
int code = SET_BUFFER_GEOMETRY;
int32_t width = 0x100;
int32_t height = 0x100;
ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
```
3. Write the produced content to the **NativeWindowBuffer** instance.
```c++
static uint32_t value = 0x00;
value++;
uint32_t *pixel = static_cast<uint32_t *>(handle->virAddr);
for (uint32_t x = 0; x < width; x++) {
for (uint32_t y = 0; y < height; y++) {
*pixel++ = value;
}
}
```
4. Flush the **NativeWindowBuffer** to the **NativeWindow**.
```c++
// Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the NativeWindowBuffer are changed.
Region region{nullptr, 0};
// Flush the buffer to the consumer through OH_NativeWindow_NativeWindowFlushBuffer, for example, by displaying it on the screen.
OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
```
5. Destroy the **NativeWindow** instance when it is no longer needed.
```c++
OH_NativeWindow_DestroyNativeWindow(nativeWindow);
```
```c++
OHNativeWindowBuffer* buffer = nullptr;
int fenceFd;
// Obtain a NativeWindowBuffer instance by calling OH_NativeWindow_NativeWindowRequestBuffer.
OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
BufferHandle *handle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
int code = SET_BUFFER_GEOMETRY;
int32_t width = 0x100;
int32_t height = 0x100;
ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
```
2. Write the produced content to the **NativeWindowBuffer** instance.
```c++
static uint32_t value = 0x00;
value++;
uint32_t *pixel = static_cast<uint32_t *>(handle->virAddr);
for (uint32_t x = 0; x < width; x++) {
for (uint32_t y = 0; y < height; y++) {
*pixel++ = value;
}
}
```
3. Flush the **NativeWindowBuffer** to the **NativeWindow**.
```c++
// Set the refresh region. If Rect in Region is a null pointer or rectNumber is 0, all contents in the NativeWindowBuffer are changed.
Region region{nullptr, 0};
// Flush the buffer to the consumer through OH_NativeWindow_NativeWindowFlushBuffer, for example, by displaying it on the screen.
OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
```
4. Destroy the **NativeWindow** instance when it is no longer needed.
```c++
OH_NativeWindow_DestroyNativeWindow(nativeWindow);
```
5. Update the content to the OpenGL texture.
```c++
// Update the content to the OpenGL texture.
......
# RelationalStore Development Guide
## When to Use
RelationalStore provides a complete mechanism for local database management. It offers a series of interfaces for adding, deleting, modifying, and querying data in an RDB store. To satisfy different needs in complicated scenarios, RelationalStore also supports direct execution of SQL statements.
## Basic concepts
- **OH_Predicates**: A representation of the property or feature of a data entity, or the relationship between data entities. It is used to define operation conditions.
- **OH_Cursor**: A set of query results, which allows access to the required data in flexible modes.
## Restrictions
- The default logging mode is Write Ahead Log (WAL), and the default flushing mode is **FULL** mode.
- RelationalStore supports a maximum of four connection pools to manage read and write operations.
- To ensure data accuracy, only one write operation is allowed at a time.
- Once an application is uninstalled, related database files and temporary files on the device are automatically deleted.
## Available APIs
For details about the APIs, see [RDB](../reference/native-apis/_r_d_b.md).
| API| Description|
| -------- | -------- |
| OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) | Obtains an OH_Rdb_Store instance for RDB store operations.|
| OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql) | Executes an SQL statement that contains specified arguments but returns no value.|
| OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket) | Inserts a row of data into a table.|
| OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valuesBucket, OH_Predicates *predicates); | Updates data in the RDB store based on the specified OH_Predicates instance.|
| OH_Rdb_Delete(OH_Rdb_Store *store, OH_Predicates *predicates) | Deletes data from the RDB store based on the specified OH_Predicates instance.|
| OH_Rdb_Query(OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length) | Queries data in the RDB store based on specified conditions.|
| OH_Rdb_DeleteStore(const OH_Rdb_Config *config) | Deletes an RDB store.|
## How to Develop
1. Obtain the OH_Rdb_Store instance and create a database file.
Example:
```c
// Create an OH_Rdb_Config object.
OH_Rdb_Config config;
// The path is the application sandbox path.
config.dataBaseDir = "xxx";
// Database file name.
config.storeName = "RdbTest.db";
// Application bundle name.
config.bundleName = "xxx";
// Module name.
config.moduleName = "xxx";
// Security level of the database file.
config.securityLevel = OH_Rdb_SecurityLevel::S1;
// Whether the database is encrypted.
config.isEncrypt = false;
// Memory size occupied by config.
config.selfSize = sizeof(OH_Rdb_Config);
int errCode = 0;
// Obtain the OH_Rdb_Store instance.
OH_Rdb_Store *store_ = OH_Rdb_GetOrOpen(&config, &errCode);
```
2. After obtaining the OH_Rdb_Store instance, call **OH_Rdb_Execute** to create a table and call **OH_Rdb_Insert** to insert data to the table created.
Example:
```c
char createTableSql[] = "CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, "
"AGE INTEGER, SALARY REAL, CODES BLOB)";
// Create a table.
OH_Rdb_Execute(store_, createTableSql);
// Create a key-value pair instance.
OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket();
valueBucket->putText(valueBucket, "NAME", "Lisa");
valueBucket->putInt64(valueBucket, "AGE", 18);
valueBucket->putReal(valueBucket, "SALARY", 100.5);
uint8_t arr[] = {1, 2, 3, 4, 5};
int len = sizeof(arr) / sizeof(arr[0]);
valueBucket->putBlob(valueBucket, "CODES", arr, len);
// Insert data.
int rowId = OH_Rdb_Insert(store_, "EMPLOYEE", valueBucket);
// Destroy the KV pair instance.
valueBucket->destroy(valueBucket);
```
> **NOTE**
>
> **RelationalStore** does not provide explicit flush operations for data persistence. **insert()** stores data in a file persistently.
3. Modify or delete data based on the specified **Predicates** instance.
Call **OH_Rdb_Update** to modify data and call **OH_Rdb_Delete** to delete data.
Example:
```c
// Modify data.
OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket();
valueBucket->putText(valueBucket, "NAME", "Rose");
valueBucket->putInt64(valueBucket, "AGE", 22);
valueBucket->putReal(valueBucket, "SALARY", 200.5);
uint8_t arr[] = {1, 2, 3, 4, 5};
int len = sizeof(arr) / sizeof(arr[0]);
valueBucket->putBlob(valueBucket, "CODES", arr, len);
OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE");
OH_VObject *valueObject = OH_Rdb_CreateValueObject();
const char *name = "Lisa";
valueObject->putText(valueObject, name);
predicates->equalTo(predicates, "NAME", valueObject)->andOperate(predicates);
uint32_t count = 1;
double salary = 100.5;
valueObject->putDouble(valueObject, &salary, count);
predicates->equalTo(predicates, "SALARY", valueObject);
int changeRows = OH_Rdb_Update(store_, valueBucket, predicates);
valueObject->destroy(valueObject);
valueBucket->destroy(valueBucket);
predicates->destroy(predicates);
```
```c
// Delete data.
OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE");
OH_VObject *valueObject = OH_Rdb_CreateValueObject();
const char *name = "Lisa";
valueObject->putText(valueObject, name);
predicates->equalTo(predicates, "NAME", valueObject);
int deleteRows = OH_Rdb_Delete(store_, predicates);
valueObject->destroy(valueObject);
predicates->destroy(predicates);
```
4. Query data based on the conditions specified by **Predicates**.
Call **OH_Rdb_Query** to query data. The data obtained is returned in a **OH_Cursor** object.
Example:
```c
OH_Predicates *predicates = OH_Rdb_CreatePredicates("EMPLOYEE");
const char *columnNames[] = {"NAME", "AGE"};
int len = sizeof(columnNames) / sizeof(columnNames[0]);
OH_Cursor *cursor = OH_Rdb_Query(store_, predicates, columnNames, len);
int columnCount = 0;
cursor->getColumnCount(cursor, &columnCount);
// OH_Cursor is a cursor of a data set. By default, the cursor points to the -1st record. Valid data starts from 0.
int64_t age;
while (cursor->goToNextRow(cursor) == OH_Rdb_ErrCode::RDB_OK) {
cursor->getInt64(cursor, 1, &age);
}
// Destroy the Predicates instance.
predicates->destroy(predicates);
// Destroy the result set.
cursor->destroy(cursor);
```
5. Delete the database.
Call **OH_Rdb_DeleteStore** to delete an RDB store and related database files.
Example:
```c
// Close the database instance.
OH_Rdb_CloseStore(store_);
// Delete the database file.
OH_Rdb_DeleteStore(&config);
```
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册